在OPEN管道命令中重定向STDERR。 Perl Linux

时间:2017-04-19 15:24:28

标签: linux perl

我所限制的perl版本是v5.10.0;

我有一个脚本,“script1”需要调用另一个脚本“script2。”

为了绕过shell并避免命令行注入,我使用“open”在perl中执行此操作。

打开(我的$ fh,“ - |”,“/ path / to / script2”,“ - n”,“$ param”)或者说“失败$ @”;

我无法修改script2。

我需要将脚本2中的stderr输出转换为script1中的变量。

我得到了“ - |”来自https://perldoc.perl.org/functions/open.html的语法,但其中的描述主要是如何执行它而不是它正在做什么的示例,因此我无法弄清楚如何将err重定向到out,甚至至少将err重定向到其他变量。

我希望看到类似于以下两个选项之一的东西:

# option 1)
open(my $fh, "-|", "/path/to/script2", "-n", "$param") or say "failure $@";
while($line = <$fh>) {  # stderr and stdout are both fed to $line
     print $line;
}

# option 2)
open(STDERR, "+<", $stderr);
open(my $fh, "-|", "/path/to/script2", "-n", "$param") or say "failure $@";
while($line = <$fh>) {  #stdout is fed to $line
     print $line;
}
while($line = <$stderr>) {  #stderr from script2 is fed to $line
     print $line;
}

2 个答案:

答案 0 :(得分:4)

我会使用IPC::Run3执行此操作:

use strict;
use warnings;
use IPC::Run3;

run3 ['script2.pl', '-n', $param], undef, \my $out, \my $err;

这会在变量script2.pl中为您提供$err的STDERR。

来自文档:

  

run3($ cmd,$ stdin,$ stdout,$ stderr,\%options)

     

$ cmd之后的所有参数都是可选的。

     

参数$ stdin,$ stdout和$ stderr表示孩子的情况   相应的文件句柄(STDIN,STDOUT和STDERR,resp。)将是   重定向。因为重定向是最后的,所以这允许STDOUT和   STDERR默认为父级,只是不指定它们 - a   常见用例。

     

<强> $ CMD

     

通常$ cmd将是ARRAY参考,并且通过

调用子项      

system @$cmd;

请注意,将$cmd作为数组引用传递将避免在与system()命令相同的条件下通过shell运行命令

答案 1 :(得分:3)

如果目标是捕获流,则一个不错的模块是Capture::Tiny

use warnings;
use strict;
use Capture::Tiny qw(capture);

my $cmd  = '/path/to/script2';
my @args = ('-n', $param);

my ($stdout, $stderr, $exit) = capture {
    system($cmd, @args);
};

您可以将命令和参数放在列表@cmd = ('ls', '-l', './')中。如果将命令和参数集中到标量中,则可以使用shell(如果有shell元字符)。

此便携式模块允许您

  

捕获几乎所有发送到STDOUT或STDERR的内容,无论它是来自Perl,来自XS代码还是来自外部程序。

如果您只想要该流,还有capture_stderr功能。

请注意,许多工具(包括system)都有一个绕过shell:pass命令和/或参数作为列表的规定。 (但是,如果您需要STDERR,则无法单独使用system直接获取它,而不使用shell重定向。)

如果@args可能为空,则应将其作为

调用
system ( {$cmd} $cmd, @args );

并且仍然避免使用shell。一个很好的尝试方法是使用$cmd = 'echo "From shell"'。感谢ikegami在评论中注意到这一切。

有关间接对象表示法的使用,请参阅exec

  

强制将LIST解释为多值列表,即使列表中只有一个标量

这确保永远不会调用shell。