.\" Automatically generated by Pod::Man 2.22 (Pod::Simple 3.13) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .ie \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . nr % 0 . rr F .\} .el \{\ . de IX .. .\} .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "MNI::Spawn 3" .TH MNI::Spawn 3 "2001-02-26" "perl v5.10.1" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" MNI::Spawn \- run sub\-programs with many bells and whistles .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use MNI::Spawn; \& \& # Conventional interface: \& \& MNI::Spawn::SetOptions (option => value, ...); \& \& RegisterPrograms ([$prog1, $prog2, ...]) || exit 1; \& RegisterPrograms ([$prog1, $prog2, ...], $path) || exit 1; \& RegisterPrograms ({$name => $executable, ... }) || exit 1; \& \& AddDefaultArgs ($prog, \e@args); \& AddDefaultArgs ($prog, \e@args, \*(Aqpre\*(Aq); # \*(Aqpre\*(Aq is default \& AddDefaultArgs ($prog, \e@args, \*(Aqpost\*(Aq); \& \& ClearDefaultArgs ($prog); \& ClearDefaultArgs ($prog, \*(Aqboth\*(Aq); # \*(Aqboth\*(Aq is default \& ClearDefaultArgs ($prog, \*(Aqpre\*(Aq); \& ClearDefaultArgs ($prog, \*(Aqpost\*(Aq); \& \& Spawn ($cmd, option => value, ...) && exit 1; \& Spawn (\e@cmd, option => value, ...) && exit 1; \& \& \& # Object\-oriented interface \& \& $spawner = new MNI::Spawn (option => value, ...); \& $spawner\->set_options (option => value, ...); \& $alt_spawner = $spawner\->copy; \& \& $spawner\->register_programs ([$prog1, $prog2, ...]) || exit 1; \& $spawner\->register_programs ([$prog1, $prog2, ...], $path) || exit 1; \& $spawner\->register_programs ({$name => $executable, ... }) || exit 1; \& \& $spawner\->add_default_args ($prog, \e@args); \& $spawner\->add_default_args ($prog, \e@args, \*(Aqpre\*(Aq); \& $spawner\->add_default_args ($prog, \e@args, \*(Aqpost\*(Aq); \& \& $spawner\->clear_default_args ($prog); \& $spawner\->clear_default_args ($prog, \*(Aqboth\*(Aq) \& $spawner\->clear_default_args ($prog, \*(Aqpre\*(Aq); \& $spawner\->clear_default_args ($prog, \*(Aqpost\*(Aq) \& \& $spawner\->spawn ($cmd, option => value, ...) && exit 1; \& $spawner\->spawn (\e@cmd, option => value, ...) && exit 1; .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" \&\fIMNI::Spawn\fR can be seen as a glorified front end to Perl's \f(CW\*(C`system\*(C'\fR (or, more accurately, to Perl's \f(CW\*(C`fork\*(C'\fR and \f(CW\*(C`exec\*(C'\fR); it's probably more helpful, though, to think of it as a limited Unix shell accessed through Perl rather than as an interactive program in its own right. However you think of it, its purpose is to execute other programs. This comes in very handy when writing programs that mainly run other programs and process the output using Perl's built-in facilities\-\-\-i.e., glorified shell scripts. The reason I think of it as more shell-like is because of the range of common tasks that \fIMNI::Spawn\fR takes out of your hands, most particularly command logging, output redirection or capturing, and error handling. .PP Here is a fairly complete list of \fIMNI::Spawn\fR's features: .IP "\(bu" 4 execution of a single command (the module's \fIraison d'etre\fR) .IP "\(bu" 4 execution through the \s-1UCSF\s0 Batch system (makes it possible to write programs that run either sequentially or in parallel, depending on a run-time option) .IP "\(bu" 4 representation of commands as a string or list\-\-\-like with Perl's \f(CW\*(C`system\*(C'\fR and \f(CW\*(C`exec\*(C'\fR, the former might mean interpretation by the shell, but the latter guarantees no shell involvement .IP "\(bu" 4 can search for programs when executing them, or look them up in a list of \&\*(L"known\*(R" programs and their locations that is created (with your help) before any programs are actually run .IP "\(bu" 4 maintains a list of default arguments for each \*(L"known\*(R" program that can be inserted into the command line when the program is run .IP "\(bu" 4 can print a detailed summary of command execution (user, host, date, time, and complete command line), to a file of your choice (normally your standard output) .IP "\(bu" 4 redirection of the sub\-process' standard output and/or standard error to files (separately or together) .IP "\(bu" 4 capture of the sub\-process' standard output and/or standard error to Perl variables (separately or together) (redirection and capturing can be mixed \&'n matched at will) .IP "\(bu" 4 merging of standard error with standard output .IP "\(bu" 4 customizable response to the child program crashing .PP The main features \fInot\fR presently in \fIMNI::Spawn\fR that I might someday add are, in approximate order of how likely I am ever to add them: .IP "\(bu" 4 input redirection .IP "\(bu" 4 background execution .IP "\(bu" 4 remote execution (through \f(CW\*(C`rsh\*(C'\fR) .IP "\(bu" 4 pipelines .PP If you find the lack of any of these a problem, be sure to tell me\-\-\-otherwise, I won't add them until \fII\fR find their lack to be a problem! .SH "INTERFACES" .IX Header "INTERFACES" \&\fIMNI::Spawn\fR comes with two complete interfaces, one object-oriented (\s-1OO\s0) and the other a more conventional subroutine-based interface. The object-oriented interface is more general and flexible, but the conventional interface is usually more convenient and will probably be the more widely-used interface. (This convenience arises from its use of some hidden global state\-\-\-you don't have to carry around anything in your code to use \fIMNI::Spawn\fR. With the \s-1OO\s0 interface, you have to carry around \*(L"spawning objects\*(R" that encapsulate the entire state of the module; with the conventional interface, one particular \*(L"global\*(R" spawning object is maintained by the module on your behalf for this purpose.) .PP Thus, the conventional interface will be discussed first, and the bulk of the documentation and example code will be in terms of it. Note that all of the subroutines in the conventional interface have corresponding methods in the \s-1OO\s0 interface, and the correspondence is fairly obvious: for instance, \f(CW\*(C`RegisterPrograms\*(C'\fR (subroutine) corresponds to \&\f(CW\*(C`register_programs\*(C'\fR (method). It's trivial to translate back and forth between the two interfaces; for instance, this code (in the conventional interface): .PP .Vb 4 \& MNI::Spawn::SetOptions (verbose => 0); \& RegisterPrograms ([qw(mincresample mincreshape mincmath)]); \& AddDefaultArgs (\*(Aqmincresample\*(Aq, \*(Aq\-quiet\*(Aq); \& Spawn ([\*(Aqmincresample\*(Aq, $invol, $outvol, @options]); .Ve .PP would, in \s-1OO\s0 terms, be: .PP .Vb 5 \& $spawner = new MNI::Spawn (verbose => 0); \& ... \& $spawner\->register_programs ([qw(mincresample mincreshape mincmath)]); \& $spawner\->add_default_args (\*(Aqmincresample\*(Aq, \*(Aq\-quiet]); \& $spawner\->spawn ([\*(Aqmincresample\*(Aq, $invol, $outvol, @options]); .Ve .PP where, of course, the spawning object \f(CW$spawn\fR only has to be created once in the course of your program's execution. .PP An important part of \fIMNI::Spawn\fR's interface is the set of \fIoptions\fR which control almost every aspect of the module's operation, and make up the bulk of the state that is carried around in \fIMNI::Spawn\fR objects (variously called \fIspawners\fR or, for the darkly whimsical, \fIspawning vats\fR). One neat thing about these options is that they can be set either semi-permanently with the \f(CW\*(C`SetOptions\*(C'\fR subroutine (or \f(CW\*(C`set_options\*(C'\fR method), or on a temporary, per-execution basis. This is convenient because some options (like \f(CW\*(C`verbose\*(C'\fR or \f(CW\*(C`execute\*(C'\fR) will most likely be set once, near the beginning of your program, and forgotten about; others (like \f(CW\*(C`stdout\*(C'\fR and \f(CW\*(C`stderr\*(C'\fR, which control output redirection and capturing) will\-\-\-if they are used at all\-\-\-usually be different with every command you execute. The module is designed so that doing things the \&\*(L"normal\*(R" way is easy and convenient, but deviating a little bit (e.g. always capturing standard error to the same variable, or changing \&\f(CW\*(C`verbose\*(C'\fR frequently), is just as easy, and just requires a little more typing on your part. The module options are fully documented in \&\*(L"\s-1OPTIONS\s0\*(R" below. .SH "OPERATION" .IX Header "OPERATION" Regardless of which interface you choose to use, the operation of \&\fIMNI::Spawn\fR is the same (hardly surprising given that the conventional interface is implemented on top of the \s-1OO\s0 interface). Generally speaking, every program you write using \fIMNI::Spawn\fR will call the \&\f(CW\*(C`Spawn\*(C'\fR subroutine (or \f(CW\*(C`spawn\*(C'\fR method) several times, and most programs will make some use of \f(CW\*(C`SetOptions\*(C'\fR, \f(CW\*(C`RegisterPrograms\*(C'\fR, and \&\f(CW\*(C`AddDefaultArgs\*(C'\fR. .PP \&\f(CW\*(C`Spawn\*(C'\fR is the call that actually executes a program; the others merely change the state of the module to customize how programs are executed. For instance, you might use \f(CW\*(C`SetOptions\*(C'\fR to turn off \f(CW\*(C`Spawn\*(C'\fR's verbosity so it doesn't print each command as it is executed; or you might use \f(CW\*(C`AddDefaultArgs\*(C'\fR to ensure that \f(CW\*(C`\-quiet\*(C'\fR appears on the command line of certain programs whenever they are run. .PP The operation of the module is therefore best explained in terms of what happens when you call \f(CW\*(C`Spawn\*(C'\fR. Here we present a broad overview of the procedure followed by \f(CW\*(C`Spawn\*(C'\fR\-\-\-more details (in particular, which options govern each step and exactly how everything interacts) will come in the following sections: .IP "\(bu" 4 command completion .Sp This consists of turning a simple program name into a full path (unless the program name you supply already includes a directory component), and adding any default arguments for that program. Each of these steps is optional. .IP "\(bu" 4 plan redirection .Sp Here we determine if the child process' standard output is to be left untouched, redirected to a file, or captured to a variable; and whether its standard error is to be left untouched, redirected to a file, captured to a variable, or merged with its standard output. .IP "\(bu" 4 hand things over to \f(CW\*(C`batch\*(C'\fR, if appropriate .IP "\(bu" 4 fork .IP "\(bu" 4 in child process: redirect and \f(CW\*(C`exec\*(C'\fR .Sp Either or both (or neither) of \f(CW\*(C`STDOUT\*(C'\fR and \f(CW\*(C`STDERR\*(C'\fR are redirected (possibly to a pipe that is being read by the parent, for capturing standard output), and the command to execute is \f(CW\*(C`exec\*(C'\fR'd. .IP "\(bu" 4 in parent process: harvest child and wait .Sp If we are to capture the child's standard output and/or standard error, we read them in here. Then, we wait for the child process to terminate. .IP "\(bu" 4 in parent process: react to child's termination status .Sp If the child program crashed (terminated with non-zero status), we react in some user-customizable way. .PP Now that you have a rough idea of where all the module's options come into play, we'll document those options. Later on, we'll get into the details of command completion, the \f(CW\*(C`batch\*(C'\fR interface, output redirection and capturing, and error handling. .PP Throughout the following documentation (and interspersed example code), it will help you to know that \f(CW\*(C`Spawn\*(C'\fR has one required argument (the command to execute), and can take any number of option/value pairs. These temporary options will override the global default options (or, if you're using the object-oriented interface, the options in the spawning object at hand) for the duration of that call to \f(CW\*(C`Spawn\*(C'\fR. .SH "COMMANDS, PROGRAMS, AND ARGUMENTS" .IX Header "COMMANDS, PROGRAMS, AND ARGUMENTS" A bit of terminology before embarking on the gory details: a \fIcommand\fR is what you pass to \f(CW\*(C`Spawn\*(C'\fR for execution. It consists of a \fIprogram\fR and zero or more \f(CW\*(C`arguments\*(C'\fR. By analogy with Perl's \f(CW\*(C`system\*(C'\fR and \&\f(CW\*(C`exec\*(C'\fR functions, commands supplied to \f(CW\*(C`Spawn\*(C'\fR can be either strings or lists (actually list refs, since the command has to be shoehorned into a single scalar). Since Perl's \f(CW\*(C`exec\*(C'\fR is ultimately used to execute the command, the same provisos apply: if you use the list form, you are guaranteed that no shell will meddle with your arguments, but passing the command as a string means a shell might be involved. This is usually undesirable, both for efficiency reasons and because of the danger of slipping into a morass of quoting if you have anything even remotely exotic in your command. .PP For example, .PP .Vb 1 \& Spawn (\*(Aqls *.t\*(Aq); .Ve .PP will result in Perl passing your command string directly to \f(CW\*(C`/bin/sh\*(C'\fR, which will then split and expand it (including expansion of the \f(CW\*(C`*.t\*(C'\fR pattern), whereas .PP .Vb 1 \& Spawn ([\*(Aqls\*(Aq, \*(Aq*.t\*(Aq]); .Ve .PP will result in \f(CW\*(C`ls\*(C'\fR being \f(CW\*(C`exec\*(C'\fR'd directly by Perl with exactly one argument, \f(CW\*(C`*.t\*(C'\fR (probably \fInot\fR what you want). You might also be tempted to take advantage of shell interpretation if you want to run your output through a pipeline before getting your hands on it: .PP .Vb 1 \& Spawn (\*(Aqls *.t | grep \-v "^a"\*(Aq); .Ve .PP (Note that quotes are already rearing their ugly head here, something that should set alarm bells ringing in your head. If it doesn't, you probably haven't done enough shell programming\-\-\-lucky you!) .PP Or, you might want to run two commands in sequence, say to change directories or impose some system limit temporarily: .PP .Vb 1 \& Spawn (\*(Aqcd /tmp ; ls *.blah\*(Aq); \& \& Spawn (\*(Aqulimit \-f 4096 ; cat /dev/zero > zeros\*(Aq); .Ve .PP The common thread here is that these all look like holdovers from a shell script\-\-\-there is usually a more powerful, efficient, and almost-as-succinct way to accomplish these things directly in Perl. You can do better pattern-based file searches using \f(CW\*(C`opendir\*(C'\fR, \f(CW\*(C`readdir\*(C'\fR, and \f(CW\*(C`grep\*(C'\fR; most simple Unix pipeline tasks (especially those involving use/abuse of \f(CW\*(C`grep\*(C'\fR, \f(CW\*(C`sed\*(C'\fR, \f(CW\*(C`awk\*(C'\fR, \f(CW\*(C`sort\*(C'\fR, \f(CW\*(C`cut\*(C'\fR, etc.) can be done directly in Perl; you can change directories with \f(CW\*(C`chdir\*(C'\fR; and you can even tweak system limits using the \fIBSD::Resource\fR module (available on \&\s-1CPAN\s0). .PP In any case, the command-as-list paradigm is definitely safer and preferable, but \f(CW\*(C`Spawn\*(C'\fR fully supports either method. .PP \&\f(CW\*(C`Spawn\*(C'\fR splits your command up into program and argument-list components when it's doing command completion, which involves expanding the program to a full path if appropriate, and possibly adding default arguments (which depend on the program name) to the command. See \&\*(L"\s-1COMMAND\s0 \s-1COMPLETION\s0\*(R", below. .SH "OPTIONS" .IX Header "OPTIONS" The actions of \fIMNI::Spawn\fR are mostly controlled through a set of module options, which (if you're using the conventional interface) you can think of as being sort of like global variables. However, the module carefully controls your access to the options\-\-\-they're write-only, and your program will crash if you try to set an option that's not really an option (because this is usually a typo in your code). .PP In the conventional interface, there is one set of options that applies to every call to \f(CW\*(C`Spawn\*(C'\fR. These options can be changed semi-permanently by calling \f(CW\*(C`SetOptions\*(C'\fR, or overridden on a temporary, per\-\f(CW\*(C`Spawn\*(C'\fR basis by adding optional arguments to the \f(CW\*(C`Spawn\*(C'\fR call. (\*(L"Semi-permanent\*(R" just means that any options set with \f(CW\*(C`SetOptions\*(C'\fR will stay the same until the next \f(CW\*(C`SetOptions\*(C'\fR call that updates that option, or until temporarily overridden for one \f(CW\*(C`Spawn\*(C'\fR call.) .PP In the object-oriented interface, every spawning object carries around its own set of options. Thus, it's easy to have one \*(L"spawner\*(R" that runs commands verbosely, and another that runs them quietly. The object-oriented interface has a method \f(CW\*(C`set_options\*(C'\fR (analogous to the \&\f(CW\*(C`SetOptions\*(C'\fR subroutine), and for convenience you can also set options when constructing a spawner with \f(CW\*(C`new\*(C'\fR. .PP For example, you might set the \f(CW\*(C`verbose\*(C'\fR option to \f(CW0\fR in the \*(L"global default spawner\*(R" (the mechanism underlying the subroutine interface) like this: .PP .Vb 1 \& MNI::Spawn::SetOptions (verbose => 0); .Ve .PP (Note that \f(CW\*(C`SetOptions\*(C'\fR is never exported from the module because of its potentially ambiguous name.) In the \s-1OO\s0 interface, you could create a spawner and set its \f(CW\*(C`verbose\*(C'\fR option like this: .PP .Vb 2 \& $spawner = new MNI::Spawn; \& $spawner\->set_options (verbose => 0); .Ve .PP or you could do them both at once: .PP .Vb 1 \& $spawner = new MNI::Spawn (verbose => 0); .Ve .PP Also, \f(CW\*(C`SetOptions\*(C'\fR (and \f(CW\*(C`set_options\*(C'\fR and \f(CW\*(C`new\*(C'\fR\-\-\-they are all effectively the same here) can take any number of option/value pairs. The important thing is that they be called with an even number of arguments; using the \f(CW\*(C`=>\*(C'\fR operator helps you ensure that this is the case: .PP .Vb 4 \& MNI::Spawn::SetOptions (verbose => 0, \& execute => 1, \& strict => 2, \& search_path => $ENV{\*(AqPATH\*(Aq}); .Ve .PP Finally, if it isn't obvious by now, each option name is a string of lowercase letters and underscores; the value for each option is some scalar value, which could of course be a reference to a list or hash or any data structure. The options and the nature of their values are as follows: .ie n .IP """verbose"" (default: undefined)" 4 .el .IP "\f(CWverbose\fR (default: undefined)" 4 .IX Item "verbose (default: undefined)" Boolean; if true \f(CW\*(C`Spawn\*(C'\fR will print a line summarizing each command and its execution environment just before executing it. This includes the name of your program (taken from \f(CW$main::ProgramName\fR, usually supplied by the \fIMNI::Startup\fR module); the user running the program, the host on which it is run, and the directory from which it is run (supplied by \&\f(CW\*(C`MNI::MiscUtilities::userstamp\*(C'\fR); the date and time of execution (from \&\f(CW\*(C`MNI::MiscUtilities::timestamp\*(C'\fR); and the full path of the program being run with all arguments. The purpose of this summary line is to answer \*(L"who, what, where, when, and how\*(R" for the execution of a given command. (Answering \*(L"why\*(R" is your job.) .Sp For example, if \f(CW\*(C`verbose\*(C'\fR is true, then the call .Sp .Vb 1 \& Spawn ("ls"); .Ve .Sp from a program called \f(CW\*(C`spawn.t\*(C'\fR might result in the following line being printed just before the command is executed: .Sp .Vb 2 \& [spawn.t] [greg@beelzebub:/home/greg/src/libperl/mnilib/t] \e \& [1997\-07\-21 23:51:41] /bin/ls .Ve .Sp (Yes, this is a rather ridiculous amount of information to provide. Trust me, though\-\-\-at some point, when trying to trace the complicated history of some data in the absence of other information, you'll be glad to have it.) .Sp A useful peculiarity of \f(CW\*(C`verbose\*(C'\fR (and its close companion \f(CW\*(C`execute\*(C'\fR) is that if it is undefined, it will take its value from the \f(CW$Verbose\fR global in the calling package. This ties in neatly with the global variable \f(CW$Verbose\fR exported (presumably into package \f(CW\*(C`main\*(C'\fR) by \&\fIMNI::Startup\fR; the fact that copying \f(CW$main::Verbose\fR to \&\fIMNI::Spawn\fR's \f(CW\*(C`verbose\*(C'\fR option happens quite late (on every call to \&\f(CW\*(C`Spawn\*(C'\fR, as long as \f(CW\*(C`verbose\*(C'\fR remains undefined in the spawning object) means that you can change \f(CW$Verbose\fR anywhere in your main program\-\-\-say, by tying it to a command-line option\-\-\-and have it continue to affect \f(CW\*(C`Spawn\*(C'\fR's behaviour. \f(CW\*(C`verbose\*(C'\fR is undefined by default, so this feature will be used in almost every program you write with \fIMNI::Spawn\fR. Note that since the \fIMNI::Startup\fR module sets its \&\f(CW$Verbose\fR to true, the \f(CW\*(C`verbose\*(C'\fR option (assuming you use \&\fIMNI::Startup\fR and \fIMNI::Spawn\fR in concert) effectively defaults to true. However, you should keep in mind that this happens through a little sleight-of-hand rather than in the obvious way. .Sp Also, the above explanation assumes that \f(CW\*(C`Spawn\*(C'\fR is being called from the same package where you \f(CW\*(C`use MNI::Startup\*(C'\fR\-\-\-usually, \f(CW\*(C`main\*(C'\fR. If you call \f(CW\*(C`spawn\*(C'\fR from other packages, you should either set the \&\f(CW\*(C`verbose\*(C'\fR and \f(CW\*(C`execute\*(C'\fR options explicitly, or arrange to \*(L"borrow\*(R" the \&\f(CW$Verbose\fR and \f(CW$Execute\fR globals from \fIMNI::Startup\fR. You can actually make aliases to these variables in your module with the following incantation: .Sp .Vb 2 \& *Verbose = \e$MNI::Startup::Verbose; \& *Execute = \e$MNI::Startup::Execute; .Ve .Sp (see pp. 51\-52 of \fIProgramming Perl, 2nd ed.\fR for more information). Then, when \f(CW\*(C`Spawn\*(C'\fR goes poking into your module for the value of its \&\f(CW$Verbose\fR global, it will actually fetch the \f(CW$Verbose\fR global from \&\fIMNI::Startup\fR\-\-\-which, due to \fIMNI::Startup\fR presumably exporting \&\f(CW$Verbose\fR to \f(CW\*(C`main\*(C'\fR, will also be the value of \f(CW$Verbose\fR in your main program. .ie n .IP """execute"" (default: undefined)" 4 .el .IP "\f(CWexecute\fR (default: undefined)" 4 .IX Item "execute (default: undefined)" Boolean; if false \f(CW\*(C`Spawn\*(C'\fR will do everything up to (and including) the \&\*(L"plan redirection\*(R" step. It won't do any of the fork/redirect/exec/gather/wait/react stuff, though. .Sp \&\f(CW\*(C`execute\*(C'\fR shares \f(CW\*(C`verbose\*(C'\fR's peculiar trait of taking its value from \&\f(CW$Execute\fR in the calling package when it is undefined, which is also the default value for \f(CW\*(C`execute\*(C'\fR. And since \fIMNI::Startup\fR also sets \&\f(CW$main::Execute\fR to true, \f(CW\*(C`execute\*(C'\fR also will usually (effectively) default to true, but again through sleight-of-hand. .ie n .IP """strict"" (default: 1)" 4 .el .IP "\f(CWstrict\fR (default: 1)" 4 .IX Item "strict (default: 1)" Three-way flag; if it is \f(CW1\fR then \f(CW\*(C`Spawn\*(C'\fR will print a warning when you try to run a program you haven't previously told it about (with \&\f(CW\*(C`RegisterPrograms\*(C'\fR\-\-\-more about this below); if it is \f(CW2\fR, then \&\f(CW\*(C`Spawn\*(C'\fR will \f(CW\*(C`die\*(C'\fR in such a situation. If it is \f(CW0\fR (or indeed any false value), \f(CW\*(C`Spawn\*(C'\fR will happily try to execute any program you wish. (Note: this will only happen if you have given \f(CW\*(C`Spawn\*(C'\fR permission to go poking around your command to fetch the program name, which is controlled by the \f(CW\*(C`complete\*(C'\fR option. In short, if \f(CW\*(C`complete\*(C'\fR is false, then \f(CW\*(C`strict\*(C'\fR is ignored: no attempt is made to ensure that you have \*(L"registered\*(R" the program ahead of time, and no \*(L"strictness\*(R" warnings will be printed.) .Sp The \f(CW\*(C`strict\*(C'\fR flag also has another interpretation: when \f(CW\*(C`AddDefaultArgs\*(C'\fR is called for an unknown program, a warning will be printed if \f(CW\*(C`strict\*(C'\fR is any true value. .ie n .IP """complete"" (default: true)" 4 .el .IP "\f(CWcomplete\fR (default: true)" 4 .IX Item "complete (default: true)" Boolean; if true, \f(CW\*(C`Spawn\*(C'\fR will attempt to \*(L"complete\*(R" each command by converting a bare program name to a full path and by adding default arguments to the command. (Each of these steps may be independently controlled with the \f(CW\*(C`search\*(C'\fR and \f(CW\*(C`add_defaults\*(C'\fR options.) .ie n .IP """search"" (default: true)" 4 .el .IP "\f(CWsearch\fR (default: true)" 4 .IX Item "search (default: true)" Boolean; if true, then \f(CW\*(C`Spawn\*(C'\fR might search a list of directories (see the \f(CW\*(C`search_path\*(C'\fR option below) to determine the location of the program it's about to execute. This won't happen if \f(CW\*(C`Spawn\*(C'\fR already has an idea of the program's location, either through a previous call to \&\f(CW\*(C`RegisterPrograms\*(C'\fR (which is how you tell \f(CW\*(C`Spawn\*(C'\fR in advance what programs you expect to be running) or if you supply a program name with directory components (either absolute or relative). Note that since searching is a sub-task of completion, \f(CW\*(C`complete\*(C'\fR must be true for \&\f(CW\*(C`search\*(C'\fR to have any effect. Also, don't assume that just because \&\f(CW\*(C`Spawn\*(C'\fR doesn't search a list of directories for your program, nobody will\-\-\-Perl's \f(CW\*(C`exec\*(C'\fR calls either the shell or \f(CWexecvp(3)\fR, which means the \s-1PATH\s0 environment variable will ultimately be searched. .ie n .IP """add_defaults"" (default: true)" 4 .el .IP "\f(CWadd_defaults\fR (default: true)" 4 .IX Item "add_defaults (default: true)" Boolean; if true, then \f(CW\*(C`Spawn\*(C'\fR will actually add the default arguments supplied with \f(CW\*(C`AddDefaultArgs\*(C'\fR to commands as appropriate. Like \&\f(CW\*(C`search\*(C'\fR, \f(CW\*(C`complete\*(C'\fR must be true for \f(CW\*(C`add_defaults\*(C'\fR to have any effect. .ie n .IP """search_path"" (default: undefined)" 4 .el .IP "\f(CWsearch_path\fR (default: undefined)" 4 .IX Item "search_path (default: undefined)" String or list ref; supplies the list of directories to search when searching for programs. This is passed directly to \&\f(CW\*(C`MNI::FileUtilities::find_programs\*(C'\fR, so the same rules apply as to the \&\f(CW$path\fR parameter to that subroutine: \f(CW\*(C`search_path\*(C'\fR may be a string containing a colon-separated list of directories or a reference to a list of directories; or it can be undefined, in which case \&\f(CW$ENV{\*(AqPATH\*(Aq}\fR is used. .Sp \&\f(CW\*(C`search_path\*(C'\fR applies both to the implicit search done by \f(CW\*(C`Spawn\*(C'\fR when it doesn't have any other information on the whereabouts of a program (and \f(CW\*(C`complete\*(C'\fR and \f(CW\*(C`search\*(C'\fR are both true), and to the search explicitly requested by calling \f(CW\*(C`RegisterPrograms\*(C'\fR. .ie n .IP """err_action"" (default: \*(Aqfatal\*(Aq)" 4 .el .IP "\f(CWerr_action\fR (default: \f(CW\*(Aqfatal\*(Aq\fR)" 4 .IX Item "err_action (default: fatal)" String; tells \f(CW\*(C`Spawn\*(C'\fR how to react when a child program crashes (has non-zero termination status). The most useful values are \f(CW\*(Aqfatal\*(Aq\fR, \&\f(CW\*(Aqnotify\*(Aq\fR, \f(CW\*(Aqwarn\*(Aq\fR, and \f(CW\*(Aqignore\*(Aq\fR; see \*(L"\s-1ERROR\s0 \s-1HANDLING\s0\*(R" below for full details. .ie n .IP """batch"" (default: false)" 4 .el .IP "\f(CWbatch\fR (default: false)" 4 .IX Item "batch (default: false)" Boolean; if true, commands will be added to the currently-open batch job (see MNI::Batch) rather than directly executed. .ie n .IP """clobber"" (default: false)" 4 .el .IP "\f(CWclobber\fR (default: false)" 4 .IX Item "clobber (default: false)" Boolean; if true, \f(CW\*(C`Spawn\*(C'\fR will overwrite files that are the destination of output redirection. \s-1NOTE:\s0 this option is ignored when running through batch; the output redirection files will be appended to if no Batch job is currently opened, or clobbered (overwriten) if you already have opened a job (by means of \fIBatch::StartJob()\fR ). .ie n .IP """loghandle"" (default: ""\e*STDOUT"")" 4 .el .IP "\f(CWloghandle\fR (default: \f(CW\e*STDOUT\fR)" 4 .IX Item "loghandle (default: *STDOUT)" Glob ref or \f(CW\*(C`IO::Handle\*(C'\fR object or \f(CW\*(C`Filehandle\*(C'\fR object; if supplied, specifies the filehandle to which \f(CW\*(C`Spawn\*(C'\fR will print the log lines described under \f(CW\*(C`verbose\*(C'\fR. .ie n .IP """notify"" (default: $ENV{\*(AqUSER\*(Aq})" 4 .el .IP "\f(CWnotify\fR (default: \f(CW$ENV{\*(AqUSER\*(Aq}\fR)" 4 .IX Item "notify (default: $ENV{USER})" User to whom \f(CW\*(C`Spawn\*(C'\fR should send mail, if a command fails and \&\f(CW\*(C`err_action\*(C'\fR is \f(CW\*(Aqnotify\*(Aq\fR. If false (eg. the empty string), then mail is \fInot\fR sent (in spite of the value of \f(CW\*(C`err_action\*(C'\fR). .ie n .IP """stdout"" (default: undefined)" 4 .el .IP "\f(CWstdout\fR (default: undefined)" 4 .IX Item "stdout (default: undefined)" Controls redirection/capture of the child program's standard output stream. If \f(CW\*(C`stdout\*(C'\fR is a string (i.e. not a reference), then it is treated as a filename and the child's stdout is redirected to the named file. If \f(CW\*(C`stdout\*(C'\fR is a scalar or array reference, the child's stdout will be captured (read through a pipe) to the referenced variable. See \&\*(L"\s-1REDIRECTION\s0 \s-1AND\s0 \s-1CAPTURING\s0\*(R", below, for full details. .ie n .IP """stderr"" (default: undefined)" 4 .el .IP "\f(CWstderr\fR (default: undefined)" 4 .IX Item "stderr (default: undefined)" Controls redirection/capture of the child program's standard error stream. Everything about \f(CW\*(C`stdout\*(C'\fR holds for \f(CW\*(C`stderr\*(C'\fR\-\-\-it can be a scalar or array ref to capture, or a string to redirect. In addition, in certain circumstances the child's stderr will be merged with its stdout. Again, see \*(L"\s-1REDIRECTION\s0 \s-1AND\s0 \s-1CAPTURING\s0\*(R" for full details. .SH "COMMAND COMPLETION" .IX Header "COMMAND COMPLETION" Before doing anything else with your command, \f(CW\*(C`Spawn\*(C'\fR attempts to fill in a few details about it. This consists of converting a bare program name to a full path and adding default arguments. Command completion can be completely disabled by setting the \f(CW\*(C`complete\*(C'\fR option to false. .PP In order to do either of these, \f(CW\*(C`Spawn\*(C'\fR must first split your command up into \*(L"program\*(R" and \*(L"argument list\*(R". If the command is represented as a list, this is trivial: the first element of the list is the program, and the other elements are the arguments. If the command is represented as a string, \f(CW\*(C`Spawn\*(C'\fR treats a leading sequence of non-whitespace characters as the program, and the rest of the string as the argument list. This means that commands that are perfectly reasonable to a shell, such as \f(CW\*(Aq ls *.foo\*(Aq\fR or \f(CW\*(Aqls>log\*(Aq\fR are not properly handled by \f(CW\*(C`Spawn\*(C'\fR (yet another reason to avoid the command-as-string method). .SS "Expanding program name" .IX Subsection "Expanding program name" If the program name is \*(L"bare\*(R" (contains no slashes), then \f(CW\*(C`Spawn\*(C'\fR will attempt to resolve it to a full path. This is first done by looking up the bare program name in an internal list of \*(L"known\*(R" programs (which you create using \f(CW\*(C`RegisterPrograms\*(C'\fR). (Keeping a list of known programs means \&\f(CW\*(C`Spawn\*(C'\fR can help save you from silly typos as well as cache program locations to avoid redundant multiple searches.) .PP If the program is not found in the list of known programs, \f(CW\*(C`Spawn\*(C'\fR tries a little harder. First, it might print a warning or even crash (depending on the value of the \f(CW\*(C`strict\*(C'\fR option) because you're trying to run a program that you didn't tell the module about ahead of time. Then, as long as the \f(CW\*(C`search\*(C'\fR option is true, \f(CW\*(C`Spawn\*(C'\fR will search the list of directories specified by the \f(CW\*(C`search_path\*(C'\fR option to find your program. If it still can't find it, then an error is triggered\-\-\-\f(CW\*(C`Spawn\*(C'\fR actually acts as though the program had run but failed with an exit status of 255 (this is the same thing Perl does when you try to \f(CW\*(C`system\*(C'\fR a non-existent program), so its action depends on the \f(CW\*(C`err_action\*(C'\fR option. .PP The result of a successful search is \fInot\fR saved anywhere\-\-\-so repeatedly running the same program may result in repeated searches for that program (another good reason to set up that \*(L"known program\*(R" list with \f(CW\*(C`RegisterPrograms\*(C'\fR). .PP If the \f(CW\*(C`search\*(C'\fR option is false, don't assume that \f(CW\*(C`Spawn\*(C'\fR will just run a program in the current directory (if it exists). \f(CW\*(C`Spawn\*(C'\fR calls Perl's \f(CW\*(C`exec\*(C'\fR function, which in turn either runs \f(CW\*(C`/bin/sh\*(C'\fR or calls the C library function \f(CW\*(C`execvp()\*(C'\fR\-\-\-both of which will search for your program if the supplied program name contains no slashes. The advantages of letting \f(CW\*(C`Spawn\*(C'\fR do the search are that the program's full path appears in the command log, and that you can search a custom path (different from the \s-1PATH\s0 environment variable). If you explicitly want to run a program in the current directory, just preface the program name with \f(CW\*(Aq./\*(Aq\fR\-\-\-that way, no searching will be done. .PP Note that one consequence of the search algorithm used by \f(CW\*(C`Spawn\*(C'\fR (and \&\f(CWexecvp(3)\fR, for that matter) is that \f(CW\*(C`Spawn\*(C'\fR, unlike (say) the C preprocessor or Perl's \f(CW\*(C`require\*(C'\fR function, will never search for programs specified as relative paths. Thus, if you try to \&\f(CW\*(C`Spawn (\*(Aq../ls\*(Aq);\*(C'\fR, then the file \fIls\fR must exist (and be executable) in the parent of the current directory when you call \f(CW\*(C`Spawn\*(C'\fR. .SS "Adding default arguments" .IX Subsection "Adding default arguments" In addition to maintaining a list of known programs, \fIMNI::Spawn\fR can also keep track of a list of default arguments to add to the command line for certain programs. In fact, it maintains two such lists: one for arguments to be inserted at the beginning of the command (\*(L"pre\*(R" arguments), and another for arguments to be tacked on at the end (\*(L"post\*(R" arguments). Since this feature is most often used for specifying program options, and since most Unix programs like their options to come first on the command line, \fIMNI::Spawn\fR assumes that you mean \*(L"pre\*(R" arguments if you don't explicitly say otherwise. .PP You can set the list of default arguments for a particular command with \&\f(CW\*(C`AddDefaultArgs\*(C'\fR; for example, .PP .Vb 1 \& AddDefaultArgs (\*(Aqls\*(Aq, \*(Aq\-1\*(Aq); .Ve .PP will cause \f(CW\*(C`Spawn\*(C'\fR always to insert \f(CW\*(Aq\-1\*(Aq\fR at the beginning of the argument list for any \f(CW\*(C`ls\*(C'\fR command. \f(CW\*(C`AddDefaultArgs\*(C'\fR takes an optional third string parameter which can be \f(CW\*(Aqpre\*(Aq\fR or \f(CW\*(Aqpost\*(Aq\fR to specify where in the command line this argument is to be added; it defaults to \f(CW\*(Aqpre\*(Aq\fR. Adding default arguments can be disabled by setting the \f(CW\*(C`add_defaults\*(C'\fR option to false. .PP You can clear the default argument lists for a program with \&\f(CW\*(C`ClearDefaultArgs\*(C'\fR. \f(CW\*(C`AddDefaultArgs\*(C'\fR and \f(CW\*(C`ClearDefaultArgs\*(C'\fR are both covered fully below, in \*(L"\s-1CONVENTIONAL\s0 \s-1INTERFACE\s0\*(R". .SH "INTERFACE TO BATCH" .IX Header "INTERFACE TO BATCH" Not implemented yet. .SH "REDIRECTION AND CAPTURING" .IX Header "REDIRECTION AND CAPTURING" The key to \fIMNI::Spawn\fR's claim to being more of a mini-shell than a maxi\-\f(CW\*(C`system\*(C'\fR call is its ability to redirect and/or capture the child program's standard output and standard error. This feature is controlled through the \f(CW\*(C`stdout\*(C'\fR and \f(CW\*(C`stderr\*(C'\fR options. .PP As mentioned above, \f(CW\*(C`stdout\*(C'\fR can be a simple string (to redirect), or a reference to a scalar or array variable (to capture). Likewise, \&\f(CW\*(C`stderr\*(C'\fR can be a string, a scalar or array reference, or one of two special constants that override \f(CW\*(C`Spawn\*(C'\fR's default behaviour. .PP The child's stdout and stderr are handled (almost) independently, so you can redirect and/or capture neither, either, or both of them as you wish. (See \*(L"Special handling of stderr\*(R" below for the only exception to this.) .SS "Redirection to a file (or filehandle)" .IX Subsection "Redirection to a file (or filehandle)" If either \f(CW\*(C`stdout\*(C'\fR or \f(CW\*(C`stderr\*(C'\fR is a simple string, that string will be treated as a filename and the corresponding stream in the child process will be redirected to that file. Normally, you can leave it at that and let \f(CW\*(C`Spawn\*(C'\fR decide\-\-\-using its \f(CW\*(C`clobber\*(C'\fR option\-\-\-whether the file in question should be clobbered or appended to. That is, you supply a bare filename, and \f(CW\*(C`Spawn\*(C'\fR will prepend either \f(CW\*(Aq>\*(Aq\fR (to clobber) or \&\f(CW\*(Aq>>\*(Aq\fR (to append), and use the resulting string as the second parameter to \f(CW\*(C`open\*(C'\fR. .PP However, if your string already starts with \f(CW\*(Aq>\*(Aq\fR, then \f(CW\*(C`Spawn\*(C'\fR leaves it alone, allowing you to choose whether to clobber or append regardless of \f(CW\*(C`Spawn\*(C'\fR's \f(CW\*(C`clobber\*(C'\fR option. To clarify: .PP .Vb 5 \& Spawn ($cmd, stdout => "log"); # maybe clobber, maybe append \& Spawn ($cmd, stdout => "log", clobber => 1); # always clobber \& Spawn ($cmd, stdout => "log", clobber => 0); # always append \& Spawn ($cmd, stdout => ">log"); # always clobber \& Spawn ($cmd, stdout => ">>log"); # always append .Ve .PP Assiduous readers of the Perl documentation will note that \f(CW\*(C`open\*(C'\fR lets you \*(L"open\*(R" more than just a filename: you can also redirect your child program's standard error or standard output to an already-open filehandle. If you're doing it yourself, this is as simple as: .PP .Vb 2 \& open (LOG, ">log") || die "couldn\*(Aqt create log: $!\en"; \& open (STDOUT, ">&LOG") || die "couldn\*(Aqt redirect stdout: $!\en"; .Ve .PP When you're trying to persuade \f(CW\*(C`Spawn\*(C'\fR to do this for you, it's a tad more involved. First, since \f(CW\*(C`Spawn\*(C'\fR lives in a different package from your filehandle, you have to specify the filehandle's package. Also, while\-\-\-according to the above rules\-\-\-you could get away with supplying \&\f(CW\*(Aq&LOG\*(Aq\fR as the \*(L"filename\*(R" and letting \f(CW\*(C`Spawn\*(C'\fR prepend \f(CW\*(Aq>\*(Aq\fR or \&\f(CW\*(Aq>>\*(Aq\fR as appropriate, this is not recommended. According to the Perl documentation, the modes used for the two open statements (one to open the actual file, one to duplicate the filehandle) should be the same. Since \f(CW\*(C`Spawn\*(C'\fR doesn't know how you originally opened your file, you should supply the open mode (\f(CW\*(Aq>\*(Aq\fR or \f(CW\*(Aq>>\*(Aq\fR). Finally, to make things a little more predictable, it's a good idea to put your filehandle into autoflush mode. .PP For example: .PP .Vb 5 \& use FileHandle; \& ... \& open (LOG, ">log") || die "couldn\*(Aqt create log: $!\en"; \& LOG\->autoflush; \& Spawn ($cmd, stdout => ">&main::LOG"); .Ve .SS "Capture to a variable" .IX Subsection "Capture to a variable" If \f(CW\*(C`stdout\*(C'\fR or \f(CW\*(C`stderr\*(C'\fR is a reference to a scalar or array variable, the corresponding stream will be \*(L"captured\*(R" by \f(CW\*(C`Spawn\*(C'\fR and put into the referenced variable. Capturing to a scalar will result in all of the child's output lines being concatenated with newlines preserved; capturing to an array means that one output line will go to each element of the array with newlines removed. .SS "Special handling of stderr" .IX Subsection "Special handling of stderr" If you don't otherwise specify what to do with the child's standard error (i.e., the \f(CW\*(C`stderr\*(C'\fR option is undefined), \fIand\fR you are redirecting stdout, then \f(CW\*(C`Spawn\*(C'\fR will automatically merge the child's stderr into its stdout. (That is, it will redirect stderr to \&\f(CW\*(Aq&STDOUT\*(Aq\fR.) This is usually desirable; if you're going to the trouble to keep a program's output, you probably want to keep its error messages in the same place. You can easily override this by redirecting or capturing stderr separately; for example, .PP .Vb 1 \& Spawn ([\*(Aqls\*(Aq, @files], stdout => \*(Aqls.log\*(Aq); .Ve .PP would put the child's stdout and stderr both in \fIls.log\fR, whereas .PP .Vb 1 \& Spawn ([\*(Aqls\*(Aq, @files], stdout => \*(Aqls.log\*(Aq, stderr => \*(Aqls.err\*(Aq); .Ve .PP would redirect them separately, and .PP .Vb 1 \& Spawn ([\*(Aqls\*(Aq, @files], stdout => \*(Aqls.log\*(Aq, stderr => \e$errors); .Ve .PP would redirect stdout and capture stderr to the \f(CW$errors\fR variable. .PP If you want to leave the child's stderr explicitly untouched, \&\fIMNI::Spawn\fR provides a special constant \f(CW\*(C`UNTOUCHED\*(C'\fR: .PP .Vb 1 \& Spawn ([\*(Aqls\*(Aq, @files], stdout => \*(Aqls.log\*(Aq, stderr => UNTOUCHED); .Ve .PP will redirect the child's stdout, but leave its stderr alone\-\-\-so it will wind up on the stderr of your program. .PP Finally, if you want to force \f(CW\*(C`Spawn\*(C'\fR to merge stderr with stdout, a second special constant, \f(CW\*(C`MERGE\*(C'\fR, is provided: .PP .Vb 1 \& Spawn ([\*(Aqls\*(Aq, @files], stdout => \e@output, stderr => MERGE); .Ve .PP will cause the child's stdout and stderr both to be captured to the \&\f(CW@output\fR array. Due to the mercurial nature of output buffering, it is unwise to make any assumptions about the order of error and output messages in this array. In fact, this sort of trickery is generally unwise in any case, because of the danger that the end user will never see some error messages at all\-\-\-almost always a situation to be avoided. It's usually best just to leave the child's stderr alone (or let \f(CW\*(C`Spawn\*(C'\fR merge it into a stdout log file), to maximize the end user's chance of seeing his error messages. .SH "INTERFACE TO MNI::STARTUP" .IX Header "INTERFACE TO MNI::STARTUP" Apart from the trickery involved in setting default values for the \&\f(CW\*(C`verbose\*(C'\fR and \f(CW\*(C`execute\*(C'\fR options, \fIMNI::Spawn\fR has another possible interaction with the \fIMNI::Startup\fR module. To make things interesting, however, this is an interaction with \fIMNI::Startup\fR\-\-\-in particular, the \f(CW\*(C`self_announce\*(C'\fR subroutine\-\-\-in child programs spawned by \f(CW\*(C`Spawn\*(C'\fR. .PP In particular, \f(CW\*(C`Spawn\*(C'\fR decides whether the child ought to announce its arguments (and other details of its execution environment) to the world. Normally, when a program's output is being logged to a file, it should make such an announcement. However, if \f(CW\*(C`Spawn\*(C'\fR's \f(CW\*(C`verbose\*(C'\fR option is true, it will have already done so. If the child program's output is not being redirected\-\-\-i.e. it will wind up in the same place as its parent's output, including \f(CW\*(C`Spawn\*(C'\fR's verbosities\-\-\-then having the child print its command line would be redundant and contribute needless clutter to the parent's log file. Thus, in that case, \f(CW\*(C`Spawn\*(C'\fR sets the environment variable \f(CW\*(C`suppress_announce\*(C'\fR to true. (It also sets the environment variable if the child's output is being captured; in that case, you probably don't want to have to filter out the excess lines in the capture variable.) .PP It is then the responsibility of \f(CW\*(C`MNI::Startup::self_announce\*(C'\fR in the child program to check the value of \f(CW\*(C`suppress_announce\*(C'\fR and act appropriately. See MNI::Startup for details of that side of the conspiracy. .SH "ERROR HANDLING" .IX Header "ERROR HANDLING" Paying attention to the failure of a child program is an important aspect of writing robust programs. In the shell (or Perl, just using \&\f(CW\*(C`system\*(C'\fR), this is a pain\-\-\-you have to check \f(CW$?\fR (or \f(CW\*(C`system\*(C'\fR's return value) after every single invocation of an external program, e.g. .PP .Vb 2 \& system ("ls", @files) && die "ls failed\en"; \& system ("cp", @files, $newdir) && die "cp failed\en"; .Ve .PP (Note that since \f(CW\*(C`system\*(C'\fR just returns the child's termination status, non-zero indicates failure.) .PP The most obvious solution to this is to write a toy subroutine that does the check for you: .PP .Vb 3 \& sub execute \& { \& my @cmd = @_; \& \& system (@cmd) && die "$cmd[0] failed\en"; \& } .Ve .PP \&\fIMNI::Spawn\fR in fact grew out of just such a subroutine, with a few features added here and there. The main advantage \fIMNI::Spawn\fR offers over this simple subroutine (for error handling, at least) is the customizable response to a child program's failure or abnormal termination. .PP First, a child is deemed to have crashed any time its termination status is non-zero. The \fItermination status\fR is the 16\-bit word provided by the \&\f(CW\*(C`wait()\*(C'\fR and \f(CW\*(C`waitpid()\*(C'\fR system calls, and made available in Perl through the \f(CW$?\fR special variable. It encapsulates both the exit status\-\-\-which is passed by a program to \f(CW\*(C`exit()\*(C'\fR in the case of normal termination\-\-\-and the signal number responsible for a program's abnormal termination (if any). Currently, \fIMNI::Spawn\fR treats any non-zero termination status the same: the child program is deemed to have \*(L"crashed\*(R". .PP When such a crash is detected, \f(CW\*(C`Spawn\*(C'\fR takes its directions from the \&\f(CW\*(C`err_action\*(C'\fR option. Currently the following values are supported: .ie n .IP "\*(Aqfatal\*(Aq (default)" 4 .el .IP "\f(CW\*(Aqfatal\*(Aq\fR (default)" 4 .IX Item "fatal (default)" \&\f(CW\*(C`Spawn\*(C'\fR will \f(CW\*(C`die\*(C'\fR (with a useful error message giving the name of your program, the sub-program that crashed, and its termination status) whenever a child program crashes. .ie n .IP "\*(Aqnotify\*(Aq" 4 .el .IP "\f(CW\*(Aqnotify\*(Aq\fR" 4 .IX Item "notify" \&\f(CW\*(C`Spawn\*(C'\fR will mail a detailed description of the child program's crash, and then \f(CW\*(C`die\*(C'\fR just like \f(CW\*(Aqfatal\*(Aq\fR. The recipient of the mail is specified by the \f(CW\*(C`notify\*(C'\fR option, which defaults to \f(CW$ENV{\*(AqUSER\*(Aq}\fR; if \f(CW\*(C`notify\*(C'\fR is false (e.g. empty or undefined), or if \f(CW\*(C`execute\*(C'\fR is false, then the mail is not sent. .ie n .IP "\*(Aqwarn\*(Aq" 4 .el .IP "\f(CW\*(Aqwarn\*(Aq\fR" 4 .IX Item "warn" \&\f(CW\*(C`Spawn\*(C'\fR will print a warning message and return the child's termination status to its caller. .ie n .IP "\*(Aqignore\*(Aq" 4 .el .IP "\f(CW\*(Aqignore\*(Aq\fR" 4 .IX Item "ignore" \&\f(CW\*(C`Spawn\*(C'\fR will simply return the child's termination status to its caller without printing any warning message. .ie n .IP "\*(Aq\*(Aq (\fIempty string\fR or undefined)" 4 .el .IP "\f(CW\*(Aq\*(Aq\fR (\fIempty string\fR or undefined)" 4 .IX Item " (empty string or undefined)" The same as \f(CW\*(Aqwarn\*(Aq\fR for backwards compatibility. (This was the default in previous incarnations of \fIMNI::Spawn\fR.) .IP "\fIany other non-empty string\fR" 4 .IX Item "any other non-empty string" The string is \f(CW\*(C`eval\*(C'\fR'd as Perl code in the package of \f(CW\*(C`Spawn\*(C'\fR's caller. If you have a regular and consistent need for this hack, err feature, please let me know\-\-\-it's probably something that should be added to the list of \*(L"magic keywords\*(R". You should avoid using code that consists solely of a string of lowercase letters and underscores, as I reserve that for future \*(L"magic keywords\*(R" (like \f(CW\*(Aqfatal\*(Aq\fR). .PP Note that \f(CW\*(C`Spawn\*(C'\fR returns the termination status (assuming it returns at all), so if it doesn't crash your program you can still detect failed executions. .SH "CONVENTIONAL INTERFACE" .IX Header "CONVENTIONAL INTERFACE" The subroutines provided by the conventional interface are: .IP "SetOptions (\s-1OPTION\s0, \s-1VALUE\s0, ...)" 4 .IX Item "SetOptions (OPTION, VALUE, ...)" Sets one or more module options. Croaks if any \s-1OPTION\s0 argument is not one of the known options, or if you don't supply an even number of arguments. See \*(L"\s-1OPTIONS\s0\*(R" for brief descriptions of all the options; complete details are scattered throughout the relevant sections of this man page. .IP "RegisterPrograms (\s-1PROGRAMS\s0 [, \s-1PATH\s0])" 4 .IX Item "RegisterPrograms (PROGRAMS [, PATH])" Tells \fIMNI::Spawn\fR about the programs you intend to run during the lifetime of your program. \s-1PROGRAMS\s0 must be a reference to either a list or a hash; \s-1PATH\s0, if it is given, must be either a reference to a list of directories or a string containing colon-separated directories. If \s-1PATH\s0 is not given, the \f(CW\*(C`search_path\*(C'\fR option is used (which in turn effectively defaults to \f(CW$ENV{\*(AqPATH\*(Aq}\fR). .Sp If \s-1PROGRAMS\s0 is a list reference, the list in question should be of bare program names (no directory components). Each program listed in \&\s-1PROGRAMS\s0 is searched for in the directories listed in \s-1PATH\s0 (or \&\f(CW\*(C`search_path\*(C'\fR, or \f(CW$ENV{\*(AqPATH\*(Aq}\fR); if any are not found, an appropriate error message (e.g. 'Couldn't find program \*(L"foo\*(R"') is printed for each missing program and \f(CW\*(C`RegisterPrograms\*(C'\fR returns false. In the event of such a failure, any successful search results are \fInot\fR kept\-\-\-this should almost always be treated as a fatal error, so \&\fIMNI::Spawn\fR doesn't expect that you'll continue marching blithely on. Only if all programs listed in \s-1PROGRAMS\s0 are found does \&\f(CW\*(C`RegisterPrograms\*(C'\fR store the full paths for later use by \f(CW\*(C`Spawn\*(C'\fR (in the \*(L"command completion\*(R" phase); it then returns true. Thus, this is usually called like .Sp .Vb 1 \& RegisterPrograms ([qw(ls rm cat cp)]) || exit 1; .Ve .Sp where we don't print an error message because \f(CW\*(C`RegisterPrograms\*(C'\fR takes care of it for us. .Sp If \s-1PROGRAMS\s0 is a hash reference, the keys of the hash must be program names, and the values must be full paths to the executable file that you want to run when \f(CW\*(C`Spawn\*(C'\fR is passed the corresponding program name. For instance, you might wish to force \f(CW\*(C`Spawn\*(C'\fR to run \f(CW\*(C`gtar\*(C'\fR in place of \&\f(CW\*(C`tar\*(C'\fR. This could be accomplished as follows: .Sp .Vb 2 \& $gtar = MNI::FileUtilities::find_program (\*(Aqgtar\*(Aq); \& RegisterPrograms ({ tar => $gtar }) || exit 1; .Ve .Sp Later on, you might have the following: .Sp .Vb 1 \& Spawn ([\*(Aqtar\*(Aq, $taropts, $tarfile, $dir]); .Ve .Sp in which case \f(CW\*(C`Spawn\*(C'\fR would actually run \f(CW\*(C`gtar\*(C'\fR (or, more accurately, the \f(CW\*(C`gtar\*(C'\fR found by \f(CW\*(C`MNI::FileUtilities::find_program\*(C'\fR). .Sp \&\f(CW\*(C`RegisterPrograms\*(C'\fR can be called any number of times in your program\-\-\-it always adds to the existing list of \*(L"known programs\*(R", and silently overrides any programs you previously registered. .Sp See also \f(CW\*(C`find_programs\*(C'\fR, \f(CW\*(C`find_program\*(C'\fR, and \f(CW\*(C`search_directories\*(C'\fR in MNI::FileUtilities. .IP "AddDefaultArgs (\s-1PROGRAMS\s0, \s-1ARGS\s0 [, \s-1WHERE\s0])" 4 .IX Item "AddDefaultArgs (PROGRAMS, ARGS [, WHERE])" Adds to one of the default argument lists for one or more programs. \&\s-1PROGRAMS\s0 can be either a string (the name of a single program) or an array reference (list of several programs); in the latter case, the same arguments will be added to the default argument list for each listed program. \s-1ARGS\s0 may be a single argument (a string), or a reference to a list of arguments. \s-1WHERE\s0, if given, must be either \f(CW\*(Aqpre\*(Aq\fR or \&\f(CW\*(Aqpost\*(Aq\fR\-\-\-it tells which of the two default argument lists we should add \s-1ARGS\s0 to, i.e. where in the argument list these arguments should be added when it comes to \*(L"command completion\*(R" time in \f(CW\*(C`Spawn\*(C'\fR. It defaults to \f(CW\*(Aqpre\*(Aq\fR. .Sp This is most useful if you have a flag in your program that you wish to propagate (via command line options) to other programs. For instance, you might wish to have a \f(CW$Verbose\fR flag determine the presence of \&\f(CW\*(C`\-quiet\*(C'\fR on the command lines of various sub-programs: .Sp .Vb 2 \& AddDefaultArgs ([qw(mincresample mincreshape mincmath)], \*(Aq\-quiet\*(Aq) \& unless $Verbose; .Ve .IP "ClearDefaultArgs (\s-1PROGRAMS\s0 [, \s-1WHERE\s0])" 4 .IX Item "ClearDefaultArgs (PROGRAMS [, WHERE])" Clears one or both of the default argument lists for one or more programs. Like with \f(CW\*(C`AddDefaultArgs\*(C'\fR, \s-1PROGRAMS\s0 may be a single program (a string) or a reference to a list of programs. \s-1WHERE\s0, if given, may be \f(CW\*(Aqpre\*(Aq\fR, \f(CW\*(Aqpost\*(Aq\fR, or \f(CW\*(Aqboth\*(Aq\fR\-\-\-it tells whether to delete the list of \*(L"pre\*(R" arguments, \*(L"post\*(R" arguments, or both lists. It defaults to \f(CW\*(C`both\*(C'\fR. .IP "Spawn (\s-1COMMAND\s0 [, \s-1OPTION\s0, \s-1VALUE\s0, ...])" 4 .IX Item "Spawn (COMMAND [, OPTION, VALUE, ...])" Executes a single command. (Or, more accurately, \f(CW\*(C`fork\*(C'\fRs and \f(CW\*(C`exec\*(C'\fRs the command in the child process with appropriate output/error redirection.) Option/value pairs may be supplied as for \f(CW\*(C`SetOptions\*(C'\fR; they only take effect for the duration of this \f(CW\*(C`Spawn\*(C'\fR call, though. \s-1COMMAND\s0 may be a string or a list ref; if it is a string, the same caveats as for Perl's \&\f(CW\*(C`system\*(C'\fR and \f(CW\*(C`exec\*(C'\fR functions apply\-\-\-namely, that the presence of shell metacharacters in your command string means it will be processed by \&\f(CW\*(C`/bin/sh\*(C'\fR; otherwise, it will be handled directly by Perl. For this reason, it is best to stick to the \*(L"command as list\*(R" paradigm; most uses for shell metacharacters can be better done within Perl, either using standard Perl features or \fIMNI::Spawn\fR's redirection/capture feature. For example, you can replace any shell globbing pattern with \f(CW\*(C`opendir\*(C'\fR, \&\f(CW\*(C`readdir\*(C'\fR, and \f(CW\*(C`grep\*(C'\fR (and use Perl's more powerful regular expression engine); most pipelines involving standard Unix utilities like \f(CW\*(C`grep\*(C'\fR, \&\f(CW\*(C`sed\*(C'\fR, \f(CW\*(C`awk\*(C'\fR, \f(CW\*(C`cut\*(C'\fR, etc. are easily and more efficiently implemented directly in Perl; and, of course, \f(CW\*(C`Spawn\*(C'\fR can do output redirection or capturing for you. .Sp Returns the program's termination status (this is the 16\-bit word supplied by \f(CWwaitpid(2)\fR that includes both the program's exit status and the signal that killed it, if any). If we couldn't even run the program, returns a made-up non-zero termination status (\f(CW\*(C`255 >> 8\*(C'\fR, for what it's worth). Thus, any non-zero return value implies failure. Thus, an alternative to setting the \f(CW\*(C`err_action\*(C'\fR option to \f(CW\*(Aqfatal\*(Aq\fR is: .Sp .Vb 2 \& MNI::Spawn::SetOptions (err_action => \*(Aqignore\*(Aq); # or \*(Aqwarn\*(Aq \& Spawn ($cmd) && die "$cmd failed\en"; .Ve .Sp Complete details of \f(CW\*(C`Spawn\*(C'\fR's operation are given in \&\*(L"\s-1COMMAND\s0 \s-1COMPLETION\s0\*(R", \*(L"\s-1INTERFACE\s0 \s-1TO\s0 \s-1BATCH\s0\*(R", \&\*(L"\s-1REDIRECTION\s0 \s-1AND\s0 \s-1CAPTURING\s0\*(R", and \*(L"\s-1ERROR\s0 \s-1HANDLING\s0\*(R" above. .SH "OBJECT-ORIENTED INTERFACE" .IX Header "OBJECT-ORIENTED INTERFACE" The methods provided by the object-oriented interface are: .IP "new ([\s-1OPTION\s0, \s-1VALUE\s0, ...])" 4 .IX Item "new ([OPTION, VALUE, ...])" Creates a new \fIMNI::Spawn\fR object (a spawner). You may supply option/value pairs just like with \f(CW\*(C`SetOptions\*(C'\fR and \f(CW\*(C`set_options\*(C'\fR here. .IP "copy" 4 .IX Item "copy" Creates a copy of an existing \fIMNI::Spawn\fR object, with internal data structures duplicated so that the copy may be changed independently of its parent. .IP "set_options (\s-1OPTION\s0, \s-1VALUE\s0, ...)" 4 .IX Item "set_options (OPTION, VALUE, ...)" Same as \f(CW\*(C`SetOptions\*(C'\fR subroutine, except called as a method: .Sp .Vb 1 \& $spawner\->set_options (option, value, ...); .Ve .IP "register_programs (\s-1PROGRAMS\s0 [, \s-1PATH\s0])" 4 .IX Item "register_programs (PROGRAMS [, PATH])" Same as \f(CW\*(C`RegisterPrograms\*(C'\fR, except called as a method. .IP "add_default_args (\s-1PROGRAMS\s0, \s-1ARGS\s0 [, \s-1WHERE\s0])" 4 .IX Item "add_default_args (PROGRAMS, ARGS [, WHERE])" Same as \f(CW\*(C`AddDefaultArgs\*(C'\fR, except called as a method. .IP "clear_default_args (\s-1PROGRAMS\s0 [, \s-1WHERE\s0])" 4 .IX Item "clear_default_args (PROGRAMS [, WHERE])" Same as \f(CW\*(C`ClearDefaultArgs\*(C'\fR, except called as a method. .IP "spawn (\s-1COMMAND\s0 [, \s-1OPTION\s0, \s-1VALUE\s0, ...])" 4 .IX Item "spawn (COMMAND [, OPTION, VALUE, ...])" Same as \f(CW\*(C`Spawn\*(C'\fR, except called as a method. .SH "AUTHOR" .IX Header "AUTHOR" Greg Ward, . .SH "COPYRIGHT" .IX Header "COPYRIGHT" Copyright (c) 1997 by Gregory P. Ward, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. .PP This file is part of the \s-1MNI\s0 Perl Library. It is free software, and may be distributed under the same terms as Perl itself.