我正在编写一个脚本,它将启动另一个进程,并在一段时间后杀死它,如果它没有自行退出。从开始这个开始,我开始意识到timeout
命令是正确的方法,但是我仍然对为什么我的一种方法失败感到困惑。
以下是我的尝试:
#!/bin/bash
backgroundScript.sh &
for((i=0; i<60; i++)); do
if ! kill -0 %1; then
exit
fi
sleep 1
done
kill %1
我很惊讶地发现kill -0 %1
总是成功,即使后台的流程已经完成。如果我将PID用于该过程,那么循环中的if
变为:
if ! kill -0 $!; then
它工作正常。那么为什么jobpec不适合我呢?
答案 0 :(得分:2)
一般来说,作业控制,特别是LOG_DEST => '/home/my_account/Desktop/gitolite-logs/gitolite-%y-%m.log',
等作业规范,是不可移植的。常见的方法是将PID从%1
保存到变量,并将其用作$!
的参数。
答案 1 :(得分:1)
好的,经过一堆挖掘后,我发现了为什么kill -0 %1
显示作业仍然存在,而kill -0 $!
显示该进程已退出。在通知来电者之前,bash不会收到工作。在交互式shell中,将打印到作业终止的屏幕。在非交互式shell中,这意味着调用脚本有机会获得进程的返回值。
让我从bash源出来的相关评论之一是在jobs.c:
/ *将所有死亡作业标记为已通知,因此delete_job()会清除它们 正确的工作表。 POSIX.2说我们需要保存 最后一个CHILD_MAX工作的状态,所以我们计算死亡人数 作业和标记仅足以通知保存CHILD_MAX状态。 * /
在wait_for_single_pid
函数中,此代码段:
/* POSIX.2: if we just waited for a job, we can remove it from the jobs
table. */
BLOCK_CHILD (set, oset);
job = find_job (pid, 0, NULL);
if (job != NO_JOB && jobs[job] && DEADJOB (job))
jobs[job]->flags |= J_NOTIFIED;
UNBLOCK_CHILD (oset);
在通知来电者已完成作业之前,该作业尚未完成。与之相关的过程可能已完成,但作业本身并未完成。