bash 如何将第二个进程的标准输出重定向回第一个进程的标准输入?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5129276/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 23:31:42  来源:igfitidea点击:

how to redirect stdout of 2nd process back to stdin of 1st process?

bashshellpipe

提问by Adrian Herscu

I have two processes which I need to connect like this:

我有两个进程需要像这样连接:

proc1 -- sends output to proc2 proc2 -- sends output to proc1

proc1 -- 将输出发送到 proc2 proc2 -- 将输出发送到 proc1

So far, all pipe examples are of this kind: proc1 | proc2

到目前为止,所有管道示例都属于这种类型: proc1 | 进程2

That's nice, but how do I make the output of proc2 go to proc1?

这很好,但是如何使 proc2 的输出转到 proc1?

A bash example would be nice. A Windows shell example would be great :)

一个 bash 示例会很好。Windows shell 示例会很棒:)

Thanks in advance, Adrian.

提前致谢,阿德里安。

Adding more details:

添加更多细节:

The system is expected to work as client-server system in which the client works with the server in a request-response interaction model. The interaction ends when the client has no more requests.

该系统预期作为客户端-服务器系统工作,其中客户端在请求-响应交互模型中与服务器一起工作。当客户端没有更多请求时,交互结束。

Interaction example: client: request1; server: response1; client: request2; server: response2; . . . . client: closeRequest; server: closeApproved;

交互示例:客户端:request1;服务器:响应1;客户:请求2;服务器:响应2;. . . . 客户端:关闭请求;服务器:closeApproved;

At this point the server exits following a client exit. End of example.

此时服务器在客户端退出后退出。示例结束。

It seems that a solution like (assuming pipe is available) client < pipe | server > pipe would not work (please correct me) because in this arrangement the client produces one big request, the shell pipes this big request to the server, then the server produces one big response, and finally the shell pipes this big response to the client.

似乎有一个解决方案(假设管道可用) client < pipe | 服务器 > 管道不起作用(请纠正我),因为在这种安排中,客户端产生一个大请求,外壳将这个大请求通过管道传送到服务器,然后服务器产生一个大响应,最后外壳将这个大响应传送到客户。

回答by Pa?lo Ebermann

It looks like a bash coprocessmay be what you want. Look up the coprocreserved word in the bash manual.

看起来 bash协进程可能正是您想要的。coproc在 bash 手册中查找保留字。



(Edit: adding simple usage scheme)

(编辑:添加简单的使用方案)

It works like this:

它是这样工作的:

# start first process as a coprocess to the current shell
coproc proc1

# now ${COPROC[0]} contains the number of an open (input) file descriptor
# connected to the output of proc1, and ${COPROC[1]} the number of an
# open (output) file descriptor connected to the input of proc1.


# start second process, connecting its input- and outputstreams
# to the output- and inputstreams of the first process
proc2 <&${COPROC[0]} >&${COPROC[1]}

# wait on the first process to finish.
wait $COPROC_PID

If you may have multiple coprocesses, give your process a name like this:

如果您可能有多个协进程,请为您的进程命名如下:

coproc NAME {
    proc1
}

Then you can use NAMEwherever COPROCwas used before.

然后你可以使用以前使用过的NAME任何地方COPROC



Here is a complete example program using a pingfunction as proc1 and proc2:

这是一个完整的示例程序,它使用了pingproc1 和 proc2 函数:

#!/bin/bash
#
# Example program using a bash coprocess to run two processes
# with their input/output streams 
#


#
# A function which reads lines of input and
# writes them back to standard output with the
# first char cut off, waiting 5s inbetween.
#
# It finishes whenever an empty line is read or written,
# or at end-of-file.
#
# The parameter  is used in debugging output on stderr.
#
function ping ()
{
    while read 
    do
        local sending
        echo "ping : received '$REPLY'" >&2
        [[ -n $REPLY ]] || break
        sleep 5s
        sending=${REPLY:1}
        echo "ping : sending '$sending'"  >&2
        echo $sending
        [[ -n $sending ]] || break
    done
    echo "ping : end" >&2
}

