Unter Linux-Anwendern genießt der Oom-Killer generell einen schlechten Ruf. Dies könnte einer der Gründe dafür sein, dass Linux es nur dann aufruft, wenn es absolut keine andere Wahl hat. Es tauscht die Desktop-Umgebung aus, löscht den gesamten Seitencache und leert jeden Puffer, bevor letztendlich ein Prozess abgebrochen wird. Zumindest denke ich, dass es das bewirken wird. Ich muss noch die Geduld aufbringen, darauf zu warten, während ich vor einem nicht reagierenden System sitze.
Dies brachte mich und andere Leute dazu, sich zu fragen, ob der Oom-Killer so konfiguriert werden könnte, dass er früher eingreift: reddit r/linux, superuser.com, unix.stackexchange.com.
Wie sich herausstellt: Nein, das geht nicht. Zumindest mit dem Oom-Killer im Kernel. Im Benutzerbereich können wir jedoch tun und lassen, was wir wollen.
Earlyoom möchte einfach und solide sein. Es ist in reinem C ohne Abhängigkeiten geschrieben. Eine umfangreiche Testsuite (Unit- und Integrationstests) ist in Go geschrieben.
Earlyoom überprüft die Menge des verfügbaren Speichers und des freien Swaps bis zu 10 Mal pro Sekunde (seltener, wenn viel freier Speicher vorhanden ist). Wenn beide unter 10 % liegen, wird standardmäßig der größte Prozess (höchster oom_score
) abgebrochen. Der Prozentwert ist über Befehlszeilenargumente konfigurierbar.
In der free -m
Ausgabe unten beträgt der verfügbare Speicher 2170 MiB und der freie Swap 231 MiB.
total used free shared buff/cache available Mem: 7842 4523 137 841 3182 2170 Swap: 1023 792 231
Warum wird „verfügbarer“ Speicher geprüft und nicht „freier“ Speicher? Auf einem fehlerfreien Linux-System sollte der „freie“ Speicher nahezu Null sein, da Linux den gesamten verfügbaren physischen Speicher zum Zwischenspeichern des Festplattenzugriffs verwendet. Diese Caches können jederzeit gelöscht werden, wenn der Speicher für etwas anderes benötigt wird.
Dafür ist der „verfügbare“ Speicher verantwortlich. Es fasst den gesamten Speicher zusammen, der nicht verwendet wird oder sofort freigegeben werden kann.
Beachten Sie, dass Sie eine aktuelle Version von free
und Linux Kernel 3.14+ benötigen, um die Spalte „verfügbar“ anzuzeigen. Wenn Sie einen aktuellen Kernel, aber eine alte Version von free
haben, können Sie den Wert von grep MemAvailable /proc/meminfo
abrufen.
Wenn sowohl Ihr verfügbarer Speicher als auch Ihr freier Swap unter 10 % des Gesamtspeichers fallen, der für Userspace-Prozesse verfügbar ist (=total-shared), wird das SIGTERM
-Signal an den Prozess gesendet, der nach Meinung des Kernels den meisten Speicher verwendet ( /proc/*/oom_score
).
nohang, ein ähnliches Projekt wie Earlyoom, geschrieben in Python und mit zusätzlichen Funktionen und Konfigurationsoptionen.
Facebooks‘ Pressure Stall Information (PSI)-Kernel-Patches und der zugehörige Oomd-Userspace-Helfer. Die Patches werden in Linux 4.20 zusammengeführt.
Earlyoom verwendet echo f > /proc/sysrq-trigger
nicht, weil:
In einigen Kernel-Versionen (getestet auf v4.0.5) funktioniert das manuelle Auslösen des Kernel-Oom-Killers überhaupt nicht. Das heißt, es wird möglicherweise nur etwas Grafikspeicher freigegeben (der sofort wieder zugewiesen wird) und kein Prozess tatsächlich beendet. Hier können Sie sehen, wie das auf meinem Rechner aussieht (Intel integrierte Grafik).
Dieses Problem wurde in Linux v5.17 (Commit f530243a) behoben.
Wie der Linux-Kernel findet Earlyoom sein Opfer, indem es /proc/*/oom_score
durchliest.
Ungefähr 2 MiB
( VmRSS
), obwohl nur 220 kiB
privater Speicher ( RssAnon
) sind. Der Rest ist die libc-Bibliothek ( RssFile
), die mit anderen Prozessen geteilt wird. Der gesamte Speicher wird mit mlockall()
gesperrt, um sicherzustellen, dass Earlyoom in Situationen mit wenig Speicher nicht langsamer wird.
Das Zusammenstellen ist ganz einfach:
Git-Klon https://github.com/rfjakob/earlyoom.gitcd Earlyoom machen
Optional: Führen Sie die integrierten Selbsttests aus:
Test machen
Starten Sie Earlyoom automatisch, indem Sie es als Dienst registrieren:
sudo make install # systemdsudo make install-initscript # non-systemd
Beachten Sie, dass bei Systemen mit deaktiviertem SELinux (Ubuntu 19.04, Debian 9 ...) chcon-Warnungen, die einen Fehler beim Festlegen des Kontexts melden, getrost ignoriert werden können.
Für Debian 10+ und Ubuntu 18.04+ gibt es ein Debian-Paket:
Sudo apt install Earlyoom
Für Fedora und RHEL 8 mit EPEL gibt es ein Fedora-Paket:
sudo dnf install Earlyoom sudo systemctl enable --now Earlyoom
Für Arch Linux gibt es ein Arch Linux-Paket:
sudo pacman -S Earlyoom sudo systemctl enable --now Earlyoom
Verfügbarkeit in anderen Distributionen: siehe Repology-Seite.
Starten Sie einfach die gerade kompilierte ausführbare Datei:
./earlyoom
Es informiert Sie darüber, wie viel Speicher und Swap Sie haben, was das Minimum ist, wie viel Speicher verfügbar ist und wie viel Swap frei ist.
./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%) [...]
Sinken die Werte unter das Minimum, werden Prozesse abgebrochen, bis der Wert wieder über dem Minimum liegt. Jede Aktion wird in stderr protokolliert. Wenn Sie Earlyoom als Systemd-Dienst ausführen, können Sie die letzten 10 Zeilen mit anzeigen
Systemctl-Status Earlyoom
Um earlyoom
in Aktion zu sehen, erstellen/simulieren Sie einen Speicherverlust und lassen Sie earlyoom
tun, was es tut:
tail /dev/zero
Wenn Sie weitere Aktionen benötigen, nachdem ein Prozess von earlyoom
beendet wurde (z. B. das Senden von E-Mails), können Sie die Protokolle wie folgt analysieren:
sudo journalctl -u earlyoom | grep sending
Die Beispielausgabe für den obigen Testbefehl ( tail /dev/zero
) sieht folgendermaßen aus:
Feb 20 10:59:34 debian earlyoom[10231]: sending SIGTERM to process 7378 uid 1000 "tail": oom_score 156, VmRSS 4962 MiB
Für ältere Versionen von
earlyoom
verwenden Sie:sudo journalctl -u earlyoom | grep -iE "(sending|killing)"
Seit Version 1.6 kann Earlyoom Benachrichtigungen über abgebrochene Prozesse über den System-D-Bus versenden. Übergeben Sie -n
um sie zu aktivieren.
Um die Benachrichtigungen in Ihrer GUI-Sitzung tatsächlich zu sehen, muss systembus-notify als Ihr Benutzer ausgeführt werden.
Darüber hinaus kann Earlyoom für jeden beendeten Prozess ein Skript ausführen, das über die Umgebungsvariablen EARLYOOM_PID
, EARLYOOM_UID
und EARLYOOM_NAME
Informationen über den Prozess bereitstellt. Übergeben Sie -N /path/to/script
zum Aktivieren.
Warnung: Im Trockenlaufmodus wird das Skript schnell hintereinander ausgeführt. Stellen Sie sicher, dass Sie eine Geschwindigkeitsbegrenzung implementiert haben.
Das Befehlszeilen-Flag --prefer
gibt an, dass Prozesse bevorzugt getötet werden sollen. Ebenso gibt --avoid
Prozesse an, um das Töten zu vermeiden. Weitere Informationen finden Sie unter https://github.com/rfjakob/earlyoom/blob/master/MANPAGE.md#--prefer-regex.
Wenn Sie Earlyoom als Systemdienst ausführen (über systemd oder init.d), können Sie seine Konfiguration über die in /etc/default/earlyoom
bereitgestellte Datei anpassen. Die Datei enthält in den Kommentaren bereits einige Beispiele, mit denen Sie Ihren eigenen Konfigurationssatz basierend auf den unterstützten Befehlszeilenoptionen erstellen können, zum Beispiel:
EARLYOOM_ARGS="-m 5 -r 60 --avoid '(^|/)(init|Xorg|ssh)$' --prefer '(^|/)(java|chromium)$'"
Nachdem Sie die Datei angepasst haben, starten Sie einfach den Dienst neu, um die Änderungen zu übernehmen. Zum Beispiel für systemd:
systemctl startet Earlyoom neu
Bitte beachten Sie, dass diese Konfigurationsdatei keine Auswirkungen auf Earlyoom-Instanzen außerhalb von systemd/init.d hat.
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
Weitere Informationen finden Sie auf der Manpage.
Fehlerberichte und Pull-Requests sind über Github willkommen. Insbesondere nehme ich diese gerne an
Anwendungsfallberichte und Feedback
Wir verwenden procps/libproc2 nicht, da procps_pids_select() aus irgendeinem Grund immer /proc/$pid/status analysiert. Das ist relativ teuer und wir brauchen es nicht.
v1.8.2, 07.05.2024
process_mrelease
zu erlaubten Systemaufrufen hinzufügen (Commit)
IPAddressDeny
Syntax korrigieren (Commit)
Erlaube -p
(festschreiben)
Korrekturen in der systemd-Einheitendatei earlyoom.service
v1.8.1, 17.04.2024
Beheben Sie triviale Testfehler, die durch das Umformulieren von Nachrichten (Commit) verursacht wurden.
v1.8, 15.04.2024
Geben Sie user mem total
/ meminfo_t.UserMemTotal
ein und berechnen Sie MemAvailablePercent darauf basierend (Commit, weitere Informationen in der Manpage).
Verwenden Sie process_mrelease
(#266)
Unterstützen Sie NO_COLOR
(https://no-color.org/)
Lassen Sie sich nicht von Prozessen mit einem Zombie-Hauptthread (Commit) verwirren.
--sort-by-rss
hinzufügen, danke @RanHuang! Dadurch wird ein Prozess zum Beenden ausgewählt. zum größten RSS statt zum größten oom_score.
Die Gitlab CI Testsuite läuft jetzt auch auf Amazon Linux 2 und Oracle Linux 7.
v1.7, 05.03.2022
Fügen Sie das Flag -N
hinzu, um jedes Mal ein Skript auszuführen, wenn ein Prozess beendet wird (Commit, Manpage-Abschnitt).
Fügen Sie das Flag -g
hinzu, um die gesamte Prozessgruppe zu beenden (#247)
Entfernen Sie das Flag -i
(wird aus Kompatibilitätsgründen ignoriert). Es funktioniert nicht ordnungsgemäß auf Linux-Kerneln 5.9+ (#234)
Härtung: Umgebungsfunktionen beim Start löschen (#234)
v1.6.2, 14.10.2020
Überprüfen Sie die Erinnerungssituation noch einmal, bevor Sie das Opfer töten (begehen)
Beenden Sie uns niemals (#205)
Dump-Puffer bei /proc/meminfo-Konvertierungsfehler (#214)
1.6.1, 07.07.2020
Dbus-Send-Zombie-Prozesse bereinigen (#200)
Prozesse mit oom_score_adj=-1000 (210) überspringen
1.6, 11.04.2020
-n
/ -N
aktiviert nun die neue Logik
Für Arbeitsbenachrichtigungen muss systembus-notify in Ihrer GUI-Sitzung ausgeführt werden
Ersetzen Sie die alte notify-send
GUI-Benachrichtigungslogik durch dbus-send
/ systembus-notify (#183)
Behandeln Sie /proc
ordnungsgemäß mit hidepid gemountet (Problem Nr. 184)
v1.5, 22.03.2020
-p
: setze oom_score_adj auf -100
statt -1000
(#170)
Erlauben Sie die Verwendung -M
und -m
sowie -S
und -s
. Es wird der niedrigere Wert (umgerechnet in Prozent) verwendet.
Stellen Sie das Speicherberichtsintervall in earlyoom.default
auf 1 Stunde statt auf 1 Minute ein (#177)
v1.4, 01.03.2020
Verwenden Sie nach Möglichkeit blocklokale Variablen
Führen Sie PATH_LEN ein, um mehrere fest codierte Pufferlängen zu ersetzen
Beschleunigen Sie die Opferauswahllogik um 50 % durch Lazy-Loading von Prozessattributen
Protokollieren Sie zusätzlich zu PID und Name die Benutzer-ID uid
abgebrochener Prozesse
Debug-Protokoll hellgrau einfärben
Code-Bereinigung
Testsuite erweitern ( make test
)
Führen Sie cppcheck
aus, sofern verfügbar
Unit-Test-Benchmarks hinzufügen ( make bench
)
Löschen Sie Root-Rechte in der Systemd-Unit-Datei earlyoom.service
v1.3.1, 27.02.2020
Behebung eines falschen Testsuite-Fehlers auf Systemen mit viel RAM (Problem Nr. 156)
v1.3, 26.05.2019
Beenden Sie nicht mit einem schwerwiegenden Fehler, wenn SIGTERM-Limit < SIGKILL-Limit ist
Null-SIGKILL-Limit zulassen
Dies behebt das Problem, dass Earlyoom manchmal mehr als einen Prozess beendet, wenn einer ausreichen würde (Problem Nr. 121).
Warten Sie, bis Prozesse tatsächlich beendet werden, wenn Sie ein Signal senden
Seien Sie liberaler bei den Akzeptanzgrenzen für SIGTERM und SIGKILL (Problem Nr. 97).
Formatieren Sie die Startausgabe neu, um deutlich zu machen, dass SOWOHL swap als auch mem <= limit sein müssen
Fügen Sie das Hilfsskript notify_all_users.py hinzu
CODE_OF_CONDUCT.md hinzufügen (Contributor Covenant 1.4) (#102)
Korrigieren Sie möglicherweise abgeschnittene UTF8-App-Namen in der Protokollausgabe (#110)
v1.2, 28.10.2018
Implementieren Sie eine adaptive Ruhezeit (= adaptive Abfragerate), um die CPU-Auslastung weiter zu senken (Problem Nr. 61).
Entfernen Sie die Option zur Verwendung des Kernel-Oom-Killers ( -k
, jetzt aus Kompatibilitätsgründen ignoriert) (Problem Nr. 80)
Behandeln Sie den Fall, dass Swap nach dem Start von Earlyoom hinzugefügt oder entfernt wird, ordnungsgemäß (Problem 62, Commit).
Implementieren Sie einen gestaffelten Kill: zuerst SIGTERM, dann SIGKILL, mit konfigurierbaren Grenzwerten (Problem Nr. 67)
v1.1, 07.07.2018
Behebung möglicher Shell-Code-Injection durch GUI-Benachrichtigungen (Commit)
Wenn ein Prozess nicht beendet werden kann, nur 1 Sekunde statt 10 Sekunden in den Ruhezustand versetzen (Problem Nr. 74)
Senden Sie die GUI-Benachrichtigung nach dem Töten, nicht vorher (Problem Nr. 73)
Akzeptieren Sie --help
zusätzlich zu -h
Korrigieren Sie den falschen Prozessnamen im Protokoll und in der Kill-Benachrichtigung (Commit 1, Commit 2, Problem Nr. 52, Problem Nr. 65, Problem Nr. 194).
Korrigieren Sie eine mögliche Division durch Null mit -S
(Commit)
v1.0, 28.01.2018
Fügen Sie die Optionen --prefer
und --avoid
hinzu (@TomJohnZ)
Unterstützung für GUI-Benachrichtigungen hinzufügen, Optionen -n
und -N
hinzufügen
v0.12: Optionen -M
und -S
hinzufügen (@nailgun); Manpage hinzufügen, Makefile parametrisieren (@yangfl)
v0.11: Undefiniertes Verhalten in get_entry_fatal behoben (fehlende Rückgabe, Festschreibung)
v0.10: Ermöglicht das Überschreiben der Makefile-Variable VERSION, um das Packen zu vereinfachen. Fügen Sie die Befehlszeilenoption -v
hinzu
v0.9: Wenn oom_score aller Prozesse 0 ist, verwenden Sie VmRss, um ein Opfer zu finden
v0.8: Verwenden Sie eine Schätzung, wenn der Kernel kein MemAvailable bereitstellt
v0.7: Opfer nach oom_score anstelle von VmRSS auswählen, Optionen -i
und -d
hinzufügen
v0.6: Befehlszeilenoptionen -m
, -s
, -k
hinzufügen
v0.5: Swap-Unterstützung hinzufügen
v0.4: SysV-Init-Skript hinzufügen (danke @joeytwiddle), das neue MemAvailable
von /proc/meminfo
verwenden (benötigt Linux 3.14+, Commit)
v0.2: Systemd-Unit-Datei hinzufügen
v0.1: Erstveröffentlichung