【问题标题】:In perl, how can I tee output to stdout and a file for system() return vals?在 perl 中,如何将输出输出到标准输出和 system() 返回值的文件?
【发布时间】:2017-12-18 18:15:00
【问题描述】:

我正在成功使用 IO::Tee 将消息打印到标准输出和日志文件。我还希望能够从 system() 命令捕获标准输出和标准错误并将其发送到同一个文件。

我尝试了各种重定向和/或管道组合,但没有成功

带有一些注释掉失败尝试的简单脚本...

#!/usr/bin/env perl

use IO:Tee;

my $teelog = "tee.log"
open my $tee, ">", $teelog or die "open tee failed.\n";
my $tee = new IO:Tee(\*STDOUT, $tee);

print $tee "First line in log\n";

# This command should work.  I want the date to go to screen and tee.log
#system("date | tee -a ${teelog}");  <- nothing goes to tee.log
#system("date >& ${teelog}") <- clobbers tee.log
#system("date >& $tee") <- generates syntax errors


# This command should fail.  I want error msg to go to screen and tee.log
#system("jibberish | tee -a ${teelog}"); <- nothing goes to tee.log
#system("jibberish >& ${teelog}") <- clobbers tee.log
system("kibberish >& $tee") <- generates syntax errors

print $tee "Last line in log\n";

exit;

【问题讨论】:

    标签: perl stdout stderr tee


    【解决方案1】:

    Perl 正在缓冲输出到 $tee 文件句柄,并且在您发出写入同一文件的 system 调用后,$tee 的光标位置未调整,因此 Perl 可能会覆盖任何输出system 调用写入文件。

    这样的调用序列更安全。通过更明智的搜索和冲洗,您可能会更简洁。

    use IO:Tee;
    my $teelog = "tee.log"
    open my $tee, ">", $teelog or die "open tee failed.\n";
    $tee = new IO:Tee(\*STDOUT, $tee);
    print $tee "First line in log\n";
    close $tee;
    
    system("date | tee -a ${teelog}");
    system("jibberish 2>&1 | tee -a ${teelog}");
    
    open $tee, ">>", $teelog or die "open tee failed.\n";  # append mode
    $tee = new IO:Tee(\*STDOUT, $tee);
    
    print $tee "Last line in log\n";
    
    exit;
    

    【讨论】:

    • 感谢 mob 的解释和建议。我还发现了另一种在 IO:CaptureOutput 中使用 capture_exec 的方法。我用一个看起来像这样的 sub 对其进行了测试.... sub tee_sys_cmd { (my $cmd) = @_; print $tee "正在执行... \"$cmd\"\n";我的 ($stdout, $stderr, $success, $exit_code) = capture_exec($cmd);打印 $tee "$stdout\n$stderr\n";返回; } 这似乎也有效。
    【解决方案2】:

    感谢您的解释和建议。

    我还发现了另一种在 IO:CaptureOutput 中使用 capture_exec 的方法。我用一个看起来像这样的潜艇对其进行了测试....

    sub tee_sys_cmd {
        (my $cmd) = @_;
    
        print $tee "Executing... \"$cmd\"\n";
        my ($stdout, $stderr, $success, $exit_code) = capture_exec($cmd);
    print $tee "$stdout\n$stderr\n";
    
        return;
    }
    

    这似乎也有效。

    【讨论】:

      【解决方案3】:

      您正在丢弃 system 返回的状态,所以我将使用反引号:

      print $tee `date`
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-09-29
        • 2018-07-20
        • 2012-03-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-02-19
        相关资源
        最近更新 更多