Não é possível matar um processo em execução - mas aparentemente não visível - no gerenciador de tarefas


6

Eu iniciei um aplicativo que não será executado, mas não posso excluí-lo porque ainda está em execução. Eu posso imprimir o PID, mas não matar o processo usando ele.

~ $ ps ax | grep snappr | awk '{print $1}'
70824
~ $ kill $(ps ax | grep snappr | awk '{print $1}')
-bash: kill: (70832) - No such process

@BeowulfOF: "Pedido de saída de ps"? Hã? Como isso faz sentido? Se snapprestivesse rodando, o primeiro comando teria listado dois PIDs: o do snappre o do grep- como explicado na minha resposta, que eu postei meia hora antes de você postar este comentário. ... ... ... ... ... PS Você pode querer revisar suas contribuições um pouco melhor ("Eu afirmo o erro", "ad", "mit").
Scott

Desculpe Scott, os erros vieram da autocorreção, eu escrevi isso em suma do meu celular. Sem desculpas, é por isso que eu deletei o comentário.
Oliver Friedrich

4
Você grep snapprestá combinando o processo grep snappr.
Sobrique

Qual plataforma? Mac OS X? Linux? Cygwin?
Peter Mortensen

Respostas:


17

Você percebeu que você tem dois PIDs diferentes nas duas tentativas?

Considere isto: se você digitar um comando como vi raven.txt, então ps axirá exibir uma linha que mostra um comando de vi raven.txt. Da mesma forma, se você digitar um comando como grep snappr, então, ps axserá exibida uma linha que mostra um comando de grep snappr. E, se você canalizar a saída desse psmeio grep snappr, a grepencontrará a linha que está descrevendo a si mesmo . 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 grepprocesso novo e exclusivo toda vez que executa o comando).

Finalmente, considere: o killcomando não pode ser executado até que seus argumentos sejam conhecidos. Para que seu argumento seja conhecido, o $(ps ax | grep snappr | awk '{print $1}')pipeline deve ter sido concluído. Isto implica que o grepdeve ter terminado 1 . Portanto, killestá sendo dado o PID do grepprocesso, mas somente após o grepprocesso ter terminado - então, naturalmente, ele reporta "Nenhum tal processo".

Talvez eu devesse ter mencionado que não há snapprprocesso em execução. Se houvesse, seu primeiro comando produziria dois números: o PID de snappre o PID de grep snappr. Agora, se snapprestava rodando, seu comando pode começar a rodar semi-corretamente, o que significa que ele faz o que você quer, mas também dá uma mensagem de erro. Se o snapprestá rodando com o PID 42097, e grep snapprroda com o PID 70848, então o killcomando será kill 42097 70858, o que irá matar o snappr e obter uma mensagem de erro de tentar matar o grepprocesso que não existe mais.

Você provavelmente vai querer melhorar isso. Meu jeito favorito, que eu inventei há 20 anos, é mudar o greppara grep "[s]nappr", o qual vai combinar snapprmas não vai se igualar. Outra abordagem é usar em pgrepvez de ps | grep.


1 Alternativamente, o awkpoderia terminar se o grepmeramente fechou sua stdout. Este seria um comportamento muito incomum para um programa * nix.


Eu tenho um script bash que eu só quero correr uma vez na minha máquina. Dentro do script que eu uso esse código para verificar (onde $ Este é o nome do script): PRIOR="$(ps --no-headers -Ao "pid,ppid,sid,args"|grep "$THIS"|grep -Ev "(grep |$PPID |$$ |<defunct>)")". Se $ PRIOR não for nulo, o script já está sendo executado. Eu tive mais sucesso com isso do que com pgrep.
gogoud

Ah, sim, a velha grep | grep -vsolução. Por que executar um processo extra que você não precisa? Trabalhe de maneira mais inteligente, não mais difícil.
Scott

Eu concordo que parece confuso. Eu ficaria feliz em encontrar um caminho melhor e confiável. ps -C não captura todos os processos, pgrep inclui processos defuntos.
gogoud

(1) Você conhece algum problema com a minha grep "[s]nappr"solução? (2) Enquanto estamos falando de processos de morte, quem se importa se os processos defuntos estão incluídos? Matar um processo extinto é um no-op.
Scott

Eu percebo que estamos ficando fora do tópico aqui. Eu gosto da sua solução de napper! Mas eu preciso excluir os defuntos porque eu realmente quero saber se existe um processo ao vivo lá fora (nesse caso, pare agora!) Ou apenas algo que está morrendo. E eu não preciso apenas excluir a chamada grep. Eu também preciso excluir a instância em execução do script em si ($$) e, possivelmente, o pai que o chamou ($ PPID).
gogoud

8

Resposta mais curta

Não saltar através de aros Bash para matar snapprcom ps, canalizada através grepe depois canalizada através awkassim. Em vez disso tente matá-lo assim usando pkill; sem confusão ou problemas e segmenta com base no nome do processo pronto para uso:

sudo pkill snappr

Resposta mais longa

Não é muito claro como o Snapper opera em um nível de processo do sistema, mas o problema pode ser que você esteja apenas capturando o ID do processo filho em vez do ID do processo pai.

Na verdade, acredito que o método que você está usando para capturar um processo ID ( ps ax | grep snappr | awk '{print $1}') retornaria uma lista inteira de IDs de processo conectadas, snapprindependentemente de ser pai ou filho. Portanto, usando isso, você pode matar 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 pegar o ID pai definitivo de qualquer ID de processo que você alimenta e age sobre ele; prova simples de conceito de como funciona:

ps -p [process ID] -o ppid=

Executar esse comando simples no Bash fornecerá o ID do processo pai do ID do processo filho inserido [process ID]. Portanto, se o ID filho 4567tiver um ID do processo pai 123, o comando será:

ps -p 4567 -o ppid=

E isso retornaria 123.

Dito isso, essa pode ser uma maneira perigosa de lidar com um processo de extravio, pois se o seu script pegar o ID do processo pai real snapper, então o pai desse ID de processo poderia ser realmente seu próprio Bash shell. Assim, você pode, inadvertidamente, simplesmente matar seu Bash shell em vez de snapperderrubá-lo do sistema enquanto deixa o snapperprocesso em execução.

Mas tudo o que disse, porque não tornar sua vida mais fácil e apenas correr pkillassim:

sudo pkill snappr

Isso matará todos os processos conectados snapprsem qualquer malabarismo de linha de comando.


1
Claro, se você está tentando matar um processo que você iniciou (como afirmado na pergunta), contanto que não esteja definido, você é o dono do processo e não precisa sudo. E você não deve usar sudose você não precisa.
Scott

2
O mais provável é que o processo não exista, grepestá se igualando.
Sobrique

use em killallvez de, pkillpor padrão, pkilloverkills.
Hongxu Chen
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.