![]() |
Practical mod_perl / HTML Book / | ![]() |
||
![]() |
||||
![]() |
![]() |
|||
![]() |
![]() |
|||
![]() |
||||
|
|
||||
![]() |
![]() |
|||
![]() |
10.2.6. Starting a Long-Running External Program |
![]() |
||
![]() |
||||
![]() |
![]() |
![]() |
||
![]() |
||||
What happens if we cannot just run Perl code from the spawned process? We may have a compiled utility, such as a program written in C, or a Perl program that cannot easily be converted into a module and thus called as a function. In this case, we have to use system( ), exec( ), qx( ) or `` (backticks) to start it.
When using any of these methods, and when taint mode is enabled, we must also add the following code to untaint the PATH environment variable and delete a few other insecure environment variables. This information can be found in the perlsec manpage.
$ENV{'PATH'} = '/bin:/usr/bin';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
Now all we have to do is reuse the code from the previous section.
First we move the core program into the external.pl file, then we add the shebang line so that the program will be executed by Perl, tell the program to run under taint mode (-T), possibly enable warnings mode (-w), and make it executable. These changes are shown in Example 10-20.
#!/usr/bin/perl -Tw open STDIN, '/dev/null' or die "Can't read /dev/null: $!"; open STDOUT, '>/dev/null' or die "Can't write to /dev/null: $!"; open STDERR, '>/tmp/log' or die "Can't write to /tmp/log: $!"; my $oldfh = select STDERR; local $| = 1; select $oldfh; warn "started\n"; # do something time-consuming sleep 1, warn "$_\n" for 1..20; warn "completed\n";
Now we replace the code that we moved into the external program with a call to exec( ) to run it, as shown in Example 10-21.
use strict;
use POSIX 'setsid';
use Apache::SubProcess;
$ENV{'PATH'} = '/bin:/usr/bin';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
my $r = shift;
$r->send_http_header("text/html");
$SIG{CHLD} = 'IGNORE';
defined (my $kid = fork) or die "Cannot fork: $!\n";
if ($kid) {
print "Parent has finished, kid's PID: $kid\n";
}
else {
$r->cleanup_for_exec( ); # untie the socket
chdir '/' or die "Can't chdir to /: $!";
open STDIN, '/dev/null' or die "Can't read /dev/null: $!";
open STDOUT, '>/dev/null' or die "Can't write to /dev/null: $!";
open STDERR, '>&STDOUT' or die "Can't dup stdout: $!";
setsid or die "Can't start a new session: $!";
exec "/home/httpd/perl/external.pl" or die "Cannot execute exec: $!";
}
Notice that exec( ) never returns unless it fails to start the process. Therefore you shouldn't put any code after exec( )—it will not be executed in the case of success. Use system( ) or backticks 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 STDstreams in the forked process, even if the called program does that.
If the external program is written in Perl, you can pass complicated data stuctures to it using one of the methods to serialize and then restore Perl data. The Storable and FreezeThaw modules come in handy. Let's say that we have a program called master.pl (Example 10-22) calling another program called slave.pl (Example 10-23).
# we are within the mod_perl code use Storable ( ); my @params = (foo => 1, bar => 2); my $params = Storable::freeze(\@params); exec "./slave.pl", $params or die "Cannot execute exec: $!";
#!/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 recovers it with Storable::thaw, by shifting the first value of the @ARGV array (if available). The FreezeThaw module does a very similar thing.
 
Continue to:
mod_perl, modperl, Apache, perl, cgi, html, mod_perl, e-commerce, scalability, free, open source, OSS, apache, squid, high availability, modperl, linux, unix, Web, www, mod_perl, webserver, admin, apache, book, webmaster, tools, modperl, guide, docs, documentation, help, mod_perl, perl, information, apache, script, errata, eric cholet, perl, apache, mod-perl, stas bekman, mod_perl, cool, perl, Apache, performance, speed, choice
![]() |
Other projects to check out: meta-religion.com is for those interested in Religious, Spiritual and Esoteric Phenomena. i-want-a-better.com is a community of people discussing what they would like to be improved in their lives and things they use and interact with. You may also want to find a healer in your area or read articles on variety of topics.