将stdout和stderr管道传输到文件的子例程 [英] Subroutine for piping stdout and stderr into file

查看:47
本文介绍了将stdout和stderr管道传输到文件的子例程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我有一个名为 simplecalc.pl 的程序:

If I have a program called simplecalc.pl:

use v5.10; 
use warnings;
use strict;

# SIMPLE CALCULATOR
# Usage: simplecalc.pl <n1> <n2> [<verbose> <logswitch>]
# Example Usage:
# normal usage      : simplecalc.pl 4 2  
# verbose usage     : simplecalc.pl 4 2 1
# support-case usage: simplecalc.pl 4 2 0 1

my($OK,$UNKNOWN)=(0,3);
my($filename, $endmsg, $exit) = ('my.log', undef, undef);
my($n1, $n2, $DEBUG, $GET_SUPPORT_FILE) = @ARGV;

# Handling of the support-file starts here ===============================
*ORIGINAL_STDOUT = *STDOUT;

if ($GET_SUPPORT_FILE) {
    $DEBUG = 1;
    $endmsg = "support-info sucessfully written into $filename";
    $exit = $UNKNOWN;
    # redirect stdout and stderr
    open my $stdout_txt, '>>:utf8', "$filename";
    *STDOUT = $stdout_txt;
    open STDERR, '>&STDOUT';
} else {
    $endmsg = "Finnished calculation - good bye.";
    $exit = $OK;
}

END {
    select *ORIGINAL_STDOUT;
    say $endmsg;
};
# end of support-file handling ============================================


say STDERR "INFO: got $n1 and $n2 from the commandline" if $DEBUG;
say "Hello, let me calc the quotient from $n1 trough $n2 for you ...";
my $quotient = $n1 / $n2;
say "Quotient: $quotient";

exit $exit;

是否有一种方法可以将对支持文件的冗长处理以可重用的方式放入模块中?(该支持文件应由用户发送到程序维护者.)

Is there a way to put the lengthy handling of the support-file in a reusable way into a module? (The support-file is meant to be sent by the user to the program-maintainer.)

注意:上面的解决方案也适用于 simplecalc.pl 4 0 0 1 ,这导致除法槽为0.在主模块使用的任何模块中捕获 die -programm并将die-msg写入支持文件是一个重要功能.

Note: The above solution also works for simplecalc.pl 4 0 0 1 which results in a division trough 0. Catching a die in any module used by the main-programm and write the die-msg into the support-file is an important feature.

推荐答案

我提出了一个问题,希望控制模块中两个流的重定向.

I take the question to want to control redirection of both streams from a module.

像这样的基本示例吗?

RedirectStreams.pm

package RedirectStreams;

use warnings;
use strict;

use Exporter qw(import);
our @EXPORT_OK = qw(redirect_streams restore_streams);

our ($stdout, $stderr) = (*STDOUT, *STDERR);

sub redirect_streams {
    my ($handle) = @_;
    *STDOUT = $handle;
    *STDERR = $handle;
}

sub restore_streams {
    *STDOUT = $stdout;
    *STDERR = $stderr;
}

1;

main.pl

use warnings;
use strict;

use RedirectStreams qw(redirect_streams restore_streams);

my $logfile = shift @ARGV  || 'streams.log';

say "Hello from ", __PACKAGE__;            
warn "WARN from ", __PACKAGE__;

open my $fh, '>', $logfile;
    
redirect_streams($fh);

say "\tHi to redirected";
warn "\tWARN to redirected";

restore_streams();
    
say  "Hi to STDOUT again";
warn "WARN in main again";

open my $fh_other, '>', 'other_' . $logfile;
redirect_streams($fh_other);
say  "STDOUT redirected to another";
warn "STDERR redirected to another";

close $_ for $fh, $fh_other;

控制台上的输出(对齐)

Output on console is (aligned)


Hello from main
WARN from main      at ... line 18.
Hi to STDOUT again
WARN in main again  at ... line 29.

文件 streams.log 具有


        Hi to redirected
        WARN to redirected at ... line 24.

other_streams.log 有两行.(如果在控制台上收起来,则可以轻松地发现它.)

and other_streams.log has its two lines. (Tabbed to spot easily if they wind up on console.)

在此示例中,管理文件句柄的责任在于调用者.

The responsibility for managing filehandles in this example rests on the caller.

这应该通过所有类型的错误检查,子选项(仅将一个流或每个流重定向到其自己的文件等)以及可能的其他一些便利例程来完成.

This should be completed with all manner of error checking, options in subs (redirect only one stream, or each to its own file, etc), and probably a few more convenience routines.

请注意,我们的$ stdout = * STDOUT 创建别名.

保存 STDOUT 以便以后恢复的另一种方法是复制它

Another way to preserve STDOUT for later restoration is to duplicate it,

open my $stdout, '>&', STDOUT;

这将创建一个独立的文件句柄,作为 STDOUT 的副本(这里我们只需要),该文件句柄不受 STDOUT 的更改(或关闭)的影响.有关示例用法,请参见这篇文章.

This creates an independent filehandle, made as a duplicate of STDOUT (what is all we need here), which is unaffected by changes (or closure) of STDOUT. See this post for an example use.

这篇关于将stdout和stderr管道传输到文件的子例程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