Co zabiło mój proces i dlaczego?

614

Moja aplikacja działa jako proces w tle w systemie Linux. Obecnie jest uruchamiany z wiersza poleceń w oknie terminala.

Niedawno użytkownik uruchamiał aplikację przez pewien czas i ta tajemnicza śmierć. Tekst:

Zabity

był na terminalu. Stało się to dwa razy. Zapytałem, czy ktoś w innym terminalu użył polecenia kill, aby zabić proces? Nie.

W jakich warunkach Linux zdecydowałby się zabić mój proces? Uważam, że powłoka wyświetlała komunikat „zabity”, ponieważ proces ten umarł po otrzymaniu sygnału zabicia (9). Jeśli Linux wysłał sygnał zabicia, czy w logu systemowym powinien znajdować się komunikat wyjaśniający, dlaczego został zabity?

sbq
źródło
23
linux zabił mój proces i zalogował go w / var / log / messages na redhat
Dean Hiller
1
Zobacz także tę odpowiedź na unix.stackexchange.com.
Richard
W tym zdarzeniu uczestniczą 3 osoby: (1) Proces, który (wspólna przyczyna) zajmuje zbyt dużo pamięci i powoduje warunek OOM (2) Jądro, które wysyła SIGKILL (sygnał 9), przerywa go i rejestruje fakt w niektórych systemach log like /var/log/messages(3) Powłoka, w której uruchomiono proces, czyli proces, który drukuje Killedpowiadomienie, gdy status wyjścia z waitpid(2)wskazuje, że proces potomny zmarł z sygnału 9.
arielf
Po przeczytaniu odpowiedzi @ DeanHiller, znalazłem komunikaty dziennika na Ubuntu pod/var/log/syslog
Dinei

Odpowiedzi:

403

Jeśli użytkownik lub sysadmin nie zabił programu, jądro może go mieć. Jądro zabiłoby proces tylko w wyjątkowych okolicznościach, takich jak ekstremalne głodzenie zasobów (pomyśl mem + wyczerpanie zamiany).

dwc
źródło
25
Gdyby jądro zabiło proces, czy umieściłoby gdzieś komunikat w dzienniku?
sbq
186
Właśnie napisałem program, który przywołał pamięć w nieokreślonej pętli. Po zwolnieniu systemu na terminalu wyświetlał się komunikat „Zabity”, a proces został zakończony. Plik /var/log/kern.log zawierał wiele informacji o zakończeniu. -Dziękujemy za wskaźnik.
sbq
6
To prawie na pewno to. Dużo to widziałem podczas TAing. Wielu studentów zapomniałoby uwolnić swoje przedmioty, a aplikacje ostatecznie osiągnęłyby 3 GB wykorzystania pamięci wirtualnej. Gdy tylko dotarł do tego punktu, został zabity.
Herms,
8
Kiedy „program po prostu ulega awarii”, to system operacyjny faktycznie zabija proces!
Bernd Jendrissek
79
Służy dmesgdo wyświetlania dziennika jądra: tutaj znajduję procesy Pythona zabite przez jądro z powodu ekstremalnego zużycia pamięci wirtualnej.
caneta
272

Próbować:

dmesg -T| grep -E -i -B100 'killed process'

Gdzie -B100oznacza liczbę linii przed zabiciem.

Pomiń -T w systemie Mac OS.

Ravindranath Akila
źródło
6
Do Twojej wiadomości, z info egrep: „egrep jest taki sam jak grep -E. ... Bezpośrednie wywołanie jako egrep lub fgrep jest przestarzałe”
Air
9
W przypadku prostego wzorca, takiego jak 'killed process'można użyć grepzamiast egrepbez innych zmian. Dla bardziej skomplikowanej strukturze, byś zmienił zastąpić np egrep -i -B100 'foo|ba[rz]'z grep -E -i -B100 'foo|ba[rz]'. Te pytania i odpowiedzi zawierają więcej szczegółów.
Air
2
Sugeruję również użycie dmesg -Tw celu uzyskania czytelnych znaczników czasu
gukoff
171

To wygląda na dobry artykuł na ten temat: Oswajanie zabójcy OOM .

