重新打开STDERR/STDOUT以写入具有时间戳的组合日志文件

问题描述:

我基本上想要重新打开STDERR/STDOUT,以便它们写入一个日志文件,并且每行都包含流和时间戳。所以print STDERR "Hello World"打印STDERR: 20130215123456: Hello World。我不想将所有打印语句重写为函数调用,也有一些输出将通过system()来自外部进程,但无论如何我都无法重写。重新打开STDERR/STDOUT以写入具有时间戳的组合日志文件

我还需要将输出放在文件“live”中,即不仅在进程完成时写入。

(PS我不是特别询问如何产生时间戳的细节,只是如何重定向到一个文件,并在前面加上一个字符串)

我已经制定了下面的代码,但它是凌乱:

my $mode = ">>"; 
my $file = "outerr.txt"; 
open(STDOUT, "|-", qq(perl -e 'open(FILE, "$mode", "$file"); while (<>) { print FILE "STDOUT: \$\_"; }')); 
open(STDERR, "|-", qq(perl -e 'open(FILE, "$mode", "$file"); while (<>) { print FILE "STDERR: \$\_"; }')); 

(以上不添加日期,但应该是微不足道的补充)

我正在寻找一个更清洁的解决办法,不需要引用perl代码并在命令行上传递它,或者至少需要隐藏一些复杂性的模块。看看Capture::Tiny的代码,它看起来并不像它可以处理输出的一部分,但我不确定这一点。 annotate-output只能使用外部命令,我需要这个来处理外部命令和普通的perl打印。

+0

我不知道这是否有帮助。 [如何将STDOUT和STERR发送到同一个文件](http://perlmonks.com/?node=579419)。 – 2013-02-15 02:18:23

+0

我可以做到这一点,但不知道如何添加时间戳和流描述。 – Clinton 2013-02-15 02:25:24

+0

我不知道Capture :: Tiny如何工作。看起来可能。你为什么不试试呢? – ikegami 2013-02-15 02:38:53

通过system启动的孩子不会写入STDOUT,因为它无法访问程序中的变量。因此,意味着在Perl文件句柄上运行代码(例如tie)将不起作用。

编写另一个脚本,用STDOUT和STDERR替换管道来运行脚本。从这些管道读取并打印出修改后的输出。我建议使用IPC :: Run来执行此操作,因为它可以帮助您避免使用select。如果将STDOUT和STDERR组合在一个流中,您可以在没有它的情况下离开。