Que fait `kill -0`?

61

Je suis récemment tombé sur cela dans un script shell.

if ! kill -0 $(cat /path/to/file.pid); then
    ... do something ...
fi

Que fait kill -0 ...-il?

slm
la source
2
Voir ici si vous ne comprenez pas les différences entre la trapcommande de Bash b / w et 0 par rapport à un signal 0 de kill: Qu'est-ce que le signal 0 dans une commande de déroutement?
slm
Voir aussi la question plus ancienne de StackOverflow Que fait kill -0 $pidun script shell? ainsi que Que fait réellement tuer 0? .
Adam Katz

Réponses:

76

Celui-ci est un peu difficile à glaner, mais si vous regardez dans les 2 pages de manuel suivantes, vous verrez les notes suivantes:

tuer (1)
$ man 1 kill
...
If sig is 0, then no signal is sent, but error checking is still performed.
...
tuer (2)
$ man 2 kill
...
If sig is 0, then no signal is sent, but error checking is still performed; 
this can be used to check for the existence of a process ID or process 
group ID.
...

Ainsi, le signal 0 n'enverra en réalité rien au PID de votre processus, mais vérifiera si vous en avez le droit.

Où cela pourrait-il être utile?

Un endroit évident serait si vous tentiez de déterminer si vous disposiez des autorisations pour envoyer des signaux à un processus en cours d'exécution via kill. Vous pouvez vérifier avant d'envoyer le killsignal que vous souhaitez, en effectuant un contrôle pour vous assurer qu'il kill -0 <PID>a d'abord été autorisé.

Exemple

Dites qu'un processus a été exécuté par root comme suit:

$ sudo sleep 2500 &
[1] 15693

Maintenant, dans une autre fenêtre, si nous exécutons cette commande, nous pouvons confirmer que ce PID est en cours d'exécution.

$ pgrep sleep
15693

Essayons maintenant cette commande pour voir si nous avons le droit d'envoyer ces signaux PID via kill.

$ if ! kill -0 $(pgrep sleep); then echo "You're weak!"; fi
bash: kill: (15693) - Operation not permitted
You're weak!

Cela fonctionne donc, mais la sortie laisse filtrer un message de la killcommande indiquant que nous ne disposons pas des autorisations. Ce n'est pas grave, attrapez simplement STDERR et envoyez-le à /dev/null.

$ if ! kill -0 $(pgrep sleep) 2>/dev/null; then echo "You're weak!"; fi
You're weak!

Exemple complet

Nous pourrions alors faire quelque chose comme ceci killer.bash:

#!/bin/bash

PID=$(pgrep sleep)
if ! kill -0 $PID 2>/dev/null; then 
  echo "you don't have permissions to kill PID:$PID"
  exit 1
fi

kill -9 $PID

Maintenant, quand je lance ce qui précède en tant qu'utilisateur non root:

$ ~/killer.bash 
you don't have permissions to kill PID:15693

$ echo $?
1

Cependant, lorsqu'il est exécuté en tant que root:

$ sudo ~/killer.bash 

$ echo $?
0

$ pgrep sleep
$
slm
la source
9
J'ajouterais également que cela pourrait être utilisé pour les scripts multi-proc pour voir si un processus est toujours actif.
Prateek61
1
@slm belle trouvaille. En utilisant cette logique maintenant dans un script, je vous écris, merci.
111 ---
12
Prateek61 a raison. Vous ne pouvez pas utiliser pgrep, psanalyser ou test -e /proc/$PIDdans des scripts portables, mais kill -0fonctionne partout. Si vous recevez un PID obsolète, par exemple une /var/runentrée, il s’agit d’un moyen portable de vérifier si le processus est toujours actif.
Warren Young
1
En plus de vous dire si le PID est actif, il vous indique également s'il exécute toujours un processus à partir de votre UID, car vous n'êtes pas autorisé à envoyer des signaux à d'autres UID (sauf si vous êtes root). Cela réduit les risques de faux positifs dus à la réutilisation de PID.
Barmar
Un échec kill -0 $(pgrep sleep)ne signifie pas forcément que vous êtes faible , il retournera faux s'il n'y a pas de sleepcommande en cours, s'il y en a plus d'une et qu'il y en a une que vous ne pouvez pas tuer, ou si l'un des dormis meurt entre le pgrep et le kill commandes en cours d'exécution.
Stéphane Chazelas
22

kill -0(ou sa variante POSIX plus portable kill -s 0) passe par l'envoi d'un signal, mais n'en envoie pas en réalité. C'est une fonctionnalité de l' API C sous - jacente que la commande shell expose de manière simple.

kill -s 0 -- "$pid"vérifie ainsi s'il existe un processus en cours avec le PID donné (ou PGID s'il $pidest négatif) et si le processus en cours aurait la permission d'envoyer $pidun signal (l'un des processus du groupe de processus en cas de résultat négatif ). C'est principalement un moyen de tester si un processus (ou un groupe de processus) est en vie.

N'oubliez pas que même s'il existe un processus en cours avec le PID et les autorisations attendus, il ne s'agit pas nécessairement du processus attendu. Il est possible que le processus attendu prenne fin plus tôt et que son PID ait été réutilisé pour un processus non lié. La bonne façon de surveiller les processus est de laisser leur parent le faire - le PID d'un processus n'est pas réutilisé tant que son parent n'a pas reconnu sa mort (c'est pourquoi les zombies existent), afin qu'un parent d'un processus puisse identifier de manière fiable ses enfants par son PID.

Gilles, arrête de faire le mal
la source
0

Le kill -0 $pidvous indique si un processus $pidexiste.

Dans l'extrait

if ! kill -0 $(cat /path/to/file.pid); then
    ... do something ...
fi

le bloc ... do something ...est exécuté si un processus avec le PID qui est stocké /path/to/file.pidest en cours d'exécution - et - à moins que l'extrait de code ne s'exécute en tant que root - si le PID s'exécute sous le même utilisateur.

La norme POSIX spécifie le rôle du 0signal:

Si sig est 0 (le signal nul), une vérification d'erreur est effectuée mais aucun signal n'est réellement envoyé. Le signal nul peut être utilisé pour vérifier la validité de pid.

(kill (3p), POSIX.1-2008 - libellé similaire dans POSIX.1-2001)

Notez que POSIX spécifie les styles kill -0et les kill -s 0styles de ligne de commande (kill (1p)).

Contrairement à l'interface kill syscall, la killcommande ne peut pas être utilisée pour vérifier de manière fiable l'existence de PID appartenant à d'autres utilisateurs (en tant qu'utilisateur normal), par exemple:

$ kill -0 123
kill: kill 123 failed: no such process
$ echo $?
1

contre.

$ kill -0 1
kill: kill 1 failed: operation not permitted
$ echo $?
1

Lors de l’appel de kill syscall, on peut distinguer ces cas de manière fiable en regardant la errnovaleur (voir par exemple un exemple Python ).

maxschlepzig
la source