为什么本地不在STDERR和STDOUT上工作?

时间:2012-12-12 05:00:24

标签: perl redirect stdout stderr

对于即将推出的PulseAudio库,我想将STDERRSTDOUT重定向到/dev/null,这在逻辑上是可行的,

sub _exec {
    open (*STDERR, '>', '/dev/null');    
    open (*STDOUT, '>', '/dev/null');    
    CORE::system('pacmd', @_ ) or die $?;

然而,这仍然是对......一词的输出。

sub _exec {
    local ( *STDERR, *STDOUT );
    open (*STDERR, '>', '/dev/null');    
    open (*STDOUT, '>', '/dev/null');    
    CORE::system('pacmd', @_ ) or die $?;

这给我留下了两个问题

  1. 首先,为什么我会遇到我所看到的行为?
  2. 其次,是否有一种更有效的方法,不涉及存储旧值并替换它?

1 个答案:

答案 0 :(得分:5)

孩子写入fd 1和2,但你没有改变fd 1和2.你刚刚用fd 3和4创建了新的Perl变量(孩子一无所知)(孩子不关心的事情)约)。

这是实现目标的一种方式:

use IPC::Open3 qw( open3 );

sub _exec {
    open(local *CHILD_STDIN,  '<', '/dev/null') or die $!;
    open(local *CHILD_STDOUT, '>', '/dev/null') or die $!;
    my $pid = open3(
        '<&CHILD_STDIN',
        '>&CHILD_STDOUT',
        undef,  # 2>&1
        'pacmd', @_,
    );
    waitpid($pid, 0);
    die $! if $? == -1;
    die &? if $?;
}

open3水平相当低,但它远高于自己做的水平*。 IPC::RunIPC::Run3的级别更高。



* - 它负责分叉并将句柄分配给正确的文件描述符。它处理错误检查,包括使子项中的exec前错误看起来是它们的启动失败,而不是执行程序中的错误。