Bash 스크립트의 프로세스가 완료될 때까지 기다립니다.

Bash 스크립트의 프로세스가 완료될 때까지 기다립니다.

Bash 스크립트에서 실행 중인 활성 프로세스 수를 확인하려고 합니다. 아이디어는 x 프로세스를 계속 실행하고 한 프로세스가 완료되면 다음 프로세스가 시작되는 것입니다.

테스트 목적으로 다음 스크립트를 설정했습니다.

find $HOME/Downloads -name "dummy" &
find $HOME/Downloads -name "dummy" &
find $HOME/Downloads -name "dummy" &

while true
do
    pids=()
    while read pid; do
        echo "PID: $pid"
        pids+=("$pid")
    done < <(jobs -p)
    
    jobs -p

    echo "Active processes: ${#pids[@]}"
    if [ ${#pids[@]} -lt 2 ]; then
        break
    fi

    echo "Process(es) still running... ${pids[@]}"
    sleep 1
done

jobs -p하지만 프로세스가 완료된 후에도 작업 ID가 계속 반환되기 때문에 작동하지 않습니다 .

다음 예에서는 문제를 자세히 설명합니다.

#!/bin/bash

find $HOME/Downloads -name "dummy" &
find $HOME/Downloads -name "dummy" &
find $HOME/Downloads -name "dummy" &

while true
do
    jobs -p # continues to print all 3 jobs
    sleep 1
done

while루프에서 활성 작업을 얻는 방법은 무엇입니까 ?

인사,

답변1

(@icarus의 의견에 따라) 이 특별한 경우에는 작동 하지만 마지막으로 시작된 프로세스의 PID가 포함되어 있다는 wait -n점에 유의해야 합니다 . $!따라서 이것을 테스트할 수도 있습니다:

#!/bin/bash

find $HOME/Downloads -name "dummy" &
p1=$!
find $HOME/Downloads -name "dummy" &
p2=$!
find $HOME/Downloads -name "dummy" &
p3=$!
while true
do
    if ps $p1 > /dev/null ; then
        echo -n "p1 runs "
    else 
        echo -n "p1 ended"
    fi
    if ps $p2 > /dev/null ; then
        echo -n "p2 runs "
    else 
        echo -n "p2 ended"
    fi
    if ps $p1 > /dev/null ; then
        echo -n "p3 runs "
    else 
        echo -n "p3 ended"
    fi
    echo ''
    sleep 1
done

그러나 parallel그것은 또한 더 나은 선택입니다.

답변2

이 스크립트의 문제점은 그 안에 있는 어떤 것도 대기 시스템 호출 중 하나를 호출하지 않는다는 것입니다. 일반적으로 커널은 wait를 호출하기 전에 프로세스에 대한 항목을 예약합니다. 왜냐하면 여기에 자식 프로세스의 반환 코드가 저장되어 있기 때문입니다. 상위 프로세스가 하위 프로세스보다 먼저 종료되면 하위 프로세스는 일반적으로 PID 1로 상위 프로세스를 재설정합니다. 시스템이 시작된 후 PID 1은 일반적으로 루프에 들어가고 대기만 호출하여 이러한 프로세스의 종료 값을 수집하도록 프로그래밍됩니다.

wait우리가 얻은 쉘 내장 함수를 호출하도록 테스트 스크립트를 다시 작성하십시오.

pids=()
find $HOME/Downloads -name "dummy" &
pids+=( $! )
find $HOME/Downloads -name "dummy" &
pids+=( $! )
find $HOME/Downloads -name "dummy" &
pids+=( $! )

echo "Initial active processes: ${#pids[@]}"
for ((i=${#pids[@]}; i>1; i--)) ; do 
do
    wait -n # Wait for  one process to exit
    echo "A process exited with RC=$?"
    # Note that -n is a bash extension, not in POSIX
    # if we have bash 5.1 then we can use "wait -np EX" to find which
    # job has finished, the value is put in $EX. Then we can remove the
    # value from the pids array. 

    echo "Still outstanding $(jobs -p)"
    sleep 1
done

답변3

Bash 스크립트에서 실행 중인 활성 프로세스 수를 확인하려고 합니다. 아이디어는 x 프로세스를 계속 실행하고 한 프로세스가 완료되면 다음 프로세스가 시작되는 것입니다.

GNU Parallel을 사용하면 다음과 같습니다:

parallel -j3 find $HOME/Downloads -name {} ::: "name1" "name2" "name3"

(다른 매개변수뿐만 아니라) 다른 프로그램을 실행해야 하는 경우:

parallel -j3 ::: "find $HOME/Downloads -name name1" "find $HOME/Downloads -name name2"  "find $HOME/Downloads -name name3" 

명령이 더 복잡하면 bash 기능을 사용하십시오.

find1() {
  find $HOME/Downloads -name "name1"
}
find2() {
  find $HOME/Downloads -name "name2"
}
find3() {
  find $HOME/Downloads -name "name3"
}
export -f find1 find2 find3
parallel -j3 ::: find1 find2 find3

생략하면 -j3CPU 코어당 하나의 작업이 실행됩니다.

관련 정보