http://www.perlmonks.org?node_id=31831

Item Description: Open a process for reading, writing, and error handling

Review Synopsis: Very useful for fine-tuned control of launching processes

A basic Unix process starts life with a default place to read data from the outside world (STDIN), a default place to write data (STDOUT), a basic place to write errors to (STDERR), and some parent process who hopefully will be interested in how you died and will catch your return code (0 by default unless you exit or die).

Perl has many ways of starting processes. The most common are the following:

  1. system: This launches a process which will use your STDIN, STDOUT, STDERR, and returns you the return code. In the process the special variables $! and $? will be set.
  2. Backticks: This launches a process which will use your STDIN and STDERR, but which will return STDOUT to you and throw away the return code.
  3. open(CMD, "| $cmd"): Open a process which you can write to the STDIN of, which uses your STDOUT and STDERR. The return of open is the process ID. You can collect the return with wait or waitpid.
  4. open(CMD, "$cmd |"): Open a process which you can read STDOUT from, which uses your STDOUT and STDERR. Essentially the same as backticks but you can start processing the data interactively. (This can matter a lot if the command returns large amounts of data.) The return of open is the process ID. You can collect the return with wait or waitpid.
This should suffice for most purposes. (See perlipc for more on inter-process communication.) But from time to time you need more control. That is where IPC::Open3 becomes useful.

IPC::Open3 exports a function, open3. This allows you to start a command and choose what it gets for STDIN, STDOUT, and STDERR. For instance you might hand it for STDIN a filehandle reading from /dev/null to supress any attempts on its part to interact. You might want to keep track of STDERR for error reporting. Anything you want.

As with open, open3 returns the process ID. When the program should have exited you can then call wait or waitpid, check that you collected the right child, then look at $? for the return value.

For an example of real use of this, see Run commands in parallel. Another useful example that would make a good exercise is to write a function to run a process and surpresses all output unless the return-code is not zero in which case it prints an error message with information on the command, the return code, and what was printed to STDERR. (I use something like this for cron jobs.)