2016-10-23 6 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"); 

この場合、stdoutのみが記録されます。どうすればstderrも記録できますか?

このコードは醜いです。より優雅に書く方法はありますか?ロン・バージンの提案に続き

+3

stderrをstdoutにリダイレクトするには、 '2>&1'を使用できます。例: '' '$ log ='サービスのサービス再開2>&1' '' ' –

+3

別の方向に進むことをお勧めします。 backticksを使う代わりに** IPC :: Open3 **を使ってstdoutとstderrを別々のvarsに取り込むことができます。 stdoutはinfoとして記録され、stderrは警告またはエラーとして記録されます。 –

+1

もう1つの提案は、実行をラップしてサブにロギングすることです。実行される項目のハッシュを作成し、特定のハッシュ要素(キー/値)をサブに渡して実行し、結果を記録します。 –

答えて

2

は、ここにIPC::Open3

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/log4perl.conf出力を使用した例であります - /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 
関連する問題