Por que o comando abaixo não sai? Em vez de sair, o loop é executado indefinidamente.
Embora eu tenha descoberto esse comportamento usando uma instalação mais complexa, a forma mais simples do comando se reduz ao seguinte.
Não sai:
while /usr/bin/true ; do echo "ok" | cat ; done | exit 1
Não há erros de digitação acima. Cada '|' é um cano. A 'saída 1' representa outro processo que foi executado e encerrado.
Eu espero que a "saída 1" cause um SIGPIPE no loop while (escreva em um pipe sem leitor) e que o loop saia. Mas, o loop continua em execução.
Por que o comando não para?
linux
command-line
bash
shell
bash-scripting
stephen.z
fonte
fonte
Respostas:
É devido a uma escolha na implementação.
A execução do mesmo script no Solaris com
ksh93
produz um comportamento diferente:O que desencadeia o problema é o pipeline interno; sem ele, o loop sai independentemente do shell / OS:
cat
está recebendo um sinal SIGPIPE no bash, mas o shell está iterando o loop de qualquer maneira.A documentação do Bash indica:
A documentação do Ksh afirma:
POSIX afirma:
fonte
echo
ignora o SIGPIPE. Você também pode reproduzir o problema usando emenv echo
vez deecho
(para forçar oecho
binário real a ser usado). (Compare também a saída do{ echo hi; echo $? >&2; } | exit 1
e{ env echo hi; echo $? >&2; } | exit 1
.)Esse problema me incomoda há anos. Obrigado a Jilliagre pela cutucada na direção certa.
Reafirmando um pouco a pergunta, na minha caixa Linux, isso é encerrado como esperado:
Mas se eu adicionar um pipe, ele não será encerrado como esperado:
Isso me frustrou por anos. Ao considerar a resposta escrita por jilliagre, criei esta correção maravilhosa:
QED ...
Bem, não exatamente. Aqui está algo um pouco mais complicado:
Isso não funciona direito. Eu adicionei o
|| exit
para que ele saiba como terminar mais cedo, mas o primeiroecho
não corresponde ao,grep
então o loop é encerrado imediatamente. Nesse caso, você realmente não está interessado no status de saída dogrep
. Minha solução alternativa é adicionar outracat
. Então, aqui está um script artificial chamado "dezenas":Isso termina corretamente quando executado como
tens | head
. Graças a Deus.fonte