众所周知,如何将一个进程的标准输出通过管道传输到另一个进程的标准输入:
proc1 | proc2
但是,如果我想将 proc1 的标准错误发送到 proc2 并将标准输出保留到其当前位置怎么办?你会认为bash
会有一个类似的命令:
proc1 2| proc2
但是,唉,没有。有没有办法做到这一点?
还有过程替换。这使得进程替代文件。
您可以stderr
按如下方式发送到文件:
process1 2> file
但是您可以按如下方式替换文件的进程:
process1 2> >(process2)
这是一个发送stderr
到屏幕并附加到日志文件的具体示例
sh myscript 2> >(tee -a errlog)
您可以使用以下技巧来交换 stdout
和stderr
. 然后,您只需使用常规管道功能。
( proc1 3>&1 1>&2- 2>&3- ) | proc2
提供stdout
并且stderr
在开始时都指向同一个地方,这将为您提供所需的东西。
该x>&y
位所做的是更改文件句柄x
,因此它现在将其数据发送到文件句柄y
当前指向的任何位置。对于我们的具体案例:
3>&1
创建一个新句柄3
,该句柄将输出到当前句柄1
(原始标准输出),只是为了将其保存在下面的最后一个要点。1>&2
修改句柄1
(stdout) 以输出到当前句柄2
(原始 stderr)。2>&3-
修改句柄2
(stderr)以输出到当前句柄3
(原始标准输出),然后关闭句柄3
(通过-
末尾的)。它实际上是您在排序算法中看到的交换命令:
temp = value1;
value1 = value2;
value2 = temp;
Bash 4 有这个功能:
如果使用了`|&',则command1的标准错误通过管道连接到command2的标准输入;它是 2>&1 | 的简写。标准错误的这种隐式重定向在命令指定的任何重定向之后执行。
zsh 也有这个功能。
--
对于其他/较旧的外壳,只需将其明确输入为
第一个命令 2>&1 | 其他命令
交换很棒,因为它可以解决问题。万一您甚至不需要原始标准输出,您可以这样做:
proc1 2>&1 1>/dev/null | proc2
顺序至关重要;你不会想要:
proc1 >/dev/null 2>&1 | proc1
因为这会将所有内容重定向到/dev/null
!
这些都不是真的很好用。我发现做你想做的最好的方法是:
(command < input > output) 2>&1 | less
这仅适用于command
不需要键盘输入的情况。例如:
(gzip -d < file.gz > file) 2>&1 | less
会将 gzip 错误放入 less