bash中的子进程

时间:2016-01-29 12:56:51

标签: linux bash

我们使用带有'&'的异步调用的bash脚本。像这样:

function test() {
   sleep 1
} 
test &
mypid=$!
# do some stuff for two hours
wait $mypid 

通常一切正常,但有时我们会收到错误

"wait: pid 419090 is not a child of this shell"

我知道bash会将子节点保存在一个特殊的表格中,我知道(等等#33;)如果没有人使用$ !,则bash不允许在此表中存储状态信息,并且没有人可以说明'等待$ mypid'。我怀疑,此优化包含导致错误的错误。有人知道如何打印此表或如何禁用此优化?

3 个答案:

答案 0 :(得分:1)

我最近尝试的东西非常相似。 你确定你同时运行的第二个进程是在之前的死之前开始的吗?在这种情况下,我认为有可能它与最近死亡的pid采用相同的pid。

另外我认为我们不能确定$!获取我们最后运行的进程的pid,因为后台可能有多个进程来自另一个同时开始或结束的函数。

我建议使用这样的东西。

mypid=$(ps -ef | grep name_of_your_process | awk ' !/grep/ {print $2} ')

grep name_of_your_process中,您也可以指定一些参数,以便获得所需的确切过程。

我希望它有所帮助。

答案 1 :(得分:0)

写了类似的东西之后,我建议正确的策略是在背景BOTH功能测试和长时间运行的2小时内进行分叉。

然后你可以等待一个pid列表,在后台调用,按预期的运行时间排序(最快的第一个)。

bash(1)wait也允许您简单地等待,以便完成所有子进程,但这可能需要检查协议才能成功完成。

提高可靠性的另一种方法是使用批处理队列,并启动单独的流程来检查是否成功完成。

答案 2 :(得分:0)

您可以使用gdb附加到正在运行的shell,看看发生了什么。在我的系统上,我运行了yum install bash-debuginfo。我运行gdb并附加到正在运行的shell。

(gdb) b wait_for_single_pid
Breakpoint 1 at 0x441840: file jobs.c, line 2115.
(gdb) c
Continuing.

Breakpoint 1, wait_for_single_pid (pid=11298) at jobs.c:2115
2115    {
(gdb) n
2120      BLOCK_CHILD (set, oset);
(gdb)
2121      child = find_pipeline (pid, 0, (int *)NULL);
(gdb) s
find_pipeline (pid=pid@entry=11298, alive_only=alive_only@entry=0, jobp=jobp@entry=0x0) at jobs.c:1308
1308    {
(gdb)
1313      if (jobp)
(gdb) n
1315      if (the_pipeline)
(gdb)
1329      job = find_job (pid, alive_only, &p);
(gdb) s
find_job (pid=11298, alive_only=0, procp=procp@entry=0x7ffdc053f038) at jobs.c:1364
1364      for (i = 0; i < js.j_jobslots; i++)
(gdb) n
1372          if (jobs[i])
(gdb)
1374              p = jobs[i]->pipe;
(gdb)
1378                  if (p->pid == pid && ((alive_only == 0 && PRECYCLED(p) == 0) || PALIVE(p)))
(gdb)
1385                  p = p->next;
(gdb)
1387              while (p != jobs[i]->pipe);

代码遍历pipe附加到jobs数组的链接列表。我没有遇到任何错误,但也许你可以用这种方法发现它们。