bash将stdout发送到一个过程,然后将stderr发送到另一个过程

发布于 2025-01-30 03:39:04 字数 365 浏览 5 评论 0原文

我有一个有关过程替代和抗议重定向的问题。

考虑一下

$ zzz > >(echo fine) 2> >(echo error)

我期望输出fine错误,因为zzz不是有效的命令,而是我得到fine。为什么这是?

这是按预期工作的

$ zzz 2> >(echo error)
error

如果我交换订单,

$ zzz 2> >(echo error) >(echo fine)
fine
error

I have a question on process substitution and bash redirection.

Consider

$ zzz > >(echo fine) 2> >(echo error)

I expected output fine error since zzz is not a valid command but instead I just get fine. Why is this?

This works as expected

$ zzz 2> >(echo error)
error

If I swap the order

$ zzz 2> >(echo error) >(echo fine)
fine
error

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

白况 2025-02-06 03:39:04

这是因为BASH将输出重定向应用于echo Error进程以及zzz >>>(echo fine) part) >命令本身。由于echo fine对该输入没有任何作用,因此“错误”文本仅消失。您可以通过将Echo Fine替换为输入的内容来看到这一点:

$ zzz > >(sed 's/^/processed through sed: /') 2> >(echo error)
$ processed through sed: error

请注意(至少在我尝试过时),这看起来很奇怪,因为外壳打印了下一个提示(“ $ ”)sed在输出修改后的错误消息之前。由>()创建的子过程有效地背景,因此Shell不会等待它们完成。

如果要避免使用此功能(或至少绕过它),则可以将Stdout文件描述符复制到其他FD,然后将输出从另一个过程重定向到该替代FD。这是一个使用fd#3:

$ zzz 3>&1 > >(echo fine) 2> >(echo error >&3)
fine
error

btw的 示例Echo Fine的输出按照终端的形式为正常。另一方面,如果这样做,则会从echo fine命令中发生错误,将被重定向到echo Error

$ zzz 2> >(echo error) > >(echo fine; yyy)
error
fine

(在此示例中,xxxyyy均已发送到echo错误, yyy 都忽略了它们。

) ^2,ZSH还实现了过程替代,但并未采用这种方式使用继承的重定向:

zsh% zzz > >(echo fine) 2> >(echo error)
fine
error

据我所知,流程替代不是任何标准定义的,所以我认为没有一种方法可以定义哪种外壳的实现是“更正确”。

It's because bash applies the output redirection (the > >(echo fine) part) to the echo error process as well as to the zzz command itself. Since echo fine doesn't do anything with that input, the "error" text just vanishes. You can see this by replacing echo fine with something that actually displays what it got as input:

$ zzz > >(sed 's/^/processed through sed: /') 2> >(echo error)
$ processed through sed: error

Note that (at least when I tried it), this looks weird because the shell printed its next prompt ("$ ") before sed got around to outputting the modified error message. The subprocesses created by >( ) are effectively backgrounded, so the shell doesn't wait for them to finish.

If you want to avoid this (or at least work around it), you can copy the stdout file descriptor to a different FD, then redirect output from the other process to that alternate FD. Here's an example using FD #3:

$ zzz 3>&1 > >(echo fine) 2> >(echo error >&3)
fine
error

BTW, if you put the redirects in the other order, the redirect to echo fine happens logically after the echo error process is started, so echo fine's output goes to the terminal as normal. On the other hand, if you do it that way, then errors from the echo fine command would be redirected to echo error.

$ zzz 2> >(echo error) > >(echo fine; yyy)
error
fine

(In this example, the "command not found" errors for both xxx and yyy are sent to echo error, which ignores them.)

BTW^2, zsh also implements process substitution, but doesn't apply inherited redirects this way:

zsh% zzz > >(echo fine) 2> >(echo error)
fine
error

As far as I know, process substitution isn't defined by any standard, so I don't think there's a way to define which shell's implementation is "more correct".

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文