如何使初始化脚本仅在所有子进程停止时才打印“OK”?

如何使初始化脚本仅在所有子进程停止时才打印“OK”?

我有一个非常复杂的 python 应用程序。它有自己的初始化脚本,但是当我执行时:

sudo service my_service_daemon stop

它打印“Stopping my_service_daemon [OK]”,但在实际子进程中仍然存在,直到它们完成工作(它们捕获信号 15,但必须完成一些工作)。因此,我希望仅当根本没有子进程时才会打印消息“[OK]”。这是初始化脚本的一部分(它在 CentOS 6 上运行)

...

. /etc/init.d/functions 

...

stop(){
    echo -n $"Stopping $prog: "
    if [ -a $pidfile ]; then
    group_id=$(ps -o pgid= $(cat $pidfile) | grep -o [0-9]*)
    if [ ! -z $group_id ]; then
            kill -- -$group_id
        success
    fi
    else
        failure
    fi
    RETVAL=$?
    echo
    [ $RETVAL = 0 ] && rm -f $lockfile $pidfile
}

答案1

使用systemd进程的处理,或者使用手动cgroup来控制后代的动物园。乱搞输出ps(1)和 PID 文件很容易引发竞赛,并且已知会因拉扯头发而导致过早秃顶。

答案2

完成后等待kill -- -$group_id所有进程结束。例如,我会做类似的事情

...
if [ ! -z "$group_id" ]; then
    kill -- -$group_id
    while pgrep -g $group_id &>/dev/null; do
        sleep 1
    done
    success
...

这将pgrep搜索进程组 ( -g)的所有成员$group_id。通常它会将所有这些 PID 打印到屏幕上,但我们并不想看到它们,所以我将所有输出重定向到/dev/null. 如果找到至少 1 个与其搜索条件匹配的进程,pgrep则将成功退出 ( ),这将保持循环继续。一旦它没有找到任何进程,它将以“false”( ) 退出,这将退出循环并到达该行。为了不因紧密循环而破坏系统,我在其中插入了一个。0while1successsleep 1

答案3

在 Python 应用程序中保持文件打开。也就是说,在启动器脚本中打开它,并且不要在应用程序中关闭它。

该文件可以是PID文件。概念证明(不处理并发):

pidfile=/var/run/myapp.pid
logfile=/var/log/myapp.log
start () {
  sh -c 'echo $$ >"$1"; exec myapp <"$1" >/dev/null 2>"$2"' &
}
stop () {
  master_pid=$(cat "$pidfile")
  while
    case " $(fuser "$pidfile" 2>/dev/null) " in
      *" $master_pid "*)
        echo "Master process is alive, killing it"
        kill "$master_pid";;
      "  ") echo "Master process is dead and no subprocesses remain"; false;;
      *) echo "Master process is already dead but some processes remain";;
    esac
  do
    sleep 1
  done
  rm "$pidfile"
}

相关内容