使用 bash,如何将标准错误导入另一个进程?

众所周知,如何将一个流程的标准输出导入另一个流程的标准输入:

proc1 | proc2

但是,如果我想将 proc1的标准错误发送到 proc2,并将标准输出保留到其当前位置,那么该怎么办呢?你可能会认为 bash的命令大致如下:

proc1 2| proc2

但是,唉,没有。有什么办法可以做到这一点吗?

79089 次浏览

您可以使用下面的技巧 交换 stdoutstderr。然后您只需使用常规的管道功能。

( proc1 3>&1 1>&2- 2>&3- ) | proc2

如果 stdoutstderr在开始时都指向同一个位置,这将给你你所需要的。

x>&y位所做的是更改文件句柄 x,因此它现在将其数据发送到文件句柄 y当前指向的任何位置。针对我们的具体案例:

  • 3>&1创建了一个 新的句柄 3,它将输出到 目前句柄 1(原始标准输出) ,只是为了将它保存到下面最后一个项目符号点的某个位置。
  • 1>&2修改句柄 1(标准输出)以输出到 目前句柄 2(原始标准输出)。
  • 2>&3-修改句柄 2(stderr)以输出到 目前句柄 3(原始标准输出) ,然后关闭句柄 3(通过末端的 -)。

它实际上就是排序算法中的交换命令:

temp   = value1;
value1 = value2;
value2 = temp;

Bash 4有这样一个特性:

如果使用“ | &”,command1的标准错误将通过管道连接到 command2的标准输入; 它是2 > & 1 | 的简写。这个标准错误的隐式重定向是在命令指定的任何重定向之后执行的。

Zsh 也有这个特性。

--

对于其他/旧的 shell,只需显式输入以下内容

FirstCommand 2 > & 1 | OtherCommand 第一命令2 > & 1 | 其他命令

交换是伟大的,因为它解决了问题。为了以防万一,你甚至不需要原始的标准输出,你可以这样做:

proc1 2>&1 1>/dev/null | proc2

命令是至关重要的,你不会想要:

proc1 >/dev/null 2>&1 | proc1

因为这将重定向到 /dev/null的一切!

也有 工序替代工序替代。它使一个进程替代文件。
您可以将 stderr发送到以下文件:

process1 2> file

但是您可以用一个进程替换文件,如下所示:

process1 2> >(process2)

下面是一个将 stderr发送到屏幕并附加到日志文件的具体示例

sh myscript 2> >(tee -a errlog)

我发现做你想做的事情的最好方法是:

(command < input > output) 2>&1 | less

这只适用于 command不需要键盘输入的情况。例如:

(gzip -d < file.gz > file) 2>&1 | less

会减少 gzip 错误