【问题标题】:Meaning of open( STDERR, ">&STDOUT" )open(STDERR, ">&STDOUT" ) 的含义
【发布时间】:2019-07-07 02:30:56
【问题描述】:

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

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

open(STDERR, ">&STDOUT");

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

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

【问题讨论】:

标签: perl io-redirection


【解决方案1】:

使用& 在模式>& 中调用

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 中的每个程序都连接到标准流stdinstdoutstderr,文件描述符分别为012。在 Perl 程序中,我们为这些准备好文件句柄,例如 STDERR(用于 fd 2)。

一些关于在 shell 中操作文件描述符的一般有用的帖子:

【讨论】:

    【解决方案2】:

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

    简而言之,它将STDERR 与系统级别的STDOUT 关联到相同的流。执行命令后,写入其中之一将与更改前写入STDOUT 相同。

    除非有人弄乱了STDOUT或STDERR,否则就相当于shell命令

    exec 2>&1
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-06-14
      • 2020-10-18
      • 2020-05-30
      • 2022-01-18
      • 2014-07-14
      • 1970-01-01
      • 2011-04-18
      • 1970-01-01
      相关资源
      最近更新 更多