Shell: tubulação mútua de STDIN / STDOUT de dois comandos [duplicado]

3

Quando executamos isso com um shell POSIX,

$ cmd0 | cmd1

STDOUT de cmd0 é canalizado para STDIN de cmd1.

P: Além disso, como posso também canalizar STDOUT de cmd1 para STDIN de cmd0?

É obrigatório usar o redirecionamento de / para um pipe nomeado (FIFO)? Eu não gosto muito de pipes nomeados porque eles ocupam alguns caminhos do sistema de arquivos e eu preciso me preocupar com colisões de nomes. Ou eu tenho que chamar pipe (2) via C, Python ou algumas linguagens de programação de propósito geral?

(Ambos cmd0 e cmd1 fazem alguma E / S de rede, então eles não bloquearão um ao outro para sempre.)

    
por nodakai 17.07.2016 / 13:03

1 resposta

11

Em sistemas com canais bidirecionais (não Linux), você pode fazer:

cmd0 <&1 | cmd1 >&0

No Linux, você pode fazer:

{ cmd0 < /dev/fd/3 | cmd1 3>&-; } 3>&1 | :

Isso funciona porque no Linux (e no Linux somente) /dev/fd/x onde x é um fd para um pipe (chamado ou não) age como um pipe nomeado, ou seja, abri-lo no modo de leitura te dá o final da leitura e no modo de gravação você recebe o fim da escrita.

Com o yash shell e seu x>>|y redirecionamento de pipeline :

{ cmd0 <&4 3<&- 4<&- | cmd1 >&3 3>&- 4>&-; } 3>>|4

Com shells com suporte a coproc :

  • zsh:

     coproc cmd0
     cmd1 <&p >&p
    
  • ksh

     cmd0 |&
     cmd1 <&p >&p
    
  • bash4 +

     coproc cmd0
     cmd1 <&"${COPROC[0]}" >&"${COPROC[1]}"
    

Algumas abordagens baseadas em ferramentas dedicadas (descaradamente copiadas das respostas em esta pergunta muito semelhante ):

pipexec [ A /path/to/cmd0 ] \
        [ B /path/to/cmd1 ] \
        '{A:1>B:0}' '{A:0>B:1}'

Ou:

dpipe cmd0 = cmd1

Ou:

socat EXEC:cmd0 EXEC:cmd1,nofork # using socketpairs
socat EXEC:cmd0,commtype=pipes EXEC:cmd1,nofork # using pipes

Eu não sei sobre python , mas isso também é relativamente fácil em perl :

perl -e 'pipe STDOUT,STDIN; exec "cmd0 | cmd1"'

De qualquer forma, tenha cuidado com os impasses!

    
por 17.07.2016 / 13:11