我所限制的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;
}
答案 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。