By Tom Christiansen and Nathan Torkington ISBN 1-56592-243-3 First Edition, published August 1998

源代码在线查看: ch16_05.htm

软件大小: 1747 K
上传用户: tiandl
关键词: Christiansen Torkington published Edition
下载地址: 免注册下载 普通下载 VIP

相关代码

								>				>				Recipe 16.4. Reading or Writing to Another Program (Perl Cookbook)								NAME="DC.title"				CONTENT="Perl Cookbook">				NAME="DC.creator"				CONTENT="Tom Christiansen & Nathan Torkington">				NAME="DC.publisher"				CONTENT="O'Reilly & Associates, Inc.">				NAME="DC.date"				CONTENT="1999-07-02T01:43:41Z">				NAME="DC.type"				CONTENT="Text.Monograph">				NAME="DC.format"				CONTENT="text/html"				SCHEME="MIME">				NAME="DC.source"				CONTENT="1-56592-243-3"				SCHEME="ISBN">				NAME="DC.language"				CONTENT="en-US">				NAME="generator"				CONTENT="Jade 1.1/O'Reilly DocBook 3.0 to HTML 4.0">				REV="made"				HREF="mailto:online-books@oreilly.com"				TITLE="Online Books Comments">				REL="up"				HREF="ch16_01.htm"				TITLE="16. Process Management and Communication">				REL="prev"				HREF="ch16_04.htm"				TITLE="16.3. Replacing the Current Program with a Different One">				REL="next"				HREF="ch16_06.htm"				TITLE="16.5. Filtering Your Own Output">				>				BGCOLOR="#FFFFFF">								WIDTH="684"				BORDER="0"				CELLSPACING="0"				CELLPADDING="0"				>				>				ALIGN="LEFT"				VALIGN="TOP"				WIDTH="228"				>				CLASS="sect1"				HREF="ch16_04.htm"				TITLE="16.3. Replacing the Current Program with a Different One"				>				SRC="../gifs/txtpreva.gif"				ALT="Previous: 16.3. Replacing the Current Program with a Different One"				BORDER="0">				>				>				ALIGN="CENTER"				VALIGN="TOP"				WIDTH="228"				>				>				FACE="ARIEL,HELVETICA,HELV,SANSERIF"				SIZE="-1"				>				CLASS="chapter"				REL="up"				HREF="ch16_01.htm"				TITLE="16. Process Management and Communication"				>				>				>				>				>				ALIGN="RIGHT"				VALIGN="TOP"				WIDTH="228"				>				CLASS="sect1"				HREF="ch16_06.htm"				TITLE="16.5. Filtering Your Own Output"				>				SRC="../gifs/txtnexta.gif"				ALT="Next: 16.5. Filtering Your Own Output"				BORDER="0">				>				>				>				>				>				CLASS="sect1"				>				CLASS="sect1"				>				CLASS="title"				NAME="ch16-16252"				>16.4. Reading or Writing to Another Program				>				>				CLASS="sect2"				>				CLASS="sect2"				>				CLASS="title"				NAME="ch16-pgfId-988"				>Problem				CLASS="indexterm"				NAME="ch16-idx-1000006259-0"				>				>				CLASS="indexterm"				NAME="ch16-idx-1000006259-1"				>				>				CLASS="indexterm"				NAME="ch16-idx-1000006259-2"				>				>				CLASS="indexterm"				NAME="ch16-idx-1000006259-3"				>				>				CLASS="indexterm"				NAME="ch16-idx-1000006259-4"				>				>				>				>				CLASS="para"				>You want to run another program and either read its output or supply the program with input.				>				>				CLASS="sect2"				>				CLASS="sect2"				>				CLASS="title"				NAME="ch16-pgfId-994"				>Solution				>				>				CLASS="para"				>Use 				CLASS="literal"				>open				>				CLASS="indexterm"				NAME="ch16-idx-1000006265-0"				>				>				CLASS="indexterm"				NAME="ch16-idx-1000006265-1"				>				> with a pipe symbol at the beginning or end. To read from a program, put the pipe symbol at the end:				>				CLASS="programlisting"				>$pid = open(README, "program arguments |")  or die "Couldn't fork: $!\n";				while (<README>) {				    # ...				}				close(README)                               or die "Couldn't close: $!\n";				>				CLASS="para"				>To write to the program, put the pipe at the beginning:				>				CLASS="programlisting"				>$pid = open(WRITEME, "| program arguments") or die "Couldn't fork: $!\n";				print WRITEME "data\n";				close(WRITEME)                              or die "Couldn't close: $!\n";				>				>				CLASS="sect2"				>				CLASS="sect2"				>				CLASS="title"				NAME="ch16-pgfId-1018"				>Discussion				>				>				CLASS="para"				>In the case of reading, this is similar to using backticks, except you have a process ID and a filehandle. As with the backticks, 				CLASS="literal"				>open				> uses the shell if it sees shell-special characters in its argument, but it doesn't if there aren't any. This is usually a welcome convenience, because it lets the shell do filename wildcard expansion and I/O redirection, saving you the trouble.				>				CLASS="para"				>However, sometimes this isn't desirable. Piped 				CLASS="literal"				>open				>s that include unchecked user data would be unsafe while running in taint mode or in untrustworthy situations. 				CLASS="xref"				HREF="ch19_07.htm"				TITLE="Executing Commands Without Shell Escapes"				>Recipe 19.6				> shows how to get the effect of a piped 				CLASS="literal"				>open				> without risking using the shell.				>				CLASS="para"				>Notice how we specifically call 				CLASS="literal"				>close				> on the filehandle. When you use 				CLASS="literal"				>open				> to connect a filehandle to a child process, Perl remembers this and automatically waits for the child when you close the filehandle. If the child hasn't exited by then, Perl waits until it does. This can be a very, very long wait if your child doesn't exit:				>				CLASS="programlisting"				>$pid = open(F, "sleep 100000|");    # child goes to sleep				close(F);                           # and the parent goes to lala land				>				CLASS="para"				>To avoid this, you can save the PID returned by 				CLASS="literal"				>open				> to kill your child, or use a manual 				CLASS="literal"				>pipe				>-				CLASS="literal"				>fork				>-				CLASS="literal"				>exec				> sequence as described in 				CLASS="xref"				HREF="ch16_11.htm"				TITLE="Communicating Between Related Processes"				>Recipe 16.10				>.				>				CLASS="para"				>If you attempt to write to a process that has gone away, your process will receive a 				CLASS="indexterm"				NAME="ch16-idx-1000006280-0"				>				>SIGPIPE. The default disposition for this signal is to kill your process, so the truly paranoid install a SIGPIPE handler just in case.				>				CLASS="para"				>If you want to run another program and be able to supply its STDIN yourself, a similar construct is used:				>				CLASS="programlisting"				>$pid = open(WRITEME, "| program args");				print WRITEME "hello\n";            # program will get hello\n on STDIN				close(WRITEME);                     # program will get EOF on STDIN				>				CLASS="para"				>The leading pipe symbol in the filename argument to 				CLASS="literal"				>open				> tells Perl to start another process instead. It connects the 				CLASS="literal"				>open				>ed filehandle to the process's STDIN. Anything you write to the filehandle can be read by the program through its STDIN. When you 				CLASS="literal"				>close				> the filehandle, the 				CLASS="literal"				>open				>ed process will get an 				CLASS="literal"				>eof				> when it next tries to read from STDIN.				>				CLASS="para"				>You can also use this technique to change your program's normal output path. For example, to automatically run everything through a pager, use something like:				>				CLASS="programlisting"				>$pager = $ENV{PAGER} || '/usr/bin/less';  # XXX: might not exist				open(STDOUT, "| $pager");				>				CLASS="para"				>Now, without changing the rest of your program, anything you print to standard output will go through the pager automatically.				>				CLASS="para"				>As with 				CLASS="literal"				>open				>ing a process for reading, text passed to the shell here is subject to shell metacharacter interpretation. To avoid the shell, a similar solution is called for. As before, the parent should also be wary of 				CLASS="literal"				>close				>. If the parent closes the filehandle connecting it to the child, the parent will block while waiting for the child to finish. If the child doesn't finish, neither will the close. The workaround as before is either to kill your child process prematurely, or else use the low-level 				CLASS="literal"				>pipe				>-				CLASS="literal"				>fork				>-				CLASS="literal"				>exec				> scenario.				>				CLASS="para"				>When using piped opens, always check return values of both 				CLASS="literal"				>open				> and 				CLASS="literal"				>close				>, not just of 				CLASS="literal"				>open				>. That's because the return value from 				CLASS="literal"				>open				> does not indicate whether the command was succesfully launched. With a piped open, you fork a child to execute the command. Assuming the system hadn't run out of processes, the 				CLASS="literal"				>fork				> immediately returns the PID of the child it just created.				CLASS="literal"				>				>				CLASS="indexterm"				NAME="ch16-idx-1000006267-0"				>				>				CLASS="indexterm"				NAME="ch16-idx-1000006267-1"				>				>				>				CLASS="para"				>By the time the child process tries to 				CLASS="literal"				>exec				> the command, it's a separately scheduled process. So if the command can't be found, there's effectively no way to communicate this back to the 				CLASS="literal"				>open				> function, because that function is in a different process!				>				CLASS="para"				>Check the return value from 				CLASS="literal"				>close				> to see whether the command was successful. If the child process exits with non-zero status - which it will do if the command isn't found - the 				CLASS="literal"				>close				> returns false and 				CLASS="literal"				>$?				> is set to the wait status of that process. You can interpret its contents as described in 				CLASS="xref"				HREF="ch16_20.htm"				TITLE="Avoiding Zombie Processes"				>Recipe 16.19				>.				>				CLASS="para"				>In the case of a pipe opened for writing, you should also install a SIGPIPE handler, since writing to a child that isn't there will trigger a SIGPIPE.				CLASS="indexterm"				NAME="ch16-idx-1000006261-0"				>				>				CLASS="indexterm"				NAME="ch16-idx-1000006261-1"				>				>				CLASS="indexterm"				NAME="ch16-idx-1000006261-2"				>				>				CLASS="indexterm"				NAME="ch16-idx-1000006261-3"				>				>				CLASS="indexterm"				NAME="ch16-idx-1000006261-4"				>				>				>				>				CLASS="sect2"				>				CLASS="sect2"				>				CLASS="title"				NAME="ch16-pgfId-1064"				>See Also				>				>				CLASS="para"				>The 				CLASS="olink"				HREF="../prog/ch03_102.htm"				>				CLASS="literal"				>open				>				> function in 				CLASS="olink"				HREF="../prog/ch03_01.htm"				>Chapter 3				> of 				CLASS="citetitle"				HREF="../prog/index.htm"				TITLE="Programming Perl"				>				CLASS="citetitle"				>Programming Perl				>				> and in 				CLASS="filename"				>perlfunc 				>(1); 				CLASS="xref"				HREF="ch16_11.htm"				TITLE="Communicating Between Related Processes"				>Recipe 16.10				>; 				CLASS="xref"				HREF="ch16_16.htm"				TITLE="Installing a Signal Handler"				>Recipe 16.15				>; 				CLASS="xref"				HREF="ch16_20.htm"				TITLE="Avoiding Zombie Processes"				>Recipe 16.19				>; 				CLASS="xref"				HREF="ch19_07.htm"				TITLE="Executing Commands Without Shell Escapes"				>Recipe 19.6				>				>				>				>				CLASS="htmlnav"				>				>				>				ALIGN="LEFT"				WIDTH="684"				TITLE="footer">				WIDTH="684"				BORDER="0"				CELLSPACING="0"				CELLPADDING="0"				>				>				ALIGN="LEFT"				VALIGN="TOP"				WIDTH="228"				>				CLASS="sect1"				HREF="ch16_04.htm"				TITLE="16.3. Replacing the Current Program with a Different One"				>				SRC="../gifs/txtpreva.gif"				ALT="Previous: 16.3. Replacing the Current Program with a Different One"				BORDER="0">				>				>				ALIGN="CENTER"				VALIGN="TOP"				WIDTH="228"				>				CLASS="book"				HREF="index.htm"				TITLE="Perl Cookbook"				>				SRC="../gifs/txthome.gif"				ALT="Perl Cookbook"				BORDER="0">				>				>				ALIGN="RIGHT"				VALIGN="TOP"				WIDTH="228"				>				CLASS="sect1"				HREF="ch16_06.htm"				TITLE="16.5. Filtering Your Own Output"				>				SRC="../gifs/txtnexta.gif"				ALT="Next: 16.5. Filtering Your Own Output"				BORDER="0">				>				>				>				>				ALIGN="LEFT"				VALIGN="TOP"				WIDTH="228"				>16.3. Replacing the Current Program with a Different One				>				ALIGN="CENTER"				VALIGN="TOP"				WIDTH="228"				>				CLASS="index"				HREF="index/index.htm"				TITLE="Book Index"				>				SRC="../gifs/index.gif"				ALT="Book Index"				BORDER="0">				>				>				ALIGN="RIGHT"				VALIGN="TOP"				WIDTH="228"				>16.5. Filtering Your Own Output				>				>				>				ALIGN="LEFT"				WIDTH="684"				TITLE="footer">				SIZE="-1"				>				>				>							

相关资源