Pergunta

Eu tenho dois programas (UNIX) A e B que ler e escrever de stdin / stdout.

Meu primeiro problema é como conectar o stdout de à stdin de B e o stdout de B para o stdin de A. Ou seja, algo como A | B, mas um tubo bidireccional. Eu suspeito que eu poderia resolver isso usando exec para redirecionar mas eu não poderia obtê-lo trabalhar. Os programas são interativos para que um arquivo temporário não iria funcionar.

O segundo problema é que eu gostaria de duplicar cada direção e tubo de uma duplicata através de um programa de log para stdout para que eu possa ver o tráfego (-line baseado em texto) que passam entre os programas. Aqui eu posso fugir com tee> (...) se eu posso resolver o primeiro problema.

Ambos estes problemas parece que eles deveriam ter sabido soluções, mas eu não ser capaz de encontrar qualquer coisa.

Eu preferiria uma solução shell POSIX, ou pelo menos algo que funciona em bash em cygwin.

Graças às suas respostas eu vim com a solução seguinte. A / B comanda usos nc para ouvir duas portas. Os usos do programa de registro sed (com u para processamento sem buffer).

bash-3.2$ fifodir=$(mktemp -d)
bash-3.2$ mkfifo "$fifodir/echoAtoB"
bash-3.2$ mkfifo "$fifodir/echoBtoA"
bash-3.2$ sed -u 's/^/A->B: /' "$fifodir/echoAtoB" &
bash-3.2$ sed -u 's/^/B->A: /' "$fifodir/echoBtoA" &
bash-3.2$ mkfifo "$fifodir/loopback"
bash-3.2$ nc -l -p 47002 < "$fifodir/loopback" \
          | tee "$fifodir/echoAtoB" \
          | nc -l -p 47001 \
          | tee "$fifodir/echoBtoA" > "$fifodir/loopback"

Este escutas para conexão à porta 47001 e 47002 e ecos todo o tráfego para a saída padrão.

No shell 2 fazer:

bash-3.2$ nc localhost 47001

No shell 3 fazer:

bash-3.2$ nc localhost 47002

Agora linhas inscritas no shell 2 será escrito que desembolsar 3 e vice-versa eo tráfego registrado que desembolsar 1, algo como:

B->A: input to port 47001
A->B: input to port 47002

O texto acima foi testado em Cygwin

Update: O script acima parou de funcionar depois de alguns dias (!). Aparentemente, ele pode impasse. Algumas das sugestões nas respostas podem ser mais confiáveis.

Outras dicas

Como cerca de um pipe nomeado?

# mkfifo foo
# A < foo | B > foo
# rm foo

Para a sua segunda parte acredito tee é a resposta correta. Assim torna-se:

# A < foo | tee logfile | B > foo

Você provavelmente poderia fugir com pipes nomeados:

mkfifo pipe
gawk '$1' < pipe | gawk '$1' > pipe

Você pode usar Esperar .

Esperar é uma ferramenta para a automatização de aplicações interactivas, tais como telnet, ftp, passwd, fsck, Rlogin, ponta, etc.

Você pode usar o código a seguir (retirado do Explorando esperar livro) como um ponto de partida - ele se conecta a saída do proc1 à entrada do proc2 e vice-versa, como você pediu:

#!/usr/bin/expect -f
spawn proc1
set proc1 $spawn_id
spawn proc2
interact -u $proc1

Eu passei muito tempo com isso, deu-se, e por último decidiu usar ksh (o shell Korn), que permite isso.

cmd1 |& cmd2 >&p <&p

onde |& é um operador (pipe) para iniciar um co-processo e &p é descritor de que a co-processo de arquivo.

Eu tive esse problema em um ponto, e eu joguei junto este programa C simples.

#include <stdio.h>
#include <unistd.h>

#define PERROR_AND_DIE(_x_) {perror(_x_); _exit(1);}

int main(int argc, char **argv) {
    int fd0[2];
    int fd1[2];


    if ( argc != 3 ) {
        fprintf(stdout, "Usage %s: \"[command 1]\" \"[command 2]\"\n", argv[0]);
        _exit(1);
    }

    if ( pipe(fd0) || pipe(fd1) ) PERROR_AND_DIE("pipe")

    pid_t id = fork();
    if ( id == -1 ) PERROR_AND_DIE("fork");

    if ( id ) {
        if ( -1 == close(0) )  PERROR_AND_DIE("P1: close 0");
        if ( -1 == dup2(fd0[0], 0) ) PERROR_AND_DIE("P1: dup 0"); //Read my STDIN from this pipe

        if ( -1 == close(1) )  PERROR_AND_DIE("P1: close 1");
        if ( -1 == dup2(fd1[1], 1) ) PERROR_AND_DIE("P1: dup 1"); //Write my STDOUT here
        execl("/bin/sh", "/bin/sh", "-c", argv[1], NULL);
        PERROR_AND_DIE("P1: exec")
    }

    if ( -1 == close(0) )  PERROR_AND_DIE("P2: close 0");
    if ( -1 == dup2(fd1[0], 0) ) PERROR_AND_DIE("P2: dup 0");

    if ( -1 == close(1) )  PERROR_AND_DIE("P2: close 1");
    if ( -1 == dup2(fd0[1], 1) ) PERROR_AND_DIE("P2: dup 1");


    execl("/bin/sh", "/bin/sh", "-c", argv[2], NULL);
    PERROR_AND_DIE("P2: exec")
}

Esta questão é semelhante ao eu perguntei antes . As soluções propostas por outros estavam a utilizar os pipes nomeados, mas eu suspeito que você não tê-los em cygwin. Atualmente eu estou aderindo a minha própria (tentativa de) solução , mas requer /dev/fd/0 que você provavelmente também não tem.

Embora eu realmente não gosto do passar-Command-linhas-as-cordas aspecto twinpipe (mencionado por JeeBee ( 139.495 )), pode ser sua única opção no cygwin.

Eu sugiro "coproc":

#! /bin/bash
# initiator needs argument

if [ $# -gt 0 ]; then
  a=$1
  echo "Question $a"
else
  read a
fi

if [ $# -gt 0 ]; then
  read a
  echo "$a" >&2
else
  echo "Answer to $a is ..."
fi

exit 0

Então veja esta sessão:

$ coproc ./dialog
$ ./dialog  test  < /dev/fd/${COPROC[0]}  > /dev/fd/${COPROC[1]}
Answer to Question test is ...
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top