问题描述
对于我即将推出的 PulseAudio 库,我想将 STDERR
和 STDOUT
重定向到 /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 $?;
这给我留下了两个问题
- 首先,为什么我会出现我所看到的行为?
- 其次,是否有不涉及存储旧值并替换它的更有效的方法?
推荐答案
孩子写入 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::Run 和 IPC::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 上不起作用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!