Qu'est-ce qui a tué mon processus et pourquoi?


614

Mon application s'exécute en arrière-plan sous Linux. Il est actuellement démarré sur la ligne de commande dans une fenêtre de terminal.

Récemment, un utilisateur exécutait l'application depuis un moment et elle est morte mystérieusement. Le texte:

Tué

était sur le terminal. Cela s'est produit deux fois. J'ai demandé si quelqu'un dans un autre terminal utilisait la commande kill pour tuer le processus? Non.

Dans quelles conditions Linux déciderait-il de tuer mon processus? Je crois que l'obus a affiché "tué" parce que le processus est mort après avoir reçu le signal kill (9). Si Linux a envoyé le signal kill, devrait-il y avoir un message dans un journal système quelque part qui explique pourquoi il a été tué?


23
linux a tué mon processus et l'a enregistré dans / var / log / messages sur redhat
Dean Hiller

1
Voir aussi cette réponse sur unix.stackexchange.com.
Richard

Il y a 3 joueurs dans cet événement: (1) Le processus qui (cause commune) prend trop de mémoire et provoque la condition OOM (2) Le noyau qui envoie le SIGKILL (signal 9) le termine et enregistre le fait dans un système log like /var/log/messages(3) Le shell sous lequel le processus s'est exécuté, qui est le processus qui imprime la Killednotification lorsque l'état de sortie de waitpid(2)indique que le processus enfant est mort du signal 9.
arielf

Après avoir lu la réponse de @ DeanHiller, j'ai trouvé des messages de journal sur Ubuntu sous/var/log/syslog
Dinei

Réponses:


403

Si l'utilisateur ou sysadmin n'a pas tué le programme, le noyau peut avoir. Le noyau ne tuerait un processus que dans des circonstances exceptionnelles telles que la famine extrême (pensez mem + épuisement swap).


25
Si le noyau tuait le processus, mettrait-il un message dans un journal quelque part?
sbq

186
Je viens d'écrire un programme qui mémoire malloc'd dans une boucle inifite. Après que le système soit devenu lent, "Killed" a été affiché dans le terminal et le processus a été interrompu. Le fichier /var/log/kern.log contenait beaucoup d'informations sur la résiliation. -Merci pour le pointeur.
sbq

6
C'est presque définitivement ça. J'ai beaucoup vu cela lors de TAing. De nombreux étudiants oublieraient de libérer leurs objets, et les applications atteindraient finalement 3 Go d'utilisation de la mémoire virtuelle. Dès qu'il a atteint ce point, il a été tué.
Herms

8
Lorsque le « programme se bloque tout simplement », qui est le système d' exploitation tuer réellement le processus!
Bernd Jendrissek

79
Utilisez dmesgpour voir le journal du noyau: ici, je trouve mes processus python tués par le noyau en raison de la consommation extrême de mémoire virtuelle.
caneta

273

Essayer:

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

-B100signifie le nombre de lignes avant la mort.

Omettez -T sur Mac OS.


6
Pour info, de info egrep: "egrep est le même que grep -E. ... L'invocation directe car egrep ou fgrep est déconseillée"
Air

9
Dans le cas d'un modèle simple comme 'killed process'vous pouvez simplement l'utiliser grepau lieu de egrepsans autres modifications. Pour un modèle plus complexe, vous devez remplacer par exemple egrep -i -B100 'foo|ba[rz]'par grep -E -i -B100 'foo|ba[rz]'. Ce Q&R donne plus de détails.
Air

2
Je suggère également d'utiliser dmesg -Tafin d'obtenir des horodatages lisibles
gukoff

171

Cela ressemble à un bon article sur le sujet: Taming the OOM killer .

L'essentiel est que Linux sur- engageMémoire. Lorsqu'un processus demande plus d'espace, Linux lui donnera cet espace, même s'il est revendiqué par un autre processus, en supposant que personne n'utilise réellement toute la mémoire qu'il demande. Le processus obtiendra une utilisation exclusive de la mémoire qu'il a allouée lorsqu'il l'utilise réellement, pas lorsqu'il le demande. Cela rend l'allocation rapide et peut vous permettre de "tricher" et d'allouer plus de mémoire que vous n'en avez vraiment. Cependant, une fois que les processus commencent à utiliser cette mémoire, Linux peut se rendre compte qu'il a été trop généreux dans l'allocation de mémoire qu'il n'a pas, et devra tuer un processus pour en libérer. Le processus à tuer est basé sur un score prenant en compte le temps d'exécution (les processus de longue durée sont plus sûrs), l'utilisation de la mémoire (les processus gourmands sont moins sûrs) et quelques autres facteurs, y compris une valeur que vous pouvez ajuster pour rendre un processus moins susceptible d'être tué. Tout est décrit dans l'article de manière beaucoup plus détaillée.

