在反引号中记录stdout和stderr中的几个命令

时间:2016-10-23 11:12:59

标签: perl

我需要在反引号中记录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?

这段代码看起来很难看。有没有办法更优雅地写它?

1 个答案:

答案 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