Bash: O que fazer quando control-c não mata um processo, devido ao fato do script bash conter um loop que chama outro processo: Existe uma solução melhor para o botão liga/desliga?

Bash: O que fazer quando control-c não mata um processo, devido ao fato do script bash conter um loop que chama outro processo: Existe uma solução melhor para o botão liga/desliga?

O título completo desta pergunta é:

Bash: O que fazer quando control-c não mata um processo, devido ao fato do script bash conter um loop que chama outro processo: Existe uma solução melhor para o botão liga/desliga?

O título desta pergunta é bastante autoexplicativo, mas aqui estão algumas informações mais detalhadas:

Eu tenho um script bash em execução que chama outro programa. (Executa/executa outro programa.)

Este programa é um programa de ajuste de dados/curvas, que não pode ser interrompido com CTRL-C. Mas, ao ler istopublicar, descobri que posso matá-lo comCTRL-\

Pensamentos hipotéticos...

Portanto, é possível simplesmente pressionar o teclado, mantendo pressionada a tecla CTRL, e pressionar a \tecla,MASe se você comprou um teclado mecânico muito caro ontem e não tem dinheiro suficiente para comprar outro teclado barato que você está disposto a "amassar" (porque você não quer usar nenhum desses 10 ^ 6 pressionamentos de tecla que você você tem antes que seu teclado mecânico novinho em folha se desgaste) ou, alternativamente, não tem tempo suficiente para encontrar seu teclado antigo em sua casa porque sua casa estáextremamentedesordenado (uma bagunça) ou porque há uma emergência, como um incêndio em uma panela de lascas ocorrendo simultaneamente...

Considere também que um loop está chamando esse programa de ajuste e talvez você esteja ajustando 1.000 arquivos de dados; pressionar a \tecla 1.000 vezes provavelmente levará muito tempo.

Pensamentos do hiperespaço...

Ou mesmo; e se você cometer um erro no script bash e ele estiver executando um loop infinito?

O que você pode fazer para interromper a execução do script pai nessa situação? Você pode desconectar o computador, manter pressionado o botão liga / desliga por 10 segundos para desligá-lo ou jogá-lo no fogo para impedir que funcione, mas essas soluções parecem insensíveis devido à possível perda de dados que pode ocorrer.

Em teoria, seria possível executar o monitor do sistema e talvez encerrar o processo bash, mas isso pode ser difícil de encontrar se você tiver muitos desses processos, todos com o mesmo nome... Além disso, você pode ter um computador com um único núcleo ou um computador multicore com, digamos, N núcleos, executando N processos que tentam usar 100% da CPU. Ou talvez apenas um processo esteja usando mais do que os 4 GB de RAM que você possui e, portanto, seu computador esteja extremamente lento por esse motivo... Lento demais, pelo menos para executar o monitor do sistema por enquanto. A próxima melhor opção depois disso é pressionar CTRL-ALT-F1 e tentar fazer login como root e encontrar o pai bash ofensivo usando ps -Athen kill PID... Mas, novamente, isso pode levar muitos minutos do seu tempo se o seu computador estiver tão carregado que está escrevendo continuamente para trocar.

SIG TERM exec cpu_broken.sh; reunir novamente; limpar tela; processos de pensamento claros; continuar...

Existe uma solução melhor?

Responder1

Então, basicamente, você executa um script que torna tudo inacessível e deseja uma solução rápida e fácil para interrompê-lo. Uma alternativa ao ciclo de energia é manter pressionada SYSRQa tecla (é o mesmo que PRTSCa tecla em muitos casos) e pressionar uma por uma R, E, I, S, U, B. Basicamente, essa é uma maneira segura de encerrar todos os processos em execução e reiniciar o sistema.

Alternativa para isso é fazer sudo nano /proc/sysrq-trigger, escrever b nesse arquivo e salvar. O sistema será reiniciado imediatamente

Mais informações: https://en.wikipedia.org/wiki/Magic_SysRq_key

Responder2

Você precisa matar todo o grupo de processos. O ID do grupo de processos (PGID) é o PID do processo que iniciou o grupo. Para encerrar o grupo de processos, você precisa encontrar o PID do processo que iniciou o grupo de processos, ou seja, o script ou comando que iniciou tudo. A sintaxe é:

kill -- -PGID

Por exemplo:

kill -- -1234

Aqui 1234 é o PGID (ID do grupo de processo).

Isso enviará o SIGTERM para todos os processos do grupo de processos. Para enviar um sinal diferente, por exemplo, SIGKILL (9), faça:

kill -9 -1234

Como encontrar o PGID:

Você pode fazer:

ps -eo 'pid,ppid,pgid,cmd'

Isso mostrará o PID, PPID (ID do processo pai), PGID e o nome do processo.

Agora você pode usar grepqualquer outro método adequado para encontrar o PGID e eliminá-lo pelos métodos mencionados acima.

A razão pela qual criei o comando para mostrar o PPID é porque você também pode tentar encerrar o processo com base na correspondência do PPID pkill:

pkill -P PPID

Por exemplo:

pkill -P 6789

Usando este método, você precisa encontrar todos os processos pai (e filho) e então eliminá-los, então, na minha opinião, matar toda a árvore de processos é a melhor maneira se você quiser matar todos eles.

Responder3

Normalmente você pode usar top, htopou similar para encontrar o processo e eliminá-lo (ou se você souber o nome ou PID do processo, você pode killall, pkilletc). Por exemplo, usando top, posso selecionar um script em execução no terminal e eliminá-lo pressionando k+ Enter:

insira a descrição da imagem aqui

Se isso não funcionar, k+ 9+ Enterdeverá usar o sinal SIGKILL. SIGKILL solicita que o processo seja eliminado imediatamente e não espera que o processo termine de limpar os recursos, etc., como faz o SIGTERM. Ctrl+ Cum processo apenas envia SIGINT para interromper o processo, como faz o SIGTERM.

Usar a visualização em árvore (pressione t) no htop também permite que você determine os processos pais de um script e elimine-os para garantir que ele não continue em loop.

Veja também:

informação relacionada