Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 如何在一行中收集bash for循环中启动的后台进程PID列表_Linux_Bash_Shell - Fatal编程技术网

Linux 如何在一行中收集bash for循环中启动的后台进程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

下面的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

我想了解:

  • 为什么bash要解释
    以这种方式
  • 正确的写作方式是什么?为什么

  • 谢谢

    历史扩展是愚蠢的

    问题不是单行,问题是启用了历史扩展(大部分)

    在交互式shell中禁用历史扩展将使此功能正常工作

    将单行放入脚本(默认情况下禁用历史扩展)也会起作用

    历史扩展和单行的组合导致扩展被尝试并爆炸

    但是,在shell中的多行上执行此操作也会失败(如果您保持分号不变……稍后会有更多内容)

    bash参考手册的一节解释了如何扫描命令行进行历史扩展,如下所示:

    历史扩展由历史扩展字符的出现引入,该字符为“!”默认情况下。只能使用“\”和“”转义历史扩展字符

    增加了(我不知道为什么参考手册没有这样说):

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


    因此,在单行版本中的
    之后添加空格/etc.应该可以工作。

    单行不是问题。“在提示下”就是问题所在。在提示下禁用历史扩展,它就会工作。将其作为脚本中的一行编写,它也会工作。历史扩展是哑的。使用
    PIDS=$PIDS'$!;
    可能会工作。是的,
    之后添加的空间工作了,因为它禁用了将
    作为命令历史扩展的解释。因此,在多行情况下,这似乎起作用的原因是
    后面的字符是回车符,因此bash不会将其解释为命令历史扩展。而且,命令历史扩展发生在
    $
    变量值替换之前。对吗?我倾向于建议使用
    PIDS=“${PIDS}$!”
    作为替代方案,@twalberg这并不能解决问题,因为
    后面的
    导致
    仍然被解释为命令历史扩展。我相信您的意思是:
    对于$中的I(seq 13);do./longlunningprocess&PIDS=“${PIDS}$!”;done
    。这将起作用,因为
    后面有一个空格。@ellitron历史扩展没有在双引号内完成,因此不需要在结尾处有额外的空格。