summaryrefslogtreecommitdiff
path: root/pod/perlfaq8.pod
diff options
context:
space:
mode:
authorRafael Garcia-Suarez <rgarciasuarez@gmail.com>2002-11-26 21:06:48 +0000
committerRafael Garcia-Suarez <rgarciasuarez@gmail.com>2002-11-26 21:06:48 +0000
commit49d635f9372392ae44fe4c5b62b06e41912ae0c9 (patch)
tree29a0e48c51466f10da69fffa12babc88587672a9 /pod/perlfaq8.pod
parentad0f383a28b730182ea06492027f82167ce7032b (diff)
downloadperl-49d635f9372392ae44fe4c5b62b06e41912ae0c9.tar.gz
PerlFAQ sync.
p4raw-id: //depot/perl@18185
Diffstat (limited to 'pod/perlfaq8.pod')
-rw-r--r--pod/perlfaq8.pod124
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?