Como parar o script de loop bash no terminal?

55

Por exemplo,

#!/bin/bash
while :
do
    sl
done

Como finalizar esse script bash?

Yinyanghu
fonte
11
Dê mais detalhes. Deseja pará-lo de forma interativa ou programática?
manatwork
11
você pode pressionar ctrl-cpara enviar o SIGINTsinal (na maioria dos shells) ou pressionar ctrl-zque envia o SIGTSTPsinal (na maioria dos shells). No caso de você pressionar ctrl-zo processo relacionado, não é eliminado, mas pausado. É possível retomar o com fg(pelo menos em bash)
user1146332
Não, não funciona!
Yinyanghu 17/09/12
4
O problema não é o script, mas o slcomando que acredito ser um comando irritante para quem comete um erro de ortografia ls, mostrando um trem passando lentamente. Até onde eu sei, ele retém o SIGINTsinal e deve ser morto com ele SIGKILL.
11
Obrigado. Não embalado para a minha distribuição, é por isso que eu não a conhecia. (Eu acho que não vai apresentar um pedido.)
manatwork

Respostas:

64

O programa slignora propositadamente SIGINT, que é o que é enviado quando você pressiona Ctrl+C. Então, primeiro, você precisará dizer slpara não ignorar SIGINTadicionando o -eargumento.

Se você tentar isso, notará que pode parar cada indivíduo sl, mas eles ainda se repetem. Você precisa dizer bashpara sair depois SIGINTtambém. Você pode fazer isso colocando um trap "exit" INTantes do loop.

#!/bin/bash
trap "exit" INT
while :
do
    sl -e
done
Jim Paris
fonte
5
Não o tenho instalado para verificar, mas você também pode matá-lo com o SIGQUIT de Ctrl- \
derobert
121
  1. pressione Ctrl-Zpara suspender o script
  2. kill %%

O %%comando informa ao bash interno killque você deseja enviar um sinal (SIGTERM por padrão) para o trabalho em segundo plano suspenso mais recentemente no shell atual, não para uma identificação de processo.

Você também pode especificar trabalhos por número ou nome. por exemplo, quando você suspender um trabalho com ^ Z, o bash informará qual é o número do trabalho com algo como [n]+ Stopped, onde o ninterior dos colchetes é o número do trabalho.

Para mais informações sobre controle de trabalho e sobre o emprego matando, executar help jobs, help fg, help bg, e help killem bash, e procurar JOB CONTROL(todas em maiúsculas) ou jobspecna página man bash.

por exemplo

$ ./killme.sh 
./killme.sh: linha 4: sl: comando não encontrado
./killme.sh: linha 4: sl: comando não encontrado
./killme.sh: linha 4: sl: comando não encontrado
./killme.sh: linha 4: sl: comando não encontrado
./killme.sh: linha 4: sl: comando não encontrado
...
...
...
./killme.sh: linha 4: sl: comando não encontrado
^ Z
[1] + Interrompido ./killme.sh
$ kill %%
$ 
[1] + Terminado ./killme.sh

Neste exemplo, o número do trabalho era 1, portanto kill %1, teria funcionado da mesma forma quekill %%

(NOTA: eu não tenho slinstalado, portanto a saída é apenas "comando não encontrado". No seu caso, você obterá qualquer saída que o sl produz. Não é importante - a ^Zsuspensão e kill %%funcionará da mesma maneira)

cas
fonte
3
Outra boa resposta!
Yinyanghu 18/09/12
2
Por outro lado, para executar rapidamente loops como esse, ^ Z pode ser uma maneira mais confiável de interromper o processo que ^ C. ^ C será enviado para o programa ( sl) sendo executado no loop, mas o script continuará em execução ... e iniciará outro sl. Se você pressionar ^ C algumas vezes muito rápido, poderá matar slo script e o script (se nenhum deles prender o SIGINT). ^ Z irá suspender o script quase imediatamente (imediatamente se você não contam saída que ainda está sendo impresso para o seu terminal em buffer), para que possa matá-lo comkill %%
cas
Exatamente! Eu tenho que dizer " slé um programa divertido". Desta vez, me divertiu de novo! @ _ @
Yinyanghu
Apenas responda que parece funcionar também quando o loop não é chamado de um script, mas diretamente da linha de comando.
Skippy le Grand Gourou
11
@DrewChapin Não me lembro quando / onde descobri isso - apenas algo que eu sei "desde sempre". A página de manual do bash (procure por jobspec ) diz:The symbols %% and %+ refer to the shell's notion of the current job, which is the last job stopped while it was in the foreground or started in the background. The previous job may be referenced using %-. If there is only a single job, %+ and %- can both be used to refer to that job
cas
7

Se você quiser que ctrl + c interrompa o loop, mas não encerre o script, poderá colocar || breakapós qualquer comando que esteja executando. Contanto que o programa que você está executando termine com ctrl + c, isso funciona muito bem.

#!/bin/bash
while :
do
    # ctrl+c terminates sl, but not the shell script
    sl -e || break
done

Se você estiver no loop aninhado, poderá usar "break 2" para sair de dois níveis, etc.

Dale Anderson
fonte
11
mais 1 para o intervalo 2
flyingfinger 18/07
3

Você pode finalizar esse script pressionando Ctrl + C no terminal onde você iniciou esse script. É claro que esse script deve ser executado em primeiro plano para que você possa pará-lo com Ctrl + C.

Ou você pode encontrar o PID (ID do processo) desse script em outro terminal aberto:

ps -ef | grep <name_of_the_script>
kill -9 <pid_of_your_running_script>

Ambas as formas devem fazer o truque que você está pedindo.

panaroik
fonte
11
Não pode ser finalizado com Ctrl + C no terminal. Então eu tenho que matá-lo por ps ou superior. Eu só quero saber como matá-lo diretamente!
Yinyanghu 17/09/12
3

A maneira mais fácil é emitir o QUITsinal, geralmente anexado Control-Backslash.

Quando você vir o trem, pressione Control- \

RobertL
fonte
1

Você pode killo pidshell (bash).
Eu apenas tentei e funciona.
Porque não consigo ver o processo ps -ef(o trabalho que executamos no script em loop).

Suwarto
fonte
0

Outra maneira de encerrar o script inteiro seria colocar o slcomando em segundo plano e, em seguida, interceptar o sinal INTpara eliminar todo o grupo de processos do script com sinal HUP.

#!/bin/bash

trap 'trap - INT; kill -s HUP -- -$$' INT
#trap 'trap - INT; kill -s HUP 0' INT

while :
do
   sl & wait
done
cantar
fonte
-1

use set -epara sair da falha.

#!/bin/bash
set -e
while :
do
    sl
done
guo chun mao
fonte
Isso não vai funcionar. slnão morre com ctrl + c.
Duncan X Simpson
-1
while [ true ] 
do

  #check if script is running
  ps | grep script_name.sh | grep -v grep >/dev/null 2>&1

  if [ "$!" != "0" ] ; then
    break
  else

    kill -9 ` ps -ef | grep script_name.sh | cut -d "a" -f 1` 
    echo "kill -9 `get script PID`"

  fi

done

isso deve ajudar.

coder007
fonte
2
Por que você acha que o PID do último comando em segundo plano será 0?
manatwork
-1

A coisa da morte é horrível, porque você nunca agora, se o script tiver que ser executado duas vezes. E seu código de saída está errado.

while [ something ]; do

 if [ somethingelse ]; then
   echo shut down script with exit code 0
   exit 0
 fi
done

echo something else not happend
exit 2 # Return val important for example for monitoring

Sem trabalho. Solução = use perl. enquanto abre a própria festança

rene
fonte