¿Qué hace `kill -0`?

61

Recientemente me encontré con esto en un script de shell.

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

¿Qué kill -0 ...hacer?

slm
fuente
2
Vea aquí si está confundido acerca de las diferencias entre el trapcomando de Bash y 0 frente a una señal 0 de kill: ¿Qué es la señal 0 en un comando de captura?
slm
Vea también la pregunta anterior de StackOverflow ¿ Qué hace kill -0 $piden un script de shell? así como ¿Qué hace realmente matar 0? .
Adam Katz

Respuestas:

76

Este es un poco difícil de obtener, pero si mira en las siguientes 2 páginas de manual, verá las siguientes notas:

matar (1)
$ man 1 kill
...
If sig is 0, then no signal is sent, but error checking is still performed.
...
matar (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.
...

Por lo tanto, la señal 0 en realidad no enviará nada al PID de su proceso, pero verificará si tiene permisos para hacerlo.

¿Dónde podría ser útil?

Un lugar obvio sería si intentara determinar si tenía permisos para enviar señales a un proceso en ejecución kill. Puede verificar antes de enviar la killseñal real que desea, envolviendo un cheque para asegurarse de que kill -0 <PID>primero se permitió.

Ejemplo

Digamos que un proceso estaba siendo ejecutado por root de la siguiente manera:

$ sudo sleep 2500 &
[1] 15693

Ahora, en otra ventana, si ejecutamos este comando, podemos confirmar que ese PID se está ejecutando.

$ pgrep sleep
15693

Ahora intentemos este comando para ver si tenemos acceso para enviar esas señales PID a través de kill.

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

Entonces funciona, pero la salida está filtrando un mensaje del killcomando de que no tenemos permisos. No es gran cosa, simplemente coge STDERR y envíalo /dev/null.

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

Ejemplo completo

Entonces podríamos hacer algo como esto 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

Ahora cuando ejecuto lo anterior como un usuario no root:

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

$ echo $?
1

Sin embargo, cuando se ejecuta como root:

$ sudo ~/killer.bash 

$ echo $?
0

$ pgrep sleep
$
slm
fuente
99
También agregaría que esto podría usarse para secuencias de comandos multiproceso para ver si un proceso aún está activo.
prateek61
1
@slm buen hallazgo. Utilizando esta lógica ahora mismo en un script que estoy escribiendo, gracias.
111 ---
12
Prateek61 tiene razón. No puede usar pgrep, psanalizar o test -e /proc/$PIDen scripts portátiles, pero kill -0funciona en todas partes. Si recibe un PID que puede estar obsoleto, por ejemplo, una /var/runentrada, esta es la forma portátil de verificar si el proceso aún está activo.
Warren Young
1
Además de decirle si el PID está vivo, también le dice efectivamente si todavía está ejecutando un proceso desde su UID, ya que no tiene permiso para enviar señales a otros UID (a menos que sea root). Esto hace que los falsos positivos debido a la reutilización de PID sean menos probables.
Barmar
Un fallo kill -0 $(pgrep sleep)puede no necesariamente significar que eres débil , devolverá falso si no se está sleepejecutando un comando, o si hay más de uno y hay uno que no puedes matar, o si uno de los durmientes muere entre el pgrep y el kill comandos que se ejecutan.
Stéphane Chazelas
22

kill -0(o su variante POSIX más portátil kill -s 0) pasa por el movimiento de enviar una señal, pero en realidad no envía una. Es una característica de la API de C subyacente que el comando de shell expone de manera directa.

kill -s 0 -- "$pid"por lo tanto, comprueba si hay un proceso en ejecución con el PID dado (o PGID si $pides negativo), y si el proceso actual tendría permiso para enviarle (cualquiera de los procesos en el grupo de procesos en caso de ser negativo $pid) una señal. Es principalmente una forma de probar si un proceso (o grupo de procesos) está vivo.

Tenga en cuenta que incluso si hay un proceso en ejecución con el PID y los permisos esperados, este no es necesariamente el proceso que espera. Es posible que el proceso que esperas haya muerto antes y que su PID se haya reutilizado para un proceso no relacionado. La forma correcta de monitorear los procesos es dejar que sus padres lo hagan: el PID de un proceso no se reutiliza hasta que su padre haya reconocido su muerte (es por eso que existen zombis ), por lo que el padre de un proceso puede identificar de manera confiable a sus hijos por su PID.

Gilles 'SO- deja de ser malvado'
fuente
0

El kill -0 $pidte dice si $pidexiste un proceso con .

En el fragmento

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

el bloque ... do something ...se ejecuta si se está ejecutando un proceso con el PID almacenado /path/to/file.pid, y, a menos que el fragmento se ejecute como root, si el PID se ejecuta bajo el mismo usuario.

El estándar POSIX especifica el papel de la 0señal:

Si sig es 0 (la señal nula), se realiza la comprobación de errores pero no se envía ninguna señal. La señal nula se puede utilizar para verificar la validez de pid.

(kill (3p), POSIX.1-2008 - redacción similar en POSIX.1-2001)

Tenga en cuenta que POSIX especifica tanto kill -0y kill -s 0estilos de línea de comandos (kill (1p)).

A diferencia de la interfaz kill syscall, el killcomando no se puede usar para verificar de manera confiable la existencia de PID propiedad de otros usuarios (como usuario normal), por ejemplo:

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

vs.

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

Al llamar al kill syscall, uno puede distinguir de manera confiable estos casos mirando el errnovalor (por ejemplo, un ejemplo de Python ).

maxschlepzig
fuente