Como posso enviar leituras e gravações em um único descritor de arquivo para diferentes locais?

7

Eu tenho um executável Linux foo que lê a entrada de fd 0 e grava a saída para fd 0 ( não fd 1). Isso funciona muito bem para uso interativo no terminal.

A partir da linha de comando do shell, como posso executar este programa de modo que as leituras de fd 0 sejam provenientes de um arquivo, mas as gravações em fd 0 entram em um arquivo diferente?

O melhor que eu posso fazer é $ goo input.txt output.txt | foo onde goo é algum programa auxiliar, mas eu não sei de nenhum programa auxiliar existente, e eu nem sei se o pipe configurado por | é bidirecional.

    
por Jay 30.07.2014 / 15:08

1 resposta

6

Com socat (versão 2 ou superior):

socat 'system:cat input.txt & cat > output.txt,commtype=socketpair' \
      'system:foo,nofork'

Ou melhor ainda:

socat 'CREATE:output.txt%OPEN:input.txt' 'system:foo,commtype=socketpair'

Estamos usando um socketpair que é bidirecional (os pipes não são bidirecionais no Linux). Outra opção é usar um pseudo-terminal (bidirecional também) usando commtype=pty acima. Essa pode ser uma maneira melhor se foo espera falar com um terminal.

Ou você implementa a abordagem socketpair em perl como:

perl -MSocket -e '
  socketpair(A, B, AF_UNIX, SOCK_STREAM, PF_UNSPEC);
  if (fork) {
    close A;
    if (fork) {
      open STDOUT, ">&B";
      exec("cat", "input.txt")
    }
    open STDIN, "<&B";
    open STDOUT, ">output.txt";
    exec("cat")
  }
  close B;
  open STDIN, "<&A";
  exec "foo"'

(aqui como uma rápida prova de conceito, você pode querer adicionar a verificação de erros e torná-la mais eficiente, não usando muitos processos e evitando a execução de cat ).

    
por 30.07.2014 / 16:54