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