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

时间:2019-07-07 02:30:56

标签: perl io-redirection

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

  

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

open(STDERR, ">&STDOUT");
     

这失败,因为open()使STDERR转到STDOUT所在的位置       open()的时间。反引号然后使STDOUT转到字符串,但是       请勿更改STDERR(仍然使用旧的STDOUT)。

现在我很困惑。 open(STDERR, ">&STDOUT");的确切含义是什么?

2 个答案:

答案 0 :(得分:5)

在通话中,&处于>&模式下

open STDERR, ">&STDOUT";  # or: open STDERR, ">&", \*STDOUT

第一个给定的文件句柄成为第二个文件句柄的副本。请参见openman 2 dup2,因为这是通过dup2 syscall进行的。该符号遵循外壳程序的I/O redirection。  由于此处存在第一个文件句柄(STDERR,因此它首先被关闭。

结果是打印到STDERR的位置将移至STDOUT进行之前的位置,而原始STDERR的副作用将被关闭。

这是合法的,不会导致错误,但是并不是通常重定向STDERR的好方法-之后,我们将无法再恢复STDERR。有关如何重定向STDERR的信息,请参见open

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

A,STDOUT是由STDERR呼叫转到open所要到达的地方而产生的,不会被反引号重定向,因此仍然会“出现”。就我而言,打印到STDOUT的打印在终端上结束,因为我看到警告(STDERR),

ls: cannot access...

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

这可能是可以预期的,因为STDOUT对文件句柄进行了复制,因此“新”文件(以前的&)仍然位于STDERR的位置正要去终点站。在这种情况下当然是意料之外的,因此是错误的。


UNIX中的每个程序都使用文件描述符STDOUT,{{}连接到标准流stdinstdoutstderr。 1}}和0。然后在Perl程序中,我们为这些文件准备好了文件句柄,例如1(对于fd 2)。

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

答案 1 :(得分:2)

基本上是dup2(fileno(STDOUT), fileno(STDERR))。请参见系统的dup2手册页。

简而言之,它在系统级别将STDERRSTDOUT相同的流相关联。执行命令后,写入任一内容都与更改之前写入STDOUT相同。

除非有人对STDOUT或STDERR感到困惑,它等同于shell命令

exec 2>&1