Reading or Writing to Another Program (Perl Cookbook, 2nd Edition)

## 16.4. Reading or Writing to Another Program

### 16.4.1. Problem

You want to run another program and either read its output or supply the program with input.

### 16.4.2. Solution

Use `open` with a pipe symbol at the beginning or end. To read from a program, put the pipe symbol at the end:

>     $pid = open $readme, "-|", "program", "arguments"
>                                                 or die "Couldn't fork: $!\n";
>     while (<$readme>) {
>         # ...
>     }
>     close $readme                               or die "Couldn't close: $!\n";

To write to the program, put the pipe at the beginning:

>     $pid = open $writeme, "|-", "program", "arguments"
>                                                 or die "Couldn't fork: $!\n";
>     print $writeme "data\n";
>     close $writeme                              or die "Couldn't close: $!\n";

### 16.4.3. Discussion

In the case of reading, this is similar to using backticks, except you have a process ID and a filehandle, and the shell is never involved. If you want Perl to use the shell when it sees shell-special characters in its argument—for example, to let the shell do filename wildcard expansion and I/O redirection—then you must use the two-argument form of `open`:

>     open($writeme, "| program args");
>     open($readme, "program args |");

However, sometimes this isn't desirable. Piped `open` s that include unchecked user data would be unsafe while running in taint mode or in untrustworthy situations.

Notice how we specifically call `close` on the filehandle. When you use `open` to connect a filehandle to a child process, Perl remembers this and automatically waits for the child when you close the filehandle. If the child hasn't exited by then, Perl waits until it does. This can be a very, very long wait if your child doesn't exit:

>     $pid = open $f, "-|", "sleep", "100000";  # child goes to sleep
>     close $f;                                 # and the parent goes to lala land

To avoid this, you can save the PID returned by `open` to kill your child, or use a manual `pipe`-`fork`-`exec` sequence as described in Recipe 16.10.

If you attempt to write to a process that has gone away, your process will receive a `SIGPIPE`. The default disposition for this signal is to kill your process, so the truly paranoid install a `SIGPIPE` handler just in case.

If you want to run another program and be able to supply its `STDIN` yourself, a similar construct is used:

>     $pid = open $writeme, "|-", "program", "args";
>     print $writeme "hello\n";            # program will get hello\n on STDIN
>     close $writeme;                      # program will get EOF on STDIN

The second argument to `open` ("`|-`") tells Perl to start another process instead. It connects the `open` ed filehandle to the process's `STDIN`. Anything you write to the filehandle can be read by the program through its `STDIN`. When you `close` the filehandle, the `open` ed process will get `EOF` when it next tries to read from `STDIN`.

You can also use this technique to change your program's normal output path. For example, to automatically run everything through a pager, use something like:

>     $pager = $ENV{PAGER} || '/usr/bin/less';  # XXX: might not exist
>     open(STDOUT, "|-", $pager);

Now, without changing the rest of your program, anything you print to standard output will go through the pager automatically.

As before, the parent should also be wary of `close`. If the parent closes the filehandle connecting it to the child, the parent will block while waiting for the child to finish. If the child doesn't finish, neither will the close. The workaround as before is to either kill your child process prematurely, or else use the low-level `pipe`-`fork`-`exec` scenario.

When using piped opens, always check return values of both `open` and `close`, not just of `open`. That's because the return value from `open` does not indicate whether the command was successfully launched. With a piped open, you fork a child to execute the command. Assuming the system hasn't run out of processes, the `fork` immediately returns the PID of the child it just created.

By the time the child process tries to `exec` the command, it's a separately scheduled process. So if the command can't be found, there's effectively no way to communicate this back to the `open` function, because that function is in a different process!

Check the return value from `close` to see whether the command was successful. If the child process exits with non-zero status—which it will do if the command isn't found—the `close` returns false and `$?` is set to the wait status of that process. You can interpret its contents as described in Recipe 16.19.

In the case of a pipe opened for writing, you should also install a `SIGPIPE` handler, since writing to a child that isn't there will trigger a `SIGPIPE`.

### 16.4.4. See Also

The `open` function in Chapter 29 of Programming Perl, and in perlfunc(1); Recipe 16.10; Recipe 16.15; Recipe 16.19; Recipe 19.5

Copyright © 2003 O'Reilly & Associates. All rights reserved.