2016-05-30 97 views
2

我已經給出了一些編譯好的程序。我想通過程序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通信。

+0

我想你的C++程序應該支持POSIX管道。檢查這個答案http://stackoverflow.com/a/2789967/524743 – Samuel

+0

重定向(使用'>'或'<')不起作用。你想要的是絕對*管道*。 –

+0

@Samuel謝謝你的回答。如果我可以編輯Cpp程序,那麼我知道如何在兩個進程之間進行通信。但是重新編譯程序並改變它是不可能的。我在程序中只有stdin和stdout通信。 – Tacet

回答

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

考慮到你的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 
+0

非常感謝您的回答,但是在第二個給我的程序依賴者的早期輸出的程序或者其他程序輸出中,第二個數字沒有簡化,所以我不能這樣做。 – Tacet

+0

@Tacet然後繼續管道鏈?這就是POSIX世界如何將一個程序的輸出鏈接到另一個程序的輸入。 –