يتمتع برنامج oom-killer عمومًا بسمعة سيئة بين مستخدمي Linux. قد يكون هذا جزءًا من سبب استدعاء Linux له فقط عندما لا يكون لديه أي خيار آخر على الإطلاق. سيقوم بتبديل بيئة سطح المكتب، وإسقاط ذاكرة التخزين المؤقت للصفحة بأكملها وإفراغ كل مخزن مؤقت قبل أن يؤدي في النهاية إلى إنهاء العملية. على الأقل هذا ما أعتقد أنه سيفعله. لا يزال يتعين علي التحلي بالصبر الكافي لانتظار ذلك، وأنا جالس أمام نظام لا يستجيب.
هذا جعلني وأشخاصًا آخرين نتساءل عما إذا كان من الممكن تكوين oom-killer للتدخل مبكرًا: reddit r/linux، superuser.com، unix.stackexchange.com.
وكما تبين، لا، لا يمكن ذلك. على الأقل باستخدام القاتل oom داخل النواة. ومع ذلك، في مساحة المستخدم، يمكننا أن نفعل ما نريد.
يريد Earlyoom أن يكون بسيطًا ومتينًا. إنه مكتوب بلغة C النقية دون أي تبعيات. تمت كتابة مجموعة اختبارات شاملة (اختبارات الوحدة والتكامل) بلغة Go.
يتحقق Earlyoom من مقدار الذاكرة المتاحة والتبديل المجاني حتى 10 مرات في الثانية (أقل في كثير من الأحيان إذا كان هناك الكثير من الذاكرة الحرة). افتراضيًا، إذا كان كلاهما أقل من 10%، فسيؤدي ذلك إلى إنهاء العملية الأكبر (أعلى درجة oom_score
). قيمة النسبة المئوية قابلة للتكوين عبر وسيطات سطر الأوامر.
في إخراج free -m
أدناه، تبلغ الذاكرة المتوفرة 2170 ميجابايت والمبادلة المجانية 231 ميجابايت.
total used free shared buff/cache available Mem: 7842 4523 137 841 3182 2170 Swap: 1023 792 231
لماذا يتم فحص الذاكرة "المتوفرة" بدلاً من الذاكرة "الفارغة"؟ في نظام Linux الصحي، من المفترض أن تكون الذاكرة "المجانية" قريبة من الصفر، لأن Linux يستخدم كل الذاكرة الفعلية المتوفرة لتخزين الوصول إلى القرص مؤقتًا. يمكن إسقاط ذاكرات التخزين المؤقت هذه في أي وقت تكون فيه الذاكرة مطلوبة لشيء آخر.
حسابات الذاكرة "المتاحة" لذلك. فهو يلخص كافة الذاكرة غير المستخدمة أو التي يمكن تحريرها على الفور.
لاحظ أنك تحتاج إلى إصدار حديث من Linux kernel 3.14+ free
لرؤية العمود "المتاح". إذا كان لديك نواة حديثة، ولكن إصدار قديم من free
، فيمكنك الحصول على القيمة من grep MemAvailable /proc/meminfo
.
عندما تنخفض كل من الذاكرة المتاحة والمبادلة المجانية إلى أقل من 10% من إجمالي الذاكرة المتاحة لعمليات مساحة المستخدم (= إجمالي المشاركة)، فسوف ترسل إشارة SIGTERM
إلى العملية التي تستخدم أكبر قدر من الذاكرة في رأي النواة ( /proc/*/oom_score
).
nohang، وهو مشروع مشابه لـ Earlyoom، مكتوب بلغة Python مع ميزات وخيارات تكوين إضافية.
تصحيحات نواة معلومات توقف ضغط فيسبوك (psi) ومساعد مساحة المستخدم OOMD المصاحب. تم دمج التصحيحات في Linux 4.20.
لا يستخدم Earlyoom echo f > /proc/sysrq-trigger
للأسباب التالية:
في بعض إصدارات kernel (التي تم اختبارها على الإصدار 4.0.5)، لا يعمل تشغيل kernel oom Killer يدويًا على الإطلاق. أي أنه قد يحرر فقط بعض ذاكرة الرسومات (التي سيتم تخصيصها على الفور مرة أخرى) ولا يقتل أي عملية فعليًا. هنا يمكنك أن ترى كيف يبدو هذا على جهازي (رسومات Intel المدمجة).
تم إصلاح هذه المشكلة في Linux v5.17 (الالتزام f530243a).
كما تفعل نواة Linux، تجد Earlyoom ضحيتها من خلال قراءة /proc/*/oom_score
.
حوالي 2 MiB
( VmRSS
)، على الرغم من أن 220 kiB
فقط هي الذاكرة الخاصة ( RssAnon
). والباقي هو مكتبة libc ( RssFile
) التي تتم مشاركتها مع العمليات الأخرى. يتم قفل كل الذاكرة باستخدام mlockall()
للتأكد من أن Earlyoom لا يتباطأ في حالات انخفاض الذاكرة.
تجميع نفسك أمر سهل:
استنساخ بوابة https://github.com/rfjakob/earlyoom.gitcd Earlyoom يصنع
اختياري: قم بإجراء الاختبارات الذاتية المتكاملة:
إجراء اختبار
ابدأ تطبيق Earlyoom تلقائيًا عن طريق تسجيله كخدمة:
sudo make install # systemdsudo make install-initscript # غير systemd
لاحظ أنه بالنسبة للأنظمة التي تم تعطيل SELinux فيها (Ubuntu 19.04، Debian 9 ...) يمكن تجاهل تحذيرات chcon التي تبلغ عن الفشل في ضبط السياق بأمان.
بالنسبة إلى Debian 10+ وUbuntu 18.04+، هناك حزمة Debian:
سودو ملائمة تثبيت Earlyoom
بالنسبة لـ Fedora وRHEL 8 مع EPEL، توجد حزمة Fedora:
Sudo dnf تثبيت Earlyoom تمكين Sudo Systemctl - الآن Earlyoom
بالنسبة لـ Arch Linux، توجد حزمة Arch Linux:
سودو بكمن -S Earlyoom تمكين Sudo Systemctl - الآن Earlyoom
التوفر في توزيعات أخرى: راجع صفحة الرد.
ما عليك سوى بدء الملف القابل للتنفيذ الذي قمت بتجميعه للتو:
./earlyom
وسوف يعلمك مقدار الذاكرة والمبادلة لديك، وما هو الحد الأدنى، ومقدار الذاكرة المتوفرة ومقدار المبادلة المجانية.
./earlyoom eearlyoom v1.8 mem total: 23890 MiB, user mem total: 21701 MiB, swap total: 8191 MiB sending SIGTERM when mem avail <= 10.00% and swap free <= 10.00%, SIGKILL when mem avail <= 5.00% and swap free <= 5.00% mem avail: 20012 of 21701 MiB (92.22%), swap free: 5251 of 8191 MiB (64.11%) mem avail: 20031 of 21721 MiB (92.22%), swap free: 5251 of 8191 MiB (64.11%) mem avail: 20033 of 21723 MiB (92.22%), swap free: 5251 of 8191 MiB (64.11%) [...]
إذا انخفضت القيم إلى ما دون الحد الأدنى، فسيتم إيقاف العمليات حتى تصبح أعلى من الحد الأدنى مرة أخرى. يتم تسجيل كل إجراء في stderr. إذا كنت تقوم بتشغيل Earlyoom كخدمة systemd، فيمكنك عرض آخر 10 أسطر باستخدام
حالة systemctl في وقت مبكر
من أجل رؤية earlyoom
عمليًا، قم بإنشاء/محاكاة تسرب للذاكرة ودع earlyoom
يفعل ما يفعله:
tail /dev/zero
إذا كنت بحاجة إلى أي إجراءات أخرى بعد إنهاء العملية بواسطة earlyoom
(مثل إرسال رسائل البريد الإلكتروني)، فيمكنك تحليل السجلات عن طريق:
sudo journalctl -u earlyoom | grep sending
سيبدو إخراج المثال لأمر الاختبار أعلاه ( tail /dev/zero
) كما يلي:
Feb 20 10:59:34 debian earlyoom[10231]: sending SIGTERM to process 7378 uid 1000 "tail": oom_score 156, VmRSS 4962 MiB
بالنسبة للإصدارات الأقدم من
earlyoom
، استخدم:sudo journalctl -u earlyoom | grep -iE "(sending|killing)"
منذ الإصدار 1.6، أصبح بإمكان Earlyoom إرسال إشعارات حول العمليات المتوقفة عبر نظام d-bus. قم بالتمرير -n
لتمكينهم.
لرؤية الإشعارات فعليًا في جلسة واجهة المستخدم الرسومية الخاصة بك، تحتاج إلى تشغيل systembus-notify كمستخدم لديك.
بالإضافة إلى ذلك، يمكن لـ Earlyoom تنفيذ برنامج نصي لكل عملية تم إيقافها، وتوفير معلومات حول العملية عبر متغيرات البيئة EARLYOOM_PID
و EARLYOOM_UID
و EARLYOOM_NAME
. قم بتمرير -N /path/to/script
للتمكين.
تحذير: في حالة التشغيل الجاف، سيتم تنفيذ البرنامج النصي بتتابع سريع، تأكد من تنفيذ نوع ما من حدود المعدل.
تحدد علامة سطر الأوامر --prefer
العمليات التي تفضل القتل؛ وبالمثل، --avoid
يحدد العمليات لتجنب القتل. راجع https://github.com/rfjakob/earlyoom/blob/master/MANPAGE.md#--prefer-regex للحصول على التفاصيل.
إذا كنت تقوم بتشغيل Earlyoom كخدمة نظام (من خلال systemd أو init.d)، فيمكنك ضبط تكوينه عبر الملف المتوفر في /etc/default/earlyoom
. يحتوي الملف بالفعل على بعض الأمثلة في التعليقات، والتي يمكنك استخدامها لإنشاء مجموعة التكوين الخاصة بك بناءً على خيارات سطر الأوامر المدعومة، على سبيل المثال:
EARLYOOM_ARGS="-m 5 -r 60 --avoid '(^|/)(init|Xorg|ssh)$' --prefer '(^|/)(java|chromium)$'"
بعد ضبط الملف، ما عليك سوى إعادة تشغيل الخدمة لتطبيق التغييرات. على سبيل المثال، بالنسبة للنظام:
إعادة تشغيل systemctl في وقت مبكر
يرجى ملاحظة أن ملف التكوين هذا ليس له أي تأثير على مثيلات Earlyoom خارج systemd/init.d.
earlyoom v1.8 Usage: ./earlyoom [OPTION]... -m PERCENT[,KILL_PERCENT] set available memory minimum to PERCENT of total (default 10 %). earlyoom sends SIGTERM once below PERCENT, then SIGKILL once below KILL_PERCENT (default PERCENT/2). -s PERCENT[,KILL_PERCENT] set free swap minimum to PERCENT of total (default 10 %). Note: both memory and swap must be below minimum for earlyoom to act. -M SIZE[,KILL_SIZE] set available memory minimum to SIZE KiB -S SIZE[,KILL_SIZE] set free swap minimum to SIZE KiB -n enable d-bus notifications -N /PATH/TO/SCRIPT call script after oom kill -g kill all processes within a process group -d, --debug enable debugging messages -v print version information and exit -r INTERVAL memory report interval in seconds (default 1), set to 0 to disable completely -p set niceness of earlyoom to -20 and oom_score_adj to -100 --ignore-root-user do not kill processes owned by root --sort-by-rss find process with the largest rss (default oom_score) --prefer REGEX prefer to kill processes matching REGEX --avoid REGEX avoid killing processes matching REGEX --ignore REGEX ignore processes matching REGEX --dryrun dry run (do not kill any processes) --syslog use syslog instead of std streams -h, --help this help text
راجع صفحة الرجل للحصول على التفاصيل.
نرحب بتقارير الأخطاء وطلبات السحب عبر جيثب. على وجه الخصوص، ويسعدني أن أقبل
استخدام تقارير الحالة وردود الفعل
نحن لا نستخدم procps/libproc2 لأن procps_pids_select()، لسبب ما، يقوم دائمًا بتوزيع /proc/$pid/status. وهذا مكلف نسبيا، ونحن لا نحتاج إليه.
الإصدار 1.8.2، 07-05-2024
إضافة process_mrelease
إلى مكالمات النظام المسموح بها (الالتزام)
إصلاح بناء جملة IPAddressDeny
(الالتزام)
السماح -p
(الالتزام)
إصلاحات في ملف وحدة systemd earlyoom.service
الإصدار 1.8.1، 17-04-2024
إصلاح حالات فشل الاختبار البسيطة الناجمة عن إعادة صياغة الرسالة (الالتزام)
الإصدار 1.8، 15-04-2024
قدم user mem total
/ meminfo_t.UserMemTotal
واحسب MemAvailablePercent بناءً عليه (الالتزام، مزيد من المعلومات في صفحة الدليل)
استخدم process_mrelease
(#266)
دعم NO_COLOR
(https://no-color.org/)
لا تخلط بين العمليات التي تحتوي على سلسلة رسائل الزومبي الرئيسية (الالتزام)
أضف --sort-by-rss
، شكرًا @RanHuang! سيؤدي هذا إلى تحديد عملية لقتل ACC. إلى أكبر RSS بدلاً من أكبر oom_score.
تعمل مجموعة اختبارات Gitlab CI الآن أيضًا على Amazon Linux 2 وOracle Linux 7.
الإصدار 1.7، 05/03/2022
إضافة علامة -N
لتشغيل البرنامج النصي في كل مرة يتم فيها إيقاف العملية (الالتزام، قسم صفحة الدليل)
إضافة علامة -g
لقتل مجموعة العمليات بأكملها (#247)
إزالة علامة -i
(تم تجاهلها من أجل التوافق)، فهي لا تعمل بشكل صحيح على نواة Linux 5.9+ (#234)
التصلب: إسقاط الإمكانات المحيطة عند بدء التشغيل (#234)
الإصدار 1.6.2، 14-10-2020
التحقق مرة أخرى من حالة الذاكرة قبل قتل الضحية (الالتزام)
لا ننهي أنفسنا أبدًا (#205)
تفريغ المخزن المؤقت في خطأ تحويل /proc/meminfo (#214)
1.6.1, 2020-07-07
تنظيف عمليات إرسال dbus-send (#200)
تخطي العمليات باستخدام oom_score_adj=-1000 (210)
1.6, 2020-04-11
-n
/ -N
يمكّن الآن المنطق الجديد
يجب أن يكون لديك systembus-notify قيد التشغيل في جلسة واجهة المستخدم الرسومية الخاصة بك للحصول على إشعارات العمل
استبدال منطق إشعار واجهة المستخدم الرسومية القديم notify-send
بـ dbus-send
/ systembus-notify (#183)
تم تثبيت المقبض /proc
مع إخفاء بأمان (الإصدار رقم 184)
الإصدار 1.5، 2020-03-22
-p
: اضبط oom_score_adj على -100
بدلاً من -1000
(#170)
السماح باستخدام كل من -M
و -m
و -S
و -s
. سيتم استخدام القيمة الأقل (المحولة إلى نسب مئوية).
ضبط الفاصل الزمني لتقرير الذاكرة في earlyoom.default
على ساعة واحدة بدلاً من دقيقة واحدة (#177)
الإصدار 1.4، 2020-03-01
استخدم متغيرات الكتلة المحلية حيثما أمكن ذلك
قدم PATH_LEN لاستبدال العديد من أطوال المخزن المؤقت المضمنة
اجعل منطق اختيار الضحية أسرع بنسبة 50% من خلال سمات عملية التحميل البطيء
قم بتسجيل معرف المستخدم uid
للعمليات المقتولة بالإضافة إلى معرف الهوية والاسم
لون سجل التصحيح باللون الرمادي الفاتح
تنظيف الكود
قم بتوسيع testsuite ( make test
)
قم بتشغيل cppcheck
عندما يكون ذلك متاحًا
إضافة معايير اختبار الوحدة ( make bench
)
قم بإسقاط امتيازات الجذر في ملف وحدة systemd earlyoom.service
الإصدار 1.3.1، 27-02-2020
إصلاح فشل testsuite الزائف على الأنظمة التي تحتوي على الكثير من ذاكرة الوصول العشوائي (الإصدار رقم 156)
الإصدار 1.3، 26/05/2019
لا تقم بالخروج مع ظهور خطأ فادح إذا كان حد SIGTERM < حد SIGKILL
السماح بحد الصفر SIGKILL
يعمل هذا على حل المشكلة المتمثلة في أن Earlyoom يقتل أحيانًا أكثر من عملية واحدة عندما تكون عملية واحدة كافية (الإصدار رقم 121)
انتظر حتى تخرج العمليات فعليًا عند إرسال الإشارة
كن أكثر ليبرالية فيما يتعلق بحدود القبول لـ SIGTERM وSIGKILL (الإصدار رقم 97)
أعد تنسيق مخرجات بدء التشغيل لتوضيح أن كلا من المبادلة والذاكرة يجب أن يكونا <= حدًا
أضف البرنامج النصي المساعد notify_all_users.py
إضافة CODE_OF_CONDUCT.md (ميثاق المساهم 1.4) (#102)
إصلاح أسماء تطبيقات UTF8 التي قد يتم اقتطاعها في إخراج السجل (#110)
الإصدار 1.2، 28/10/2018
تنفيذ وقت النوم التكيفي (= معدل الاستقصاء التكيفي) لتقليل استخدام وحدة المعالجة المركزية بشكل أكبر (الإصدار رقم 61)
إزالة الخيار لاستخدام kernel oom-killer ( -k
، تم تجاهله الآن من أجل التوافق) (الإصدار رقم 80)
التعامل بلطف مع حالة المبادلة التي تمت إضافتها أو إزالتها بعد بدء التشغيل المبكر (الإصدار 62، الالتزام)
تنفيذ القتل المرحلي: أولاً SIGTERM، ثم SIGKILL، بحدود قابلة للتكوين (الإصدار رقم 67)
الإصدار 1.1، 07/07/2018
إصلاح إمكانية إدخال رمز الصدفة من خلال إشعارات واجهة المستخدم الرسومية (الالتزام)
في حالة الفشل في إيقاف أي عملية، نام لمدة ثانية واحدة فقط بدلاً من 10 (الإصدار رقم 74)
إرسال إشعار واجهة المستخدم الرسومية بعد القتل وليس قبله (الإصدار رقم 73)
قبول --help
بالإضافة إلى -h
إصلاح اسم العملية الخاطئ في السجل وفي إشعار القتل (الالتزام 1، الالتزام 2، الإصدار رقم 52، الإصدار رقم 65، الإصدار رقم 194)
إصلاح القسمة المحتملة على صفر باستخدام -S
(الالتزام)
الإصدار 1.0، 28/01/2018
أضف خيارات --prefer
و --avoid
(@TomJohnZ)
إضافة دعم لإشعارات واجهة المستخدم الرسومية وإضافة الخيارات -n
و -N
الإصدار 0.12: إضافة خيارات -M
و- -S
(@nailgun)؛ إضافة صفحة الدليل، وتحديد معلمة Makefile (@yangfl)
الإصدار 0.11: إصلاح السلوك غير المحدد في get_entry_fatal (الإرجاع المفقود والالتزام)
الإصدار 0.10: السماح بتجاوز متغير VERSION الخاص بـ Makefile لتسهيل عملية التعبئة، وإضافة خيار سطر الأوامر -v
الإصدار 0.9: إذا كانت قيمة oom_score لجميع العمليات هي 0، فاستخدم VmRss للعثور على الضحية
الإصدار 0.8: استخدم تقديرًا تخمينيًا إذا كانت النواة لا توفر MemAvailable
الإصدار 0.7: حدد الضحية بواسطة oom_score بدلاً من VmRSS، وأضف الخيارات -i
و- -d
الإصدار 0.6: إضافة خيارات سطر الأوامر -m
, -s
, -k
v0.5: إضافة دعم المبادلة
الإصدار 0.4: أضف البرنامج النصي SysV init (شكرًا @joeytwiddle)، واستخدم MemAvailable
الجديد من /proc/meminfo
(يحتاج إلى Linux 3.14+، الالتزام)
v0.2: إضافة ملف وحدة systemd
v0.1: الإصدار الأولي