如何在单行中收集在bash for循环中启动的后台进程PID列表

时间:2015-06-11 18:38:05

标签: linux bash shell

以下bash脚本在循环中分叉几个进程,沿途收集所有PID,然后等待它们全部完成:

PIDS=''
for i in $(seq 1 3); do  
  ./longRunningProcess & 
  PIDS=$PIDS' '$!
done

wait $PIDS

这个在bash中逐行输入时工作正常,但是我想在一行上执行for循环,我认为应该如下:

for i in $(seq 1 3); do ./longRunningProcess & PIDS=$PIDS' '$!; done

但是当我尝试执行此操作时,我得到:

-bash: !: event not found

似乎bash以某种方式解释了!作为命令历史扩展,但我认为前面的$会将其解释更改为最后一个分叉后台进程的PID。

我想了解:

  1. 为什么bash以这种方式解释!
  2. 写作的正确方法是什么,为什么
  3. 谢谢!

1 个答案:

答案 0 :(得分:1)

历史扩张是愚蠢的。

问题不在于单线问题是启用了历史扩展(主要是)。

在交互式shell中禁用历史记录扩展可以使其正常工作。

将单行放在脚本中(默认情况下禁用历史记录扩展)也可以。

历史扩张和单线的结合导致扩张被尝试和爆炸。

在shell中的多行上执行此操作会失败(如果你让分号保持完整......在一秒内更多内容)。

bash参考手册的History Expansion部分解释了如何扫描命令行以进行历史记录扩展:

  

历史扩展是由历史扩展字符的外观引入的,默认情况下为“!”。只有'\'和'''可用于转义历史记录扩展字符。

bash man page添加了(我不确定为什么参考手册没有说明这一点):

  

如果在历史记录扩展字符后面立即找到,则有几个字符会禁止历史记录扩展,即使它没有引用:空格,制表符,换行符,回车符和=。如果启用了extglob shell选项,(也将禁止扩展。

所以添加一个空格/等。在该单行版本的!之后应该有效。