使用& 在模式>& 中调用
open STDERR, ">&STDOUT"; # or: open STDERR, ">&", \*STDOUT
第一个给定的文件句柄是第二个的副本。请参阅open,并参阅man 2 dup2,因为这是通过dup2 系统调用进行的。该符号遵循 shell 的I/O redirection。
因为这里第一个文件句柄存在 (STDERR)† 它首先被关闭。
效果是打印到STDERR 将转到STDOUT 在此完成之前要去的地方,原始STDERR 的副作用被关闭。
这是合法的,不会导致错误,但通常不是重定向STDERR 的好方法——之后我们无法再恢复STDERR。请参阅open 了解如何重定向STDERR。
评论的其余部分清楚地提到了在open 调用之后使用反引号(参见qx)将已执行命令的STDOUT 重定向到程序的情况。这一切似乎是指以这种方式将STDERR重定向到STDOUT的想法。
唉,STDERR 是由 open 调用产生的,指向 STDOUT 要去的地方,不会被反引号重定向,因此仍然“在那里”。在我的情况下,当我看到警告 (ls: cannot access...) 时,终端上会打印到 STDERR
perl -we'open STDERR, ">&STDOUT"; $out = qx(ls no_such)'
(与perl -we'$out = qx(ls no_such 2>&1)' 不同)。显式打印到STDERR 也以STDOUT 的形式进入终端(添加此类打印并将输出重定向到文件以查看)。
这可能是意料之中的,因为& 制作了文件句柄的副本,所以“新”的(以前的STDERR)仍然在STDOUT 要去的地方,也就是说终点站。在这种情况下当然是无意的,因此是错误的。
† UNIX 中的每个程序都连接到标准流stdin、stdout 和stderr,文件描述符分别为0、1 和2。在 Perl 程序中,我们为这些准备好文件句柄,例如 STDERR(用于 fd 2)。
一些关于在 shell 中操作文件描述符的一般有用的帖子: