[英]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.