Quais são as diferenças entre “kill -PIPE $$” vs. “exit 1”?

5

No meu script Bash, usei a seguinte sintaxe para sair do script Bash:

kill -PIPE $$

Eu uso porque às vezes em uma função ou em um shell interno no script, o exit 1 realmente não sai do script do Bash.

Por isso, uso kill em vez de exit 1 .

Parece que

exit 1

e

kill -PIPE $$

são quase iguais. Minha suposição é verdadeira?

Segundo - sobre kill -PIPE $$ , existe um risco em usar essa sintaxe?

    
por yael 28.10.2018 / 18:01

1 resposta

10

exit 1 sai do ambiente subshell atual com o código de saída 1, portanto, por exemplo, em:

sh -c '(echo 1; exit 1; echo 2); echo 3'

Esse exit 1 sai do subshell executando o código no lado (...) , de modo que 2 não seja produzido e o processo do shell pai seja retomado, fazendo eco ao 3 .

kill -s PIPE "$$" ¹ envia o sinal SIGPIPE para o processo que executou o interpretador de shell interpretando atualmente o script. O sinal SIGPIPE, por padrão, faz com que os processos terminem, e o fato de que esse processo tenha sido eliminado pelo SIGPIPE é refletido em seu status de saída.

Então, em:

sh -c '(echo 1; kill -s PIPE "$$"; echo 2); echo 3'

Um sinal SIGPIPE é enviado pelo processo subshell para seu processo pai (aquele que executou sh ). Esse processo pai morrerá e não produzirá 3 , enquanto o processo subshell continuará executando em background e a saída 2 .

Se você executou esse comando no shell bash ou zsh (e alguns outros shells semelhantes a Bourne), esses shells definirão o parâmetro $? (sua representação interna do status de saída do último comando ) para algo como 141, que é 128 + SIGPIPE (13 na maioria dos sistemas).

Agora SIGPIPE é o sinal enviado pelo sistema para processos que estão tentando gravar em um pipe ou soquete que não tem fim de leitura (um cano / soquete quebrado), então enviá-lo aqui é um pouco enganador. O sinal reservado para finalizar administrativamente um processo é SIGTERM, que por acaso é o sinal kill envia por padrão.

Agora, uma razão pela qual você pode querer usar SIGPIPE em vez de SIGTERM é que existem shells como bash que geram uma mensagem quando um de seus trabalhos é terminado por um sinal, enquanto eles geralmente não o fazem por SIGPIPE (como é comum que processos sejam terminados por um SIGPIPE, e não necessariamente significa que há um problema como em cmd | head -n 1 ), então usar o SIGPIPE é uma maneira de evitar essas mensagens.

bash-4.4$ /bin/kill 0
Terminated
bash-4.4$ /bin/kill -s PIPE 0
bash-4.4$

mesmo quando não interativo:

$ bash -c 'sh -c "kill \$\$"; exit'
bash: line 1:  6665 Terminated              sh -c "kill \$\$"
$ bash -c 'sh -c "kill -s PIPE \$\$"; exit'
$

1 Aqui adicionamos as aspas faltantes em torno de $$ para confiabilidade e usando o standard (não opcional em POSIX) kill -s PIPE de sintaxe para portabilidade (embora kill -PIPE também funcione na maioria dos sistemas) .

    
por 28.10.2018 / 21:31