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