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

问题描述 投票:1回答:3

我成功地使用IO::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;
perl stdout stderr tee
3个回答
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;

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

这似乎也有效。


-1
投票

你丢弃了system返回的状态,所以我会改用反引号:

print $tee `date`
© www.soinside.com 2019 - 2024. All rights reserved.