O que `kill -0` faz?

61

Recentemente, deparei com isso em um shell script.

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

O que kill -0 ...faz?

slm
fonte
2
Veja aqui se você está confuso sobre as diferenças entre o trapcomando do Bash e 0 vs. um sinal 0 de kill: O que é o sinal 0 em um comando trap?
slm
Consulte também a pergunta StackOverflow mais antiga O que faz kill -0 $pidem um script de shell? assim como o que kill 0 realmente faz? .
Adam Katz

Respostas:

76

Este é um pouco difícil de entender, mas se você olhar nas duas páginas seguintes, verá as seguintes notas:

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

Portanto, o sinal 0 na verdade não envia nada para o PID do seu processo, mas verifica se você tem permissões para fazê-lo.

Onde isso pode ser útil?

Um lugar óbvio seria se você estivesse tentando determinar se tinha permissões para enviar sinais para um processo em execução kill. Você pode verificar antes de enviar o killsinal real que deseja, enviando uma verificação para garantir que kill -0 <PID>foi permitido pela primeira vez.

Exemplo

Digamos que um processo estava sendo executado pela raiz da seguinte maneira:

$ sudo sleep 2500 &
[1] 15693

Agora, em outra janela, se executarmos este comando, podemos confirmar que o PID está sendo executado.

$ pgrep sleep
15693

Agora vamos tentar este comando para ver se temos acesso para enviar esses sinais PID via kill.

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

Portanto, funciona, mas a saída está vazando uma mensagem do killcomando que não temos permissões. Não é grande coisa, basta pegar o STDERR e enviá-lo para /dev/null.

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

Exemplo completo

Então, poderíamos fazer algo assim 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

Agora, quando executo o acima como um usuário não root:

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

$ echo $?
1

No entanto, quando é executado como root:

$ sudo ~/killer.bash 

$ echo $?
0

$ pgrep sleep
$
slm
fonte
9
Eu também acrescentaria que isso poderia ser usado para scripts multiprocessos para ver se um processo ainda está ativo.
prateek61
1
@slm bom encontrar. Usando essa lógica agora em um script que estou escrevendo, obrigado.
111 ---
12
Prateek61 está certo. Você não pode usar pgrep, psanalisar ou test -e /proc/$PIDem scripts portáteis, mas kill -0funciona em qualquer lugar. Se você receber um PID que pode ser obsoleto - por exemplo, uma /var/runentrada -, esta é a maneira portátil de verificar se o processo ainda está ativo.
Warren Young
1
Além de informar se o PID está ativo, ele também informa se ainda está executando um processo a partir do seu UID, já que você não tem permissão para enviar sinais para outros UIDs (a menos que você seja root). Isso torna menos positivos os falsos positivos devido à reutilização do PID.
Barmar
Uma falha kill -0 $(pgrep sleep)pode não necessariamente significar que você está fraco , retornará falso se não houver nenhum sleepcomando em execução, ou se houver mais de um e houver um que você não possa matar, ou se um dos dormentes morrer entre o pgrep e o kill comandos sendo executados.
Stéphane Chazelas
22

kill -0(ou sua variante POSIX mais portátil kill -s 0) passa pelo movimento de enviar um sinal, mas na verdade não envia um. É um recurso da API C subjacente que o comando shell expõe de maneira direta.

kill -s 0 -- "$pid"assim, testa se existe um processo em execução com o PID especificado (ou PGID, se $pidfor negativo) e se o processo atual teria permissão para enviar $pidum sinal a ele (qualquer um dos processos do grupo de processos em caso de negativo ). É principalmente uma maneira de testar se um processo (ou grupo de processos) está vivo.

Lembre-se de que, mesmo que exista um processo em execução com o PID e as permissões esperados, esse não é necessariamente o processo esperado. É possível que o processo que você espera tenha morrido mais cedo e seu PID tenha sido reutilizado para um processo não relacionado. A maneira correta de monitorar processos é permitir que seus pais o façam - o PID de um processo não é reutilizado até que seu pai reconheça sua morte (é por isso que existem zumbis ), para que o pai de um processo possa identificar seus filhos de maneira confiável por seu PID.

Gilles 'SO- parar de ser mau'
fonte
0

O kill -0 $pidinforma se $pidexiste um processo com .

No trecho

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

o bloco ... do something ...é executado se um processo com o PID armazenado estiver em /path/to/file.pidexecução - e - a menos que o trecho seja executado como root - se o PID for executado no mesmo usuário.

O padrão POSIX especifica o papel do 0sinal:

Se sig for 0 (o sinal nulo), a verificação de erros será realizada, mas nenhum sinal será realmente enviado. O sinal nulo pode ser usado para verificar a validade do pid.

(kill (3p), POSIX.1-2008 - redação semelhante em POSIX.1-2001)

Observe que o POSIX especifica os estilos de linha de comando kill -0e de kill -s 0comando (kill (1p)).

Ao contrário da interface kill syscall, o killcomando não pode ser usado para verificar com segurança a existência de PIDs pertencentes a outros usuários (como um usuário normal), por exemplo:

$ 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

Ao chamar o kill syscall, é possível distinguir esses casos de maneira confiável, observando o errnovalor (consulte, por exemplo, um exemplo em Python ).

maxschlepzig
fonte