يتمتع برنامج 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
).
لا يستخدم 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 لا يتباطأ في حالات انخفاض الذاكرة.
تجميع نفسك أمر سهل:
git clone https://github.com/rfjakob/earlyoom.git
cd earlyoom
make
اختياري: قم بإجراء الاختبارات الذاتية المتكاملة:
make test
ابدأ تطبيق Earlyoom تلقائيًا عن طريق تسجيله كخدمة:
sudo make install # systemd
sudo make install-initscript # non-systemd
لاحظ أنه بالنسبة للأنظمة التي تم تعطيل SELinux فيها (Ubuntu 19.04، Debian 9 ...) يمكن تجاهل تحذيرات chcon التي تبلغ عن الفشل في ضبط السياق بأمان.
بالنسبة إلى Debian 10+ وUbuntu 18.04+، هناك حزمة Debian:
sudo apt install earlyoom
بالنسبة لـ Fedora وRHEL 8 مع EPEL، توجد حزمة Fedora:
sudo dnf install earlyoom
sudo systemctl enable --now earlyoom
بالنسبة لـ Arch Linux، توجد حزمة Arch Linux:
sudo pacman -S earlyoom
sudo systemctl enable --now earlyoom
التوفر في توزيعات أخرى: راجع صفحة الرد.
ما عليك سوى بدء الملف القابل للتنفيذ الذي قمت بتجميعه للتو:
./earlyoom
وسوف يعلمك مقدار الذاكرة والمبادلة لديك، وما هو الحد الأدنى، ومقدار الذاكرة المتوفرة ومقدار المبادلة المجانية.
./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 status earlyoom
من أجل رؤية 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 restart earlyoom
يرجى ملاحظة أن ملف التكوين هذا ليس له أي تأثير على مثيلات 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
راجع صفحة الرجل للحصول على التفاصيل.
نرحب بتقارير الأخطاء وطلبات السحب عبر جيثب. على وجه الخصوص، ويسعدني أن أقبل
الإصدار 1.8.2، 07-05-2024
earlyoom.service
process_mrelease
إلى مكالمات النظام المسموح بها (الالتزام)IPAddressDeny
(الالتزام)-p
(الالتزام)الإصدار 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.الإصدار 1.7، 05/03/2022
-N
لتشغيل البرنامج النصي في كل مرة يتم فيها إيقاف العملية (الالتزام، قسم صفحة الدليل)-g
لقتل مجموعة العمليات بأكملها (#247)-i
(تم تجاهلها من أجل التوافق)، فهي لا تعمل بشكل صحيح على نواة Linux 5.9+ (#234)الإصدار 1.6.2، 14-10-2020
1.6.1, 2020-07-07
1.6, 2020-04-11
notify-send
بـ dbus-send
/ systembus-notify (#183)-n
/ -N
يمكّن الآن المنطق الجديد/proc
باستخدام Hidepid بأمان (الإصدار رقم 184)الإصدار 1.5، 22-03-2020
-p
: اضبط oom_score_adj على -100
بدلاً من -1000
(#170)-M
و -m
و -S
و -s
. سيتم استخدام القيمة الأقل (المحولة إلى نسب مئوية).earlyoom.default
على ساعة واحدة بدلاً من دقيقة واحدة (#177)الإصدار 1.4، 2020-03-01
uid
للعمليات المقتولة بالإضافة إلى معرف الهوية والاسمmake test
)cppcheck
عندما يكون ذلك متاحًاmake bench
)earlyoom.service
الإصدار 1.3.1، 27-02-2020
الإصدار 1.3، 26/05/2019
الإصدار 1.2، 2018/10/28
-k
، تم تجاهله الآن من أجل التوافق) (الإصدار رقم 80)الإصدار 1.1، 07/07/2018
--help
بالإضافة إلى -h
-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: الإصدار الأولي