繁体   English   中英

我怎样才能摆脱 Perl 中的 STDERR

[英]How can I get rid of the STDERR in Perl

我在 Perl 中使用一些系统命令。

在下面的例子中,我得到 output 如下:

ls: import-log.*: No such file or directory

ls: error-log.*: No such file or directory

No specified files found for deletion

我的代码:

sub monthoryear() 
{

  @importlog = `ls -al import-log.*`;

  @errorlog = `ls -al error-log.*`;

}

我不想在output中看到下面的内容,即使没有文件。

ls: import-log.*: No such file or directory &

ls: error-log.*: No such file or directory

尽管其他答案对于您提出的确切技术问题是正确的,但您也应该考虑不要在Perl中编写有效的shell脚本。

您应该使用Perl本机方法来获取文件列表(例如glob()File::Find ),而不要调用反引号ls

将STDERR重定向到空设备:

use File::Spec;
open STDERR, '>', File::Spec->devnull() or die "could not open STDERR: $!\n";

您可以在子shell命令中添加stderr重定向:

@importlog = `ls -al import-log.* 2>/dev/null`;
@errorlog = `ls -al error-log.* 2>/dev/null`;

查看perlfaq8 如果您不在意它是STDOUT还是STDERR ,则可以将它们都重定向到STDOUT

$output = `$cmd 2>&1`;

就您而言,您可能只想摆脱STDERR

$output = `$cmd 2>/dev/null`;

但是,我同意DVK的回答 使用外部命令获取文件列表似乎很愚蠢。 您应该使用File :: Find 这样,万一发生故障,您可以使用Perl的常规错误处理。

#!/usr/bin/perl
use strict;
use warnings;
use File::Find;

my @importlog;
my @errorlog;
find(sub {
    push @importlog, $File::Find::name if /^import-log\.*/;
    push @errorlog, $File::Find::name if /^error-log\.*/;
}, '.');

print "Import log:\n", join("\n", @importlog), "\n";
print "Error log:\n", join("\n", @errorlog), "\n";

创建一个新的警告挂钩,然后对消息进行处理,存储,忽略它,等等。

local $SIG{__WARN__} = sub {
  my $message = shift;

  ## do nothing to ignore all together

  ## ignore specific message
  # warn $message unless $message =~ /No such file or directory/;

  ## or do something else
  # die $message ## make fatal
  # open my $fh, '>', 'file.log'; print $fh $message;
};

您可以通过以下方式将stderr重定向到/dev/null

@importlog = `ls -al import-log.* 2> /dev/null`;

@errorlog = `ls -al error-log.* 2> /dev/null`;

子外壳程序将继承父级的STDERR,因此,如果要在全局级别执行此操作,可以执行以下操作:

open(STDERR,'>/dev/null');
`ls non-existent-file`;
`ls non-existent-file2`;
`ls non-existent-file3`;
`ls non-existent-file4`;
`ls non-existent-file5`;

通常您还想稍后恢复STDERR 我这样做:

#!/usr/bin/perl

print STDERR "This will be send to the old (readable) STDERR\n";

my $oldstderr = readlink "/proc/self/fd/2"; #Remember the location of the old STDERR
open(STDERR, ">/dev/null"); #Ignore STDERR now

print STDERR "This will be send to a STDERR that is 'gone'\n";

open(STDERR, ">$oldstderr"); #restores STDERR to the old state

print STDERR "This will be send to the old (readable) STDERR again\n";

或者

您可以使用Capture::Tiny模块,它更易于阅读和便携。

#!/usr/bin/perl
use Capture::Tiny qw/capture_stderr/;

print STDERR "This will be send to the old (readable) STDERR\n";
capture_stderr sub {
  print STDERR "This will be send to a STDERR that is 'gone'\n";
};
print STDERR "This will be send to the old (readable) STDERR again\n";

下面介绍了如何抑制 STDERR、捕获关闭时出现的错误消息、恢复 STDERR 以及报告任何捕获的错误消息。

#!/usr/bin/perl
use warnings;
use strict;

print STDERR "STDERR is on.\n";
my ($stderr_fh, $err_msg_ref) = suppress_std_err();
print "STDERR is now off and error messages are being suppressed and saved.\n";
print STDERR "I'm an error message.\n";
restore_std_err($stderr_fh);
print STDERR "STDERR is back on\n";
print "Errors reported while STDERR was off: $$err_msg_ref\n";

#Saves STDERR in filehandle then turns it off.
#Any error messages that occur while STDERR is off are stored for safekeeping.
sub suppress_std_err {
        my $suppressed_std_error_messages;
        open (my $saved_std_err_fh, ">&", STDERR);
        close STDERR;
        open (STDERR, ">", \$suppressed_std_error_messages);
        return ($saved_std_err_fh, \$suppressed_std_error_messages);
}

#Restores STDERR from saved filehandle.
sub restore_std_err {
        my $old_std_err_fh = shift;
        close STDERR;
        open (STDERR, ">&", $old_std_err_fh);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM