Frage

Ich habe zwei (UNIX) Programme A und B, die von stdin / stdout lesen und schreiben.

Mein erstes Problem ist, wie die Standardausgabe von A bis stdin von B verbinden und die stdout von B auf den stdin von A. D. h, so etwas wie A | B, sondern ein bidirektionaler Rohr. Ich vermute, ich könnte dieses Problem lösen, indem exec umleiten, aber ich konnte es nicht bekommen arbeiten. Die Programme sind interaktiv so eine temporäre Datei nicht funktionieren würde.

Das zweite Problem ist, dass ich mag jede Richtung und Rohr über ein Logging-Programm ein Duplikat duplizieren und stdout, dass ich die (Text-Linie basiert) Verkehr sehen, die zwischen den Programmen bestehen. Hier kann ich mit T-Stück weg> (...), wenn ich das erste Problem lösen kann.

Diese beiden Probleme scheinen, wie sollten sie auch Lösungen bekannt, aber ich habe nicht in der Lage sein, etwas zu finden.

Ich würde eine POSIX-Shell-Lösung bevorzugen, oder zumindest etwas, das in bash auf Cygwin funktioniert.

Dank Ihre Antworten kam ich mit der folgenden Lösung auf. Die A / B-Befehle verwendet nc zu zwei Ports zu hören. Das Logging-Programm verwendet sed (mit -u für ungepufferte Verarbeitung).

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"

Das hört für den Anschluss an Port 47001 und 47002 und echos der gesamten Datenverkehrs auf der Standardausgabe.

In Schale 2 zu tun:

bash-3.2$ nc localhost 47001

In Schale 3 zu tun:

bash-3.2$ nc localhost 47002

Jetzt in der Schale eingegeben Linien 2 geschrieben werden 3 und umgekehrt, Shell und der Verkehr angemeldet 1, Shell, so etwas wie:

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

Das oben wurde auf Cygwin getestet

Update: Das Skript oben gestoppt, nachdem ein paar Tage arbeiten (!). Offenbar kann es Deadlock. Einige der Vorschläge in den Antworten können zuverlässiger sein.

War es hilfreich?

Andere Tipps

Wie über eine Named Pipe?

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

Für Ihren zweiten Teil Ich glaube, T-Shirt ist die richtige Antwort. So wird es:

# A < foo | tee logfile | B > foo

Sie könnten wahrscheinlich mit Named Pipes weg:

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

Sie können mit erwarten .

  

Erwarten Sie ist ein Werkzeug für die Automatisierung von interaktiven Anwendungen wie Telnet, FTP, passwd, fsck, rlogin, Spitze, etc.

Sie können den folgenden Code verwenden (aus dem Erwarten Explo Buch) als Ausgangspunkt - den Ausgang des proc1 an den Eingang des proc2 und umgekehrt verbindet, wie gewünscht:

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

Ich habe auf diese viel Zeit, gab es auf, und zuletzt entschieden KSH (die Korn-Shell) zu verwenden, die dies ermöglicht.

cmd1 |& cmd2 >&p <&p

wobei |& ist ein (Rohr) Bediener einen Coprozess und &p ist Dateideskriptor dieses Co-Prozess zu starten.

Ich hatte dieses Problem an einem Punkt, und ich warf zusammen dieses einfache C-Programm.

#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")
}

Ich würde vorschlagen, "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

Dann diese Sitzung finden Sie unter:

$ coproc ./dialog
$ ./dialog  test  < /dev/fd/${COPROC[0]}  > /dev/fd/${COPROC[1]}
Answer to Question test is ...
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top