Tenho um comando que quero que seja executado automaticamente sempre que ele terminar, então executei algo assim:
while [ 1 ]; do COMMAND; done;
mas se eu não conseguir parar o loop com Ctrl-c , pois isso simplesmente mata COMMAND
e não o loop inteiro.
Como eu alcançaria algo semelhante, mas que posso parar sem ter que fechar o terminal?
Comentários
- Se eu ‘ m no bash, apenas uso Ctrl-Z para interromper o trabalho e ” kill% 1 ” para matá-lo.
- Espere … Linus foi citado como tendo dito: “Todos nós sabemos que o Linux é ótimo … ele faz loops infinitos em 5 segundos. ” – então, sério … espere mais alguns segundos, ele deve terminar.
- @PaulCager funcionou para mim também! Por que funciona onde Ctrl-C funciona não?
- @cirosantilli ele mata o trabalho externo (o bash ” wrapper “). Em algumas situações, ele conseguiu ‘ t matar imediatamente o ” COMANDO “, por exemplo , se você fizer isso em segundo plano, ele pode passar despercebido mesmo se ‘ seu pai estiver morto. Mas o loop está morto e essa ‘ é a parte importante.
Resposta
Verifique o status de saída do comando. Se o comando foi encerrado por um sinal, o código de saída será 128 + o número do sinal. Da documentação online do GNU para bash :
Para fins de shell, um comando que sai com um status de saída zero foi bem-sucedido. Um status de saída diferente de zero indica falha. Esse esquema aparentemente contra-intuitivo é usado para que haja uma maneira bem definida de indicar o sucesso e uma variedade de maneiras de indicar vários modos de falha. Quando um comando termina em um sinal fatal cujo número é N, o Bash usa o valor 128 + N como o status de saída.
POSIX também especifica que o valor de um comando que termina por um sinal é maior que 128, mas não parece especificar seu valor exato como o GNU faz:
O status de saída de um comando que terminou porque recebeu um sinal deve ser relatado como superior a 128.
Por exemplo, se você interromper um comando com control-C, o código de saída será 130, porque SIGINT é o sinal 2 em sistemas Unix. Portanto:
while [ 1 ]; do COMMAND; test $? -gt 128 && break; done
Comentários
Resposta
Você pode interromper e colocar seu trabalho em segundo plano enquanto ele está sendo executado usando ctrl + z . Então você pode eliminar seu trabalho com:
$ kill %1
Onde [1] é o número do seu trabalho.
Comentários
- Consulte também esta resposta para obter explicações e muito mais.
- Esta resposta relativamente recente simplesmente funciona. Precisa ser voto positivo. +1
- Você me ajudou muito. Isso é o que eu pesquisei nesta pergunta 🙂
Resposta
Eu diria que pode ser melhor colocar seu loop infinito em um script e manipular sinais lá. Aqui é um ponto de partida básico . Tenho certeza que você vai querer modificá-lo para se adequar. O script usa trap
para capturar ctrl – c (ou SIGTERM
), mata o comando (eu usei sleep
aqui como um teste) e sai.
cleanup () { kill -s SIGTERM $! exit 0 } trap cleanup SIGINT SIGTERM while [ 1 ] do sleep 60 & wait $! done
Comentários
- Legal. Aqui ‘ como usei esta dica para fazer um wrapper netcat de reinicialização automática:
trap "exit 0" SIGINT SIGTERM; while true; do netcat -l -p 3000; done
- se você adicionar esta abordagem
trap
ao mesmo script (bash) com o loop infinito a ser eliminado, use$$
em vez de$!
(veja aqui )
Resposta
Geralmente, apenas mantenho pressionado Ctrl-C . Mais cedo ou mais tarde, ele “será registrado entre COMMAND
” se encerrar o loop while
. Talvez haja uma maneira melhor.
Comentários
- Não sei por que, mas falha para certos COMANDOS como
paplay
em um arquivo 1s . - Funcionou para mim
- Essa ‘ é a força bruta de todas as soluções aqui. : /
Resposta
Se você executar o bash com -e
ele sairá em qualquer condição de erro:
#!/bin/bash -e false # returns 1 echo This won"t be printed
Comentários
- A primeira linha aqui é de longe a solução mais simples para um script trivial no qual você não ‘ não deseja gastar muito tempo!
Resposta
Por que não simplesmente,
while [ 1 ]; do COMMAND || break; done;
Ou quando usado em um script,
#!/bin/bash while [ 1 ]; do # ctrl+c terminates COMMAND and exits the while loop # (assuming COMMAND responds to ctrl+c) COMMAND || break done;
Comentários
- Solução muito elegante. Mas não ‘ isso só funcionaria se COMMAND sempre retornasse um status de saída de sucesso?
- Sim @howardh, que ‘ está correto.
Resposta
- Você sempre pode matar um processo usando seu PID, ” não há necessidade de fechar seu terminal
- Se você deseja executar algo em um loop infinito como um daemon, é melhor colocá-lo em segundo plano
-
while :
criará um loop infinito e evitará que você escreva[ 1 ]
while :; do COMMAND; done &
Isso imprimirá o PID. Se você sair do prompt usando ctrl+d
, o trabalho em segundo plano não será encerrado e você poderá encerrar o trabalho posteriormente de qualquer lugar usando kill PID
Se você perder o controle do seu PID, poderá usar pstree -pa $USER
ou pgrep -fl ".*PROCESS.*"
para ajudá-lo a encontrá-lo
Resposta
Prefiro outra solução:
touch .runcmd; while [ -f ".runcmd" ]; do COMMAND; sleep 1; done
Em ordem para encerrar o loop, basta fazer:
rm .runcmd && kill `pidof COMMAND`
Responder
O que funciona razoavelmente bom para mim é:
while sleep 1; do COMMAND; done
Isso funciona porque o sono 1 permanece por um enquanto e se ele obtiver ctrl + c, ele retorna com um valor diferente de zero e o loop será encerrado.
Comentários
- +1, o tempo de sono também pode ser reduzido para
0.5
ou0.1
:while sleep 0.1; do COMMAND; done
Resposta
Use trap
–
exit_() { exit } while true do echo "running.." trap exit_ int done
paplay alert.ogg
, talvez porquepaplay
lida com o sinal?