#
# Start first ping process as a coprocess with name 'p1'.
#

coproc p1 {
    ping 1
}

# send some initial data to p1. (Not needed if one of the processes
# starts writing before first reading.)
echo "Hello World" >&${p1[1]}
sleep 2.5s

#
# Run second ping process, connecting its default input/output
# to the default output/input of p1.
# 
ping 2 <&${p1[0]} >&${p1[1]}

# wait for the coprocess to finish too.
wait $p1_PID

It uses two invocations of a shell function instead of external programs, but it would work with such programs too. Here is the output (on stderr):

它使用 shell 函数的两次调用而不是外部程序,但它也适用于此类程序。这是输出(在 stderr 上):

ping 1: received 'Hello World'
ping 1: sending 'ello World'
ping 2: received 'ello World'
ping 2: sending 'llo World'
ping 1: received 'llo World'
ping 1: sending 'lo World'
ping 2: received 'lo World'
ping 2: sending 'o World'
ping 1: received 'o World'
ping 1: sending ' World'
ping 2: received 'World'
ping 2: sending 'orld'
ping 1: received 'orld'
ping 1: sending 'rld'
ping 2: received 'rld'
ping 2: sending 'ld'
ping 1: received 'ld'
ping 1: sending 'd'
ping 2: received 'd'
ping 2: sending ''
ping 2: end
ping 1: received ''
ping 1: end

回答by codecraft

here is a bash example using echo to provide some initial input and a named pipeto allow for the feedback loop:

这是一个使用 echo 提供一些初始输入和命名管道以允许反馈循环的 bash 示例:

mkfifo fifo
echo "fifo forever" | cat - fifo | tee fifo
  • proc1 (cat) takes input from stdin and fifo
  • proc2 (tee) passes output to stdout and fifo
  • proc1 (cat) 从 stdin 和 fifo 获取输入
  • proc2 (tee) 将输出传递给 stdout 和 fifo

回答by cprcrack

This is an example showing what you want, with two processes that both take one argument:

这是一个显示您想要的示例,其中两个进程都采用一个参数:

mkfifo fifo
./process1 argument1 < fifo | ./process2 argument1 > fifo

First we create a named pipe called fifoin the current directory. Then we execute process1with fifoas input, whose output will go through the anonymous pipe |to the input of process2, whose output will go to fifo, closing the loop.

首先我们创建一个fifo在当前目录中调用的命名管道。然后我们执行process1withfifo作为输入,其输出将通过匿名管道|到达 的输入process2,其输出将转到 ,从而fifo关闭循环。

After exiting both processes you should delete the pipe, just the same way you delete a regular file:

退出两个进程后,您应该删除管道,就像删除常规文件一样:

rm fifo

回答by bobah

#!/bin/bash

fifo=$(/bin/mktemp -u)
/usr/bin/mkfifo $fifo

# register resources cleanup trap
trap "/bin/unlink $fifo" INT TERM EXIT

# start a background shell redirecting its output to the pipe
(for ((i=0; i < 5; ++i)); do echo "pam pam, i = $i"; sleep 1; done ) 1> $fifo&

# read the output of the background shell from the pipe
while read line 0< $fifo; do
  echo "param $line"
done

# wait for child process to terminate
wait

回答by Quentin Smith

Most shells make this hard to do, for good reason - it's very easy to get your programs deadlocked, where each is waiting for input from the other. Can you tell us more about what information you're trying to pass around? If you are just trying to make an RPC-like system, you should probably use a library that's designed for that.

大多数 shell 很难做到这一点,这是有充分理由的 - 很容易让您的程序陷入死锁,其中每个都在等待另一个的输入。你能告诉我们更多关于你试图传递什么信息的信息吗?如果您只是想制作一个类似 RPC 的系统,您可能应该使用专为此设计的库。