Sim, bashcomo em ksh(de onde o recurso vem), os processos dentro da substituição do processo não são esperados (antes de executar o próximo comando no script).
para <(...)um, geralmente é bom como em:
cmd1 <(cmd2)
o shell estará aguardando cmd1e cmd1normalmente estará aguardando em cmd2virtude da leitura até o final do arquivo no tubo substituído, e esse fim do arquivo normalmente acontece quando cmd2morre. Essa é a mesma razão várias conchas (não bash) não se incomode à espera de cmd2no cmd2 | cmd1.
Pois cmd1 >(cmd2), no entanto, esse geralmente não é o caso, pois é mais o cmd2que normalmente espera por cmd1isso, e geralmente sai depois.
Isso está fixo no zshque aguarda por cmd2lá (mas não se você o escrever como cmd1 > >(cmd2)e cmd1não estiver embutido, use {cmd1} > >(cmd2)como documentado ).
kshnão espera por padrão, mas permite que você espere por ele com o waitbuilt-in (também disponibiliza o pid $!, embora isso não ajude se você o fizer cmd1 >(cmd2) >(cmd3))
rc(com a cmd1 >{cmd2}sintaxe), o mesmo que com a kshexceção de que você pode obter os pids de todos os processos em segundo plano $apids.
es(também com cmd1 >{cmd2}) aguarda o cmd2like in zshe também aguarda redirecionamentos cmd2no <{cmd2}processo.
bashtorna disponível o pid cmd2(ou mais exatamente do subshell, como ele é executado cmd2em um processo filho desse subshell, mesmo que seja o último comando) $!, mas não deixa você esperar por ele.
Se você precisar usar bash, poderá solucionar o problema usando um comando que aguardará os dois comandos com:
{ { cmd1 >(cmd2); } 3>&1 >&4 4>&- | cat; } 4>&1
Isso faz os dois cmd1e cmd2tem seu fd 3 aberto em um cano. cataguardará o final do arquivo na outra extremidade e, portanto, normalmente somente sairá quando ambos cmd1e cmd2estiverem mortos. E o shell aguardará esse catcomando. Você pode ver isso como uma rede para capturar o término de todos os processos em segundo plano (você pode usá-lo para outras coisas iniciadas em segundo plano, como &coprocs ou mesmo comandos que são em segundo plano, desde que não fechem todos os descritores de arquivos, como os daemons normalmente fazem )
Observe que, graças ao processo desperdiçado do subshell mencionado acima, ele funciona mesmo se cmd2fechar o fd 3 (os comandos geralmente não fazem isso, mas alguns gostam sudoou sshfazem). Versões futuras do bashpodem eventualmente fazer a otimização como em outros shells. Então você precisaria de algo como:
{ { cmd1 >(sudo cmd2; exit); } 3>&1 >&4 4>&- | cat; } 4>&1
Para garantir que ainda haja um processo de shell extra com esse fd 3 aberto aguardando esse sudocomando.
Observe que catnão lerá nada (já que os processos não gravam em seu fd 3). Está lá apenas para sincronização. Ele fará apenas uma read()chamada do sistema que retornará sem nada no final.
Na verdade, você pode evitar a execução catusando uma substituição de comando para fazer a sincronização de pipe:
{ unused=$( { cmd1 >(cmd2); } 3>&1 >&4 4>&-); } 4>&1
Desta vez, é o shell, em vez disso, catque está lendo no canal, cuja outra extremidade está aberta nos fd 3 de cmd1e cmd2. Estamos usando uma atribuição de variável para que o status de saída de cmd1esteja disponível em $?.
Ou você pode fazer a substituição do processo manualmente, e então você pode até usar o sistema, shpois isso se tornaria a sintaxe padrão do shell:
{ cmd1 /dev/fd/3 3>&1 >&4 4>&- | cmd2 4>&-; } 4>&1
observe, como observado anteriormente, que nem todas as shimplementações esperariam cmd1após a cmd2conclusão (embora isso seja melhor do que o contrário). Nesse momento, $?contém o status de saída de cmd2; embora bashe zshdisponibilize cmd1o status de saída em ${PIPESTATUS[0]}e $pipestatus[1]respectivamente (consulte também a pipefailopção em algumas conchas para que $?possamos relatar a falha de outros componentes do tubo que não o anterior)
Observe que yashhá problemas semelhantes com o recurso de redirecionamento de processo . cmd1 >(cmd2)seria escrito cmd1 /dev/fd/3 3>(cmd2)lá. Mas cmd2não é esperado e você também não pode waitesperar por isso, e seu pid também não é disponibilizado na $!variável. Você usaria as mesmas soluções alternativas de bash.