简体   繁体   English

如何使两个程序使用std io通信?

[英]How to have two programs communicate using std io?

I have two different programs A and B. Both the programs take user input from stdin and output to stdout. 我有两个不同的程序A和B。这两个程序都将用户输入从stdin输入到stdout。 How can I have the programs talk to each other? 我如何让程序互相对话? ie i want program A to use B as it's stdout and stdin and program B to take A's output as stdin and give it's own output to A. 即我希望程序A使用B作为标准输出和标准输入,程序B将A的输出作为标准输入并将其自己的输出提供给A。

I can't seem to figure out how i can do it using Linux pipelines. 我似乎无法弄清楚如何使用Linux管道做到这一点。

I'm using bash. 我正在使用bash。 I want a solution which doesn't involve creating another program or modifying any of the existing ones. 我想要一个不涉及创建另一个程序或修改任何现有程序的解决方案。

socat lets you relay I/O from anything to anything else and back, including between two programs: socat使您可以将I / O从任何东西中继到其他任何东西,包括两个程序之间:

$ cat a
#!/bin/bash -e
var="World"
echo "$var"
echo "a wrote '$var'" >&2
read -r var
echo "a read '$var'" >&2

$ cat b
#!/bin/bash -e
read -r var
echo "b read '$var'" >&2
echo "Hello $var"
echo "b replied" >&2

$ chmod +x a b

$ socat exec:./a exec:./b
b read 'World'
b replied
a wrote 'World'
a read 'Hello World'

Note that it is your responsibility to avoid deadlocks by ensuring that both programs flush their buffers appropriately. 请注意,您有责任通过确保两个程序都适当地刷新其缓冲区来避免死锁。

If you eg replace exec:./b with exec:rev , you will cause a deadlock because most standard tools will buffer output to pipes by default. 如果将exec:./b替换为exec:rev ,则会导致死锁,因为大多数标准工具默认都会将输出缓冲到管道中。

i want program A to use B as it's stdout and stdin and program B to take A's output as stdin and give it's own output to A. 我希望程序A使用B作为标准输出和标准输入,程序B将A的输出作为标准输入并将其自己的输出提供给A。

Create two fifos and run A | B 创建两个fifos并运行A | B A | B in background, but connect input to A from a fifo and output from B to a fifo. A | B在后台,但将输入从fifo连接到A,将输出从b连接到fifo。 Then connect fifos together with cat: 然后将fifos与cat连接在一起:

fifoAin=$(mktemp -u)
fifoBout=$(mktemp -u)
mkfifo "$fifoAin" "$fifoBout"
A < "$fifoAin" | B > "$fifoBout" &
cat < "$fifoBout" > "$fifoAin"

The following, although looks cool, will not(!) work, because cat will block on file descriptor: 以下内容虽然看起来很酷,但却无法使用(!),因为cat将阻止文件描述符:

exec 3<> <(A | B)
cat <&3 >&3

Example with comments: 带有注释的示例:

# output 1
# then read number and if a number is greater then 20
# output the number on stderr and exit
# otherwise add to number 3 and output
A() {
  echo 1
  while read n; do
    if ((n > 20)); then
      echo "Answer: $n" >&2
      break;
    fi
    echo "$((n + 3))"
  done
}


# read a number and output the number multiplied by 2
B() {
  while read n; do
    echo "$((n * 2))"
  done
}

# the code
fifoAin=$(mktemp -u)
fifoBout=$(mktemp -u)
mkfifo "$fifoAin" "$fifoBout"
A < "$fifoAin" | B > "$fifoBout" &
cat < "$fifoBout" > "$fifoAin"

Will output on stderr: 将在stderr上输出:

Answer: 26

It may be worth thinking about what you need to achieve and the best way to do that. 可能值得考虑您需要实现的目标以及实现此目标的最佳方法。

You have a problem with the current software. 您当前的软件有问题。 The solution (pseudo code) (A || B) && (B || A) is difficult to achieve properly, even with bash . 即使使用bash ,也很难正确地实现解决方案(伪代码)(A || B)&&(B || A)。 There may well be easier, cleaner solutions. 可能会有更简单,更清洁的解决方案。 Such as removing dependencies between A and B, or modifying the software so that A depends on B, or vice versa. 例如删除A和B之间的依赖关系,或修改软件以使A依赖B,反之亦然。

For example if B depended solely on the output of A, all that is needed is connect A and B with a pipe, and the data streams from A to B: 例如,如果B仅依赖于A的输出,则所需要做的就是用管道将A和B连接起来,以及从A到B的数据流:

A || B

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM