标准错误到标准输出 - 除了重定向之外还有其他选项吗?

标准错误到标准输出 - 除了重定向之外还有其他选项吗?

standard error我对standard output……的了解非常有限。

常见的方法之一是重定向standard errorstandard output.这是否意味着错误(通常会转到)因为重定向standard error而不会再出现?standard error

如果这是真的,是否有任何方法可以复制standard error、重定向副本并让原始内容按预期standard output定向?standard error

答案1

在我接触 Unix 的早期,有人向我解释管道的工作原理就像管道一样。

一个流程基本上有 3 个用于填充的连接点:

           stdin
             |
          +--+--+
          | pgm |
          ++---++
           |   |
      stdout   stderr

所以,当你这样做时cat | grep pattern,你会得到

         stdin
           |
        +--+--+
        | cat |
        ++---++
   stdout|   |stderr
         |   \
    stdin|    \
     +------+  |
     | grep |  |
     +-+---++  |
 stdout|   |   |
       |   \__ |
       |      \|
       |       |stderr

(那时候都是ascii图形……)

当您将 stderr 重定向到 stdout 时,如图所示pgm 2>&1,图片变为:

    stdin |
          |
       +--+--+
       | pgm |
       ++---++
  stdout|   |stderr
        |   /
        |  /
        | /
        |/
        |

理论上,您可以通过这种方式完成很多管道工作。例如:awk '{print;print > "/dev/stderr"}'将 stdin 复制到 stdout 和 stderr。

然而,它很快就会变得非常混乱。详细信息请参阅 bash 手册。

笔记:pgm = 上图中的程序。

编辑:为了好玩,我尝试使用简单的 shell 脚本进行一些更复杂的管道操作。

generate.sh:

echoerr() { echo "$@" 1>&2; }
for i in 1 2 3 4 5 6 ; do
        echo "STDOUT $i"
        echoerr "STDERR $i"
done

copytee.sh

#!/bin/bash
echoerr() { echo "$@" 1>&2; }
while read line; do
        echo "stdout $line"
        echoerr "stderr $line"
done

(请注意,copytee ads 小写,generate 添加大写)

要获得高级形式的重定向,bash generate.sh 2> >(bash copytee.sh )请给出输出:

STDOUT 1
STDOUT 2
STDOUT 3
STDOUT 4
STDOUT 5
STDOUT 6
stdout STDERR 1
stderr STDERR 1
stdout STDERR 2
stderr STDERR 2
stdout STDERR 3
stderr STDERR 3
stdout STDERR 4
stderr STDERR 4
stdout STDERR 5
stderr STDERR 5
stdout STDERR 6
stderr STDERR 6

这正是你所要求的。

答案2

“标准误差”并不是一个特别定义的地方。 “标准错误”是附加到文件描述符 2 的任何内容。

当您将“标准错误”重定向到“标准输出”时,您所做的是关闭文件描述符 2,然后将其作为文件描述符 1 的副本重新打开,因此它会附加到文件描述符 1 恰好附加到的任何位置那一刻。原来的文件描述符2丢失了(字面意思就是文件描述符被关闭)。所以,你不能完全做你想做的事。如果您将“标准错误”重定向到其他地方,文件描述符 2 将被关闭(并重新打开以将其附加到您重定向到的任何位置),并且不再有任何有关它“应该在”的位置的信息。

相关内容