我想将我的Perl脚本的stdout和stderr复制到一个文件中,同时也将它保留在屏幕上,并且最好在脚本本身内部使用一些技巧。即我想要类似于
的东西./ test.pl 2>& 1 | tee foo.bar
但隐藏在perl脚本实现中。目前我刚刚编写了一个子程序,可以在屏幕上和文件句柄上打印所有消息,但缺点是如果脚本死掉,则消息将不会出现在日志中。 有办法吗?
答案 0 :(得分:7)
请参阅Perl食谱中的“13.15.9。绑定示例:多个接收文件句柄”部分。
最重要的是tie *TEE, "Tie::Tee", @handles;
注意:Tie :: Tee包是您需要自己创建的,代码在本书的相同部分。
注意:然后您可以执行select(TEE)
,并且会在每个常规print
语句中使用它,因此您无需执行print TEE xxx
。
注意:要让任何STDERRy输出(包括die)转到同一个文件句柄,请将STDERR更改为TEE,如下所示:
use Tie::Tee;
use Symbol;
@handles = (*STDOUT);
push(@handles, $handle = gensym( ));
open($handle, ">/tmp/teetest.xxx");
tie *TEE, "Tie::Tee", @handles;
select(TEE);
*STDERR = *TEE;
print "raw print\n";
die "XXXX\n";
输出将是:
raw print
XXXX
文件内容为:
raw print
XXXX
答案 1 :(得分:4)
看看Log::Dispatch
将消息分发到一个或多个输出。
use Log::Dispatch;
# Simple API
#
my $log =
Log::Dispatch->new
( outputs =>
[ [ 'File', min_level => 'debug', filename => 'logfile' ],
[ 'Screen', min_level => 'warning' ],
],
);
$log->info('Blah, blah');
# More verbose API
#
my $log = Log::Dispatch->new();
$log->add( Log::Dispatch::File->new
( name => 'file1',
min_level => 'debug',
filename => 'logfile'
)
);
$log->add( Log::Dispatch::Screen->new
( name => 'screen',
min_level => 'warning',
)
);
$log->log( level => 'info', message => 'Blah, blah' );
my $sub = sub { my %p = @_; return reverse $p{message}; };
my $reversing_dispatcher = Log::Dispatch->new( callbacks => $sub );
它也有一些辅助/实用程序模块,你也应该看一下。
Log :: Dispatch :: DBI - 将输出记录到数据库表。
Log :: Dispatch :: FileRotate - 定期轮换日志文件作为其一部分 的使用。
Log :: Dispatch :: File :: Stamped - Stamps log 包含日期和时间信息的文件。
Log :: Dispatch :: Jabber - Logs 通过Jabber的消息。
Log :: Dispatch :: Tk - Logs 消息到Tk窗口。
Log :: Dispatch :: Win32EventLog - 日志 消息到Windows事件日志。
Log :: Dispatch :: Config - 允许 通过文本记录的配置 文件类似(或者我被告知)如何 它是用log4j完成的。
答案 2 :(得分:1)
根据脚本的大小,我强烈建议使用Log :: Log4perl ...每次编写脚本时都会保存重新实现的日志记录。
如果您在简易模式下使用Log4perl,它只会增加大约10行代码并且非常有用。
Log4perl可以非常灵活地将输出重定向到您想要的任何地方,包括一次输出多个输出。
答案 3 :(得分:0)
This听起来就像你需要的那样,不幸的是它是一个bash脚本,你希望这一切都在你的perl代码中处理。
答案 4 :(得分:0)
Capture::Tiny有一个tee子。