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

时间:2013-02-15 01:02:44

标签: perl

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

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

(p.s。我不是特别要求详细说明如何生成时间戳,如何重定向到文件并添加字符串)

我已经制定了以下代码,但它很混乱:

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打印。

1 个答案:

答案 0 :(得分:2)

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

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