我们使用带有'&'的异步调用的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'。我怀疑,此优化包含导致错误的错误。有人知道如何打印此表或如何禁用此优化?
答案 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
数组的链接列表。我没有遇到任何错误,但也许你可以用这种方法发现它们。