代码之家  ›  专栏  ›  技术社区  ›  Ryley

wget未通过ipc::open3与bash执行操作

  •  4
  • Ryley  · 技术社区  · 14 年前

    我正在尝试将文件从远程网站传输到本地命令,并且在尝试检测错误时遇到一些问题。

    代码如下所示:

    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
    

    当我直接从命令行运行wget命令并将stderr重定向到一个文件时,会发生一些异常情况——stdout将是下载的页面,stderr将包含有关打开给定页面的信息。

    wget -O - http://10.10.1.72/index.php 2> stderr_test_file
    

    当我通过open3运行wget时,我会在stdout中将页面和信息混合在一起。我期望的是一个流中的已加载页和另一个流中wget的stderr。

    我可以看到我已经将代码简化到不清楚为什么我要使用Open3的程度,但是总的计划是,当我收到它时,我想将stdout流到另一个筛选程序,然后在最后,我将从wget和筛选程序中读取stderr,以确定出了什么问题,如果出了什么问题。

      其他重要事项:
    • 我试图避免将wget的数据写入一个文件,然后将该文件过滤到另一个文件,然后读取输出。
    • 关键是我能看到哪里出了问题,而不仅仅是读美元?>gt;8(也就是说,我必须告诉用户,嘿,IP地址错误,或者不是正确的网站类型,或者其他)。
    • 最后,我选择System/Open3/Exec而不是其他Perl ISM(即backticks),因为有些输入是由不值得信任的用户提供的。
    1 回复  |  直到 14 年前
        1
  •  3
  •   mob    14 年前

    将未定义的值作为错误句柄参数传递给open3,并作为 IPC::Open3 说:

    如果chld_err为false,或者与chld_out具有相同的文件描述符,则子级的stdout和stderr位于同一个filehandle上。 (这意味着自动激活的词汇不能用于stderr文件句柄 ,请参阅摘要…

    解决方法是初始化 $wget_err 在打电话之前 open3 :

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