2016-05-30 8 views
2

私はいくつかのコンパイルされたプログラムを与えました。私はプログラムstdinとstdoutでbashスクリプトからそれと通信したい。私は双方向コミュニケーションが必要です。情報交換の間にプログラムを殺すことはできません。私はそれをどのようにすることができますか? 簡単な例:プロセスと双方向通信

このプログラムを部分集計(C++)でコンパイルし、スクリプト結果をその合計の2乗にします。プログラム:

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

私のスクリプトはそのように見えるはずです。もっと見hereについて

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

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

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)を持っている場合は、私はそのような何かを行うことができます。一方からは、プログラムの中で、私はstd::cout << sum * sum;を持っている場合、その解決策は次のようになります。

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

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

私の問題は、他のプロセス/プログラムとの双方向通信です。私はエグゼクティブを使う必要はありません。私はサードパーティのソフトウェアをインストールすることはできません。ファイルのないBash専用のソリューションは素晴らしいでしょう。

私は他のプロセスを実行すると、スクリプトの最後にpidを殺すことを知ってうれしいです。

今後2つのプロセス、あるいは3つのプロセスとの通信を考えます。 firsプログラムの出力は、第2プログラムの出力に依存してもよく、第2プログラムの出力に依存してもよい。プロセスのコミュニケータと同様。

しかし、私はプログラムを再コンパイルして何かを変更することはできません。私は、プログラムでは標準と標準コミュニケーションしか持っていません。

+0

あなたのC++プログラムはPOSIXパイプをサポートしているはずです。この回答を確認してくださいhttp://stackoverflow.com/a/2789967/524743 – Samuel

+0

リダイレクション( '>'や '<を使用)は、そのようには動作しません。あなたが欲しいのは間違いなくパイプ*です。 –

+0

@Samuelあなたの答えに感謝します。私がCppプログラムを編集できるのであれば、私は2つのプロセス間の通信方法を知っています。しかし、プログラムを再コンパイルして変更することは不可能です。私はプログラムの中でstdinとstdoutのコミュニケーションしか持っていません。 – Tacet

答えて

3

あなたが4.0よりも新しいbashのを持っている場合は、coprocを使用することができます。そして、あなたはこのように、それは非常にシンプル行うことができますので。

ただし、通信したいコマンドの入出力がバッファされている可能性があることを忘れないでください。その場合

あなたはstdbuf -i0 -o0

リファレンスのようなものを使用して、コマンドをラップする必要があります。ここでは、あなたのbashの場合

#!/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 

になります例ですHow to make output of any shell command unbuffered?

4歳以上です。0の場合、を使用すると、次のようなことができます。

#!/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

あなたのC++プログラムは、標準出力に標準出力、および印刷物から読み込み、それがパイプの簡単な連鎖の中に置くのは簡単だということを考慮すると:あなたはおそらくする必要があり、あなたの特定のケースで

command_that_writes_output | your_cpp_program | command_that_handle_output 

1つの単一入力のみを処理し、1つの出力を書き込むようにプログラムを修正し、ループを削除します。

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

あなたの答えはありがたいですが、私の単純化していない問題の2番目の数字は、プログラムの以前の出力や他のプログラムの出力に依存しているので、そのようにはできません。 – Tacet

+0

@Tacetその後、パイプのチェーンを続けますか?これは、あるプログラムから別のプログラムへの出力をPOSIX世界で連鎖させる方法です。 –

関連する問題