使用bash,如何将标准错误传递到另一个进程?


137

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

proc1 | proc2

但是,如果我想将proc1的标准错误发送到proc2并将标准输出留到当前位置怎么办?您可能会想到bash以下命令:

proc1 2| proc2

但是,a,不。有什么办法吗?


您可以在rc另一个shell中进行如此简单的重定向。例如:proc1 |[2] proc2。好不好 不是bash虽然。
罗夫(Rolf)'18

Answers:


168

也有过程替代。这使得进程可以代替文件。
您可以stderr按以下方式发送到文件:

process1 2> file

但是您可以按以下步骤用文件代替进程:

process1 2> >(process2)

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

sh myscript 2> >(tee -a errlog)

23
这正确回答了所述问题,应该是@paxdiablo接受的答案
mmlb 2014年

我试过了 它没有工作(weston --help 2> >(less)),它打破了我的贝壳,我不得不退出并重新登录。
罗尔夫

1
@Rolf如果weston --helpless都希望与键盘进行交互,但是只有其中之一接收到它,那么您可能处于尴尬境地。尝试使用类似的方法进行测试grep。另外,您可能会发现两个鼠标/键盘输入都将转到第二个命令,而不是转到weston。
BeowulfNode42 '18

88

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

( 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(原始stdout),然后关闭句柄3(通过-末尾的)。

它实际上是您在排序算法中看到的swap命令:

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

3
1>&2-在这里而不是仅仅使用它的价值是什么1>&2?我不明白为什么我们要立即关闭fd 2,如果我们要立即重新打开/重新分配它。
dubiousjim 2012年

1
@dubiousjim,在特定情况下没有优势,我怀疑我只是为了保持一致而这样做-关闭文件句柄3是释放它的好主意。
paxdiablo 2012年

好点,@ ovgolovin,我不敢相信自从我进行编辑以来的七个月内没有人发现这一点。已根据您的建议进行修复。
paxdiablo 2013年

试图让gcc的make(在我的系统上是彩色的)与此“(make 3>&1 1>&2- 2>&3-)| less -R”一起工作,而“(ls -al 3>&1 1>&2- 2>&3-)| less -R“如预期的那样工作。
2015年

似乎您的解释是针对后两个重定向的。1>&2-将文件句柄2(原始stderr)设置为句柄1(原始stdout)2>&3-将文件句柄3(复制的stdout)设置为句柄2(原始stderr)。如果我错了,请纠正我。顺便说一句,我想2上的破折号是为了防止新的stderr数据被填充到stdout的数据时发送到此缓冲区。
aghsmith

70

Bash 4具有此功能:

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

zsh也具有此功能。

-

对于其他/较旧的外壳,只需将其明确输入为

FirstCommand 2>&1 | 其他命令


14
通过阅读文档,可以做到标准错误输出,而不仅仅是stderr,但是很高兴知道。我想是时候开始看bash 4了。
paxdiablo

当前的bash手册显示为“如果使用|&,则命令的标准错误, 除了其标准输出外,还连接到command2的标准输入”。这显然不是OP想要的。
彼得-恢复莫妮卡

@ PeterA.Schneider:OP表示“将标准输出留到当前位置”可能是模棱两可的。
暂停,直到另行通知。

我没有看到任何歧义。您的建议(1)融合了两个流。(2)OtherCommand合并的数据写入某个地方,可能在其他地方。因此,它不是相同的数据,并且可能会转移到其他地方。那与OP的愿望相反,不是吗?
彼得-恢复莫妮卡

@ PeterA.Schneider:标准输出的当前位置在哪里?如果proc1输出到stdout和stderr,并且您希望stderr转到stdin proc2(这是proc1的stdout所在的位置),那么我的答案就可以实现。我给了OP他所的,也许不是他的。其中存在潜在的歧义。OP接受了交换 stdout和stderr 的答案,这不是他要求的。
暂停,直到另行通知。

27

交换非常好,因为它可以解决问题。以防万一您甚至不需要原始的stdout,可以通过以下方式进行操作:

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

秩序至关重要。您不想要:

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

因为这会将所有内容重定向到/dev/null


0

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

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

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

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

会使gzip错误减少

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.