What's the difference between Perl's backticks, system, and exec?
Solution 1:
exec
executes a command and never returns.
It's like a return
statement in a function.
If the command is not found exec
returns false.
It never returns true, because if the command is found it never returns at all.
There is also no point in returning STDOUT
, STDERR
or exit status of the command.
You can find documentation about it in perlfunc
,
because it is a function.
system
executes a command and your Perl script is continued after the command has finished.
The return value is the exit status of the command.
You can find documentation about it in perlfunc
.
backticks
like system
executes a command and your perl script is continued after the command has finished.
In contrary to system
the return value is STDOUT
of the command.
qx//
is equivalent to backticks.
You can find documentation about it in perlop
, because unlike system
and exec
it is an operator.
Other ways
What is missing from the above is a way to execute a command asynchronously.
That means your perl script and your command run simultaneously.
This can be accomplished with open
.
It allows you to read STDOUT
/STDERR
and write to STDIN
of your command.
It is platform dependent though.
There are also several modules which can ease this tasks.
There is IPC::Open2
and IPC::Open3
and IPC::Run
, as well as
Win32::Process::Create
if you are on windows.
Solution 2:
In general I use system
, open
, IPC::Open2
, or IPC::Open3
depending on what I want to do. The qx//
operator, while simple, is too constraining in its functionality to be very useful outside of quick hacks. I find open
to much handier.
system
: run a command and wait for it to return
Use system
when you want to run a command, don't care about its output, and don't want the Perl script to do anything until the command finishes.
#doesn't spawn a shell, arguments are passed as they are
system("command", "arg1", "arg2", "arg3");
or
#spawns a shell, arguments are interpreted by the shell, use only if you
#want the shell to do globbing (e.g. *.txt) for you or you want to redirect
#output
system("command arg1 arg2 arg3");
qx//
or ``: run a command and capture its STDOUT
Use qx//
when you want to run a command, capture what it writes to STDOUT, and don't want the Perl script to do anything until the command finishes.
#arguments are always processed by the shell
#in list context it returns the output as a list of lines
my @lines = qx/command arg1 arg2 arg3/;
#in scalar context it returns the output as one string
my $output = qx/command arg1 arg2 arg3/;
exec
: replace the current process with another process.
Use exec
along with fork
when you want to run a command, don't care about its output, and don't want to wait for it to return. system
is really just
sub my_system {
die "could not fork\n" unless defined(my $pid = fork);
return waitpid $pid, 0 if $pid; #parent waits for child
exec @_; #replace child with new process
}
You may also want to read the waitpid
and perlipc
manuals.
open
: run a process and create a pipe to its STDIN or STDERR
Use open
when you want to write data to a process's STDIN or read data from a process's STDOUT (but not both at the same time).
#read from a gzip file as if it were a normal file
open my $read_fh, "-|", "gzip", "-d", $filename
or die "could not open $filename: $!";
#write to a gzip compressed file as if were a normal file
open my $write_fh, "|-", "gzip", $filename
or die "could not open $filename: $!";
IPC::Open2: run a process and create a pipe to both STDIN and STDOUT
Use IPC::Open2
when you need to read from and write to a process's STDIN and STDOUT.
use IPC::Open2;
open2 my $out, my $in, "/usr/bin/bc"
or die "could not run bc";
print $in "5+6\n";
my $answer = <$out>;
IPC::Open3: run a process and create a pipe to STDIN, STDOUT, and STDERR
use IPC::Open3
when you need to capture all three standard file handles of the process. I would write an example, but it works mostly the same way IPC::Open2 does, but with a slightly different order to the arguments and a third file handle.
Solution 3:
Let me quote the manuals first:
perldoc exec():
The exec function executes a system command and never returns-- use system instead of exec if you want it to return
perldoc system():
Does exactly the same thing as exec LIST , except that a fork is done first, and the parent process waits for the child process to complete.
In contrast to exec and system, backticks don't give you the return value but the collected STDOUT.
perldoc `String`:
A string which is (possibly) interpolated and then executed as a system command with /bin/sh or its equivalent. Shell wildcards, pipes, and redirections will be honored. The collected standard output of the command is returned; standard error is unaffected.
Alternatives:
In more complex scenarios, where you want to fetch STDOUT, STDERR or the return code, you can use well known standard modules like IPC::Open2 and IPC::Open3.
Example:
use IPC::Open2;
my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'some', 'cmd', 'and', 'args');
waitpid( $pid, 0 );
my $child_exit_status = $? >> 8;
Finally, IPC::Run from the CPAN is also worth looking at…