Trecho do Bash por matar um processo até que ele esteja morto?

8

Estou tentando escrever um script bash robusto e nele crio um processo em segundo plano. No final do script, eu quero matá-lo. Eu tenho o PID.

Eu estava pensando em algo assim

while [[ ps ef $PID ]] ; do
  kill $PID
  sleep 0.5
done

Alguma sugestão para algo melhor? Algum problema possível com essa abordagem?

Rory
fonte
Você não quis dizer ps -ef?
User1686
11
grawity: Isso é apenas estilo BSD versus opções UNIX, mas ef parece se encaixar melhor com as opções UNIX. Eu iria com 'ps ao pid' eu mesmo
Kyle Brandt
while [[ ps ef $PID ]]é um erro de sintaxe. Eu suponho que você quis dizer while ps ef $PID.
Dennis

Respostas:

10

O problema de matar repetidamente um processo é que você tem uma condição de corrida com a criação do novo processo. Não é particularmente provável, mas é possível que o processo seja encerrado e um novo processo seja iniciado com o mesmo PID enquanto você dorme.

Por que você está tendo que matar repetidamente o processo? Se é porque o processo será encerrado, mas pode demorar algum tempo para sair depois de receber o sinal, você pode usar wait:

 kill $PID
 wait $PID

Em um sistema ideal, você nunca precisaria repetir um killou problema kill -9 $PID. Se você precisar, considere consertar o que quer que esteja executando para não precisar. Enquanto isso, você provavelmente não atingirá a condição de corrida e poderá se proteger contra (digamos) verificando o carimbo de data / hora de / proc / $ PID / antes de interromper o processo. Isso é mau truque, no entanto.

Andrew Aylett
fonte
11
Isso não funciona se o PID não pertencer a um processo filho, ou seja, este script está tentando controlar a execução de um processo que se originou em outro lugar. Eu recebo bash: wait: pid 32137 is not a child of this shellquando tento. :(
Justin Force
9

Para todos recomendando o passo a partir kill $PIDde kill -9 $PID, eu teria que lembrá-lo de uso inútil de kill -9 .

Não não não. Não use kill -9.

Não dá ao processo a chance de limpar:

  1. desligar conexões de soquete

  2. limpar arquivos temporários

  3. informar seus filhos que está indo embora

  4. redefinir suas características terminais

e assim por diante e assim por diante.

Geralmente, envie 15 e aguarde um ou dois segundos e, se isso não funcionar, envie 2 e, se isso não funcionar, envie 1. Se isso não funcionar, REMOVA O BINÁRIO, pois o programa está se comportando mal!

Não use kill -9. Não traga a colheitadeira apenas para arrumar o vaso de flores.

Agora, eu não concordo com o "remover a parte binária", mas a progressão parece menos prejudicial do que apenas um kill -9.

Também concordo com o cuidado com as condições de corrida na criação de novos processos com o mesmo IDP mencionado aqui .

Adriano Varoli Piazza
fonte
0

Primeiro, faça sua matança normal, durma x número de segundos e, em seguida, mate -9 se ainda estiver por perto. Além disso, isso parece uma situação estranha em que você entrou, talvez queira nos explicar o problema maior.

Kyle Brandt
fonte
Acordado. Se ele não responder e fechar após um SIGTERM (o sinal enviado por padrão por kill), provavelmente não responderá a um 2º, 3º, 4º, ...., então o próximo curso de ação deve ser SIGKILL (kill - 9) É claro que você deve garantir que o X em "suspensão X segundos" seja longo o suficiente para permitir que o processo execute uma operação normal de limpar sua mesa e sair, mesmo se o sistema estiver muito carregado - pode levar uma fração de um segundo normalmente, mas dezenas de segundos quando o sistema está debulhando.
22415 David Spillett
0

Normalmente você quer tentar kill $PIDprimeiro,

então deixe-o dormir um pouco para ver se ele sairá normalmente.

Caso contrário, execute kill -9 $PIDpara se livrar dele com força.

Brent
fonte
-1

porque não apenas

kill -9 $PID

chris
fonte
2
Porque você deseja dar aos processos a chance de limpar e morrer bem, que é o que o sinal TERM faz (o sinal padrão). O sinal KILL ("-9") não dá aos processos essa chance.
ktower
Bom ponto, mas o pôster original dizia que ele só queria matá-lo.
chris