"Perl for Perl Newbies" - Part 4Executing Other Processesopen() for Command Execution

4.3. open() for Command Execution

The opencommand can be used for command execution. By prefixing the filename with a pipe ( |), the rest of it is interpreted as a command invocation, which accepts standard input by printing to the filehandle, and is executed after the filehandle is closed. If the last character is a pipe, then the command is executed and its standard output is fed into the filehandle where it can be read using Perl's file input mechanisms.

Here are some examples:

#!/usr/bin/perl

use strict;
use warnings;

open
my
$in,
"/sbin/ifconfig |";

my (
@addrs);

while (
my
$line = <
$in>)
{

if (
$line =~
/
inet addr:
((\d+\.)+\d)
/)
    {

push
@addrs,
$1;
    }
}
close(
$in);

print
"You have the following addresses: 
\n
",
join(
"
\n
",
@addrs),
"
\n
";

#!/usr/bin/perl

use strict;
use warnings;

# Send an E-mail to myself
# Note: this is just an example - there are modules to do this on CPAN.

open
MAIL,
"|/usr/sbin/sendmail shlomif
\@
shlomifish.org";
print
MAIL
"To: Shlomi Fish <shlomif
\@
shlomifish.org>
\n
";
print
MAIL
"From: Shlomi Fish <shlomif
\@
shlomifish.org>
\n
";
print
MAIL
"
\n
";
print
MAIL
"Hello there, moi!
\n
";
close(
MAIL);

Pipe to @args

Recent versions of Perl also have a syntax that allows opening a process for input or output using its command line arguments. These are:

open my $print_to_process, "|-", $cmd, @args;
print {$print_to_process} ...;

and:

open my $read_from_process, "-|", $cmd, @args;
while (my $line = <$read_from_process>)
{
.
.
.
}

Doing something like open my $print_to_process, "|-", "sendmail", $to_address;is safer than doing: open my $print_to_process, "|-", "sendmail $to_address";Because a malicious person may put some offending shell characters in $to_addressand end up with something like:

sendmail ; rm -fr $HOME

Written by Shlomi Fish