=head1 NAME
-perlfaq8 - System Interaction ($Revision: 1.4 $, $Date: 2001/11/09 08:06:04 $)
+perlfaq8 - System Interaction ($Revision: 1.27 $, $Date: 2005/12/31 00:54:37 $)
=head1 DESCRIPTION
=item Keyboard
- Term::Cap Standard perl distribution
- Term::ReadKey CPAN
- Term::ReadLine::Gnu CPAN
- Term::ReadLine::Perl CPAN
- Term::Screen CPAN
+ Term::Cap Standard perl distribution
+ Term::ReadKey CPAN
+ Term::ReadLine::Gnu CPAN
+ Term::ReadLine::Perl CPAN
+ Term::Screen CPAN
=item Screen
- Term::Cap Standard perl distribution
- Curses CPAN
- Term::ANSIColor CPAN
+ Term::Cap Standard perl distribution
+ Curses CPAN
+ Term::ANSIColor CPAN
=item Mouse
- Tk CPAN
+ Tk CPAN
=back
-Some of these specific cases are shown below.
+Some of these specific cases are shown as examples in other answers
+in this section of the perlfaq.
=head2 How do I print something out in color?
Controlling input buffering is a remarkably system-dependent matter.
On many systems, you can just use the B<stty> command as shown in
L<perlfunc/getc>, but as you see, that's already getting you into
-portability snags.
+portability snags.
open(TTY, "+</dev/tty") or die "no tty: $!";
system "stty cbreak </dev/tty >/dev/tty 2>&1";
=head2 How do I get the screen size?
-If you have Term::ReadKey module installed from CPAN,
+If you have Term::ReadKey module installed from CPAN,
you can use it to fetch the width and height in characters
and in pixels:
use Term::ReadKey;
($wchar, $hchar, $wpixels, $hpixels) = GetTerminalSize();
-This is more portable than the raw C<ioctl>, but not as
+This is more portable than the raw C<ioctl>, but not as
illustrative:
require 'sys/ioctl.ph';
If you expect characters to get to your device when you print() them,
you'll want to autoflush that filehandle. You can use select()
-and the C<$|> variable to control autoflushing (see L<perlvar/$|>
-and L<perlfunc/select>, or L<perlfaq5>, ``How do I flush/unbuffer an
-output filehandle? Why must I do this?''):
+and the C<$|> variable to control autoflushing (see L<perlvar/$E<verbar>>
+and L<perlfunc/select>, or L<perlfaq5>, "How do I flush/unbuffer an
+output filehandle? Why must I do this?"):
$oldh = select(DEV);
$| = 1;
=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 &")
=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 &")>.
generates a signal which is sent to your terminal's currently
foregrounded process group, which you then trap in your process.
Signals are documented in L<perlipc/"Signals"> and the
-section on ``Signals'' in the Camel.
+section on "Signals" in the Camel.
-Be warned that very few C libraries are re-entrant. Therefore, if you
-attempt to print() in a handler that got invoked during another stdio
-operation your internal structures will likely be in an
-inconsistent state, and your program will dump core. You can
-sometimes avoid this by using syswrite() instead of print().
+You can set the values of the %SIG hash to be the functions you want
+to handle the signal. After perl catches the signal, it looks in %SIG
+for a key with the same name as the signal, then calls the subroutine
+value for that key.
-Unless you're exceedingly careful, the only safe things to do inside a
-signal handler are (1) set a variable and (2) exit. In the first case,
-you should only set a variable in such a way that malloc() is not
-called (eg, by setting a variable that already has a value).
+ # as an anonymous subroutine
-For example:
+ $SIG{INT} = sub { syswrite(STDERR, "ouch\n", 5 ) };
- $Interrupted = 0; # to ensure it has a value
- $SIG{INT} = sub {
- $Interrupted++;
- syswrite(STDERR, "ouch\n", 5);
- }
+ # or a reference to a function
+
+ $SIG{INT} = \&ouch;
+
+ # or the name of the function as a string
+
+ $SIG{INT} = "ouch";
+
+Perl versions before 5.8 had in its C source code signal handlers which
+would catch the signal and possibly run a Perl function that you had set
+in %SIG. This violated the rules of signal handling at that level
+causing perl to dump core. Since version 5.8.0, perl looks at %SIG
+*after* the signal has been caught, rather than while it is being caught.
+Previous versions of this answer were incorrect.
-However, because syscalls restart by default, you'll find that if
-you're in a "slow" call, such as <FH>, read(), connect(), or
-wait(), that the only way to terminate them is by "longjumping" out;
-that is, by raising an exception. See the time-out handler for a
-blocking flock() in L<perlipc/"Signals"> or the section on ``Signals''
-in the Camel book.
=head2 How do I modify the shadow password file on a Unix system?
properly, the getpw*() functions described in L<perlfunc> should in
theory provide (read-only) access to entries in the shadow password
file. To change the file, make a new shadow password file (the format
-varies from system to system--see L<passwd(5)> for specifics) and use
-pwd_mkdb(8) to install it (see L<pwd_mkdb(8)> for more details).
+varies from system to system--see L<passwd> for specifics) and use
+pwd_mkdb(8) to install it (see L<pwd_mkdb> for more details).
=head2 How do I set the time and date?
Release 5 of Perl added the END block, which can be used to simulate
atexit(). Each package's END block is called when the program or
-thread ends (see L<perlmod> manpage for more details).
+thread ends (see L<perlmod> manpage for more details).
For example, you can use this to make sure your filter program
managed to finish its output without filling up the disk:
END {
close(STDOUT) || die "stdout close failed: $!";
- }
+ }
The END block isn't called when untrapped signals kill the program,
though, so if you use END blocks you should also use
Perl's exception-handling mechanism is its eval() operator. You can
use eval() as setjmp and die() as longjmp. For details of this, see
the section on signals, especially the time-out handler for a blocking
-flock() in L<perlipc/"Signals"> or the section on ``Signals'' in
+flock() in L<perlipc/"Signals"> or the section on "Signals" in
the Camel Book.
If exception handling is all you're interested in, try the
L<perlfunc>).
Remember to check the modules that came with your distribution, and
-CPAN as well--someone may already have written a module to do it.
+CPAN as well---someone may already have written a module to do it. On
+Windows, try Win32::API. On Macs, try Mac::Carbon. If no module
+has an interface to the C function, you can inline a bit of C in your
+Perl source with Inline::C.
=head2 Where do I get the include files to do ioctl() or syscall()?
The IPC::Open2 module (part of the standard perl distribution) is an
easy-to-use approach that internally uses pipe(), fork(), and exec() to do
the job. Make sure you read the deadlock warnings in its documentation,
-though (see L<IPC::Open2>). See
-L<perlipc/"Bidirectional Communication with Another Process"> and
+though (see L<IPC::Open2>). See
+L<perlipc/"Bidirectional Communication with Another Process"> and
L<perlipc/"Bidirectional Communication with Yourself">
You may also use the IPC::Open3 module (part of the standard perl
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_tmpfile;
+ local *CATCHERR = IO::File->new_tmpfile;
+ 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_tmpfile;
+ 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");
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
while (<PH>) { } # plus a read
To read both a command's STDOUT and its STDERR separately, it's easiest
-and safest to redirect them separately to files, and then read from those
-files when the program is done:
+to redirect them separately to files, and then read from those files
+when the program is done:
- system("program args 1>/tmp/program.stdout 2>/tmp/program.stderr");
+ system("program args 1>program.stdout 2>program.stderr");
Ordering is important in all these examples. That's because the shell
processes file descriptor redirections in strictly left to right order.
=head2 Why doesn't open() return an error when a pipe open fails?
-Because the pipe open takes place in two steps: first Perl calls
-fork() to start a new process, then this new process calls exec() to
-run the program you really wanted to open. The first step reports
-success or failure to your process, so open() can only tell you
-whether the fork() succeeded or not.
-
-To find out if the exec() step succeeded, you have to catch SIGCHLD
-and wait() to get the exit status. You should also catch SIGPIPE if
-you're writing to the child--you may not have found out the exec()
-failed by the time you write. This is documented in L<perlipc>.
-
-In some cases, even this won't work. 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. Now when you call wait(), you only learn whether or not the
-I<shell> could be successfully started...it's best to avoid shell
-metacharacters.
+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
+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
+IPC::Open3 module.
-On systems that follow the spawn() paradigm, open() I<might> do what
-you expect--unless perl uses a shell to start your command. In this
-case the fork()/exec() description still applies.
+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.
=head2 What's wrong with using backticks in a void context?
Strictly speaking, nothing. Stylistically speaking, it's not a good
-way to write maintainable code because backticks have a (potentially
-humongous) return value, and you're ignoring it. It's may also not be very
-efficient, because you have to read in all the lines of output, allocate
-memory for them, and then throw it away. Too often people are lulled
-to writing:
+way to write maintainable code. Perl has several operators for
+running external commands. Backticks are one; they collect the output
+from the command for use in your program. The C<system> function is
+another; it doesn't do this.
- `cp file file.bak`;
-
-And now they think "Hey, I'll just always use backticks to run programs."
-Bad idea: backticks are for capturing a program's output; the system()
-function is for running programs.
+Writing backticks in your program sends a clear message to the readers
+of your code that you wanted to collect the output of the command.
+Why send a clear message that isn't true?
Consider this line:
`cat /etc/termcap`;
-You haven't assigned the output anywhere, so it just wastes memory
-(for a little while). You forgot to check C<$?> to see whether
-the program even ran correctly, too. Even if you wrote
+You forgot to check C<$?> to see whether the program even ran
+correctly. Even if you wrote
print `cat /etc/termcap`;
=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, "-|")) {
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)?
process are not reflected in its parent--only in any children
created after the change. There is shell magic that may allow you to
fake it by eval()ing the script's output in your shell; check out the
-comp.unix.questions FAQ for details.
+comp.unix.questions FAQ for details.
=back
=item *
-Open /dev/tty and use the TIOCNOTTY ioctl on it. See L<tty(4)>
+Open /dev/tty and use the TIOCNOTTY ioctl on it. See L<tty>
for details. Or better yet, you can just use the POSIX::setsid()
function, so you don't have to worry about process groups.
Use the alarm() function, probably in conjunction with a signal
handler, as documented in L<perlipc/"Signals"> and the section on
-``Signals'' in the Camel. You may instead use the more flexible
+"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.
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 .
-A lot of information on this can be found at http://dbi.perl.org/
+The DBI module provides an abstract interface to most database
+servers and types, including Oracle, DB2, Sybase, mysql, Postgresql,
+ODBC, and flat files. The DBI module accesses each database type
+through a database driver, or DBD. You can see a complete list of
+available drivers on CPAN: http://www.cpan.org/modules/by-module/DBD/ .
+You can read more about DBI on http://dbi.perl.org .
+
+Other modules provide more specific access: Win32::ODBC, Alzabo, iodbc,
+and others found on CPAN Search: http://search.cpan.org .
=head2 How do I make a system() exit on control-C?
passes the signal on to the subprocess. Or you can check for it:
$rc = system($cmd);
- if ($rc & 127) { die "signal death" }
+ if ($rc & 127) { die "signal death" }
=head2 How do I open a file without blocking?
sysopen():
use Fcntl;
- sysopen(FH, "/tmp/somefile", O_WRONLY|O_NDELAY|O_CREAT, 0644)
- or die "can't open /tmp/somefile: $!":
+ sysopen(FH, "/foo/somefile", O_WRONLY|O_NDELAY|O_CREAT, 0644)
+ or die "can't open /foo/somefile: $!":
+
+=head2 How do I tell the difference between errors from the shell and perl?
+
+(answer contributed by brian d foy, C<< <bdfoy@cpan.org> >>
+
+When you run a Perl script, something else is running the script for you,
+and that something else may output error messages. The script might
+emit its own warnings and error messages. Most of the time you cannot
+tell who said what.
+
+You probably cannot fix the thing that runs perl, but you can change how
+perl outputs its warnings by defining a custom warning and die functions.
+
+Consider this script, which has an error you may not notice immediately.
+
+ #!/usr/locl/bin/perl
+
+ print "Hello World\n";
+
+I get an error when I run this from my shell (which happens to be
+bash). That may look like perl forgot it has a print() function,
+but my shebang line is not the path to perl, so the shell runs the
+script, and I get the error.
+
+ $ ./test
+ ./test: line 3: print: command not found
+
+A quick and dirty fix involves a little bit of code, but this may be all
+you need to figure out the problem.
+
+ #!/usr/bin/perl -w
+
+ BEGIN {
+ $SIG{__WARN__} = sub{ print STDERR "Perl: ", @_; };
+ $SIG{__DIE__} = sub{ print STDERR "Perl: ", @_; exit 1};
+ }
+
+ $a = 1 + undef;
+ $x / 0;
+ __END__
+
+The perl message comes out with "Perl" in front. The BEGIN block
+works at compile time so all of the compilation errors and warnings
+get the "Perl:" prefix too.
+
+ Perl: Useless use of division (/) in void context at ./test line 9.
+ Perl: Name "main::a" used only once: possible typo at ./test line 8.
+ Perl: Name "main::x" used only once: possible typo at ./test line 9.
+ Perl: Use of uninitialized value in addition (+) at ./test line 8.
+ Perl: Use of uninitialized value in division (/) at ./test line 9.
+ Perl: Illegal division by zero at ./test line 9.
+ Perl: Illegal division by zero at -e line 3.
+
+If I don't see that "Perl:", it's not from perl.
+
+You could also just know all the perl errors, and although there are
+some people who may know all of them, you probably don't. However, they
+all should be in the perldiag manpage. If you don't find the error in
+there, it probably isn't a perl error.
+
+Looking up every message is not the easiest way, so let perl to do it
+for you. Use the diagnostics pragma with turns perl's normal messages
+into longer discussions on the topic.
+
+ use diagnostics;
+
+If you don't get a paragraph or two of expanded discussion, it
+might not be perl's message.
=head2 How do I install a module from CPAN?
The easiest way is to have a module also named CPAN do it for you.
-This module comes with perl version 5.004 and later. To manually install
-the CPAN module, or any well-behaved CPAN module for that matter, follow
-these steps:
+This module comes with perl version 5.004 and later.
+
+ $ perl -MCPAN -e shell
+
+ cpan shell -- CPAN exploration and modules installation (v1.59_54)
+ ReadLine support enabled
+
+ cpan> install Some::Module
+
+To manually install the CPAN module, or any well-behaved CPAN module
+for that matter, follow these steps:
=over 4
get a new F<perl> binary with your extension linked in.
See L<ExtUtils::MakeMaker> for more details on building extensions.
-See also the next question, ``What's the difference between require
-and use?''.
+See also the next question, "What's the difference between require
+and use?".
=head2 What's the difference between require and use?
=head2 How do I keep my own module/library directory?
-When you build modules, use the PREFIX option when generating
+When you build modules, use the PREFIX and LIB options when generating
Makefiles:
- perl Makefile.PL PREFIX=/u/mydir/perl
+ perl Makefile.PL PREFIX=/mydir/perl LIB=/mydir/perl/lib
then either set the PERL5LIB environment variable before you run
scripts that use the modules/libraries (see L<perlrun>) or say
- use lib '/u/mydir/perl';
+ use lib '/mydir/perl/lib';
This is almost the same as
BEGIN {
- unshift(@INC, '/u/mydir/perl');
+ unshift(@INC, '/mydir/perl/lib');
}
except that the lib module checks for machine-dependent subdirectories.
use lib "$FindBin::Bin";
use your_own_modules;
-=head2 How do I add a directory to my include path at runtime?
+=head2 How do I add a directory to my include path (@INC) at runtime?
Here are the suggested ways of modifying your include path:
=head1 AUTHOR AND COPYRIGHT
-Copyright (c) 1997-1999 Tom Christiansen and Nathan Torkington.
-All rights reserved.
+Copyright (c) 1997-2006 Tom Christiansen, Nathan Torkington, and
+other authors as noted. All rights reserved.
This documentation is free; you can redistribute it and/or modify it
under the same terms as Perl itself.