与流程进行双向沟通

时间:2016-05-30 07:20:36

标签: linux bash

我已经给了一些编译程序。我想通过程序stdin和stdout从我的bash脚本与它进行通信。我需要双向沟通。程序不能在交换信息之间被杀死。我怎么能这样做? 简单的例子:

让程序编译为部分求和(C ++),脚本结果将是该求和的平方。程序:

int main() {
    int num, sum = 0;
    while(true) {
        std::cin >> num;
        sum += num;
        std::cout << sum << std::endl;
    }
}

我的脚本应该是这样的:

for i in 1 2 3 4; do
    echo "$i" > program
    read program to line;
    echo $((line * line))
done

如果在程序中我有for(int i = 1; i <= 4; ++i),那么我可以做类似的事情:

 
exec 4< <(./program); # Just read from program

for i in 1 2 3 4; do
    read <&4 line;
    echo "sh: $((line * line))";
done

了解更多here。另一方面,如果在程序中我有std::cout << sum * sum;,那么解决方案可能是:

 
exec &3> >(./program); # Write to program

for i in 1 2 3 4; do
    echo "$i" > &3
done

我的问题是与其他流程/程序的双向沟通​​。我不必使用exec。我无法安装第三方软件。只有Bash的解决方案,没有文件,会很好。

如果我运行其他进程,那么在脚本结束时知道pid来杀死它会很好。

我考虑将来与两个或三个流程进行沟通。第一个项目的输出可以依赖于第二个项目的输出,也可以依赖于第二个项目的输出。就像流程的沟通者一样。

但是,我不能重新编译程序并改变一些东西。我在程序中只有stdin和stdout通信。

2 个答案:

答案 0 :(得分:3)

如果你的bash比4.0更新,你可以使用coproc

但是,不要忘记您要通信的命令的输入/输出可能是缓冲的。

在这种情况下,您应该使用stdbuf -i0 -o0

之类的命令包装命令

参考:How to make output of any shell command unbuffered?

这是一个例子

#!/bin/bash
coproc mycoproc {
  ./a.out # your C++ code
}
# input to "std::cin >> num;"
echo "1" >&${mycoproc[1]}
# get output from "std::cout << sum << std::endl;"
# "-t 3" means that it waits for 3 seconds
read -t 3 -u ${mycoproc[0]} var 
# print it
echo $var

echo "2" >&${mycoproc[1]}
read -t 3 -u ${mycoproc[0]} var
echo $var

echo "3" >&${mycoproc[1]}
read -t 3 -u ${mycoproc[0]} var
echo $var

# you can get PID
kill $mycoproc_PID

输出

1
3
6

如果您的bash高于4.0,则使用mkfifo可以执行相同的操作:

#!/bin/bash
mkfifo f1 f2
exec 4<> f1
exec 5<> f2
./a.out < f1 > f2 &

echo "1" >&4
read -t 3 -u 5 var
echo $var

rm f1 f2

答案 1 :(得分:1)

考虑到你的C ++程序从标准输出读取并打印到标准输出,很容易将它放在一个简单的管道链中:

command_that_writes_output | your_cpp_program | command_that_handle_output

在您的特定情况下,您可能需要修改程序以仅处理一个输入并写入一个输出,并删除循环。因为那时你可以很简单地做到这一点:

for i in 1 2 3 4; do
    result=`echo $i | ./program`
    echo $((result * result))
done