本文介绍了为什么本地在 STDERR 和 STDOUT 上不起作用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

For my upcoming PulseAudio library I want to redirect STDERR and STDOUT to /dev/null logically this works,

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

然而,这仍然输出到术语......

However, this still outputs to the term....

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

这给我留下了两个问题

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

推荐答案

孩子写入 fd 1 和 2,但您没有更改 fd 1 和 2.您刚刚创建了新的 Perl 变量(孩子对此一无所知)) 与 fd 3 和 4(孩子不关心的东西).

The child writes to fd 1 and 2, yet you didn't change fd 1 and 2. You just created new Perl variables (something the child knows nothing about) with fd 3 and 4 (something the child doesn't care about).

这是实现您想要的一种方式:

Here's one way of achieving what you want:

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 甚至更高.

open3 is pretty low level, but it's far higher level than doing it yourself*. IPC::Run and IPC::Run3 are even higher level.


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

* — It takes care for forking and assigning the handles to the right file descriptors. It handles error checking, including making pre-exec errors in the child appear to be the launch failures they are and not errors from the executed program.

这篇关于为什么本地在 STDERR 和 STDOUT 上不起作用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-05 04:09