Tacet
Tacet

Reputation: 1421

Two way communication with process

I have given some compiled program. I want to communicate with it from my bash script by program stdin and stdout. I need two way communication. Program cannot be killed between exchange of information. How I can do that? Simple example:

Let that program be compiled partial summation (C++) and script results will be squares of that sums. Program:

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

My script should looks like that:

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

If in program I have for(int i = 1; i <= 4; ++i), then I can do something like that:

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

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

For more look here. From the other hand, if in program I have std::cout << sum * sum;, then solution could be:

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

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

My problem is two way communication with other process / program. I don't have to use exec. I cannot install third party software. Bash-only solution, without files, will be nice.

If I run other process, it will be nice to know pid to kill that at the end of script.

I think about communication with two or maybe three processes in the future. Output of firs program may dependents on output of second program and also in second side. Like communicator of processes.

However, I cannot recompile programs and change something. I have only stdin and stdout communication in programs.

Upvotes: 3

Views: 1254

Answers (2)

ymonad
ymonad

Reputation: 12090

If you have bash which is newer than 4.0, you can use coproc.

However, don't forget that the input/output of the command you want to communicate might be buffered.

In that case you should wrap the command with something like stdbuf -i0 -o0

Reference: How to make output of any shell command unbuffered?

Here's an example

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

output will be

1
3
6

If your bash is older than 4.0, using mkfifo can do the same thing like:

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

Upvotes: 4

Some programmer dude
Some programmer dude

Reputation: 409176

Considering that your C++ program reads from standard output, and prints to standard output, it's easy to put it inside a simple chain of pipes:

command_that_writes_output | your_cpp_program | command_that_handle_output

In your specific case you probably need to modify the program to only handle one single input and writing one single output, and remove the loop. Because then you can do it very simple, like this:

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

Upvotes: 1

Related Questions