Eu tenho um script bash chamado test.sh
como abaixo:
#!/bin/bash
while :
do
echo xxx
sleep 1
done
Não sei porque ./test.sh & | ./test.sh
me dá um erro: -bash: syntax error near unexpected token |'
, considerando que ./test.sh | ./test.sh
e ./test.sh | ./test.sh &
funciona.
Isso simplesmente não é permitido pela gramática do shell :
Observe como
&
ou;
só pode encerrar listas, e listas são apenas parte de um complete_command, que não pode fazer parte de outras produções.Isso é apenas uma peculiaridade gramatical; assim como
{ foo & }
é semanticamente semelhante afoo &
(as chaves, ao contrário dos parênteses, são usadas apenas para agrupar comandos, elas não criam por si um subshell ou qualquer tipo de escopo), você pode considerar{ foo & } | bar
ser semanticamente semelhante afoo & | bar
, se este último fosse permitido pela gramática.Portanto, a solução alternativa para o seu exemplo é apenas:
Se você executar isso a partir de um shell interativo, observe que não
&
criará um job em segundo plano , mas apenas executará o comando de forma assíncrona, porque o lado direito de um pipeline sempre é executado em um subshell e os comandos de um subshell são executados com job controle desabilitado.Isso é semelhante a:
As listas assíncronas (comandos terminados por
&
) em um subshell são executadas com seu stdin redirecionado/dev/null
e seus sinaisSIGINT
eSIGQUIT
ignorados. Eles continuarão sendo executados em segundo plano, mas você não poderá trazê-los para o primeiro plano comfg
,disown
them, etc, como você pode fazer com trabalhos normais. Além disso, você não será notificado quando eles forem interrompidos ou encerrados.Em um script, isso não faz absolutamente nenhuma diferença, pois os scripts são executados com o controle de trabalho desabilitado.
Mas se você quiser canalizar a saída de um trabalho em segundo plano para um trabalho em primeiro plano em um shell interativo , a única solução portátil que consigo pensar é usar um canal nomeado.