IT story

프로세스가 끝날 때까지 기다리십시오

hot-time 2020. 7. 6. 07:11
반응형

프로세스가 끝날 때까지 기다리십시오


프로세스가 완료 될 때까지 Bash에 내장 기능이 있습니까?

wait명령을 사용하면 하위 프로세스가 완료 될 때까지 기다릴 수 있습니다. 스크립트를 진행하기 전에 프로세스가 끝날 때까지 기다리는 방법이 있는지 알고 싶습니다.

이를 수행하는 기계적인 방법은 다음과 같지만 Bash에 내장 기능이 있는지 알고 싶습니다.

while ps -p `cat $PID_FILE` > /dev/null; do sleep 1; done

프로세스가 완료 될 때까지 기다리려면

리눅스 :

tail --pid=$pid -f /dev/null

다윈 ( $pid파일을 열어야 함) :

lsof -p $pid +r 1 &>/dev/null

시간 초과 (초)

리눅스 :

timeout $timeout tail --pid=$pid -f /dev/null

다윈 ( $pid파일을 열어야 함) :

lsof -p $pid +r 1m%s -t | grep -qm1 $(date -v+${timeout}S +%s 2>/dev/null || echo INF)

내장이 없습니다. kill -0실행 가능한 솔루션을 위해 루프에서 사용하십시오 .

anywait(){

    for pid in "$@"; do
        while kill -0 "$pid"; do
            sleep 0.5
        done
    done
}

또는 한 번 사용하기 쉬운 더 간단한 oneliner로 :

while kill -0 PIDS 2> /dev/null; do sleep 1; done;

여러 주석 작성자가 언급 한 것처럼 신호를 보낼 권한이없는 프로세스를 기다리려면 kill -0 $pid통화 를 대체하기 위해 프로세스가 실행 중인지 감지하는 다른 방법을 찾으십시오 . Linux에서 test -d "/proc/$pid"작동하면 다른 시스템에서 (사용 pgrep가능한 경우) 또는 이와 비슷한 것을 사용해야 할 수도 있습니다 ps | grep "^$pid ".


프로세스가 루트 (또는 다른) 소유인 경우 "kill -0"이 작동하지 않는다는 것을 알았으므로 pgrep을 사용하여 다음을 수행했습니다.

while pgrep -u root process_name > /dev/null; do sleep 1; done

이것은 아마도 좀비 프로세스를 일치시키는 단점이 있습니다.


프로세스가 존재하지 않거나 좀비 인 경우이 bash 스크립트 루프가 종료됩니다.

PID=<pid to watch>
while s=`ps -p $PID -o s=` && [[ "$s" && "$s" != 'Z' ]]; do
    sleep 1
done

편집 : 위의 스크립트 Rockallite에 의해 아래주어 졌습니다 . 감사!

에 의존하는 Linux 용 작품 아래에 내 시킴으로 빨리 대답, procfs/proc/. 이식성에 대해 잘 모르겠습니다.

while [[ ( -d /proc/$PID ) && ( -z `grep zombie /proc/$PID/status` ) ]]; do
    sleep 1
done

쉘에만 국한되지는 않지만 OS 자체에는 자식 프로세스가 아닌 프로세스 종료를 감시하는 시스템 호출이 없습니다.


FreeBSD와 Solaris는이 편리한 pwait(1)유틸리티를 가지고 있습니다.

다른 현대 OS에도 필요한 시스템 호출 (예 : MacOS, BSD 구현 kqueue)도 있지만 명령 줄에서 모두 사용할 수있는 것은 아닙니다.


bash 맨 페이지에서

   wait [n ...]
          Wait for each specified process and return its termination  status
          Each  n  may be a process ID or a job specification; if a
          job spec is given, all processes  in  that  job's  pipeline  are
          waited  for.  If n is not given, all currently active child processes
          are waited for, and the return  status  is  zero.   If  n
          specifies  a  non-existent  process or job, the return status is
          127.  Otherwise, the return status is the  exit  status  of  the
          last process or job waited for.

이 모든 솔루션은 Ubuntu 14.04에서 테스트되었습니다.

해결책 1 (ps 명령을 사용하여) : Pierz 답변까지 추가하려면 다음을 제안합니다.

while ps axg | grep -vw grep | grep -w process_name > /dev/null; do sleep 1; done

In this case, grep -vw grep ensures that grep matches only process_name and not grep itself. It has the advantage of supporting the cases where the process_name is not at the end of a line at ps axg.

Solution 2 (by using top command and process name):

while [[ $(awk '$12=="process_name" {print $0}' <(top -n 1 -b)) ]]; do sleep 1; done

Replace process_name with the process name that appears in top -n 1 -b. Please keep the quotation marks.

To see the list of processes that you wait for them to be finished, you can run:

while : ; do p=$(awk '$12=="process_name" {print $0}' <(top -n 1 -b)); [[ $b ]] || break; echo $p; sleep 1; done

Solution 3 (by using top command and process ID):

while [[ $(awk '$1=="process_id" {print $0}' <(top -n 1 -b)) ]]; do sleep 1; done

Replace process_id with the process ID of your program.


Okay, so it seems the answer is -- no, there is no built in tool.

After setting /proc/sys/kernel/yama/ptrace_scope to 0, it is possible to use the strace program. Further switches can be used to make it silent, so that it really waits passively:

strace -qqe '' -p <PID>

Had the same issue, I solved the issue killing the process and then waiting for each process to finish using the PROC filesystem:

while [ -e /proc/${pid} ]; do sleep 0.1; done

There is no builtin feature to wait for any process to finish.

You could send kill -0 to any PID found, so you don't get puzzled by zombies and stuff that will still be visible in ps (while still retrieving the PID list using ps).


On a system like OSX you might not have pgrep so you can try this appraoch, when looking for processes by name:

while ps axg | grep process_name$ > /dev/null; do sleep 1; done

The $ symbol at the end of the process name ensures that grep matches only process_name to the end of line in the ps output and not itself.


Blocking solution

Use the wait in a loop, for waiting for terminate all processes:

function anywait()
{

    for pid in "$@"
    do
        wait $pid
        echo "Process $pid terminated"
    done
    echo 'All processes terminated'
}

This function will exits immediately, when all processes was terminated. This is the most efficient solution.

Non-blocking solution

Use the kill -0 in a loop, for waiting for terminate all processes + do anything between checks:

function anywait_w_status()
{
    for pid in "$@"
    do
        while kill -0 "$pid"
        do
            echo "Process $pid still running..."
            sleep 1
        done
    done
    echo 'All processes terminated'
}

The reaction time decreased to sleep time, because have to prevent high CPU usage.

A realistic usage:

Waiting for terminate all processes + inform user about all running PIDs.

function anywait_w_status2()
{
    while true
    do
        alive_pids=()
        for pid in "$@"
        do
            kill -0 "$pid" 2>/dev/null \
                && alive_pids+="$pid "
        done

        if [ ${#alive_pids[@]} -eq 0 ]
        then
            break
        fi

        echo "Process(es) still running... ${alive_pids[@]}"
        sleep 1
    done
    echo 'All processes terminated'
}

Notes

These functions getting PIDs via arguments by $@ as BASH array.

참고URL : https://stackoverflow.com/questions/1058047/wait-for-a-process-to-finish

반응형