Istotą jest to, że Linux przesadapamięć. Kiedy proces poprosi o więcej miejsca, Linux da mu to miejsce, nawet jeśli jest zajęte przez inny proces, przy założeniu, że nikt tak naprawdę nie wykorzystuje całej pamięci, o którą prosi. Proces uzyska wyłączne wykorzystanie pamięci, którą przydzielił, kiedy faktycznie z niego korzysta, a nie kiedy o to poprosi. Dzięki temu alokacja jest szybka i może pozwolić ci „oszukać” i przydzielić więcej pamięci, niż naprawdę masz. Jednak gdy procesy zaczną korzystać z tej pamięci, Linux może zdać sobie sprawę, że zbyt hojnie przydzielał pamięć, której nie ma, i będzie musiał zabić proces, aby zwolnić trochę. Proces, który ma zostać zabity, opiera się na wynikach uwzględniających czas działania (procesy długotrwałe są bezpieczniejsze), użycie pamięci (procesy zachłanne są mniej bezpieczne) i kilka innych czynników, w tym wartość, którą możesz dostosować, aby zmniejszyć prawdopodobieństwo śmierci procesu. Wszystko to opisano w artykule bardziej szczegółowo.

Edycja: A oto kolejny artykuł, który całkiem dobrze wyjaśnia, jak wybierany jest proces (opatrzony adnotacjami w niektórych przykładach kodu jądra). Wspaniałą rzeczą jest to, że zawiera komentarz dotyczący uzasadnienia różnych badness()zasad.

Adam Jaskiewicz
źródło
3
Naprawdę kocham linki do artykułów. Sugerowałbym każdemu, kto jest zainteresowany tym tematem, aby je przeczytał - zwłaszcza komentarze do lwn artykułu.
Jon Bringhurst,
4
„Linux da mu tę przestrzeń, nawet jeśli jest zajęty przez inny proces”. Nie tak działa pamięć wirtualna ...
Mooing Duck
1
artykuł jest dość stary (2009) i nie wszystkie funkcje sugerowane w artykule są w głównej linii.
Alex
50

Pozwól mi najpierw wyjaśnić, kiedy i dlaczego wywoływany jest OOMKiller?

Załóżmy, że masz 512 pamięci RAM + 1 GB pamięci wymiany. Teoretycznie procesor ma dostęp do łącznie 1,5 GB pamięci wirtualnej.

Od pewnego czasu wszystko działa dobrze w granicach 1,5 GB całkowitej pamięci. Ale nagle (lub stopniowo) twój system zaczął zużywać coraz więcej pamięci i osiągnął poziom około 95% całkowitej zajętej pamięci.

Powiedzmy teraz, że jakikolwiek proces zażądał dużego fragmentu pamięci z jądra. Jądro sprawdza dostępną pamięć i stwierdza, że ​​nie ma możliwości, aby przydzielić procesowi więcej pamięci. Spróbuje więc zwolnić część pamięci wywołując / wywołując OOMKiller ( http://linux-mm.org/OOM ).

OOMKiller ma swój własny algorytm do oceny rangi dla każdego procesu. Zazwyczaj proces, który zużywa więcej pamięci, staje się ofiarą do zabicia.

Gdzie mogę znaleźć dzienniki OOMKiller?

Zazwyczaj w katalogu / var / log. Albo /var/log/kern.log lub / var / log / dmesg

Mam nadzieję, że to ci pomoże.

Niektóre typowe rozwiązania:

  1. Zwiększ pamięć (nie zamień)
  2. Znajdź wycieki pamięci w swoim programie i napraw je
  3. Ogranicz pamięć, którą może zużyć dowolny proces (na przykład pamięć JVM można ograniczyć za pomocą JAVA_OPTS)
  4. Zobacz dzienniki i google :)
Jadav Bheda
źródło
17

To jest Linux out of memory manager (OOM) . Twój proces został wybrany z powodu „ złości ” - połączenia aktualności, wielkości rezydenta (używana pamięć, a nie tylko przydzielona) i innych czynników.

sudo journalctl -xb

Zobaczysz komunikat taki jak:

Jul 20 11:05:00 someapp kernel: Mem-Info:
Jul 20 11:05:00 someapp kernel: Node 0 DMA per-cpu:
Jul 20 11:05:00 someapp kernel: CPU    0: hi:    0, btch:   1 usd:   0
Jul 20 11:05:00 someapp kernel: Node 0 DMA32 per-cpu:
Jul 20 11:05:00 someapp kernel: CPU    0: hi:  186, btch:  31 usd:  30
Jul 20 11:05:00 someapp kernel: active_anon:206043 inactive_anon:6347 isolated_anon:0
                                    active_file:722 inactive_file:4126 isolated_file:0
                                    unevictable:0 dirty:5 writeback:0 unstable:0
                                    free:12202 slab_reclaimable:3849 slab_unreclaimable:14574
                                    mapped:792 shmem:12802 pagetables:1651 bounce:0
                                    free_cma:0
