bash 스크립트에서 생성된 모든 프로세스와 백그라운드 프로세스가 완료될 때까지 기다리는 방법

bash 스크립트에서 생성된 모든 프로세스와 백그라운드 프로세스가 완료될 때까지 기다리는 방법

프로세스를 종료하고 기다렸다가 프로세스가 완료될 때까지 생성하기 위해 생성하려는 bash 스크립트에 대한 작동 솔루션을 찾고 또 찾았지만 찾을 수 없습니다. 나는 아직도 리눅스에 대해 많은 것을 배우고 있다.

문맥: 프로세스 FOO가 실행 중입니다. 프로세스 BAR은 FOO를 확인하고 종료하는 데 사용됩니다(이 두 프로세스의 내부를 제어할 수 없습니다). 내가 할 수 있는 일은 BAR에 명령을 전달하고 실행하는 것뿐입니다.

이 예에서는 FOO를 종료하라는 명령을 BAR에 보냅니다. 그러면 다른 프로세스가 생성되어 백그라운드에 배치됩니다.

표적: 20개의 FOO에 대해 (BAR을 통해) 종료를 수행하고 스크립트의 다음 부분을 계속하기 전에 모든 FOO가 죽을 때까지 기다리기 위해 동시에 20개의 명령을 실행하려고 합니다.

질문: 지금까지 내가 할 수 있는 일은 BAR이 실행될 때까지 기다렸다가 백그라운드 프로세스가 FOO를 종료하기 전에 계속하는 것뿐입니다.

BAR exit FOO1
BAR exit FOO2
...
BAR exit FOO20
wait
do more stuff

나도 시도했다

BAR exit FOO1
PID1=$!
BAR exit FOO2
PID2=$!
wait $PID1 $PID2

불운.

답변1

대기 중인 다른 프로세스가 없으면 wait인수 없이 모든 백그라운드 작업이 완료될 때까지 기다립니다. 나는 종종 다음과 같은 구조를 사용합니다.

for i in *; do md5sum $i & done
wait

그러나 스크립트에 다른 백그라운드 작업이 있으면 중단되지만 하위 쉘로 래핑할 수 있습니다.

(for i in *; do md5sum $i & done; wait) & all_md5sum=$!
...
wait $all_md5sum

답변2

FOO1먼저 2개의 프로세스만 사용 하고 다음 FOO2과 같은 스크립트에서 실행하려는 경우와 같이 더 간단한 시나리오를 시도해 보십시오 parent.sh.

#!/bin/bash

FOO1 &
pid1=$!

echo "Child PID=$pid1 launched"

FOO2 &
pid2=$!

echo "Child PID=$pid2 launched"

BAR exit FOO1
BAR exit FOO2

echo "Pausing to wait for children to finish..."

wait $pid1
wait $pid2

echo "Children finished, moving on."

이것이 2 FOO초 동안 작동하는지 확인하고, 그렇다면 20초 동안 작동하는지 확인하십시오.

설명하다

FOO우리는 내부 와 프로세스를 볼 수 없기 때문에 BAR귀하가 게시한 내용에만 의존하고 있으며 귀하가 말씀하신 것으로 이해합니다

  • "프로세스 BAR은 FOO를 확인하고 종료하는 데 사용됩니다."
  • 즉, 클립을 게시하기 전 어느 시점에서 FOO1특정 방식으로 시작하여 BAR exit FOO1클립에 영향을 미치게 됩니다.

원래 게시한 스니펫에서는 다음과 같이 작성했습니다.

BAR exit FOO1
PID1=$!
  • $!최근 백그라운드 프로세스 캡처
  • 하지만 BAR exit FOO1이는 백그라운드로 들어가는 프로세스가 아닙니다. 말씀하신 대로 BAR을 사용하여 FOO를 제어하는 ​​수단입니다. "BAR은 FOO를 확인하고 죽이는 데 사용됩니다."
  • 따라서 PID를 $!캡처할 가능성은 거의 없습니다.FOO1

따라서 FOO* 프로세스가 실제로 시작되는 pid를 캡처해야 합니다. 예를 들어 올인을 실행 중이고 parent.sh프로세스가 2개만 있는 경우 다음을 수행합니다.

#!/bin/sh

FOO1 &
pid1=$!

echo "Child PID=$pid1 launched"

FOO2 &
pid2=$!

echo "Child PID=$pid2 launched"
  • Lowercase pid1, 일관성이 있는 한 원래 대문자를 사용할 수도 있습니다. 저는 단지 잘못 사용되는 환경 변수와 구별하기 위한 관례로 소문자를 사용하는 것을 선호합니다.
  • #echo는 무슨 일이 일어나고 있는지 알 수 있도록 추적하기 위한 선택 사항이며, 문제 해결 시 사용하고, 문제가 해결되면 주석 처리하거나 삭제합니다.

그런 다음 확인하고 종료하기 위해 요청한 명령을 실행합니다 FOO1.FOO2

BAR exit FOO1
BAR exit FOO2

그 다음에,

echo "Pausing to wait for children to finish..."

wait $pid1
wait $pid2

echo "Children finished, moving on."
  • 다시 말하지만 echos는 선택 사항이지만 문제를 해결하는 동안 정보를 제공하고 무슨 일이 일어나고 있는지 알려줍니다.
  • wait모두를위한 $pid...
  • 다음은 ing이 끝났음 echo을 알려주는 또 다른 옵션입니다.wait

신용 거래

2009년 촬영무료 PDF 506페이지의 비동기 스크립트 예

답변3

각 명령에 대한 파일을 터치하고 파일을 검사할 수 있습니다. 간단한 예는 다음과 같습니다.

#!/usr/local/bin/bash

# Flag to knkow when completed
finished=0;

# The commands t run
declare -a commands=('cmd1' 'cmd2' 'cmd3' 'cmd4');

# Fork all commands
for cmd in "${commands[@]}"; do
        ./$cmd &
done

# Loop to wait for all processes to finish
loop=0;
while [ $finished -eq 0 ]; do
        # Just for visual effect
        loop=$((loop+1));
        echo "Loop $loop";
        sleep 1;

        files=0;
        for cmd in "${commands[@]}"; do
                # Each program shoudl touch a file so that we
                # can know it has completed successfully
                if [ -e ".$cmd" ]; then
                        echo "Process $cmd completed";
                        files=$((files+1));
                else
                        # No need to continue if anything is not done
                        # Error checking here like a TTL value or ps -ef | grep pid etc
                        echo "Waiting for process $cmd";
                        break;
                fi;
        done

        # if we have as many files as executed commands
        if [ "$files" -eq ${#commands[@]} ]; then
                finished=1;
        fi
done;

echo 'All jobs completed successfully';
# Clean up after yourself
for cmd in "${commands[@]}"; do
        rm -f ".$cmd";
done;

그런 다음 각 cmd1, cmd2...cmdN을 테스트하려면 다음과 같이 할 수 있습니다.

#!/usr/local/bin/bash
num=1;

echo "Enter cmd$num";
sleep 1; # use different sleep values to simulate execution
touch ".cmd$num"
echo "Exit cmd$num";

답변4

$PID1이 실행 중이면 true로 평가됩니다. if [kill -s 0 $PID1 ]

if 절을 여러 개 가질 수 있습니다. PID가 실행되고 있지 않으면 false로 평가됩니다. 이 절(다른 절과 함께)은 필요에 따라 스크립트의 흐름을 제어해야 합니다.

관련 정보