我需要在反引号中记录stdout和stderr中的几个命令。
my $logger = Log::Log4perl->get_logger("test_app");
...
my $log;
$log = `service someservice restart`;
$logger->info("someservice: $log");
$log = `~/scripts/test.pl param1`;
$logger->info("test.pl: $log");
$log = `~/scripts/script.pl param2`;
$logger->info("script.pl: $log");
$log = `~/scripts/env.pl param3`;
$logger->info("env.pl: $log");
$log = `~/scripts/monitor.pl param4`;
$logger->info("monitor.pl: $log");
在这种情况下,只会记录stdout。我怎样才能记录stderr?
这段代码看起来很难看。有没有办法更优雅地写它?
答案 0 :(得分:2)
根据Ron Bergin的建议,以下是使用IPC::Open3
的示例<强> /tmp/log4perl.conf 强>
log4perl.logger.test_app = INFO, FileAppndr1
log4perl.appender.FileAppndr1 = Log::Log4perl::Appender::File
log4perl.appender.FileAppndr1.filename = /tmp/test_app.log
log4perl.appender.FileAppndr1.layout = Log::Log4perl::Layout::SimpleLayout
<强> test.pl 强>
#!/usr/bin/env perl
use warnings;
use strict;
use IPC::Open3;
use Log::Log4perl;
use Symbol 'gensym'; # Create anonymous glob (filehandle)
Log::Log4perl::init("/tmp/log4perl.conf");
my $logger = Log::Log4perl->get_logger("test_app");
$logger->info('-'x40); # New run
my @tasks = (
[ 'ls', '-lt', '/tmp/test_app.log' ], # ok
[ 'df', '-h' ], # ok
[ 'grep', 'foo', '/var/log/foo' ], # error
);
for my $task (@tasks) {
run_command($task);
}
sub run_command {
my ($command_with_args) = @_;
my ($writer, $reader, $error);
$error = gensym;
my $pid = open3($writer, $reader, $error, @$command_with_args);
waitpid( $pid, 0 );
my $child_exit_status = $? >> 8;
$logger->info("Running [ " . join(' ', @$command_with_args) . " ]");
{
local $/; # Read all of $reader/$error at one go, but do not affect rest of program
if ($child_exit_status) {
$logger->error("ERROR: Got status code [ $child_exit_status ]");
$logger->error("Error Message:\n" . <$error>);
} else {
$logger->info("SUCCESS");
$logger->info("Output:\n" . <$reader>);
}
}
}
输出 - /tmp/test_app.log
INFO - ----------------------------------------
INFO - Running [ ls -lt /tmp/test_app.log ]
INFO - SUCCESS
INFO - Output:
-rw-rw-r-- 1 felix felix 29129 Oct 24 00:06 /tmp/test_app.log
INFO - Running [ df -h ]
INFO - SUCCESS
INFO - Output:
Filesystem Size Used Avail Use% Mounted on
/dev/xvda2 30G 13G 18G 41% /
devtmpfs 3.6G 0 3.6G 0% /dev
/dev/xvdh 100G 25G 76G 25% /data/home
INFO - Running [ grep foo /var/log/foo ]
ERROR - ERROR: Got status code [ 2 ]
ERROR - Error Message:
grep: /var/log/foo: No such file or directory