继罗恩·伯金的建议,这里是/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>);
}
}
}
输出使用IPC::Open3
一个例子 - /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
您可以使用'2>&1'将stderr重定向到标准输出。例如:'''$ log ='service someservice restart 2>&1'''' –
我建议走不同的方向。我不会使用反引号,而是使用** IPC :: Open3 **,以便可以在单独的变量中捕获stdout和stderr。 stdout被记录为info,stderr被记录为警告或错误。 –
另一个建议是包装执行并记录在一个子文件中。创建要执行的项目的哈希值,并将特定的哈希元素(键/值)传递给子项以执行并记录结果。 –