【问题标题】:Copy all output of a perl script into a file将 perl 脚本的所有输出复制到文件中
【发布时间】:2009-10-27 16:05:18
【问题描述】:

我想将我的 Perl 脚本的 stdout 和 stderr 复制到一个文件中,同时将其保留在屏幕上,并且最好在脚本本身中使用一些技巧。 IE。我想要类似的东西

./test.pl 2>&1 | tee foo.bar

但隐藏在 perl 脚本实现中。目前我刚刚编写了一个子程序,它在屏幕上和文件句柄上打印所有消息,但缺点是如果脚本死了,死消息将不会出现在日志中。 有没有办法做到这一点?

【问题讨论】:

  • @azerole - 如果这些答案中的任何一个对您有帮助,那么接受您认为最有帮助的答案被认为是一种良好的礼仪。干杯!
  • 是的,我知道,但我不想接受我没有尝试过的事情。我花了一些时间来决定我最喜欢哪一个。

标签: perl


【解决方案1】:

请参阅 Perl 手册中的“13.15.9. Tie Example: Multiple Sink Filehandles”部分。

主要要知道的是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

【讨论】:

  • 那个 perl 食谱链接是盗版的。您可以链接到谷歌图书以获得合法链接。 CD书架系列的猖獗盗版杀死了它,现在我买不到新的了。
  • @daotoad - 抱歉,没明白这一点。我刚刚从 Google 搜索中挑选了第一个链接。随意使用正确的链接进行编辑 - 如果您当时还没有添加,我会在有时间搜索 Google 图书时尽快进行编辑
  • @DVK:不,这不是一个真正合理的回应。如果您知道该链接指向一本书的盗版副本,请立即删除该链接。如果您(或其他人)找到合法链接,很好 - 您可以稍后发布。但删除盗版。
  • 不,这是一个不合理的要求。这是一个 Wiki - 人们应该修复它(就像你所做的那样),而不是抱怨某事。我现在在工作,没有时间进行详细搜索以找到正确的电子副本 - 如果这个人这么关心,他应该自己做。
  • 我修复了一个链接 - 在 3 分钟的谷歌搜索中得到了答案。不是很难吗?
【解决方案2】:

看看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 - 邮票日志 包含日期和时间信息的文件。

Log::Dispatch::Jabber - 日志 通过 Jabber 发送消息。

Log::Dispatch::Tk - 日志 消息到 Tk 窗口。

Log::Dispatch::Win32EventLog - 日志 Windows 事件日志中的消息。

Log::Dispatch::Config - 允许 通过文本配置日志记录 文件类似于(或者我被告知)如何 它是用 log4j 完成的。

【讨论】:

    【解决方案3】:

    根据脚本的大小,我强烈推荐 Log::Log4perl ... 节省每次编写脚本时重新实现日志记录。

    如果你在简单模式下使用Log4perl,它只增加了大约10行左右的代码,非常有用。

    Log4perl 在将输出重定向到几乎任何您想要的位置方面非常灵活,包括一次多个输出。

    【讨论】:

      【解决方案4】:

      This 听起来正是你所需要的,不幸的是它是一个 bash 脚本,你希望这一切都在你的 perl 代码中处理。

      【讨论】:

      • 如果 OP 想使用 bash,他已经知道怎么说./test.pl 2>&1 | tee foo.bar
      【解决方案5】:

      Capture::Tiny 有一个 tee 子。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-06-17
        • 1970-01-01
        • 2020-05-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多