使用 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】:

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

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

如果stdoutstderr 在开始时都指向同一个地方,这将为您提供所需的内容。

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) OtherCommandcombined 数据写入某处,可能在其他某处。所以这不是相同的数据,它可能会转移到其他地方。这与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 --helpless 都希望有键盘交互但只有其中一个接收到它,那么您可能处于尴尬的境地。尝试使用 grep 之类的东西进行测试。另外,您可能会发现鼠标/键盘输入无论如何都会转到第二个命令而不是韦斯顿。 如果你想同时重定向stderr和stdout使用|&,我从here学到的【参考方案5】:

这些都不是真的很好用。我发现做你想做的最好的方法是:

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

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

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

将 gzip 错误放入 less

【讨论】:

以上是关于使用 bash,我如何将标准错误传递到另一个进程?的主要内容,如果未能解决你的问题,请参考以下文章

如何在bash脚本中通过函数调用将参数/参数从一个函数传递到另一个函数[重复]

如何使用 WCF 将数据从一个进程传递到另一个进程?

将数组从一个 Bash 脚本传递到另一个

Dart:如何通过流将数据从一个进程传递到另一个进程

Python子进程错误:使用标准输入将输入传递到终端

在 Bash 中重定向标准错误和标准输出 [重复]