2008-09-26 78 views
10

我有兩個(UNIX)程序A和B從stdin/stdout讀取和寫入。在shell/bash中連接兩個命令之間的輸入_and_output

我的第一個問題是如何A的標準輸出連接到B B相對於A的標準輸入標準輸出的標準輸入,即,像A | B而是一個雙向管道。我懷疑我可以通過using exec to redirect來解決這個問題,但我無法完成它的工作。這些程序是交互式的,所以臨時文件不起作用。

第二個問題是,我想通過記錄程序到stdout複製每個方向和管重複這樣我可以看到,程序之間傳遞(基於文本的線)的流量。如果我可以解決第一個問題,那麼在這裏,我可能會開球>(...)。

這兩個問題似乎是,他們應該有衆所周知的解決方案,但我沒能找到任何東西。

我寧願POSIX殼溶液,或至少一些在bash在Cygwin上工作。

感謝您的回答,我提出了以下解決方案。 A/B命令使用nc來偵聽兩個端口。日誌程序使用sed(使用-u進行無緩衝處理)。

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" 

這聽取連接到端口47001和47002和回聲所有流量到標準輸出。

在殼2做:

bash-3.2$ nc localhost 47001 

在殼3做:

bash-3.2$ nc localhost 47002 

現在線在殼2中輸入將被寫入到殼3並且反之亦然,交通記錄到外殼1 ,是這樣的:

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

上面已經在Cygwin

測試

更新:上面的腳本幾天後停止工作(!)。顯然它可能會陷入僵局。答案中的一些建議可能更可靠。

回答

5

你也許可以使用命名管道逃脫:

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

如何命名管道?

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

對於你的第二部分,我相信三通是正確的答案。因此它變成:

# A < foo | tee logfile | B > foo 
4

您可以使用Expect

Expect是一個自動化交互式應用程序的工具,例如telnet,f​​tp,passwd,fsck,rlogin,tip等。

你可以使用下面的代碼(從探索採取期待書)爲起點 - 它連接PROC1的輸出PROC2,反之亦然的輸入,爲你的要求:

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

這個問題類似於one我以前問過。其他人提出的解決方案是使用命名管道,但我懷疑你沒有在cygwin中使用它們。目前我堅持my own (attempt at a) solution,但它需要/dev/fd/0,你可能也沒有。

儘管我不太喜歡twinpipe(由JeeBee(139495)提到)的通過命令行作爲字符串的方面,但它可能是您在cygwin中的唯一選項。

3

我在這花了很多時間,放棄了它,最後決定使用ksh(Korn shell),它允許這樣做。

cmd1 |& cmd2 >&p <&p 

其中|&是(管道)操作者啓動一個共同加工和&p是共同加工的文件描述符。

2

我曾經有過這個問題,我把這個簡單的C程序扔在一起。

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

我建議 「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 

然後看到這個會話:

$ coproc ./dialog 
$ ./dialog test < /dev/fd/${COPROC[0]} > /dev/fd/${COPROC[1]} 
Answer to Question test is ... 
相關問題