这些流重定向如何工作?

Laz*_*zer 5 bash shell io-redirection

这个 perldoc 页面

  1. 要一起捕获命令的 STDERR 和 STDOUT:

    $输出 = `cmd 2>&1`;
  2. 要捕获命令的 STDOUT 但丢弃其 STDERR:

    $output = `cmd 2>/dev/null`;
  3. 要捕获命令的 STDERR 但丢弃其 STDOUT(此处顺序很重要):

    $output = `cmd 2>&1 1>/dev/null`;
  4. 要交换命令的 STDOUT 和 STDERR 以捕获 STDERR,但保留其 STDOUT 以输出旧的 STDERR:

    $输出 = `cmd 3>&1 1>&2 2>&3 3>&-`;

我不明白3和4是如何工作的,我也不太确定我对1和2的理解是否正确。下面是我的理解。有不对的地方请指正。

我知道012象征STDINSTDOUTSTDERR

  1. 将 2 重定向到 1,以便它们现在都使用相同的流(&转义1以确保STDERR不会重定向到名为的文件1

  2. 将 2 (STDERR) 重定向到空流,以便它被丢弃

  3. 我不明白这个。难道不应该只是

    $output = `cmd 1>/dev/null`;

    另外,如果目标是获取STDERR的消息STDOUT,不会1>/dev/null将所有内容重定向到 吗/dev/null

  4. 这里发生了什么?什么是流3?它就像一个临时变量吗?

hob*_*bbs 4

实际上,这些都不是 Perl —— 所有这些都是由您使用反引号运算符调用的 shell 处理的。所以你最好的读物是Unix 标准的 Shellman sh章节。

简而言之,对于#4:

  • 3>&1:打开FD 3指向stdout当前指向的位置。
  • 1>&2:重新打开stdout以指向stderr当前指向的位置。
  • 2>&3:重新打开stderr,使其指向FD 3当前指向的位置,也就是上一步完成之前stdout所指向的位置。现在stdout和stderr已经成功交换了。
  • 3>&-:关闭 FD 3,因为不再需要它。