【问题标题】:How to fork/pipe stdin in bash script?如何在 bash 脚本中分叉/管道标准输入?
【发布时间】:2016-09-29 00:04:02
【问题描述】:

我有一个要运行的脚本

$ myscript < mydata.dat

myscript 内部,我需要将 STDIN 分叉/管道到多个目的地

#!/usr/bin/env bash

php script1.php > out1
php script2.php > out2
php script3.php > out3

每个人都需要一份 STDIN。有可能吗?

有点像

# obviously this is broken ...
STDIN | php script1.php > out1
STDIN | php script2.php > out2
STDIN | php script3.php > out3

【问题讨论】:

标签: bash pipe stdin


【解决方案1】:

要将标准输入复制到多个进程,请使用tee进程替换

tee >(script1 > out1) >(script2 >out2) ... | lastscript >outlast

构造&gt;(...) 称为进程替换。它创建了一个tee 可以写入的类文件对象。括号内的命令被执行,tee 写入的任何内容都作为标准输入提供给命令。

进程替换 受 bash、ksh 和 zsh 支持。它不是 POSIX,无法在 dash 下工作。

简单示例

让我们考虑这个简单的脚本:

$ cat myscript 
#!/bin/bash
tee >(grep 1 >out1) >(grep 2 >out2) | grep 3 >out3

我们可以运行它并验证结果:

$ seq 10 | bash myscript
$ cat out1
1
10
$ cat out2
2
$ cat out3
3

【讨论】:

  • 您不需要多个tee 命令。您可以为单个命令提供多个 &gt;(...) 参数。
  • 你能解释一下&gt;(...)吗?我从没见过。
  • @naomik 我在上次更新中添加了一些解释。您可能需要刷新浏览器才能看到它。如果有帮助,请告诉我。
【解决方案2】:

John1024 的答案的一个变体是使用命名管道代替进程替换。

mkfifo p1 p2 p3
tee p1 p2 p3 > /dev/null & # or tee p1 p2 > p3 &
php script1 < p1 > out1 &
php script2 < p2 > out2 &
php script2 < p3 > out3 &
wait
rm p1 p2 p3

(进程替换是有效的,在某些实现中,实际上是对创建、管理和清理显式命名管道的语法支持。)

【讨论】:

  • 看到非快捷版本非常酷。我非常感谢。
  • @chepner,问题在于它们是在文件系统中创建的,并且是与其他进程的文件名冲突以及权限失败的主题。或许,我们应该使用 tmp 文件来使解决方案更加健壮。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-06-10
  • 1970-01-01
  • 1970-01-01
  • 2015-10-08
  • 1970-01-01
  • 2012-03-07
  • 1970-01-01
相关资源
最近更新 更多