2016-10-23 31 views
2

我需要在反引号中记录几条命令的stdout和stderr。在反引号中记录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"); 

在这种情况下,只会记录标准输出。我怎样才能记录stderr呢?

此代码看起来很丑。有办法更优雅地写下它吗?

+3

您可以使用'2>&1'将stderr重定向到标准输出。例如:'''$ log ='service someservice restart 2>&1'''' –

+3

我建议走不同的方向。我不会使用反引号,而是使用** IPC :: Open3 **,以便可以在单独的变量中捕获stdout和stderr。 stdout被记录为info,stderr被记录为警告或错误。 –

+1

另一个建议是包装执行并记录在一个子文件中。创建要执行的项目的哈希值,并将特定的哈希元素(键/值)传递给子项以执行并记录结果。 –

回答

2

继罗恩·伯金的建议,这里是/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 
相关问题