views:

73

answers:

3

Using PHP's proc_open(), I can start a process, read from STDOUT and STDERR (separately) an arbitrary number of bytes at a time using fread() while the process is running, detect when the process is done using feof() on the STDOUT and STDERR pipes, and then use proc_close() to get the exit code of the process. I've done all of this in PHP. It works well, and gives me a lot of control.

Is there a way to do all of these things in Perl? To summarize, I need to be able to do the following:

  • start an external process
  • read STDOUT and STDERR separately
  • read STDOUT and STDERR an arbitrary number of bytes at a time while the process is running (i.e. without having to wait for the process to finish)
  • detect when the process is finished
  • get the exit code of the process

Thanks in advance for your answers.

+2  A: 

You want this module: IPC::Open3

ennuikiller
Thanks for the push in the right direction (that's all I really needed). Although, I found this example to be more helpful (and more relevant to my situation) than the one on perldoc: http://docstore.mik.ua/orelly/perl/prog3/ch32_31.htm
Jonathan R
+4  A: 

You could roll your own solution using Perl's system call interface, but it's easier to use the built-in module IPC::Open3. As for your list:

Start an external process:

use IPC::Open3;
use IO::Handle;
use strict;

my $stdout = IO::Handle->new;
my $stderr = IO::Handle->new;
my $pid = open3(undef, $stdout, $stderr, 'my-command', 'arg1', 'arg2');

Read STDOUT and STDERR separately, an arbitrary number of bytes at a time:

my $line = <$stdout>;
# Or
sysread $stderr, my $buffer, 1024;

Detect when the process is finished:

use POSIX qw(sys_wait_h);

waitpid $pid, 0;  # Waits for process to terminate
waitpid $pid, WNOHANG;  # Checks if the process has terminated

Get the exit code of the process:

my $status = $?;  # After waitpid indicates the process has exited

Be sure to read the IPC::Open3 documentation; as it warns, it's easy to get yourself deadlocked when you have separate stdout and stderr pipes, if you're not careful. If the child process fills either pipe, it will block, and if the parent process reads the other pipe, it will block.

Sean
+1  A: 

You want IPC::Run, it captures the IO and returns the exit value