views:

519

answers:

3

I want to set up a pipeline of processes from within Perl (running on Linux), consisting of two parts run at separate times.

Eg:

Start the consumer process:

open( OUT, "| tar xvf - " ) || die "Failed: tar: $!";

then much later start the producer process:

open( IN, "gpg -d $file |" ) || die "Failed: gpg: $!";

but then somehow redirect the output from gpg into the input to tar.

I can do this by building a loop:

while (<IN> ) {
  print OUT;
}

But I would like to know if I can somehow glue the two processes together with redirection.

+11  A: 

Add

pipe( IN, OUT );

Before the two open statements. That's it!

If you want to do anything more complicated, I would recommend the IPC::Run CPAN module:

http://search.cpan.org/dist/IPC-Run/

It lets you start processes, tie their input and outputs together, and add logging or redirection at any point in the chain.

rjh
This works beautifully for a small test script. Thanks.#! /usr/bin/perl -wpipe( IN, OUT ) || die "Failed: pipe: $!";open( OUT, "| cat -n " ) || die "Failed: cat: $!\n";open( IN, "netstat -n |" ) || die "Failed: netstat: $!";close( IN );close( OUT );
Martin
+1  A: 

If the two processes are completely unrelated, use a FIFO.

use POSIX qw(mkfifo);
mkfifo($path, 0700) or die "mkfifo $path failed: $!";

This creates a FIFO at $path. Now have one process write to that file, and the other process read from it.

rjh
+1  A: 

I like Proc::SafeExec it lets you tie together processes and file handles in almost arbitrary ways easily. Here's an example:

use strict;
use warnings;

use Proc::SafeExec;

open(my $ls, "-|", "ls", "-l") or die "Err: $!";
open(my $fh, ">", "tmp.txt") or die "Err: $!";

my $p = Proc::SafeExec->new({
  exec => [qw(sed -e s/a/b/)],
  stdin => $ls,
  stdout => $fh,
});
$p->wait();

After looking at IPC::Run, it looks a lot simpler...here's the same example using IPC::Run instead:

use IPC::Run qw(run);

run [qw(ls -l)], "|", [qw(sed -e s/a/b/)], ">", "tmp.txt";
runrig
These modules look interesting. I will look into these next week. Thanks.
Martin
Yes, I spent far too long doing things like input/output redirection, fork/exec, signal handling and PID monitoring manually until I discovered IPC::Run. (And to a lesser extent, Proc::Simple)
rjh