【问题标题】:How do these stream redirections work?这些流重定向如何工作?
【发布时间】:2011-04-27 03:14:05
【问题描述】:

来自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>&-`;

我不明白 3 和 4 是如何工作的,我不太确定我对 1 和 2 的理解是否正确。以下是我的理解。请纠正我的错误。

我知道012象征着STDINSTDOUTSTDERR

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

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

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

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

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

  4. 这里发生了什么?什么是流3?是不是像临时变量?

【问题讨论】:

  • @skaffman - 为什么要重新添加 perl 标签? perl 的提及与问题无关。

标签: bash shell io-redirection


【解决方案1】:

通常我们有这个:

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)。

整个过程有效地交换了 fd1 和 fd2。 fd3 充当临时变量。

1 --STDOUT
 X
2 `-STDERR

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

【讨论】:

    【解决方案2】:

    虽然在 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;
    

    【讨论】:

      【解决方案3】:

      真的,这些都不是 Perl —— 所有这些都由您使用反引号运算符调用的 shell 处理。所以你最好的阅读是man sh,或者Shell 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,因为它不再需要了。

      【讨论】:

      • @Lazer 是的。标准也说了这么多。 :)
      【解决方案4】:

      3.不。顺序很重要,所以它摆脱了原来的标准输出,然后将标准错误移动到标准输出。

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

      【讨论】:

      • "2>&1 1>/dev/null" -> "...然后将 stderr 移动到 stdout"。你确定吗?它不是以相反的顺序发生的吗?
      • @Ignacio:那么它在4中是如何工作的?这意味着流 3 在打开之前就已关闭!
      • 这只是意味着任何可能已经打开它已经被关闭了。
      • 这仍然没有意义。对于2>&3,怎么能2点无处呢? (因为 3 指向的任何东西都刚刚使用 3>&- 关闭)
      • FD 2 被复制到 FD 3。2 没有指向任何地方,3 现在指向 2 的位置。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-13
      • 2021-03-13
      • 1970-01-01
      • 1970-01-01
      • 2011-01-05
      • 1970-01-01
      相关资源
      最近更新 更多