【问题标题】:Perl STDOUT redirection not working in childPerl STDOUT 重定向在子进程中不起作用
【发布时间】:2012-08-01 16:25:56
【问题描述】:

在运行 Perl 程序时,子脚本的输出被打印到终端而不是进入$v。请告诉我如何解决它。

open (OUTPUT, '>', \$v);
select OUTPUT;
$| = 1;

open (SUB, "| sh print_user_input.sh");
print SUB "Hello World\n";
close(SUB);

close(OUTPUT);
select STDOUT;

print "Output: $v\n";

程序的输出是:

你好世界 输出:

【问题讨论】:

  • 您应该考虑使用词法文件句柄(如 $output)而不是 typeglob(如 OUTPUT),open 的 3 参数版本(如 open my $sub, "|-", "./print_user_input.sh"use autodie 来捕获错误opencloseuse strict,如果你还没有的话。

标签: perl


【解决方案1】:
  1. select 不会改变 STDOUT。
  2. open '>', \$buf 不创建系统文件句柄。 (谁会读取它并将数据放入$buf?另一个进程不能直接写入$buf,即使perl是一个进程。)

一个解决方案:

use IPC::Run3 qw( run3 );
run3 [ 'sh', 'print_user_input.sh' ],
   \"Hello World\n",
   \my $v;

【讨论】:

    【解决方案2】:

    你有两个问题。 select 并没有改变 STDOUT,它只是改变了 Perl 关于应该打印到哪个文件句柄的想法。像您尝试使用的内存中文件句柄只能在单个 Perl 进程中工作;您不能在子进程中使用它们。

    您想查看IPC::Open3 或类似模块。

    【讨论】:

    • 这对于IPC::Open3 来说实际上很难。它需要一个select 循环来避免死锁。我推荐IPC::Run3IPC::Run。我的回答就是一个例子。
    【解决方案3】:

    使用IPC::Open2open2函数:

    #!/usr/bin/env perl
    
    use strict;
    use warnings;
    
    use IPC::Open2;
    
    my $pid = open2( \*CHLD_OUT, \*CHLD_IN, 'sh print_user_input.sh' );
    print CHLD_OUT "Hello World\n";
    close CHLD_OUT;
    
    my $output = do { local $/; <CHLD_OUT> };
    print "Output: $output";
    

    【讨论】:

    • 请注意,"Hello World\n" 确实是一个更长的字符串。
    • 如果程序继续运行,你会想调用waitpid($pid, 0); 来收割孩子。无论如何,您可能都想这样做以确保孩子成功运行。
    猜你喜欢
    • 1970-01-01
    • 2015-08-18
    • 1970-01-01
    • 2012-07-14
    • 2021-06-01
    • 2012-02-11
    • 2014-11-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多