这些流重定向如何工作?

时间:2010-10-18 19:35:51

标签: bash shell io-redirection

来自this perldoc page

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

     
    $output = `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:

     
    $output = `cmd 3>&1 1>&2 2>&3 3>&-`;

  5. 我不明白3和4是如何工作的,我不太清楚我对1和2的理解是对的。以下是我的理解。请纠正我错在哪里。

    我知道012代表STDINSTDOUTSTDERR

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

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

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

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

      此外,如果目标是在1处收到STDERR条消息,则不会STDOUT将所有内容重定向到1>/dev/null

    4. 这里发生了什么?什么是流/dev/null?它是否像临时变量?

4 个答案:

答案 0 :(得分:3)

虽然在perldocs中有记录,但重定向都是标准的linux重定向。你正确理解1和2。

3)只有STDOUT通常被基本重定向(>)捕获,因此必须丢弃原始STDOUT, STDERR必须发送到STDOUT。

4)cmd 3>&1 1>&2 2>&3 3>&-相当于

var tmp = STDOUT;
STDOUT = STDERR;
STDERR = tmp;
delete tmp;

答案 1 :(得分:3)

真的,这些都不是Perl - 所有这些都是由你使用反引号运算符调用的shell处理的。因此,您的最佳阅读时间为man shShell chapter of the Unix standard

简而言之,对于#4:

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

答案 2 :(得分:3)

通常我们有这个:

1-->STDOUT
2-->STDERR

2>&1将文件描述符fd2重定向到fd1

1-->STDOUT
   /
2./

2>/dev/nullfd2重定向到/dev/null

1-->STDOUT
2-->/dev/null

2>&1 1>/dev/nullfd2重定向到fd1,然后将fd1重定向到/dev/null

    /dev/null
   /
1./ STDOUT
   /
2./

3>&1 1>&2 2>&3 3>&-

  1. 首先将新的fd 3指向任何地方 fd 1当前正指向(STDOUT)。
  2. 然后将fd1重定向到fd2所在的位置 当前指向(STDERR),
  3. 然后将fd 2重定向到fd 3的任何位置 目前指向(STDOUT)
  4. 然后关闭fd3(3>& - 表示关闭 文件描述符3)。
  5. 整个事情有效地交换了fd1和fd2。 fd3充当临时变量。

    1 --STDOUT
     X
    2 `-STDERR
    

    有关IO重定向的更多信息,请参阅the docs

答案 3 :(得分:-2)

3.Nope。排序很重要,所以它摆脱了原来的标准输出,然后它将stderr移动到标准输出。

4. 3只是另一个文件描述符,与前3个相同。大多数进程可以使用总共256个不同的文件描述符。