I'm trying to capture the output of the command executed as a different user using:
my $command = qq(sudo su - <username> -c '/usr/bin/whatever');
my $pid = open $cmdOutput, "-|", $command;
/usr/bin/whatever
$pid = open $cmdOutput, "-|", $command || die " something went wrong: $!";
my $command = qq(sudo su - <username> -c '/usr/bin/whatever' 2>/tmp/error.message);
This is covered thoroughly in perlfaq8
. Since you are using a piped open, the relevant examples are those that go by open3
from the core IPC::Open3
module.
Another option is to use IPC::Run
for managing your processes, and the pump
function will do what you need. The IPC::Open3
documentation says for IPC::Run
This is a CPAN module that has better error handling and more facilities than Open3.
With either of these you can manipulate STDOUT
and STDERR
separately or together, as needed.
Other than 2>output
redirection, there are no more elementary methods for the piped open.
If you don't mind mixing the streams or losing STDOUT
altogether, another option is
my $command = 'cmd 2>&1 1>/dev/null' # Remove 1>/dev/null to have both
my $pid = open my $cmdOutput, "-|", $command;
while (<$cmdOutput>) { print } # STDERR only
The first redirection merges STDERR
stream with STDOUT
, so you would get them both, and mixed (with STDOUT
subject to buffering, so things may well come out of order). The second redirect sends the STDOUT
away so with it in place you read only the command's STDERR
from the handle.
The question is about running an external command using open
, but I'd like to mention that the canonical and simple qx
(backticks) can be used in the same way. It returns the STDOUT
, so redirection just like above is needed to get STDERR
. For completeness:
my $cmd = 'cmd_to_execute';
my $allout = qx($cmd 2>&1); # Both STDOUT and STDERR in $out, or
my $stderr = qx($cmd 2>&1 1>/dev/null); # Only STDERR
my $exit_status = $?;
The qx
puts the child process exit code (status) in $?
. This can then be inspected for failure modes; see a summary in the qx
page or a very thorough discussion in I/O operators in perlop.
Note the the STDERR
returned this way is from the command, if it ran. If the command itself couldn't be run (for a typo in command name, or fork
failed for some reason) then $?
will be -1
and the error will be in $!
.