Jul 20 11:05:00 someapp kernel: Node 0 DMA free:4576kB min:708kB low:884kB high:1060kB active_anon:10012kB inactive_anon:488kB active_file:4kB inactive_file:4kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present
Jul 20 11:05:00 someapp kernel: lowmem_reserve[]: 0 968 968 968
Jul 20 11:05:00 someapp kernel: Node 0 DMA32 free:44232kB min:44344kB low:55428kB high:66516kB active_anon:814160kB inactive_anon:24900kB active_file:2884kB inactive_file:16500kB unevictable:0kB isolated(anon):0kB isolated
Jul 20 11:05:00 someapp kernel: lowmem_reserve[]: 0 0 0 0
Jul 20 11:05:00 someapp kernel: Node 0 DMA: 17*4kB (UEM) 22*8kB (UEM) 15*16kB (UEM) 12*32kB (UEM) 8*64kB (E) 9*128kB (UEM) 2*256kB (UE) 3*512kB (UM) 0*1024kB 0*2048kB 0*4096kB = 4580kB
Jul 20 11:05:00 someapp kernel: Node 0 DMA32: 216*4kB (UE) 601*8kB (UE) 448*16kB (UE) 311*32kB (UEM) 135*64kB (UEM) 74*128kB (UEM) 5*256kB (EM) 0*512kB 0*1024kB 1*2048kB (R) 0*4096kB = 44232kB
Jul 20 11:05:00 someapp kernel: Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
Jul 20 11:05:00 someapp kernel: 17656 total pagecache pages
Jul 20 11:05:00 someapp kernel: 0 pages in swap cache
Jul 20 11:05:00 someapp kernel: Swap cache stats: add 0, delete 0, find 0/0
Jul 20 11:05:00 someapp kernel: Free swap  = 0kB
Jul 20 11:05:00 someapp kernel: Total swap = 0kB
Jul 20 11:05:00 someapp kernel: 262141 pages RAM
Jul 20 11:05:00 someapp kernel: 7645 pages reserved
Jul 20 11:05:00 someapp kernel: 264073 pages shared
Jul 20 11:05:00 someapp kernel: 240240 pages non-shared
Jul 20 11:05:00 someapp kernel: [ pid ]   uid  tgid total_vm      rss nr_ptes swapents oom_score_adj name
Jul 20 11:05:00 someapp kernel: [  241]     0   241    13581     1610      26        0             0 systemd-journal
Jul 20 11:05:00 someapp kernel: [  246]     0   246    10494      133      22        0         -1000 systemd-udevd
Jul 20 11:05:00 someapp kernel: [  264]     0   264    29174      121      26        0         -1000 auditd
Jul 20 11:05:00 someapp kernel: [  342]     0   342    94449      466      67        0             0 NetworkManager
Jul 20 11:05:00 someapp kernel: [  346]     0   346   137495     3125      88        0             0 tuned
Jul 20 11:05:00 someapp kernel: [  348]     0   348    79595      726      60        0             0 rsyslogd
Jul 20 11:05:00 someapp kernel: [  353]    70   353     6986       72      19        0             0 avahi-daemon
Jul 20 11:05:00 someapp kernel: [  362]    70   362     6986       58      18        0             0 avahi-daemon
Jul 20 11:05:00 someapp kernel: [  378]     0   378     1621       25       8        0             0 iprinit
Jul 20 11:05:00 someapp kernel: [  380]     0   380     1621       26       9        0             0 iprupdate
Jul 20 11:05:00 someapp kernel: [  384]    81   384     6676      142      18        0          -900 dbus-daemon
Jul 20 11:05:00 someapp kernel: [  385]     0   385     8671       83      21        0             0 systemd-logind
Jul 20 11:05:00 someapp kernel: [  386]     0   386    31573      153      15        0             0 crond
Jul 20 11:05:00 someapp kernel: [  391]   999   391   128531     2440      48        0             0 polkitd
Jul 20 11:05:00 someapp kernel: [  400]     0   400     9781       23       8        0             0 iprdump
Jul 20 11:05:00 someapp kernel: [  419]     0   419    27501       32      10        0             0 agetty
Jul 20 11:05:00 someapp kernel: [  855]     0   855    22883      258      43        0             0 master
Jul 20 11:05:00 someapp kernel: [  862]    89   862    22926      254      44        0             0 qmgr
Jul 20 11:05:00 someapp kernel: [23631]     0 23631    20698      211      43        0         -1000 sshd
Jul 20 11:05:00 someapp kernel: [12884]     0 12884    81885     3754      80        0             0 firewalld
Jul 20 11:05:00 someapp kernel: [18130]     0 18130    33359      291      65        0             0 sshd
Jul 20 11:05:00 someapp kernel: [18132]  1000 18132    33791      748      64        0             0 sshd
Jul 20 11:05:00 someapp kernel: [18133]  1000 18133    28867      122      13        0             0 bash
Jul 20 11:05:00 someapp kernel: [18428]    99 18428   208627    42909     151        0             0 node
Jul 20 11:05:00 someapp kernel: [18486]    89 18486    22909      250      46        0             0 pickup
Jul 20 11:05:00 someapp kernel: [18515]  1000 18515   352905   141851     470        0             0 npm
Jul 20 11:05:00 someapp kernel: [18520]     0 18520    33359      291      66        0             0 sshd
Jul 20 11:05:00 someapp kernel: [18522]  1000 18522    33359      294      64        0             0 sshd
Jul 20 11:05:00 someapp kernel: [18523]  1000 18523    28866      115      12        0             0 bash
Jul 20 11:05:00 someapp kernel: Out of memory: Kill process 18515 (npm) score 559 or sacrifice child
Jul 20 11:05:00 someapp kernel: Killed process 18515 (npm) total-vm:1411620kB, anon-rss:567404kB, file-rss:0kB
mikemaccana
źródło
12

Jak stwierdzili dwc i Adam Jaskiewicz, winowajcą jest prawdopodobnie zabójca OOM. Następne pytanie brzmi jednak: jak temu zapobiec?

Istnieje kilka sposobów:

  1. Daj systemowi więcej pamięci RAM, jeśli możesz (łatwo, jeśli jest to maszyna wirtualna)
  2. Upewnij się, że zabójca OOM wybiera inny proces.
  3. Wyłącz zabójcę OOM
  4. Wybierz dystrybucję Linuksa, która jest dostarczana z wyłączonym OOM Killerem.

Dzięki temu artykułowi stwierdziłem, że (2) jest szczególnie łatwa do wdrożenia .

Carl
źródło
2
To była dla mnie pamięć RAM. Zaktualizowałem z 2 do 4 GB pamięci RAM i problem zniknął. Teraz problem polega na rachunku: P
Gus
9

Moduł PAM do zasobów granicznych spowodowane dokładnie opisane wyniki Państwo: Mój proces zmarł w tajemniczych okolicznościach z tekstem Killed w oknie konsoli. Brak danych wyjściowych dziennika, ani w syslog, ani w kern.log . Top Program pomógł mi odkryć, że dokładnie po minucie od użycia procesora mój proces ginie.

Christian Ammer
źródło
8

Narzędzie takie jak systemtap (lub tracer) może monitorować logikę transmisji sygnału jądra i raportować. np. https://sourceware.org/systemtap/examples/process/sigmon.stp

# stap .../sigmon.stp -x 31994 SIGKILL
   SPID     SNAME            RPID  RNAME            SIGNUM SIGNAME
   5609     bash             31994 find             9      SIGKILL

ifBlok filtrujący w tym skrypcie można dostosować do gustu lub wyeliminować, aby śledzić ruch sygnału w całym systemie. Przyczyny mogą być dalej izolowane poprzez zbieranie śladów wstecznych (dodaj a print_backtrace()i / lub print_ubacktrace()do sondy, odpowiednio dla jądra i przestrzeni użytkownika).

fche
źródło
4

W środowisku lsf (interaktywnym lub innym), jeśli aplikacja przekracza wykorzystanie pamięci przekraczające pewien wstępnie ustalony próg przez administratorów w kolejce lub żądanie zasobów przesłane do kolejki, procesy zostaną zabite, aby inni użytkownicy nie padli ofiarą potencjalnego uciec. Nie zawsze wysyła wtedy wiadomość e-mail, w zależności od konfiguracji.

Jednym z rozwiązań w tym przypadku jest znalezienie kolejki z większymi zasobami lub zdefiniowanie większych wymagań dotyczących zasobów podczas przesyłania.

Możesz także chcieć przejrzeć man ulimit

Chociaż nie pamiętam ulimitco skutkuje Killedjego Dawno Potrzebowałem tego.

