【问题标题】:How can I redirect STDOUT and STDERR to a log file in Perl? [duplicate]如何将 STDOUT 和 STDERR 重定向到 Perl 中的日志文件? [复制]
【发布时间】:2010-09-29 14:48:05
【问题描述】:

可能重复:
Can I send STDOUT and STDERR to a log file and also to the screen in Win32 Perl?

我想在过程完成后将 STDOUT、STDERR 重定向到 temp_log,然后再重定向到 logfile.txt。该进程运行了完整的 20 分钟,因此我想在进程运行时聚集 temp_log

【问题讨论】:

  • 您的问题是什么?你需要帮助哪一部分?你试过什么?

标签: perl


【解决方案1】:

STDOUTSTDERR 只是初始化为程序的标准输出和错误的文件句柄,但它们可以随时出于任何原因重新分配。为此,您需要保存原始设置以便恢复它们。

sub process_that_writes_to_temp_log {

    # save original settings. You could also use lexical typeglobs.
    *OLD_STDOUT = *STDOUT;
    *OLD_STDERR = *STDERR;

    # reassign STDOUT, STDERR
    open my $log_fh, '>>', '/logdirectory/the-log-file';
    *STDOUT = $log_fh;
    *STDERR = $log_fh;

    # ... 
    # run some other code. STDOUT/STDERR are now redirected to log file
    # ...

    # done, restore STDOUT/STDERR
    *STDOUT = *OLD_STDOUT;
    *STDERR = *OLD_STDERR;
}

根据程序的布局,可以使用local 自动保存和恢复旧的 STDOUT/STDERR 设置。

sub routine_that_writes_to_log {
    open my $log_fh, '>>', 'log-file';
    local *STDOUT = $log_fh;
    local *STDERR = $log_fh;

    # now STDOUT,STDERR write to log file until this subroutine ends.
    # ...

}

【讨论】:

  • local 可以在任何块中使用。它不必是子程序。
  • 系统/exec函数调用的命令在linux上不起作用。
  • system 始终适用于文件描述符 0、1 和 2。如果您注意如何重新初始化 STDOUTSTDERR,则可以让您的新标准文件句柄与 @ 一起使用987654330@。 exec 将您的 Perl 程序替换为另一个程序,这将使您丢失对 STDOUT/STDERR 的更改。
【解决方案2】:

Can I send STDOUT and STDERR to a log file and also to the screen in Win32 Perl? 已经回答了您问题的重定向部分。尽管它说“Win32”,但答案是针对便携式 Perl。

另一部分,临时文件,在你至少被它烧过一次之前有点棘手。

  • 使用在运行期间应该唯一的名称为临时文件命名。包括PID或程序开始时间。您可以使用$filename.$$ 之类的方式自行执行此操作,但您也可以使用File::Temp

  • 如果您想将临时日志附加到现有日志,您可能需要创建另一个临时文件以获取整个结果。将整个东西缝合在一起后,将其移动到位。这样一来,您就不会让竞争进程更改同一个文件,因为它们都试图将其临时日志附加到主日志。

  • 更好的是,使用Log::Log4perl 之类的东西,因为它会为您处理所有细节。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-07-22
    • 1970-01-01
    • 1970-01-01
    • 2011-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多