Linux 如何在一行中收集bash for循环中启动的后台进程PID列表
下面的bash脚本在一个循环中分叉几个进程,收集它们的所有PID,然后等待它们全部完成:Linux 如何在一行中收集bash for循环中启动的后台进程PID列表,linux,bash,shell,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 & PI
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
我想了解:
代码>以这种方式
谢谢 历史扩展是愚蠢的 问题不是单行,问题是启用了历史扩展(大部分) 在交互式shell中禁用历史扩展将使此功能正常工作 将单行放入脚本(默认情况下禁用历史扩展)也会起作用 历史扩展和单行的组合导致扩展被尝试并爆炸 但是,在shell中的多行上执行此操作也会失败(如果您保持分号不变……稍后会有更多内容) bash参考手册的一节解释了如何扫描命令行进行历史扩展,如下所示: 历史扩展由历史扩展字符的出现引入,该字符为“!”默认情况下。只能使用“\”和“”转义历史扩展字符 增加了(我不知道为什么参考手册没有这样说): 如果在历史扩展字符之后立即找到几个字符,即使它没有引号,也会禁止历史扩展:空格、制表符、换行符、回车符和=。如果启用了extglob shell选项,则还将禁止扩展
因此,在单行版本中的
!
之后添加空格/etc.应该可以工作。单行不是问题。“在提示下”就是问题所在。在提示下禁用历史扩展,它就会工作。将其作为脚本中的一行编写,它也会工作。历史扩展是哑的。使用PIDS=$PIDS'$!;
可能会工作。是的,!
之后添加的空间工作了,因为它禁用了将!
作为命令历史扩展的解释。因此,在多行情况下,这似乎起作用的原因是!
后面的字符是回车符,因此bash不会将其解释为命令历史扩展。而且,命令历史扩展发生在$
变量值替换之前。对吗?我倾向于建议使用PIDS=“${PIDS}$!”
作为替代方案,@twalberg这并不能解决问题,因为!
后面的“
导致!
仍然被解释为命令历史扩展。我相信您的意思是:对于$中的I(seq 13);do./longlunningprocess&PIDS=“${PIDS}$!”;done
。这将起作用,因为!
后面有一个空格。@ellitron历史扩展没有在双引号内完成,因此不需要在结尾处有额外的空格。