<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>The Effective Perler &#187; external interactions</title>
	<atom:link href="http://www.effectiveperlprogramming.com/blog/category/book/new-chapters/external-interactions/feed" rel="self" type="application/rss+xml" />
	<link>http://www.effectiveperlprogramming.com</link>
	<description>Effective Perl Programming - write better, more idiomatic Perl</description>
	<lastBuildDate>Sat, 28 Jan 2012 02:19:01 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Interact with the system when Perl isn&#8217;t enough</title>
		<link>http://www.effectiveperlprogramming.com/blog/150</link>
		<comments>http://www.effectiveperlprogramming.com/blog/150#comments</comments>
		<pubDate>Sun, 18 Apr 2010 04:36:09 +0000</pubDate>
		<dc:creator>Josh McAdams</dc:creator>
				<category><![CDATA[external interactions]]></category>
		<category><![CDATA[item]]></category>

		<guid isPermaLink="false">http://www.effectiveperlprogramming.com/?p=150</guid>
		<description><![CDATA[Usually, you want to do as much of your work inside your Perl program as you can. CPAN has a wealth of modules that accomplish many tasks, including those that you normally do very easily from the command line. In the cases where you can&#8217;t find a module, you might not be able to improve [...]]]></description>
			<content:encoded><![CDATA[<p>Usually, you want to do as much of your work inside your Perl program as you can. <a href="http://search.cpan.org">CPAN</a> has a wealth of modules that accomplish many tasks, including those that you normally do very easily from the command line. In the cases where you can&#8217;t find a module, you might not be able to improve on the command-line siutation for complicated tasks. Perl is, after all, a glue language, so you don&#8217;t always have to do everything in Perl. When you decide to use an external program, there are many Perl features waiting to help, although you have to choose the right one for the job.</p>
<h3>Backticks capture output</h3>
<p>One of the easiest and most common methods of running a command on the underlying operating system is to simply put the command in backticks. Whatever text you put in in the backticks is executed on the system. The backticks also trigger the same interpolation that double-quotes do, so you can place variables in the backticks and they will be converted into text before Perl executes the command.</p>
<p>If you use the backticks in scalar context, Perl returns all of the standard output (but not standard error!) as a single, possibly multi-line string. If you use it in list context, then Perl returns a list that has one line per element:</p>
<pre class="brush:perl"># Full directory listing in a single scalar
my $output = `ls -l`;

# Full directory listing, one line per list item
my @output = `ls -l`;</pre>
<p>The backticks have a generalized quoting syntax too. The <code>qx{}</code> quoting is the same as the literal <code>``</code> but allows you to choose the delimiter (see <a href="http://perldoc.perl.org/perlop.html">perlop</a>). These are all the same code:</p>
<pre class="brush:perl">my $output = `ls -l`;

my $output = qx{ls -l};

my $output = qx(ls -l);</pre>
<p>Remember, the backticks return only the standard output, so you have to do more work to grab the standard error. If your particular shell command does not support merging output streams, you might need a shell feature to tell it to combine standard error (conventionally, file descriptor 2), with standard output (file descriptor 1). The syntax is a bit odd because you have to use a bit of Bourne shell magic (and if you aren&#8217;t using that shell, you&#8217;ll have a different goofy syntax):</p>
<pre class="brush:perl">my $output = `scp xyz\@example.com:x.dat ./ 2&gt;&amp;1`</pre>
<h3>Detecting errors from external commands</h3>
<p>In modern Perl, you can mostly skip this section because you should use <a href="http://search.cpan.org/dist/IPC-System-Simple">IPC::System::Simple</a>, but we don&#8217;t talk about that until the end of this Item. If you can&#8217;t use that module, you just have a little extra work to do. For the most part, this section applies to Perl&#8217;s interaction with all external commands, not just those you fire off from backticks.</p>
<p>If there is an error with an external command (not just through backticks), Perl sets the child error special variable, <code>$?</code>, with the error value. If <code>$?</code>, you had a problem with the last external command. If <code>$?</code> is false, then your command exited successfully. If you prefer the <a>English</a>, you can use<br />
the <code>$CHILD_ERROR</code> variable instead of <code>$?</code>:</p>
<pre class="brush:perl">my $output = `ls -l`;
die "something went horribly wrong' if $CHILD_ERROR;</pre>
<p>The value in <code>$?</code> is acutally more than a single value. It&#8217;s two bytes, and you need to look at certain bits to extract values:</p>
<pre class="brush:perl">if ( $? == -1 ) {
	print "Command failed to execute: $!\n";
	}
elsif ( $? &amp; 127 ) {
	printf "The child died with signal %d, %s a coredump\n",
	( $? &amp; 127 ), ( $? &amp; 128 ) ? 'with' : 'without';
	}
else {
	printf "child exited with value %d\n", $? &gt;&gt; 8;
	}</pre>
<h3>Fire and forget with system</h3>
<p>If you don&#8217;t care about the output, you can use <a href="http://perldoc.perl.org/functions/system.html">system</a> to start a command. It&#8217;s output goes to the same place your Perl output goes to (e.g. to the screen):</p>
<pre class="brush:perl">system( 'ls', '-l' )
	and die 'something went horribly wrong';</pre>
<p>Your program waits (&#8220;blocks&#8221;) while the external command runs, and your program only continues once the external command completes.</p>
<p>The return value from <code>system</code> is the exit value from the external command. Each command can define its own exit values, but most commonly they return 0 for success or a non-zero number to indicate a particular sort of failure. At first glance the <code>and</code> looks odd, but that&#8217;s because an error from <code>ls</code> returns a value that Perl considers true.</p>
<p>If you are using <a>autodie</a> (<span class="item">Item 27:  Use autodie to simplify error handling</span>), you don&#8217;t have to do that work yourself.</p>
<h3>Turn into other programs with <code>exec</code></h3>
<p>The <a href="http://perldoc.perl.org/functions/exec.html">exec</a> function is similar to system, but it turns your program into that other process. If you can run that command, you never come back to your Perl program. There&#8217;s usually no point in continuing if your <code>exec</code> fails:</p>
<pre class="brush:perl">unless( exec( 'myprogram.sh', $@ ) ) {
	die "Could not exec! Oh noes!\n"
	}</pre>
<p>That&#8217;s not really Perl programming, but many people use <code>exec</code> after they set up an environment or do other work to set up the situation. Essentially, this is a wrapper program:</p>
<pre class="brush:perl">my $line = ;

$ENV{DEBUG} = 1 if $line =~ /debug\s+on/i;

exec( 'myprogram.sh', $@ );</pre>
<h3>Use IPC::System::Simple to make life easier</h3>
<p>Running external commands from within a Perl program is<br />
easy enough, but you can easily get confused about whether or not those<br />
commands succeeded or failed. <a href="http://search.cpan.org/dist/IPC-System-Simple">IPC::System::Simple</a> provides its own versions of <code>system</code> that dies when it encounters an error:</p>
<pre class="brush:perl">use IPC::System::Simple qw(system);
use Try::Tiny;

try {
	system( 'ls', '-l', $ARGV[0] );
	}
catch {
	print $_;
	};</pre>
<p>When you run this command, you see that <code>IPC::System::Simple</code> figures out the success or failure for you (much like <code>autodie</code>):</p>
<pre class="brush:plain">% perl ipc_system_simple.pl /does/exist
-rw-rw-r-- 1 buster  staff  555 Jan  1 00:00 /does/exist
% perl ipc_system_simple.pl /does/not/exist
ls: /does/not/exist: No such file or directory
"ls" unexpectedly returned exit value 1 at ipc_system_simple.pl line 5</pre>
<p><code>IPC::System::Simple</code> also has a replacement for backticks, which it calls <code>capture</code>. You could run the <code>ps</code> command to get a list of running processes then look for the line with your program (<code>$0</code> is the name of the currently running Perl program):</p>
<pre class="brush:perl">use IPC::System::Simple qw(capture);

my @processes = capture( 'ps', 'ux' );

print grep { /$0/o } @processes;</pre>
<p>This program just prints the <code>ps</code> line that applies to itself:</p>
<pre class="brush:plain">% perl ipc_system_simple_capture.pl
buster 74442   0.0  0.1   601344   2876 s000  S+   11:08 AM 0:00.04 perl ipc_system_simple_capture.pl</pre>
<p><code>IPC::System::Simple</code>&#8216;s <code>system</code> and <code>capture</code> commands behave much like Perl&#8217;s built-in <code>system</code> command, so they might invoke an underlying shell. If you want to prevent an shell interaction (i.e. don&#8217;t interpret metacharacters), you can use the <code>systemx</code> and <code>capturex</code> versions instead. This prevents you from accidently starting a command that does more than you wanted:</p>
<pre class="brush:perl">use IPC::System::Simple qw(systemx);
systemx("ps ux | rm -rf /");</pre>
<p>The <code>systemx</code> thinks its argument a file with the literal characters you specified in the argument, and fails instead of trying to remove all of your files:</p>
<pre class="brush:plain">% perl ipc_system_simple_systemx.pl
"ps ux | rm -rf /" failed to start: "No such file or directory" at ipc_system_simple_system x.pl line 2</pre>
<h3>Use IPC::Run3 to connect filehandles to external processes</h3>
<p>Backticks, <code>system</code>, <code>exec</code>, and <code>IPC::System::Simple</code> are all fine ways of running processes in Perl; however, they don&#8217;t do a great job in working with output streams. What if you want to write to an external program, or if you want to both read and write to the same external process? In those cases, you want the <a href="http://search.cpan.org/dist/IPC-Run3">IPC::Run3</a> module. This module is the modern successor to the core module <a href="http://search.cpan.org/perldoc?IPC::Open3">IPC::Open3</a>, which though more flexible, is also more complex to use.</p>
<p><code>IPC::Run3</code> is best served by an example. In this example you are going to send some input to the <code>sort</code> command and capture the standard input, and standard output.</p>
<p>With <code>IPC::Run3</code>, you can define a scalar variable (<code>$stdin</code>) that represents the input, and the scalar variables where it should put the output (<code>$stdout</code> and <code>$stderr</code>):</p>
<pre class="brush:perl">use IPC::Run3;
my @command = qw(sort -n);

my $stdin   = "5\n34\n32\n12\nhi\n";
my ( $stdout, $stderr ) = ( '', '' );

run3 \@command, \$stdin, \$stdout, \$stderr;

die "something went horribly wrong" if $?;

print "STDOUT\n$stdout\nSTDERR\n$stderr\n";</pre>
<p>You can even do fancy things like bypass writing to a scalar and directly write to a file. You can also choose to ignore any or all of the standard filehandles and instead just run the command directly, though it seems like <code>IPC::Run3</code> might be more than you are needing in that case.</p>
<h3>Things to remember</h3>
<ul>
<li>The backticks capture output.</li>
<li>The <code>system</code> command does not capture output</li>
<li>A successful <code>exec</code> never returns</li>
<li><code>IPC::System::Simple</code> handles most of the shell and error details for you.</li>
<li><code>IPC::Run3</code> allows you to work with input and output at the same time</li>
</ul>
<p align="left"><a class="tt" href="http://twitter.com/home/?status=Interact+with+the+system+when+Perl+isn%E2%80%99t+enough+http://tinyurl.com/62ncyyk" title="Post to Twitter"><img class="nothumb" src="http://www.effectiveperlprogramming.com/wp-content/plugins/tweet-this/icons/tt-twitter2.png" alt="Post to Twitter" /></a> <a class="tt" href="http://twitter.com/home/?status=Interact+with+the+system+when+Perl+isn%E2%80%99t+enough+http://tinyurl.com/62ncyyk" title="Post to Twitter"> </a> <a class="tt" href="http://delicious.com/post?url=http://www.effectiveperlprogramming.com/blog/150&amp;title=Interact+with+the+system+when+Perl+isn%E2%80%99t+enough" title="Post to Delicious"><img class="nothumb" src="http://www.effectiveperlprogramming.com/wp-content/plugins/tweet-this/icons/tt-delicious.png" alt="Post to Delicious" /></a> <a class="tt" href="http://delicious.com/post?url=http://www.effectiveperlprogramming.com/blog/150&amp;title=Interact+with+the+system+when+Perl+isn%E2%80%99t+enough" title="Post to Delicious"> </a> <a class="tt" href="http://digg.com/submit?url=http://www.effectiveperlprogramming.com/blog/150&amp;title=Interact+with+the+system+when+Perl+isn%E2%80%99t+enough" title="Post to Digg"><img class="nothumb" src="http://www.effectiveperlprogramming.com/wp-content/plugins/tweet-this/icons/tt-digg.png" alt="Post to Digg" /></a> <a class="tt" href="http://digg.com/submit?url=http://www.effectiveperlprogramming.com/blog/150&amp;title=Interact+with+the+system+when+Perl+isn%E2%80%99t+enough" title="Post to Digg"> </a> <a class="tt" href="http://www.facebook.com/share.php?u=http://www.effectiveperlprogramming.com/blog/150&amp;t=Interact+with+the+system+when+Perl+isn%E2%80%99t+enough" title="Post to Facebook"><img class="nothumb" src="http://www.effectiveperlprogramming.com/wp-content/plugins/tweet-this/icons/tt-facebook.png" alt="Post to Facebook" /></a> <a class="tt" href="http://www.facebook.com/share.php?u=http://www.effectiveperlprogramming.com/blog/150&amp;t=Interact+with+the+system+when+Perl+isn%E2%80%99t+enough" title="Post to Facebook"> </a> <a class="tt" href="http://reddit.com/submit?url=http://www.effectiveperlprogramming.com/blog/150&amp;title=Interact+with+the+system+when+Perl+isn%E2%80%99t+enough" title="Post to Reddit"><img class="nothumb" src="http://www.effectiveperlprogramming.com/wp-content/plugins/tweet-this/icons/tt-reddit.png" alt="Post to Reddit" /></a> <a class="tt" href="http://reddit.com/submit?url=http://www.effectiveperlprogramming.com/blog/150&amp;title=Interact+with+the+system+when+Perl+isn%E2%80%99t+enough" title="Post to Reddit"> </a></p>]]></content:encoded>
			<wfw:commentRss>http://www.effectiveperlprogramming.com/blog/150/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

