繁体   English   中英

使用带有perlcritic的IPC :: Open3

[英]Use IPC::Open3 with perlcritic

我想在子进程中压缩输出并只读取stderr。 perlfaq8建议做以下事项:

# To capture a program's STDERR, but discard its STDOUT:
use IPC::Open3;
use File::Spec;
use Symbol qw(gensym);
open(NULL, ">", File::Spec->devnull);
my $pid = open3(gensym, ">&NULL", \*PH, "cmd");
while( <PH> ) { }
waitpid($pid, 0);

但随后perlcritic争论使用裸字文件句柄

我唯一可以设计的是在STDOUTselect新打开的描述符到/dev/null ,如下所示:

# To capture a program's STDERR, but discard its STDOUT:
use IPC::Open3;
use File::Spec;
use Symbol qw(gensym);
open my $null, ">", File::Spec->devnull;
my $old_stdout = select( $null );
my $pid = open3(gensym, ">&STDOUT", \*PH, "cmd");
select( $old_stdout );
while( <PH> ) { }
waitpid($pid, 0);

但是, perlcritic并不喜欢使用select 有更优雅的解决方案吗?

最小的改变就是通过将NULL更改为* NULL来使open中的NULL不再是一个裸字。

使用这种形式的句柄通常被认为是不好的形式(因为它们是全局变量,尽管你可以通过对它们应用local来使它们更不全局化)。 因此我建议将其更改为使用我的变量来处理所有句柄。 它看起来像你丢弃stdin文件句柄,所以也可以传递null文件句柄(注意我在读写模式下打开它)

use strict;
use warnings;

use IPC::Open3;
use File::Spec;
use Symbol qw(gensym);

open(my $null, '+>', File::Spec->devnull);

my $childErr = gensym;

my $pid = open3($null, $null, $childErr, "cmd");

while(<$childErr>) { }
waitpid($pid, 0);
  • 你的select实际上什么也没做! select不会更改STDOUT
  • 将已关闭的文件句柄传递给程序的STDIN会导致问题。

固定:

use File::Spec qw( );
use IPC::Open3 qw( open3 );

my $child_stderr;
my $pid = do {
   open(local *CHILD_STDIN,  '<', File::Spec->devnull) or die $!;
   open(local *CHILD_STDOUT, '>', File::Spec->devnull) or die $!;
   $child_stderr = \( local *CHILD_STDERR );
   open3('<&CHILD_STDIN', '>&CHILD_STDOUT', $child_stderr, $cmd)
};
while (<$child_stderr>) { }
waitpid($pid, 0);

笔记:

  1. 我不使用通打开的文件句柄open3除了通过'<&SYM''>&SYM'机制。 如果不这样做,至少有一个地方存在问题。

  2. 有更高级别的模块更易于使用,如IPC :: Run3IPC :: Run

  3. 使用File::Spec->devnull()而不是'/dev/null'可能File::Spec->devnull()过分。 你的程序是否真的可以在没有/dev/null其他平台上运行?

>&...表达式还可以包含数字文件描述符,所以

open my $NULL, '>', ... ;
my $pid = open3(gensym, ">&" . fileno($NULL), \*PH, "cmd");

是词法文件句柄的等价物

open NULL, '>', ... ;
my $pid = open3(gensym, ">&NULL", \*PH, "cmd");

暂无
暂无

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

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