【发布时间】:2014-06-08 23:13:17
【问题描述】:
我正在开发一个管道,它有几个分支点随后合并——它们看起来像这样:
command2
/ \
command1 command4
\ /
command3
每个命令都写入 STDOUT 并通过 STDIN 接受输入。来自command1 的STDOUT 需要传递给command2 和command3,它们顺序 运行,并且它们的输出需要有效连接并传递给command4。我最初认为这样的事情会起作用:
$ command1 | (command2; command3) | command4
但这不起作用,因为只有来自 command2 的 STDOUT 被传递给命令 4,当我删除 command4 时,很明显 command3 没有从 command1 传递适当的流——换句话说,就好像 command2正在耗尽或消耗流。我得到与 { command2 相同的结果;命令3; } 也在中间。所以我想我应该使用'tee' with process substitution,并尝试了这个:
$ command1 | tee >(command2) | command3 | command4
但令人惊讶的是,这也不起作用 - 似乎 command1 的输出 和 command2 的输出通过管道传输到 command3,这会导致错误,并且只有 command3 的输出通过管道传输到命令 4.我确实发现以下内容在 command2 和 command3 之间获得了适当的输入和输出:
$ command1 | tee >(command2) >(command3) | command4
但是,这也会将 command1 的输出流式传输到 command4,这会导致出现问题,因为 command2 和 command3 生成的规范与 command1 不同。我得到的解决方案似乎很老套,但确实有效:
$ command1 | tee >(command2) >(command3) > /dev/null | command4
这会抑制 command1 将其输出传递给 command4,同时从 command2 和 command3 收集 STDOUT。它有效,但我觉得我错过了一个更明显的解决方案。我是吗?我已经阅读了几十个线程,但还没有找到适用于我的用例的这个问题的解决方案,也没有看到拆分和重新连接流的确切问题的详细说明(尽管我不能成为第一个一个来处理这个)。我应该只使用命名管道吗?我尝试过,但也很难让它发挥作用,所以也许这是另一个线程的另一个故事。我在 RHEL5.8 中使用 bash。
【问题讨论】:
-
看起来您的问题有一个解决方案可行 -- 那么您是否要求不同的解决方案?通常,这种拆分不会经常出现在 shell 脚本中,但会经常出现在 Hadoop-MapReduce 等专用工具中——我认为您不会找到比 bash 管道更好的东西。
-
@Soren -- 是的,我想知道是否有更好的解决方案。我并没有为此失眠,因为我的解决方案似乎有效,但我希望有一个解决方案不涉及将 stdout 重定向到 /dev/null 并且我很好奇我犯错的地方,因为它可能会提供信息为我(或其他人)继续发展。
标签: bash stdout stdin pipe tee