如何确保在bash管道中
bash>foo | bar
bar
仅在foo
完成后启动?
答案 0 :(得分:3)
这不是管道的工作方式。 foo | bar
始终同时运行foo
和bar
,因为它将foo
的输出连接到bar
的输入最小缓冲区(如果有的话)。
如果要单独运行它们,请不要使用管道;而是将输出写入文件:
foo >out
bar <out
...您还可以选择使用变量将输出存储在内存中:
out=$(foo)
bar <<<"$out"
...虽然这不是逐字节准确的(例如,丢弃尾随换行符)。
答案 1 :(得分:1)
管道用于将foo的输出连接到bar的输入。如果foo完成,bar无法获得任何输入。
也许你想要的只是
foo ; bar
如果bar需要消耗foo
的输出,那么中间文件就是一个解决方案。另一个,如果grep
的参数是硬编码的,则使用括号
ps aux | grep [p]attern
另一种解决方案是安装和使用[buffer][1]
命令
foo | buffer -m ... | bar
-m ...
缓冲区的大小足以容纳foo
命令的输出。
答案 2 :(得分:1)
管道的工作方式,foo
和bar
在两个独立的子壳中运行。因此,只要foo
输出可用,bar
就可以使用它(通过读取它的stdin
- 因为基于管道的IPC,运行的进程之间的通信两个单独的子shell完全使用FIFO队列,用于将stdout
从foo
发送到bar
的{{1}}。因此,stdin
在此上下文中我不知道或关心bar
是否已经结束。它只关心foo
上的内容。
如果您关心stdin
的完成,则必须对foo
和bar
使用其他类型的调用。
答案 3 :(得分:1)
您不能使用管道,因为它们总是同时运行。使该机制有效的正确方法是使用缓冲区:
buffer=$(foo)
echo "$buffer" | bar
或者
bar <<EOF
$(foo)
EOF
echo -n
并没有真正严格,因为$()
最后修剪0x0A
。