打开的含义(STDERR,“>&STDOUT”)

ton*_*ibm 2 perl io-redirection

我在一个示例脚本中找到了它,然后我从Google搜索并找到了以下单词,

请注意,您不能简单地将STDERR打开为Perl程序中STDOUT的副本,并避免调用Shell进行重定向。这不起作用:

open(STDERR, ">&STDOUT");
Run Code Online (Sandbox Code Playgroud)

之所以失败,是因为open()使STDERR转到open()时STDOUT所在的位置。然后,反引号使STDOUT转到字符串,但不要更改STDERR(仍将其转到旧的STDOUT)。

现在我很困惑。到底是什么意思open(STDERR, ">&STDOUT");

zdi*_*dim 5

随着&在模式>&呼叫

open STDERR, ">&STDOUT";  # or: open STDERR, ">&", \*STDOUT
Run Code Online (Sandbox Code Playgroud)

第一个给定的文件句柄是第二个的副本。参见open,然后查看,man 2 dup2因为这是通过dup2syscall进行的。该符号遵循Shell的I / O重定向。由于此处存在第一个文件句柄(STDERR†,因此它首先被关闭。

这样做的结果是,打印到的位置STDERR将转到STDOUT完成此操作之前要去的地方,同时STDERR关闭了原件的副作用。

这是合法的,并不会导致错误,但不是重定向的好方法STDERR一般 -毕竟,我们不能恢复STDERR了。请参阅open了解如何重定向STDERR

注释的其余部分显然是指在调用之后使用反引号(请参阅qx)的情况,该反引号将STDOUT已执行的命令重定向到程序open。所有这些似乎都涉及以这种方式重定向STDERR到的想法STDOUT

遗憾的是STDERR,通过open调用转到要去的地方STDOUT而产生的,不会被反引号重定向,因此仍然“存在”。就我而言,STDERR当我看到警告(ls: cannot access...

perl -we'open STDERR, ">&STDOUT"; $out = qx(ls no_such)'
Run Code Online (Sandbox Code Playgroud)

(与不同perl -we'$out = qx(ls no_such 2>&1)')。显式打印STDERR也以同样的方式发送到终端STDOUT(添加此类打印并将输出重定向到文件以查看)。

这可能是意料之中的,因为&做了一个拷贝的文件句柄,所以“新”一个(前STDERR)还是飞到哪里,STDOUT要去,那就是终端。在这种情况下当然是意料之外的,因此是错误的。


 在UNIX中的每个程序被连接到标准的数据流stdinstdout以及stderr与文件描述符012分别。然后在Perl程序中,我们为这些文件准备好了文件句柄,例如STDERR(对于fd 2)。

有关在Shell中操作文件描述符的一些普遍有用的文章: