diff options
author | Rafael Garcia-Suarez <rgarciasuarez@gmail.com> | 2002-11-26 21:06:48 +0000 |
---|---|---|
committer | Rafael Garcia-Suarez <rgarciasuarez@gmail.com> | 2002-11-26 21:06:48 +0000 |
commit | 49d635f9372392ae44fe4c5b62b06e41912ae0c9 (patch) | |
tree | 29a0e48c51466f10da69fffa12babc88587672a9 /pod/perlfaq8.pod | |
parent | ad0f383a28b730182ea06492027f82167ce7032b (diff) | |
download | perl-49d635f9372392ae44fe4c5b62b06e41912ae0c9.tar.gz |
PerlFAQ sync.
p4raw-id: //depot/perl@18185
Diffstat (limited to 'pod/perlfaq8.pod')
-rw-r--r-- | pod/perlfaq8.pod | 124 |
1 files changed, 108 insertions, 16 deletions
diff --git a/pod/perlfaq8.pod b/pod/perlfaq8.pod index feb10f3947..e00d007912 100644 --- a/pod/perlfaq8.pod +++ b/pod/perlfaq8.pod @@ -1,6 +1,6 @@ =head1 NAME -perlfaq8 - System Interaction ($Revision: 1.8 $, $Date: 2002/05/16 12:41:42 $) +perlfaq8 - System Interaction ($Revision: 1.14 $, $Date: 2002/11/10 17:35:47 $) =head1 DESCRIPTION @@ -346,7 +346,12 @@ passwd(1), for example). =head2 How do I start a process in the background? -You could use +Several modules can start other processes that do not block +your Perl program. You can use IPC::Open3, Parallel::Jobs, +IPC::Run, and some of the POE modules. See CPAN for more +details. + +You could also use system("cmd &") @@ -375,9 +380,25 @@ not an issue with C<system("cmd&")>. =item Zombies -You have to be prepared to "reap" the child process when it finishes +You have to be prepared to "reap" the child process when it finishes. $SIG{CHLD} = sub { wait }; + + $SIG{CHLD} = 'IGNORE'; + +You can also use a double fork. You immediately wait() for your +first child, and the init daemon will wait() for your grandchild once +it exits. + + unless ($pid = fork) { + unless (fork) { + exec "what you really wanna do"; + die "exec failed!"; + } + exit 0; + } + waitpid($pid,0); + See L<perlipc/"Signals"> for other examples of code to do this. Zombies are not an issue with C<system("prog &")>. @@ -604,6 +625,68 @@ With system(), both STDOUT and STDERR will go the same place as the script's STDOUT and STDERR, unless the system() command redirects them. Backticks and open() read B<only> the STDOUT of your command. +You can also use the open3() function from IPC::Open3. Benjamin +Goldberg provides some sample code: + +To capture a program's STDOUT, but discard its STDERR: + + use IPC::Open3; + use File::Spec; + use Symbol qw(gensym); + open(NULL, ">", File::Spec->devnull); + my $pid = open3(gensym, \*PH, ">&NULL", "cmd"); + while( <PH> ) { } + waitpid($pid, 0); + +To capture a program's STDERR, but discard its STDOUT: + + use IPC::Open3; + use File::Spec; + use Symbol qw(gensym); + open(NULL, ">", File::Spec->devnull); + my $pid = open3(gensym, ">&NULL", \*PH, "cmd"); + while( <PH> ) { } + waitpid($pid, 0); + +To capture a program's STDERR, and let its STDOUT go to our own STDERR: + + use IPC::Open3; + use Symbol qw(gensym); + my $pid = open3(gensym, ">&STDERR", \*PH, "cmd"); + while( <PH> ) { } + waitpid($pid, 0); + +To read both a command's STDOUT and its STDERR separately, you can +redirect them to temp files, let the command run, then read the temp +files: + + use IPC::Open3; + use Symbol qw(gensym); + use IO::File; + local *CATCHOUT = IO::File->new_tempfile; + local *CATCHERR = IO::File->new_tempfile; + my $pid = open3(gensym, ">&CATCHOUT", ">&CATCHERR", "cmd"); + waitpid($pid, 0); + seek $_, 0, 0 for \*CATCHOUT, \*CATCHERR; + while( <CATCHOUT> ) {} + while( <CATCHERR> ) {} + +But there's no real need for *both* to be tempfiles... the following +should work just as well, without deadlocking: + + use IPC::Open3; + use Symbol qw(gensym); + use IO::File; + local *CATCHERR = IO::File->new_tempfile; + my $pid = open3(gensym, \*CATCHOUT, ">&CATCHERR", "cmd"); + while( <CATCHOUT> ) {} + waitpid($pid, 0); + seek CATCHERR, 0, 0; + while( <CATCHERR> ) {} + +And it'll be faster, too, since we can begin processing the program's +stdout immediately, rather than waiting for the program to finish. + With any of these, you can change file descriptors before the call: open(STDOUT, ">logfile"); @@ -636,7 +719,7 @@ Note that you I<must> use Bourne shell (sh(1)) redirection syntax in backticks, not csh(1)! Details on why Perl's system() and backtick and pipe opens all use the Bourne shell are in the F<versus/csh.whynot> article in the "Far More Than You Ever Wanted To -Know" collection in http://www.cpan.org/olddoc/FMTEYEWTK.tgz . To +Know" collection in http://www.cpan.org/misc/olddoc/FMTEYEWTK.tgz . To capture a command's STDERR and STDOUT together: $output = `cmd 2>&1`; # either with backticks @@ -680,7 +763,7 @@ there, and the old standard error shows up on the old standard out. =head2 Why doesn't open() return an error when a pipe open fails? -If the second argument to a piped C<open> contains shell +If the second argument to a piped open() contains shell metacharacters, perl fork()s, then exec()s a shell to decode the metacharacters and eventually run the desired program. If the program couldn't be run, it's the shell that gets the message, not Perl. All @@ -688,9 +771,9 @@ your Perl program can find out is whether the shell itself could be successfully started. You can still capture the shell's STDERR and check it for error messages. See L<"How can I capture STDERR from an external command?"> elsewhere in this document, or use the -L<IPC::Open3> module. +IPC::Open3 module. -If there are no shell metacharacters in the argument of C<open>, Perl +If there are no shell metacharacters in the argument of open(), Perl runs the command directly, without using the shell, and can correctly report whether the command started. @@ -728,11 +811,20 @@ processing may take place, whereas backticks do not. =head2 How can I call backticks without shell processing? -This is a bit tricky. Instead of writing +This is a bit tricky. You can't simply write the command +like this: @ok = `grep @opts '$search_string' @filenames`; -You have to do this: +As of Perl 5.8.0, you can use open() with multiple arguments. +Just like the list forms of system() and exec(), no shell +escapes happen. + + open( GREP, "-|", 'grep', @opts, $search_string, @filenames ); + chomp(@ok = <GREP>); + close GREP; + +You can also: my @ok = (); if (open(GREP, "-|")) { @@ -748,12 +840,9 @@ You have to do this: Just as with system(), no shell escapes happen when you exec() a list. Further examples of this can be found in L<perlipc/"Safe Pipe Opens">. -Note that if you're stuck on Microsoft, no solution to this vexing issue +Note that if you're use Microsoft, no solution to this vexing issue is even possible. Even if Perl were to emulate fork(), you'd still -be hosed, because Microsoft gives no argc/argv-style API. Their API -always reparses from a single string, which is fundamentally wrong, -but you're not likely to get the Gods of Redmond to acknowledge this -and fix it for you. +be stuck, because Microsoft does not have a argc/argv-style API. =head2 Why can't my script read from STDIN after I gave it EOF (^D on Unix, ^Z on MS-DOS)? @@ -929,6 +1018,9 @@ handler, as documented in L<perlipc/"Signals"> and the section on ``Signals'' in the Camel. You may instead use the more flexible Sys::AlarmCall module available from CPAN. +The alarm() function is not implemented on all versions of Windows. +Check the documentation for your specific version of Perl. + =head2 How do I set CPU limits? Use the BSD::Resource module from CPAN. @@ -937,12 +1029,12 @@ Use the BSD::Resource module from CPAN. Use the reaper code from L<perlipc/"Signals"> to call wait() when a SIGCHLD is received, or else use the double-fork technique described -in L<perlfunc/fork>. +in L<perlfaq8/"How do I start a process in the background?">. =head2 How do I use an SQL database? There are a number of excellent interfaces to SQL databases. See the -DBD::* modules available from http://www.cpan.org/modules/DBD . +DBD::* modules available from http://www.cpan.org/modules/by-module/DBD/ . A lot of information on this can be found at http://dbi.perl.org/ =head2 How do I make a system() exit on control-C? |