durandaltheta durandaltheta - 1 year ago 166
Bash Question

How to write bash output to arbitrary program stdin

I want to (hopefully easily) write from a bash script to any arbitrary program that is already running via that program's stdin.

Say I have some arbitrary program "Sum", that constantly takes user input from the terminal. Every integer it receives from stdin it adds to the current sum and outputs the new sum. Here's example terminal text of what I mean:

$: ./Sum
Sum: 0
Give me an integer: 2
Sum: 2
Give me an integer: 5
Sum: 7

How would automate this process in a bash script? If I had control of Sum's source code I could let it accept integer arguments. But if I don't have said control of the program, how can I automate the interaction with Sum? Here's a psuedo code of a bash snippet of what I want to do:

In example.sh:

my_program_input_point=./Sum &
echo 2 > my_program_input_point
echo 5 > my_program_input_point

Thus on my terminal screen it would still look like this:

$: ./example.sh
Sum: 0
Give me an integer: 2
Sum: 2
Give me an integer: 5
Sum: 7

The difference is I wouldn't have typed any of it.

It feels like this task should be really easy, because basically anything you can do in a terminal, you can also easily do in a script. Except, apparently, directly interact with an arbitrary process once its started.

This topic answers some aspects of my question by using pipes. However the accepted answer only works if I have control of both programs on each side of the pipe, the "recipient" program is under no obligation to read from the pipe automatically.

This is assuming I can't modify the program/script in question. I also can't write a "pipe reader" script to wrap around the program (Sum), because that wrapper script would still be required to interact with the running process Sum.

The second answer to this question on serverfault.com (written by jfgagne) seems much closer, but I can't seem to get it working. Is there any easier way to do this that I just don't know about?

Answer Source

You can use a named pipe. Whatever starts Sum is responsible for creating the named pipe some place convenient, then starting Sum with the named pipe as its standard input.

mkfifo /tmp/pipe
Sum < /tmp/pipe

Then your script could take the name of the pipe as an argument, then treat it as a file it can write to.


echo 2 > "$p"
echo 5 > "$p"

Then you could call your script with client /tmp/pipe.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download