在perl中,我如何将输出发送到stdout和system()的文件返回val?

时间:2017-12-18 18:15:01

标签: perl stdout stderr tee

我成功使用了 IO::Tee tee打印消息到stdout和日志文件。我也希望能够从系统()命令捕获和发送stdout和stderr到同一个文件。

我尝试了各种重定向和/或管道组合而没有运气

简单的脚本,几乎没有注释失败的尝试...

#!/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;

3 个答案:

答案 0 :(得分:1)

Perl正在缓冲输出到$tee文件句柄,并且在您进行写入同一文件的$tee调用后,system的光标位置未调整,因此很可能是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;

答案 1 :(得分:0)

感谢你们的解释和建议。

我还发现在IO中使用capture_exec的另一种方式:CaptureOutput。我用一个看起来像这样的子测试它....

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;
}

这似乎也有效。

答案 2 :(得分:-1)

您正在放弃system返回的状态,因此我会使用反引号:

print $tee `date`