为什么我用kill -0得到不同的结果(<jobspec> | pid)

时间:2015-08-01 01:48:42

标签: bash

我正在编写一个脚本,它将启动另一个进程,并在一段时间后杀死它,如果它没有自行退出。从开始这个开始,我开始意识到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不适合我呢?

2 个答案:

答案 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);

在通知来电者已完成作业之前,该作业尚未完成。与之相关的过程可能已完成,但作业本身并未完成。