Perl wget未通过IPC::Open3 vs bash运行

Perl wget未通过IPC::Open3 vs bash运行,perl,ipc,wget,Perl,Ipc,Wget,我试图将文件从远程网站流式传输到本地命令,在尝试检测错误时遇到了一些问题 代码如下所示: use IPC::Open3; my @cmd = ('wget','-O','-','http://10.10.1.72/index.php');#any website will do here my ($wget_pid,$wget_in,$wget_out,$wget_err); if (!($wget_pid = open3($wget_in,$wget_out,$wget_err,@cmd)

我试图将文件从远程网站流式传输到本地命令,在尝试检测错误时遇到了一些问题

代码如下所示:

use IPC::Open3;

my @cmd = ('wget','-O','-','http://10.10.1.72/index.php');#any website will do here

my ($wget_pid,$wget_in,$wget_out,$wget_err);
if (!($wget_pid = open3($wget_in,$wget_out,$wget_err,@cmd))){
    print STDERR "failed to run open3\n";
    exit(1)
}
close($wget_in);
my @wget_outs = <$wget_out>;
my @wget_errs = <$wget_err>;
print STDERR "wget stderr: ".join('',@wget_errs);
#page and errors outputted on the next line, seems wrong
print STDERR "wget stdout: ".join('',@wget_outs);

#clean up after this, not shown is running the filtering command, closing and waitpid'ing
当我通过open3运行wget时,我在标准输出中将页面和信息混合在一起。我期望的是在一个流中加载页面,在另一个流中加载wget中的STDERR

我可以看出,我已经将代码简化到了不清楚为什么要使用open3的程度,但总体计划是,我希望在收到stdout时将其流式传输到另一个过滤程序,然后在最后,我将从wget和过滤程序中读取stderr,以确定如果出现任何错误,会发生什么

    其他重要事项:
  • 我试图避免将wget的数据写入一个文件,然后将该文件过滤到另一个文件,然后读取输出
  • 关键是我能够看到哪里出了问题,而不仅仅是阅读$?>>8(也就是说,我必须告诉用户,嘿,IP地址错了,或者不是正确的网站类型,或者别的什么)
  • 最后,我选择system/open3/exec而不是其他perl ISM(即backticks),因为一些输入是由不可信的用户提供的

您正在将一个未定义的值作为错误句柄参数传递给open3,如下所示:

如果CHLD_ERR为false,或者与CHLD_OUT相同的文件描述符,则子项的STDOUT和STDERR位于同一个文件句柄上(这意味着无法将自动激活的词法用于STDERR文件句柄,请参见概要)

解决方法是在调用
open3
之前将
$wget\u err
初始化为以下内容:

my ($wget_pid, $wget_in, $wget_out, $wget_err);
use Symbol qw(gensym);
$wget_err = gensym();
if (!$wget_pid = open3( ... ) ) { ... 

@我不知道你是什么意思?在标准输入上输入wget?我不确定我需要给它什么?好的,试过了,通过一个bash shell,stdout和stderr仍然是可分离的…而且,这就是我得到的不是真正的RTFM。。。我阅读了Open2文档,然后意识到在这个过程的后面我需要STDERR,而没有阅读过Open3文档的第一行。
my ($wget_pid, $wget_in, $wget_out, $wget_err);
use Symbol qw(gensym);
$wget_err = gensym();
if (!$wget_pid = open3( ... ) ) { ...