使用 bash,我如何将标准错误传递到另一个进程?
Posted
技术标签:
【中文标题】使用 bash,我如何将标准错误传递到另一个进程?【英文标题】:With bash, how can I pipe standard error into another process? 【发布时间】:2010-12-03 05:31:09 【问题描述】:众所周知,如何将一个进程的标准输出通过管道传输到另一个进程的标准输入:
proc1 | proc2
但是如果我想将 proc1 的标准错误发送到 proc2 并将标准输出保留到其当前位置怎么办?你会认为bash
会有如下命令:
proc1 2| proc2
但是,唉,没有。有没有办法做到这一点?
【问题讨论】:
你可以在rc
中做这样一个简单的重定向,这是另一个shell。例如:proc1 |[2] proc2
。这不是很好吗?但不在bash
中。
相关:Piping both stdout and stderr in bash?。和here is 管道标准输出和标准错误的最简单答案。
【参考方案1】:
您可以使用以下技巧交换 stdout
和 stderr
。然后,您只需使用常规管道功能。
( proc1 3>&1 1>&2- 2>&3- ) | proc2
如果stdout
和stderr
在开始时都指向同一个地方,这将为您提供所需的内容。
x>&y
位所做的是更改文件句柄 x
,因此它现在将其数据发送到文件句柄 y
当前指向的任何位置。对于我们的具体情况:
3>&1
创建一个 new 句柄 3
,它将输出到 current 句柄 1
(原始标准输出),只是为了将它保存在下面的最后一个要点.
1>&2
修改句柄 1
(stdout) 以输出到 current 句柄 2
(原始 stderr)。
2>&3-
修改句柄 2
(stderr) 以输出到 current 句柄 3
(原始标准输出) 然后关闭句柄 3
(通过最后的 -
)。李>
这实际上是您在排序算法中看到的交换命令:
temp = value1;
value1 = value2;
value2 = temp;
【讨论】:
在这里使用1>&2-
而不仅仅是1>&2
有什么价值?我不明白为什么我们要关闭 fd 2
,如果我们只是要立即重新打开/重新分配它。
@dubiousjim,在这种特殊情况下没有优势,我怀疑我这样做只是为了保持一致 - 关闭文件句柄 3 是释放它的好主意。
试图让 gcc 的 make(在我的系统上是彩色的)与这个 "( make 3>&1 1>&2- 2>&3- ) | less -R" 而 "( ls - al 3>&1 1>&2- 2>&3- ) | less -R" 按预期工作。
对于后两个重定向,您的解释似乎是从头到尾的。 1>&2- 将文件句柄 2(原始标准错误)设置为句柄 1(原始标准输出) 2>&3- 将文件句柄 3(复制的标准输出)设置为句柄 2(原始标准错误)。如果我错了,请纠正我。顺便说一句,我猜想 2 上的破折号是为了防止新的 stderr 数据在填充来自 stdout 的数据时被发送到该缓冲区。
@aghsmith,不是这样的,左边的句柄总是被设置,右边的东西被用来设置它(无论是句柄还是文件名)。【参考方案2】:
Bash 4 有这个功能:
如果使用`|&',则command1的标准错误通过管道连接到command2的标准输入;它是 2>&1 | 的简写。这种标准错误的隐式重定向是在命令指定的任何重定向之后执行的。
zsh 也有这个功能。
--
对于其他/较旧的 shell,只需将其显式输入为
FirstCommand 2>&1 |其他命令
【讨论】:
通过阅读文档,可以同时输出标准错误 和 而不仅仅是 stderr,但很高兴知道。我想是时候开始研究 bash 4 了。 当前的 bash 手册显示“如果使用 |&,则命令的标准错误,除了其标准输出之外, 连接到命令 2 的标准输入”。这显然不是 OP 想要的。 @PeterA.Schneider:OP 说“将标准输出保留到其当前位置”,这可能是模棱两可的。 我没有看到任何歧义。您的建议 (1) 合并 两个流。 (2)OtherCommand
将 combined 数据写入某处,可能在其他某处。所以这不是相同的数据,它可能会转移到其他地方。这与OP的愿望相反,不是吗?
@PeterA.Schneider:标准输出的当前位置在哪里?如果proc1
输出到stdout 和stderr,并且您希望stderr 转到proc2
的stdin(这是proc1 的stdout 所在的位置),那么我的回答就完成了。我给了 OP 他要求的东西,也许不是他打算要求的东西。其中存在潜在的歧义。 OP 接受了 swaps stdout 和 stderr 的答案,这 not 是他所要求的。【参考方案3】:
交换很棒,因为它可以解决问题。以防万一您甚至不需要原始标准输出,您可以这样做:
proc1 2>&1 1>/dev/null | proc2
顺序至关重要;你不会想要的:
proc1 >/dev/null 2>&1 | proc1
因为这会将所有内容重定向到/dev/null
!
【讨论】:
【参考方案4】:还有process substitution。这使得进程替代了文件。
您可以将stderr
发送到文件,如下所示:
process1 2> file
但您可以按如下方式替换文件的进程:
process1 2> >(process2)
这是一个具体的例子,它将stderr
发送到屏幕并附加到日志文件
sh myscript 2> >(tee -a errlog)
【讨论】:
我试过这个。它不起作用(weston --help 2> >(less)
),它破坏了我的外壳,我不得不退出并重新登录。
@Rolf 如果weston --help
和less
都希望有键盘交互但只有其中一个接收到它,那么您可能处于尴尬的境地。尝试使用 grep
之类的东西进行测试。另外,您可能会发现鼠标/键盘输入无论如何都会转到第二个命令而不是韦斯顿。
如果你想同时重定向stderr和stdout使用|&
,我从here学到的【参考方案5】:
这些都不是真的很好用。我发现做你想做的最好的方法是:
(command < input > output) 2>&1 | less
这仅适用于command
不需要键盘输入的情况。例如:
(gzip -d < file.gz > file) 2>&1 | less
将 gzip 错误放入 less
【讨论】:
以上是关于使用 bash,我如何将标准错误传递到另一个进程?的主要内容,如果未能解决你的问题,请参考以下文章