Notice that exec()
never returns unless it fails to start the
process. Therefore you shouldn’t put any code after exec()–it will be
not executed in the case of success. Use system()
or back-ticks
instead if you want to continue doing other things in the process.
But then you probably will want to terminate the process after the
program has finished. So you will have to write:
system "/home/httpd/perl/external.pl" or die "Cannot execute system: "; CORE::exit(0);
Another important nuance is that we have to close all STD* stream in
the forked process, even if the called program does that.
If the external program is written in Perl you may pass complicated
data stuctures to it using one of the methods to serialize Perl data
and then to restore it. The Storable
and FreezeThaw
modules come
handy. Let’s say that we have program master.pl calling program
slave.pl:
master.pl --------- # we are within the mod_perl code use Storable (); my @params = (foo => 1, bar => 2); my = Storable::freeze(@params); exec "./slave.pl", or die "Cannot execute exec: ";
slave.pl -------- #!/usr/bin/perl -w use Storable (); my @params = @ARGV ? @{ Storable::thaw(shift)||[] } : (); # do something
As you can see, master.pl serializes the @params
data structure
with Storable::freeze
and passes it to slave.pl as a single
argument. slave.pl restores the it with Storable::thaw
, by
shifting the first value of the ARGV
array if available. The
FreezeThaw
module does a very similar thing.
Starting a Short Running External Program
Sometimes you need to call an external program and you cannot continue
before this program completes its run and optionally returns some
result. In this case the fork solution doesn’t help. But we have a few
ways to execute this program. First using system():
system "perl -e 'print 5+5'"We believe that you will never call the perl interperter for doing
this simple calculation, but for the sake of a simple example it's
good enough.The problem with this approach is that we cannot get the results
printed toSTDOUT
, and that's where back-ticks orqx()
come to
help. If you use either:my = 'perl -e 'print 5+5'';or:
my = qx{perl -e 'print 5+5'};the whole output of the external program will be stored in the
variable.
Of course you can use other solutions, like opening a pipe (
|
to
the program) if you need to submit many arguments and more evolved
solutions provided by other Perl modules likeIPC::Open2
which
allows to open a process for both reading and writing.Executing
system()
orexec()
in the Right WayThe
exec()
andsystem()
system calls behave identically in the way
they spawn a program. For example, let's usesystem()
as an
example. Consider the following code:system("echo","Hi");Perl will use the first argument as a program to execute, find
/bin/echo
along the search path, invoke it directly and pass the
Hi string as an argument.