starzec
źródło
2

Mieliśmy powtarzające się problemy pod Linuksem w witrynie klienta (myślę, że Red Hat), gdzie OOMKiller (zabójca braku pamięci) zabija zarówno naszą główną aplikację (tj. Powód istnienia serwera), jak i procesy w bazie danych.

W każdym przypadku OOMKiller po prostu zdecydował, że procesy wykorzystują zbyt wiele zasobów ... maszyna nawet nie zawiedzie z powodu braku zasobów. Ani aplikacja, ani jej baza danych nie ma problemów z wyciekami pamięci (lub innymi wyciekami zasobów).

Nie jestem ekspertem od Linuksa, ale raczej zebrałem jego algorytm do decydowania, kiedy coś zabić, a co zabić jest skomplikowane. Powiedziano mi również (nie mogę powiedzieć o dokładności tego), że OOMKiller jest upieczony w jądrze i nie można go po prostu uruchomić.

Lawrence Dol
źródło
1
IIRC, OOMKiller jest wywoływany tylko w ostateczności. Myślę, że system wyśle ​​nawet sygnał do różnych aplikacji, prosząc je o rezygnację z niektórych zasobów, zanim będzie zmuszony wywołać OOMKiller. Weź ziarenko soli, ponieważ minęło dużo czasu ...
rmeador
1
Po prostu nie możesz go uruchomić. Jest upieczony w jądrze, ale istnieją opcje dostrajania jego działania, a nawet procesów, które prawdopodobnie zabije. Działa, gdy w całym systemie brakuje pamięci, a nie wtedy, gdy określony proces zużywa za dużo. Zobacz moją odpowiedź, aby uzyskać więcej informacji.
Adam Jaskiewicz
6
Nie uruchamianie programu Oomkiller jest dość łatwe. echo "2" > /proc/sys/vm/overcommit_memory
R .. GitHub ZATRZYMAJ LÓD
Red Hat nie chce zezwalać na zmianę: sudo echo "2" > /proc/sys/vm/overcommit_memory/ proc / sys / vm / overcommit_memory: Odmowa dostępu
Brent Faust
2
Spróbujecho 2 | sudo tee /proc/sys/vm/overcommit_memory
Hypershadsy,
2

W moim przypadku działo się tak z pracownikiem kolejki Laravel. Dzienniki systemowe nie wspominały o żadnym zabijaniu, więc spojrzałem dalej i okazało się, że pracownik w zasadzie sam się zabijał z powodu zadania, które przekroczyło limit pamięci (domyślnie ustawiony na 128M).

Uruchomienie kolejek roboczych --timeout=600i --memory=1024naprawiłem problem.

iSWORD
źródło
0

Użytkownik ma możliwość zabijania własnych programów za pomocą kill lub Control + C, ale mam wrażenie, że tak się nie stało, a użytkownik narzekał.

root ma oczywiście możliwość zabijania programów, ale jeśli ktoś ma root na twoim komputerze i zabija rzeczy, masz większe problemy.

Jeśli nie jesteś sysadminem, sysadmin mógł ustawić limity wykorzystania procesora, pamięci RAM lub dysku i automatycznie zabija procesy, które je przekraczają.

Poza tymi domysłami, nie jestem pewien bez dodatkowych informacji o programie.

Tom Ritter
źródło
6
CTRL-C wysyła inne zabójstwo niż raportowane OP (SIGINT (2), jak pamiętam, podczas gdy program odbiera SIGKILL (9)).
Władca
0

Ostatnio napotkałem ten problem. W końcu odkryłem, że moje procesy zostały zabite zaraz po automatycznym wywołaniu aktualizacji opensuse zypper. Aby wyłączyć aktualizację zypper, rozwiązałem mój problem.

poordeveloper
źródło
Widzę ten sam problem. Jak wyśledziłeś, który proces zabił twój proces? Wydaje się, że istnieje narzędzie do sprawdzania, kto wysyła SIGKILL do procesu.
Howy
0

Rozwiązano ten problem, zwiększając rozmiar wymiany :

/ubuntu/1075505/how-do-i-increase-swapfile-in-ubuntu-18-04

Lejla
źródło
3
Nie publikuj odpowiedzi zawierających tylko linki na inne pytania dotyczące wymiany stosów. Zamiast tego dołącz tutaj istotne części odpowiedzi i dostosuj odpowiedź do tego konkretnego pytania.
podwójny dźwięk