Leif Pedersen > Proc-SafeExec-1.4 > Proc::SafeExec

Download:
Proc-SafeExec-1.4.tar.gz

Dependencies

Annotate this POD

CPAN RT

Open  0
View/Report Bugs
Module Version: 1.4   Source   Latest Release: Proc-SafeExec-1.5

NAME ^

Proc::SafeExec - Convenient utility for executing external commands in various ways.

SYNOPSIS ^

        use Proc::SafeExec;
        my $command = new Proc::SafeExec({
                # Choose just one of these.
                exec => ["ls", "-l", "myfile"],  # exec() after forking.
                fork => 1,                       # Return undef in the child after forking.

                # Specify whether to capture each.  Specify a file handle ref to dup an
                # existing one.  Specify "new" to create a new file handle, "default" or undef
                # to keep the parent's descriptor, or "close" to close it.
                stdin => \*INPUT_PIPE,
                stdout => \*OUTPUT_PIPE,
                stderr => "new",

                # Miscellaneous options.
                child_callback => \&fref,  # Specify a function to call in the child after fork(), for example, to drop privileges.
                debug => 1,  # Emit some information via warnings, such as the command to execute.
                no_autowait => 1,  # Don't automatically call $command->wait() when $command is destroyed.
                real_arg0 => "/bin/ls",  # Specify the actual file to execute.
                untaint_args => 1,  # Untaint the arguments before exec'ing.
        });
        printf "Child's PID is %s\n", $command->child_pid() if $command->child_pid();

The wait method waits for the child to exit or checks whether it already exited:

        $command->wait({
                # Optional hash of options.
                no_close => 1,  # Don't close "new" file handles.
                nonblock => 1,  # Don't wait if the child hasn't exited (implies no_close).
        });

To communicate with the child:

        # Perl doesn't understand <$command->stdout()>.
        my $command_stdout = $command->stdout();
        my $command_stderr = $command->stderr();

        $line = <$command_stdout>;
        $line = <$command_stderr>;
        print {$command->stdin()} "mumble\n";

To check whether the child exited yet:

        print "Exit status:  ", $command->exit_status(), "\n" if $command->wait({nonblock => 1});

To wait until it exits:

        $command->wait();
        print "Exit status:  ", $command->exit_status(), "\n";

A convenient quick tool for an alternative to $output = `@exec`:

        ($output, $?) = Proc::SafeExec::backtick(@exec);

DESCRIPTION ^

Proc::SafeExec provides an easy, safe way to execute external programs. It replaces all of Perl's questionable ways of accomodating this, including system(), open() with a pipe, exec(), back-ticks, etc. This module will never automatically invoke /bin/sh. This module is easy enough to use that /bin/sh should be unnecessary, even for complex pipelines.

For all errors, this module dies setting $@.

Errors from exec() in the child are reported gracefully to the parent. This means that if anything fails in the child, the error is reported through $@ with die just like any other error. This also reports $@ if child_callback dies when it is called between fork() and exec(). This is accomplished by passing $@ through an extra pipe that's closed when exec succeeds. Note: A side-effect of this is $@ is stringified if it isn't a string.

CAVEATS ^

When using an existing file handle by passing a reference for stdin, stdout, or stderr, new() closes the previously open file descriptor. This is to make sure, for example, that when setting up a pipeline the child process notices EOF on its stdin. If you need this file handle to stay open, dup it first. For example:

        open my $tmp_fh, "<&", $original_fh or die "dup:  $!";
        my $ls = new Proc::SafeExec({exec => ["ls"], stdout => $tmp_fh});
        # $tmp_fh is now closed.

By default, $command->wait() closes any new pipes opened in the constructor. This is to prevent a deadlock where the child is waiting to read or write and the parent is waiting for the child to exit. Pass no_close to $command->wait() to prevent this (see above). Also, by default the destructor calls $command->wait() if child hasn't finished. This is to prevent zombie processes from inadvertently accumulating. To prevent this, pass no_autowait to the constructor. The easiest way to wait for the child is to call the wait method, but if you need more control, set no_autowait, then call child_pid to get the PID and do the work yourself.

This will emit a warning if the child exits with a non-zero status, and the caller didn't inspect the exit status, and the caller didn't specify no_autowait (which may imply the exit status might not be meaningful). It's bad practice not to inspect the exit status, and it's easy enough to quiet this warning if you really don't want it by calling $command->exit_status() and discarding the result.

EXAMPLES ^

It's easy to execute several programs to form a pipeline. For the first program, specify "new" for stdout. Then execute the second one, and specify stdout from the first one for the stdin of the second one. For example, here's how to write the equivalent of system("ls | sort > output.txt"):

        open my $output_fh, ">", "output.txt" or die "output.txt:  $!\n";
        my $ls = new Proc::SafeExec({exec => ["ls"], stdout => "new"});
        my $sort = new Proc::SafeExec({exec => ["sort"], stdin => $ls->stdout(), stdout => $output_fh});
        $ls->wait();
        $sort->wait();
        printf "ls exited with status %i\n", ($ls->exit_status() >> 8);
        printf "sort exited with status %i\n", ($sort->exit_status() >> 8);

INSTALLATION ^

This module has no dependencies besides Perl itself. Follow your favorite standard installation procedure.

To test the module, run the following command line:

        $ perl -e 'use Proc::SafeExec; print Proc::SafeExec::test();'

VERSION AND HISTORY ^

SEE ALSO ^

The source repository is at git://git.devpit.org/Proc-SafeExec/

See also Proc::SafeExec::Queue.

AUTHOR ^

Leif Pedersen, <bilbo@hobbiton.org>

COPYRIGHT AND LICENSE ^

 This may be distributed under the terms below (BSD'ish) or under the GPL.
 
 Copyright (c) 2007
 All Rights Reserved
 Meridian Environmental Technology, Inc.
 4324 University Avenue, Grand Forks, ND 58203
 http://meridian-enviro.com
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are
 met:
 
  1. Redistributions of source code must retain the above copyright
     notice, this list of conditions and the following disclaimer.
 
  2. Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in the
     documentation and/or other materials provided with the
     distribution.
 
 THIS SOFTWARE IS PROVIDED BY AUTHORS AND CONTRIBUTORS "AS IS" AND ANY
 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL AUTHORS OR CONTRIBUTORS BE
 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
syntax highlighting: