Iniciei um aplicativo que não funciona, mas não consigo excluí-lo porque ele ainda está em execução. Posso imprimir o PID, mas não encerrar o processo usando-o.
~ $ ps ax | grep snappr | awk '{print $1}'
70824
~ $ kill $(ps ax | grep snappr | awk '{print $1}')
-bash: kill: (70832) - No such process
Responder1
Você notou que obteve dois PIDs diferentes nas duas tentativas?
Considere o seguinte: se você digitar um comando como vi raven.txt
, ps ax
será exibida uma linha que mostra um comando de vi raven.txt
. Da mesma forma, se você digitar um comando como grep snappr
, ps ax
será exibida uma linha que mostra um comando de grep snappr
. E, se você ps
canalizar a saída disso grep snappr
, grep
encontrará a linhaque está se descrevendo. Então, se você digitar
$ ps ax | grep snappr | awk '{print $1}'
repetidamente, ele imprimirá um número diferente a cada vez (porque está imprimindo o PID de grep
e você obtém um grep
processo novo e exclusivo toda vez que executa o comando).
Finalmente, considere: o kill
comando não pode ser executado até que seu(s) argumento(s) seja(m) conhecido(s). Para que seu argumento seja conhecido, o $(ps ax | grep snappr | awk '{print $1}')
pipeline deve estar concluído. Isso implica que o grep
deve ter terminado em 1 . Portanto, kill
está sendo fornecido o PID do grep
processo, mas somente após grep
o término do processo - então, naturalmente, ele informa "Nenhum processo".
Talvez eu devesse ter mencionado que não há nenhum snappr
processo em execução. Se houvesse, seu primeiro comando geraria dois números: o PID de snappr
e o PID de grep snappr
. Agora, se snappr
estivesse em execução, seu comando poderia começar a ser executado de maneira semicorreta, ou seja, ele faz o que você deseja, mas também fornece uma mensagem de erro. Se o snappr
estiver rodando com PID 42097 e grep snappr
rodar com PID 70848, então o kill
comando será kill 42097 70858
, que matará o snappr
e receberá uma mensagem de erro ao tentar matar o grep
processo que não existe mais.
Você provavelmente desejará melhorar isso. Minha maneira favorita, que inventei há 20 anos, é mudar o grep
to grep "[s]nappr"
, que irá corresponder snappr
, mas não irá corresponder a si mesmo. Outra abordagem é usar pgrep
em vez de ps | grep
.
1 Alternativamente, o awk
poderia terminar se grep
apenas fechasse seu stdout. Este seria um comportamento muito incomum para um programa *nix.
Responder2
Resposta mais curta
Não pule através dos aros do Bash para matar snappr
com ps
, passe grep
e depois passe awk
assim. Em vez disso, tente matá-lo assim usandopkill
; sem confusão ou confusão e tem como alvo o nome do processo pronto para uso:
sudo pkill snappr
Resposta mais longa
Não está muito claro comoPargoopera em um nível de processo do sistema, mas o problema pode ser que você está capturando apenas o ID do processo filho em vez do ID do processo pai.
Na verdade, acredito que o método que você está usando para obter um ID de processo ( ps ax | grep snappr | awk '{print $1}'
) retornaria uma lista completa de IDs de processos conectados, snappr
independentemente de ser pai ou filho. Então, usando isso vocêpodermatar um ID de processo que é apenas um ID de processo filho, mas o ID pai ainda estaria ativo e capaz de “gerar” outro processo filho para compensar.
Então, talvez você possa fazer algo assim para obter o ID pai definitivo de qualquer ID de processo que você alimentar e agir de acordo com ele; simples prova de conceito de como funciona:
ps -p [process ID] -o ppid=
Executar esse comando básico no Bash fornecerá o ID do processo pai do ID do processo filho que você inseriu [process ID]
. Portanto, se o ID filho 4567
tiver um ID de processo pai, 123
o comando seria:
ps -p 4567 -o ppid=
E isso retornaria, 123
.
Dito isso, essa pode ser uma maneira perigosa de lidar com um processo perdido, pois se o seu script capturar o ID real do processo pai snapper
, o pai desse ID do processo poderá realmente ser seu próprio shell Bash. Portanto, você pode inadvertidamente simplesmente matar seu shell Bash em vez de snapper
desligá-lo do sistema enquanto deixa snapper
o processo em execução.
Mas tudo isso dito, por que não facilitar sua vida e simplesmente correrpkill
assim:
sudo pkill snappr
Isso eliminará todos os processos conectados snappr
sem nenhum malabarismo sofisticado de linha de comando.