모든 하위 프로세스가 중지된 경우에만 init 스크립트가 "OK"를 인쇄하도록 하려면 어떻게 해야 합니까?

모든 하위 프로세스가 중지된 경우에만 init 스크립트가 "OK"를 인쇄하도록 하려면 어떻게 해야 합니까?

나는 매우 복잡한 Python 응용 프로그램을 가지고 있습니다. 자체 초기화 스크립트가 있지만 실행하면 다음과 같습니다.

sudo service my_service_daemon stop

"Stopping my_service_daemon [OK]"가 인쇄되지만 작업이 완료될 때까지 실제 하위 프로세스에 남아 있습니다(신호 15를 포착하지만 일부 작업을 수행해야 함). 따라서 자식 프로세스가 전혀 없는 경우에만 "[OK]" 메시지가 인쇄되기를 원합니다. 이는 init 스크립트의 일부입니다(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검색 됩니다 . 일반적으로 이 모든 PID를 화면에 인쇄하지만 우리는 이를 보고 싶지 않으므로 모든 출력을 로 리디렉션했습니다 . 검색 기준과 일치하는 프로세스가 하나 이상 발견되면 성공적으로 종료됩니다( ). 주기를 계속 유지하세요. 프로세스를 찾지 못하면 "false"( )로 종료되며, 이는 루프를 종료하고 해당 라인에 도달합니다. 단단한 루프로 인해 시스템이 파괴되지 않도록 시스템을 삽입했습니다.-g$group_id/dev/nullpgrep0while1successsleep 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"
}

관련 정보