首页 文章

如何从多个进程中拆分和重新加入STDOUT?

提问于
浏览
8

我正在研究一个有一些分支点然后合并的管道 - 它们看起来像这样:

command2
        /        \
command1          command4
        \        /
         command3

每个命令都写入STDOUT并通过STDIN接受输入 . 来自command1的STDOUT需要传递给command2和command3,它们按顺序运行,并且它们的输出需要有效地连接并传递给command4 . 我最初认为像这样的东西会起作用:

$ command1 | (command2; command3) | command4

那显然command3 isn 't being passed the appropriate stream from command1 -- in other words, it' s,好像command2正在耗尽或消耗流 . 我用{command2;得到了相同的结果command3;在中间也是如此 . 所以我想我应该使用'tee' with process substitution,并试过这个:

$ command1 | tee >(command2) | command3 | command4

但令人惊讶的是,这也没有用 - 看起来command1的输出和command2的输出被传送到command3,这导致错误,只有command3的输出通过管道输入command4 . 我确实发现以下内容从command2和command3获取适当的输入和输出:

$ command1 | tee >(command2) >(command3) | command4

但是,这会将command1的输出流式传输到command4,这会导致问题,因为command2和command3产生的命令与command1不同 . 我到达的解决方案看起来很hacky,但确实有效:

$ command1 | tee >(command2) >(command3) > /dev/null | command4

这会抑制command1将其输出传递给command4,同时从command2和command3收集STDOUT . 它有效,但我觉得我错过了一个更明显的解决方案 . 我呢?我已经阅读了几十个主题并且没有找到解决这个问题的解决方案,这个问题在我的用例中有效,也没有看到详细解决拆分和重新加入流的问题(尽管我不能成为第一个一个来处理这个) . 我应该只使用命名管道吗?我试过但很难让它工作,所以也许这是另一个故事的另一个故事 . 我在RHEL5.8中使用bash .

3 回答

  • 0

    你可以玩这样的文件描述符;

    ((date | tee >( wc >&3) | wc) 3>&1) | wc
    

    要么

    ((command1 | tee >( command2 >&3) | command3) 3>&1) | command4
    

    为了解释,那是 tee >( wc >&3) 将在stdout上输出原始数据,而内部 wc 将在FD 3上输出结果 . 外部3>&1)然后将FD3输出合并回STDOUT,因此来自两个wc的输出被发送到尾部命令 .

    但是,此管道(或您自己的解决方案中的那个)中没有任何内容可以保证输出不会被破坏 . 这是来自command2的不完整的行不会与command3的行混淆 - 如果这是一个问题,你将需要做两件事之一;

    • 编写自己的 tee 程序,在内部使用popen并在将完整行发送到stdout之前读取每一行,以便command4读取

    • 将command2和command3的输出写入文件并使用 cat 将数据合并为command4的输入

  • 0

    请参阅https://unix.stackexchange.com/questions/28503/how-can-i-send-stdout-to-multiple-commands . 在所有答案中,我发现this answer特别适合我的需要 .

    展开一点@Soren的回答,

    $ ((date | tee >( wc >&3) | wc) 3>&1) | cat -n
         1         1       6      29
         2         1       6      29
    

    你可以不使用tee而是环境变量,

    $ (z=$(date); (echo "$z"| wc ); (echo "$z"| wc) ) | cat -n
         1         1       6      29
         2         1       6      29
    

    在我的例子中,我应用了这种技术并编写了一个在busybox下运行的非常复杂的脚本 .

  • 4

    我相信你的解决方案是好的,它使用tee记录 . 如果您阅读tee的联机帮助页,它会说:

    Copy standard input to each FILE, and also to standard output
    

    您的文件是进程替换 .

    标准输出是你需要删除的,因为你不需要它,这就是你将它重定向到/ dev / null所做的

相关问题