Dans quel ordre devrais-je envoyer des signaux aux processus d'arrêt gracieux?
Dans un commentaire sur cette réponse de l'autre question , le commentateur dit:
n'utilisez kill -9 que si absolument nécessaire! SIGKILL ne peut pas être piégé alors le programme tué ne peut pas fonctionner routines d'arrêt pour, par exemple, effacer dossiers temporaires. First try HUP (1), puis INT (2), puis QUIT (3)
I d'accord en principe sur SIGKILL
, mais le reste est nouvelles pour moi. Étant donné que le signal par défaut envoyé par kill
est SIGTERM
, Je m'attendrais à ce qu'il soit le signal le plus communément attendu pour l'arrêt gracieux d'un processus arbitraire. Aussi, j'ai vu SIGHUP
utilisé pour des raisons non terminales, comme le fait de dire à un démon "relire votre fichier de configuration."Et il me semble que SIGINT
(la même interruption que vous obtenez généralement avec Ctrl-C, non? n'est-ce pas aussi largement pris en charge comme il se doit soit, ou se termine plutôt avec ingratitude.
étant donné que SIGKILL
est un dernier recours - qui signale, et dans quel ordre , devez-vous envoyer à un processus arbitraire, afin de l'arrêter aussi gracieusement que possible?
veuillez justifier vos réponses par des faits à l'appui (au-delà de vos préférences ou opinions personnelles) ou des références, si vous le pouvez.
Note: je m'intéresse particulièrement aux meilleures pratiques Cela inclut la considération de bash / Cygwin.
Edit: jusqu'à présent, personne ne semble en parler, INT ou CESSER de fumer, et il est rarement fait mention de l'HUP. Est-il une raison de les inclure dans un processus ordonné de tuer?
7 réponses
SIGTERM indique une application à terminer. les autres signaux indiquent à l'application d'autres choses qui ne sont pas liées à l'arrêt, mais qui peuvent parfois avoir le même résultat. Ne pas utiliser ceux. Si vous voulez qu'une application s'arrête, dites-le. Ne lui donnez pas trompeuses.
certaines personnes croient que la façon standard intelligente de mettre fin à un processus est en lui envoyant un tas de signaux, tels que HUP, INT, TERM et finalement KILL. C'est ridicule. Le bon signal pour la terminaison est SIGTERM et si SIGTERM ne termine pas le processus instantanément, comme vous pourriez le préférer, c'est parce que l'application a choisi de gérer le signal. Ce qui signifie qu'il a une très bonne raison de ne pas mettre fin immédiatement: il a du travail de nettoyage à faire. Si vous interrompez ce travail de nettoyage avec d'autres signaux, il n'y a pas de dire quelles données de la mémoire il n'a pas encore enregistré sur le disque, quelles applications client sont laissées en suspens ou si vous l'interrompez "mid-phrase" qui est effectivement la corruption de données.
Pour plus d'informations sur la signification réelle des signaux, voir sigaction(2). Ne confondez pas" Action par défaut "avec" Description", Ce n'est pas la même chose.
SIGINT est utilisé pour signaler une "interruption de clavier" interactive du processus. Certains programmes peuvent gérer la situation d'une manière spéciale dans le but de terminaux utilisateurs.
SIGHUP est utilisé pour signaler que le terminal a disparu et ne regarde plus le processus. C'est tout. Certains processus choisissent de s'arrêter en réponse, généralement parce que leur fonctionnement n'a pas de sens sans terminal, d'autres choisissent de faire d'autres choses comme revérifier les fichiers de configuration.
SIGKILL est utilisé pour enlever le processus du noyau. Il est spécial dans le sens où il ne s'agit pas en fait d'un signal au processus mais plutôt d'une interprétation directe par le noyau.
N'envoyez pas SIGKILL. SIGKILL ne devrait certainement jamais être envoyé par des scripts. Si L'application gère le SIGTERM, il peut prendre une seconde pour nettoyer, il peut prendre une minute, il peut prendre une heure . Selon ce que l'application doit faire avant qu'elle ne soit prête à finir. Toute logique qui" suppose " la séquence de nettoyage d'une application a pris assez de temps et doit être raccourci ou Sigqualifié après X secondes est tout simplement faux .
la seule raison pour laquelle une application a besoin D'un SIGKILL à terminer, est si quelque chose buggé pendant sa séquence de nettoyage. Dans ce cas, vous pouvez ouvrir un terminal et le SIGKILL il manuellement. En dehors de cela, la seule autre raison pour laquelle vous SIGKILL quelque chose est parce que vous veulent pour l'empêcher de se nettoyer.
Even bien que la moitié du monde envoie SIGKILL aveuglément après 5 secondes, C'est toujours une chose affreuse à faire.
typiquement vous enverriez SIGTERM
, la valeur par défaut de kill. C'est la valeur par défaut pour une raison. Ce n'est que si un programme ne s'arrête pas dans un délai raisonnable que vous devez recourir à SIGKILL
. Mais notez qu'avec SIGKILL
le programme n'a aucune possibilité de nettoyer les choses et les données pourraient être corrompues.
comme pour SIGHUP
, HUP
signifie" raccrocher " et signifie historiquement que le modem s'est déconnecté. C'est essentiellement équivalent à SIGTERM
. La raison pour laquelle les démons utilisent parfois SIGHUP
pour redémarrer ou recharger la config est que les démons se détachent de n'importe quel terminal de contrôle car un démon n'en a pas besoin et ne recevrait donc jamais SIGHUP
, de sorte que le signal a été considéré comme "libéré" pour un usage général. Tous les démons n'utilisent pas ça pour recharger! L'action par défaut pour SIGHUP est de terminer et de nombreux démons se comportent de cette façon! Donc vous ne pouvez pas envoyer aveuglément SIGHUP
aux démons et attendre d'eux qu'ils survivent.
" Edit: SIGINT
est probablement inapproprié pour arrêter un processus, car il est normalement lié à ^C
ou quel que soit le réglage du terminal est d'interrompre un programme. De nombreux programmes en tiennent compte à leurs propres fins, de sorte qu'il est assez courant que cela ne fonctionne pas. SIGQUIT
a typiquement la valeur par défaut de créer un dump core, et à moins que vous ne vouliez que les fichiers core soient disposés autour, ce n'est pas un bon candidat non plus.
Résumé: si vous envoyez SIGTERM
et que le programme ne meurt pas dans votre délai, alors envoyez-le SIGKILL
.
Réponse Courte : Envoyer SIGTERM
, 30 secondes plus tard, SIGKILL
. C'est-à-dire , envoyer SIGTERM
, attendre un peu (il peut varier d'un programme à l'autre, vous connaissez peut-être mieux votre système, mais 5 à 30 secondes suffisent. Quand vous fermez une machine, vous pouvez la voir attendre automatiquement jusqu'à 1'30s. Pourquoi cette hâte, après tout?), puis de l'envoyer SIGKILL
.
Réponse Raisonnable : SIGTERM
, SIGINT
, SIGKILL
C'est plus que suffisant. Le processus très se terminera probablement avant SIGKILL
.
Longue Réponse : SIGTERM
, SIGINT
, SIGQUIT
, SIGABRT
, SIGKILL
c'est inutile, mais au moins vous ne trompez pas le processus concernant votre message. Tous ces signaux do signifient que vous voulez que le processus cesse ce qu'il fait et à la sortie.
peu importe la réponse que vous choisissez dans cette explication, gardez cela à l'esprit!
si vous envoyez un signal qui signifie autre chose, le processus peut le gérer de manière très différente (d'une part). D'un autre côté, si le processus ne gère pas le signal, peu importe ce que vous envoyez après tout, le processus cessera de toute façon (lorsque l'action par défaut est de terminer, bien sûr).
Donc, vous devez penser comme vous-même en tant que programmeur. Coderiez-vous un gestionnaire de fonction pour, disons, SIGHUP
pour arrêter un programme qui se connecte avec quelque chose, ou le boucleriez-vous pour essayer de se connecter à nouveau? C'est la principale question ici! C'est pourquoi il est important de simplement envoyer des signaux qui signifie que vous avez l'intention.
Réponse Presque Stupide :
le tableau ci-dessous contient les signaux pertinents, et les actions par défaut dans le cas où le programme ne pas les traiter.
je les ai commandés dans l'ordre que je suggère d'utiliser (BTW, je vous suggère d'utiliser la réponse raisonnable , pas celui-ci ici), si vous avez vraiment besoin de les essayer tous (il serait amusant de dire que la table est ordonnée en termes de la destruction qu'ils peuvent causer, mais ce n'est pas complètement vrai).
les signaux avec un astérisque (*) sont Non recommandé. Le ce qui est important à ce sujet, c'est que vous ne saurez peut-être jamais ce qu'il est programmé pour faire. Spécialement SIGUSR
! Il peut démarrer l'apocalipse (c'est un signal gratuit pour un programmeur qui fait ce qu'il/elle veut!). Mais, si elle n'est pas traitée ou dans le cas peu probable où elle est traitée pour terminer, le programme se terminera.
dans le tableau, les signaux avec options par défaut pour terminer et générer un dump core sont laissés à la fin, juste avant SIGKILL
.
Signal Value Action Comment
----------------------------------------------------------------------
SIGTERM 15 Term Termination signal
SIGINT 2 Term Famous CONTROL+C interrupt from keyboard
SIGHUP 1 Term Disconnected terminal or parent died
SIGPIPE 13 Term Broken pipe
SIGALRM(*) 14 Term Timer signal from alarm
SIGUSR2(*) 12 Term User-defined signal 2
SIGUSR1(*) 10 Term User-defined signal 1
SIGQUIT 3 Core CONTRL+\ or quit from keyboard
SIGABRT 6 Core Abort signal from abort(3)
SIGSEGV 11 Core Invalid memory reference
SIGILL 4 Core Illegal Instruction
SIGFPE 8 Core Floating point exception
SIGKILL 9 Term Kill signal
alors je suggérerais pour ce réponse presque stupide longue :
SIGTERM
, SIGINT
, SIGHUP
, SIGPIPE
, SIGQUIT
, SIGABRT
, SIGKILL
et enfin, le
Certainement Stupide De Longue De Longue Réponse :
N'essayez pas ça à la maison.
SIGTERM
, SIGINT
, SIGHUP
, SIGPIPE
, SIGALRM
, SIGUSR2
, SIGUSR1
, SIGQUIT
, SIGABRT
, SIGSEGV
, SIGILL
, SIGFPE
et si rien n'a fonctionné, SIGKILL
.
SIGUSR2
devrait être essayé avant SIGUSR1
parce que nous sommes mieux lotis si le programme ne gère pas le signal. Et il est beaucoup plus probable pour gérer SIGUSR1
si il gère juste l'un d'eux.
BTW, the KILL : il n'est pas erroné d'envoyer SIGKILL
à un processus, comme l'indique une autre réponse. Que se passe-t-il quand tu envoies un ordre shutdown
? Il essaiera SIGTERM
et SIGKILL
seulement. Pourquoi pensez-vous que c'est le cas? Et pourquoi avez-vous besoin d'autres signaux, si le shutdown
commande utilise uniquement ces deux?
maintenant, retour à la longue réponse , c'est un joli oneliner:
for SIG in 15 2 3 6 9 ; do echo $SIG ; echo kill -$SIG $PID || break ; sleep 30 ; done
Il dort pendant 30 secondes entre les signaux. Pour quelle autre raison auriez-vous besoin d'un oneliner ? ;)
aussi, recommandé: essayez avec seulement les signaux 15 2 9
de la réponse raisonnable .
sécurité : retirez le second echo
lorsque vous êtes prêt à partir. Je l'appelle mon dry-run
pour onliners . Toujours l'utiliser pour tester.
Script killgracifly
en Fait, j'étais tellement intrigué par cette question que j'ai décidé de créer un petit script pour le faire. S'il vous plaît, n'hésitez pas à le télécharger (cloner) ici:
GitHub link to killgracifly repository
SIGTERM
en fait, signifie envoyer une demande un message: " "seriez-vous si gentil et de se suicider ". Il peut être piégé et manipulé par application pour exécuter le nettoyage et le code d'arrêt.
SIGKILL
ne peut pas être piégé par l'application. Application se fait tuer par OS sans aucune chance de nettoyage.
il est typique d'envoyer SIGTERM
d'abord, dormir un peu heure, puis envoyer SIGKILL
.
- SIGTERM est équivalent à " cliquer sur le 'X' " dans une fenêtre.
- SIGTERM est ce que Linux utilise en premier, quand il s'éteint.
HUP sonne comme de la merde pour moi. Je l'enverrais pour qu'un démon relise sa configuration.
SIGTERM peut être intercepté; vos démons peuvent juste avoir le code de nettoyage à exécuter quand il reçoit ce signal. Tu ne peux pas faire ça pour SIGKILL. Ainsi, avec SIGKILL, vous ne donnez aucune option à l'auteur du démon.
plus d'informations sur Wikipedia
avec toutes les discussions en cours ici, aucun code n'a été proposé. Voici mon avis:
#!/bin/bash
$pid = 1234
echo "Killing process $pid..."
kill $pid
waitAttempts=30
for i in $(seq 1 $waitAttempts)
do
echo "Checking if process is alive (attempt #$i / $waitAttempts)..."
sleep 1
if ps -p $pid > /dev/null
then
echo "Process $pid is still running"
else
echo "Process $pid has shut down successfully"
break
fi
done
if ps -p $pid > /dev/null
then
echo "Could not shut down process $pid gracefully - killing it forcibly..."
kill -SIGKILL $pid
fi