Edit: Et voici un autre article qui explique assez bien comment un processus est choisi (annoté avec quelques exemples de code du noyau). La grande chose à ce sujet est qu'il comprend des commentaires sur le raisonnement derrière les différentes badness()règles.


3
J'adore vraiment les liens vers les articles. Je suggère à toute personne intéressée par le sujet de les lire - en particulier les commentaires sur l'article lwn.
Jon Bringhurst

4
"Linux lui donnera cet espace, même s'il est revendiqué par un autre processus" Ce n'est pas tout à fait le fonctionnement de la mémoire virtuelle ...
Mooing Duck

1
l'article est assez ancien (2009) et toutes les fonctionnalités suggérées dans l'article ne sont pas dans la ligne principale.
Alex

50

Permettez-moi d'abord d'expliquer quand et pourquoi OOMKiller est invoqué?

Supposons que vous disposiez de 512 RAM + 1 Go de mémoire d'échange. Donc, en théorie, votre processeur a accès à un total de 1,5 Go de mémoire virtuelle.

Maintenant, pendant un certain temps, tout fonctionne bien dans 1,5 Go de mémoire totale. Mais tout à coup (ou progressivement) votre système a commencé à consommer de plus en plus de mémoire et il a atteint à un point environ 95% de la mémoire totale utilisée.

Supposons maintenant que tout processus ait demandé un gros morceau de mémoire au noyau. Le noyau vérifie la mémoire disponible et constate qu'il n'y a aucun moyen d'allouer plus de mémoire à votre processus. Il essaiera donc de libérer de la mémoire en appelant / invoquant OOMKiller ( http://linux-mm.org/OOM ).

OOMKiller a son propre algorithme pour marquer le rang pour chaque processus. Généralement, quel processus utilise plus de mémoire devient la victime à tuer.

Où puis-je trouver les journaux d'OOMKiller?

Généralement dans le répertoire / var / log. Soit /var/log/kern.log ou / var / log / dmesg

J'espère que cela vous aidera.

Quelques solutions typiques:

  1. Augmentez la mémoire (pas échange)
  2. Trouvez les fuites de mémoire dans votre programme et corrigez-les
  3. Restreindre la mémoire que tout processus peut consommer (par exemple, la mémoire JVM peut être restreinte à l'aide de JAVA_OPTS)
  4. Voir les journaux et google :)

17

Il s'agit du gestionnaire de mémoire insuffisante Linux (MOO) . Votre processus a été sélectionné en raison de la « méchanceté » - une combinaison de la nouveauté, de la taille du résident (mémoire utilisée, plutôt que simplement allouée) et d'autres facteurs.

sudo journalctl -xb

Vous verrez un message comme:

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

12

Comme l'ont déclaré dwc et Adam Jaskiewicz, le coupable est probablement le tueur OOM. Cependant, la question suivante qui suit est: Comment puis-je empêcher cela?

Il existe plusieurs façons:

  1. Donnez plus de RAM à votre système si vous le pouvez (facile si c'est une VM)
  2. Assurez-vous que le tueur OOM choisit un processus différent.
  3. Désactiver le OOM Killer
  4. Choisissez une distribution Linux livrée avec OOM Killer désactivé.

J'ai trouvé que (2) était particulièrement facile à implémenter, grâce à cet article .


2
C'était la RAM pour moi. J'ai mis à niveau de 2 à 4 Go de RAM et le problème a disparu. Maintenant, le problème est avec le projet de loi: P
Gus

9

Le module PAM pour limiter les ressources a provoqué exactement les résultats que vous avez décrits: Mon processus est mort mystérieusement avec le texte Tué sur la fenêtre de la console. Aucune sortie de journal, ni dans syslog ni dans kern.log . Le programme supérieur m'a aidé à découvrir qu'exactement après une minute d'utilisation du processeur, mon processus est tué.


8

Un outil comme systemtap (ou un traceur) peut surveiller la logique de transmission des signaux du noyau et générer des rapports. par exemple, 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

Le ifbloc de filtrage dans ce script peut être ajusté au goût, ou éliminé pour tracer le trafic du signal à l'échelle du système. Les causes peuvent être davantage isolées en collectant des backtraces (ajoutez un print_backtrace()et / ou print_ubacktrace()à la sonde, respectivement pour le noyau et l'espace utilisateur).


