在shell / bash中的两个命令之间连接输入和输出

时间:2020-03-06 14:47:01  来源:igfitidea点击:

我有两个(UNIX)程序A和B,它们从stdin / stdout读取和写入。

我的第一个问题是如何将A的标准输出连接到B的标准输入,以及如何将B的标准输出连接到A的标准输入。 B但是双向管道。我怀疑我可以通过使用exec重定向来解决此问题,但我无法使其正常工作。这些程序是交互式的,因此临时文件将不起作用。

第二个问题是我想复制每个方向,并通过日志记录程序将重复的内容通过管道传送到stdout,以便我可以看到在程序之间传递的(基于文本行的)流量。如果可以解决第一个问题,在这里我可以不考虑tee>(...)。

这两个问题似乎都应该有众所周知的解决方案,但我什么也找不到。

我希望使用POSIX Shell解决方案,或者至少可以在cygwin的bash中运行的解决方案。

感谢回答,我提出了以下解决方案。 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

现在,将在shell 2中输入的行写入shell 3,反之亦然,并将流量记录到shell 1,如下所示:

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

上面已经在Cygwin上测试过

更新:几天后(!),以上脚本停止工作。显然,它可能会陷入僵局。答案中的某些建议可能更可靠。

解决方案

http://bisqwit.iki.fi/source/twinpipe.html

我们可能可以摆脱命名管道的困扰:

mkfifo pipe
gawk '' < pipe | gawk '' > pipe

命名管道怎么样?

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

对于第二部分,我相信tee是正确的答案。这样就变成了:

# A < foo | tee logfile | B > foo

我们可以使用Expect。

Expect is a tool for automating interactive applications such as telnet, ftp, passwd, fsck, rlogin, tip, etc.

我们可以根据需要使用以下代码(从Exploring Expect书中获取)作为起点,将proc1的输出连接到proc2的输入,反之亦然:

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

这个问题类似于我之前问过的问题。其他人提出的解决方案是使用命名管道,但我怀疑我们在cygwin中没有这些管道。目前,我坚持使用自己的解决方案,但是它需要/ dev / fd / 0,我们可能也没有。

尽管我不太喜欢twinpipe的字符串传递方式(由JeeBee(139495)提及),但它可能是cygwin中的唯一选择。

我花了很多时间,放弃了它,最后决定使用ksh(Korn shell),它允许这样做。

cmd1 |& cmd2 >&p <&p

其中," |&"是启动协同处理的(管道)运算符,而"&p"是该协同处理的文件描述符。