entrada de tubulação do processo em segundo plano

14

se eu quiser exibir "aaa" na tela:

(1)$: echo aaa | cat                 ... works OK
(2)$: echo aaa | ( cat )             ... works OK
(3)$: echo aaa | ( cat & )           ... NOT working
(4)$: ( echo aaa & ) | cat           ... works OK 
(5)$: echo aaa | ( cat <&0 & )       ... works ok in BASH (but not in SH)
(6)$: echo aaa | ( cat <&3 & ) 3<&0  ... works ok in BASH and SH

A confusão de (3) e (4) -> processo desanexado ainda tem saída conectada que pode ser controlada, usada, redirecionada ..., mas não é entrada!

Minha pergunta é: alguém entende por que e como a linha (5) funciona ???

... "<& 0" é a abreviação de "0 <& 0", por que redirecionar 0 a 0 é solução e o que realmente acontece por trás da entrada do processo desanexado. O subshell não é o problema, usar chaves {...} em vez de (...) fornece os mesmos resultados.

... e question2: existe melhor solução para "dar entrada ao processo desanexado" do que a linha (6).

Asain Kujovic
fonte

Respostas:

12

Sim, conforme exigido pelo POSIX , os comandos iniciados em segundo plano &têm sua entrada padrão redirecionada /dev/null.

E realmente

{ cmd <&3 3<&- & } 3<&0

é a maneira mais óbvia de contornar isso.

Não está claro por que você deseja executar parte do pipeline em segundo plano.

Stéphane Chazelas
fonte
O motivo foi obter o PID de um comando específico dentro da cadeia de tubulação (cmd1 | {cmd2 &; pid2 = $ !;} | cmd3 ..., então / dev / null == & 0 é o padrão para processos BG, você também sabe por que "0 <& 0" obras em festa ... e é seguro?
Asain Kujovic
3
@OmerMerdan POSIX diz Em todos os casos, o redirecionamento explícito da entrada padrão substituirá essa atividade , o que contradiz de alguma forma o que foi dito acima, então acredito que a bashinterpreta (e isso soa como uma interpretação razoável) como cancelamento do /dev/nullredirecionamento. Agora, poucas conchas fazem o mesmo. Ash e pdksh não.
Stéphane Chazelas 04/04
Por que a 3<&-peça é necessária e é seguro usá-la (não fechará o tubo antes da leitura completa da entrada)?
Mrvisek
1
@Mvorisek, esse fd 3 é usado apenas temporariamente para restaurar o stdin original. Nós o fechamos porque cmdnão é necessário. Nós o fechamos depois de colocá-lo em fd 0 ( <&3abreviação de 0<&3).
Stéphane Chazelas
1
@Mvorisek, nohuptambém redireciona stdin para / dev / null, então você precisa: { nohup sh -c 'cmd <&3 3<&-' & } 3<&0. Ou(trap '' HUP; cmd <&3 3<&- > nohup.out 2>&1 &) 3<&0
Stéphane Chazelas