4

Dans un environnement lsf (interactif ou autre) si l'application dépasse l'utilisation de la mémoire au-delà d'un certain seuil prédéfini par les administrateurs de la file d'attente ou la demande de ressources à soumettre à la file d'attente, les processus seront tués afin que les autres utilisateurs ne soient pas victimes d'un potentiel fuyez. Il n'envoie pas toujours un e-mail lorsqu'il le fait, selon la façon dont il est configuré.

Dans ce cas, une solution consiste à trouver une file d'attente avec des ressources plus importantes ou à définir des besoins en ressources plus importants dans la soumission.

Vous pouvez également consulter man ulimit

Bien que je ne me souvienne pas que cela ulimiten Killedsoit un depuis que j'en avais besoin.


2

Nous avons eu des problèmes récurrents sous Linux sur un site client (Red Hat, je pense), avec OOMKiller (tueur de mémoire insuffisante) tuant à la fois notre application principale (c'est-à-dire la raison pour laquelle le serveur existe) et ses processus de base de données.

Dans chaque cas, OOMKiller a simplement décidé que les processus utilisaient trop de ressources ... la machine n'était même pas sur le point de tomber en panne par manque de ressources. Ni l'application ni sa base de données n'ont de problèmes de fuites de mémoire (ou de toute autre fuite de ressources).

Je ne suis pas un expert Linux, mais j'ai plutôt compris que son algorithme pour décider quand tuer quelque chose et quoi tuer est complexe. De plus, on m'a dit (je ne peux pas parler de l'exactitude de cela) que OOMKiller est intégré dans le noyau et que vous ne pouvez tout simplement pas ne pas l'exécuter.


1
IIRC, OOMKiller n'est invoqué qu'en dernier recours. Je pense que le système enverra même un signal à diverses applications leur demandant de bien vouloir abandonner certaines ressources avant d'être obligé d'invoquer OOMKiller. Prenez avec un grain de sel, car cela fait longtemps ...
rmeador

1
Vous ne pouvez tout simplement pas l'exécuter. Il est intégré dans le noyau, mais il existe des options pour régler son fonctionnement et même les processus qu'il est susceptible de tuer. Il s'exécute lorsque l'ensemble du système manque de mémoire, et non lorsqu'un processus spécifique en utilise trop. Voir ma réponse pour plus de détails.
Adam Jaskiewicz

6
Ne pas exécuter oomkiller est assez facile. echo "2" > /proc/sys/vm/overcommit_memory
R .. GitHub STOP HELPING ICE

Red Hat ne veut pas autoriser sa modification: sudo echo "2" > /proc/sys/vm/overcommit_memory/ proc / sys / vm / overcommit_memory: Autorisation refusée
Brent Faust

2
Essayezecho 2 | sudo tee /proc/sys/vm/overcommit_memory
Hypershadsy

2

Dans mon cas, cela se passait avec un travailleur de file d'attente Laravel. Les journaux système ne mentionnaient aucun meurtre, j'ai donc cherché plus loin et il s'est avéré que le travailleur se tuait essentiellement en raison d'un travail qui dépassait la limite de mémoire (qui est définie à 128 Mo par défaut).

Exécuter le gestionnaire de files d'attente avec --timeout=600et --memory=1024résolu le problème pour moi.


0

L'utilisateur a la possibilité de tuer ses propres programmes, en utilisant kill ou Control + C, mais j'ai l'impression que ce n'est pas ce qui s'est passé, et que l'utilisateur s'est plaint à vous.

root a bien sûr la capacité de tuer des programmes, mais si quelqu'un a root sur votre machine et tue des trucs, vous avez de plus gros problèmes.

Si vous n'êtes pas l'administrateur système, l'administrateur système peut avoir configuré des quotas sur le processeur, la mémoire RAM, l'utilisation du disque ou les processus de suppression automatique qui les dépassent.

À part ces suppositions, je ne suis pas sûr sans plus d'informations sur le programme.


6
CTRL-C envoie un kill différent de l'OP rapporté (SIGINT (2) si je me souviens bien, alors que le programme reçoit un SIGKILL (9)).
Powerlord

0

J'ai rencontré ce problème récemment. Enfin, j'ai découvert que mes processus avaient été tués juste après l'appel automatique de la mise à jour d'Opsuse zypper. Pour désactiver la mise à jour zypper, j'ai résolu mon problème.


Je vois le même problème. Comment avez-vous trouvé quel processus a tué votre processus? Il semble qu'il existe un outil pour vérifier qui envoie SIGKILL à un processus.
Howy

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.