在开放式管道组件中重定向STDERR。Perl Linux

在开放式管道组件中重定向STDERR。Perl Linux,linux,perl,Linux,Perl,我限制使用的perl版本是v5.10.0 我有一个脚本“script1”,需要调用另一个脚本“script2” 为了绕过shell并避免命令行注入,我在perl中使用“open”来实现这一点 打开(my$fh、“-|”、“/path/to/script2”、“-n”、“$param”)或说“failure$@” 我不能修改脚本2 我需要将stderr的输出从script2获取到script1中的一个变量中 我从中得到了“-|”语法,但描述中主要是一个如何执行的示例,而不是它正在执行的操作,因此我

我限制使用的perl版本是v5.10.0

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

为了绕过shell并避免命令行注入,我在perl中使用“open”来实现这一点

打开(my$fh、“-|”、“/path/to/script2”、“-n”、“$param”)或说“failure$@”

我不能修改脚本2

我需要将stderr的输出从script2获取到script1中的一个变量中

我从中得到了“-|”语法,但描述中主要是一个如何执行的示例,而不是它正在执行的操作,因此我无法确定如何将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;
}
#选项1)
打开(my$fh、“-|”、“/path/to/script2”、“-n”、“$param”)或说“failure$@”;
而($line=){#stderr和stdout都被馈送到$line
打印$行;
}
#备选方案2)
打开(STDERR,“+我将使用以下方法执行此操作:

这将在变量
$err
中为您提供
script2.pl
的标准

从文件中:

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

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

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

$cmd

通常$cmd是一个数组引用,通过

system@$cmd;


请注意,如果目标是捕获流,那么将
$cmd
作为数组引用传递将避免在与命令相同的条件下通过shell运行命令

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

此便携式模块允许您

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

如果您只需要该流,还可以使用
capture\u stderr
功能

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


如果
@args
可能为空,则应按如下方式调用

system ( {$cmd} $cmd, @args );
而且shell仍然是可以避免的。一个很好的尝试方法是使用
$cmd='echo''From shell'
。感谢您在评论中注意到这一切

有关间接对象表示法的用法,请参见

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


这确保了永远不会调用shell。

您可以安装其他模块吗?如果可以,请查看Capture::Tiny。另请参见,您是否可以将
$cmd
作为列表传递,或者是否需要清理输入?是的,我想您可以将其作为列表传递,与
系统
命令完全相同,shell不会被调用invoked@mob,你可以s一个数组引用以避免shell。例如,
my$cmd=[$prog,@args]
将不使用shell(即使
@args
为空)。我最终使用了open3,并且让stderr和stdout存在于同一个var中,但是这个run3也会起作用。@FredMan。如果您使用
open3
分别捕获孩子的stdout和stderr,我打赌您的代码是有缺陷的。具体来说,我打赌您有可能导致死锁的竞争条件。您使用了threads还是IO::Select或n关于阻止读取?
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);
};
system ( {$cmd} $cmd, @args );