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) .