스크립트는 루프에서 하위 프로세스를 기다리지 않습니다.

스크립트는 루프에서 하위 프로세스를 기다리지 않습니다.

Bash 스크립트에서는 일부 파일을 찾기 위해 폴더를 순회하고, 파일을 찾으면 해당 파일이 포함된 디렉터리에서 함수를 호출합니다. 아래를 참조하세요

pairedread $1 &
pairedread $2 &
pairedread $3 & 
wait
echo "Done ..."

echo 
echo "======================"
echo "Testing again"
echo "======================"
echo

find . -type d -print | while read DIR; do
    echo "reading..."
    test -r "$DIR"/*_1.gz -a -r "$DIR"/*_2.gz || continue
    ( pairedread $DIR &  )
    done

wait
echo "Done..."

pairedread폴더를 가져오고 지정된 디렉터리의 파일에 대해 Python 스크립트를 호출하는 함수입니다. 첫 번째 경우,관심 있는 파일이 포함된 폴더를 명시적으로 제공하면 스크립트가 pairedread실행 인스턴스를 실행하고 결국 종료된 다음 유용한 메시지를 표시합니다."Done..." 뒤쪽에모든 하위 프로세스가 완료되었습니다.

두 번째 경우에는 동일한 세 개의 디렉터리를 선택하고 세 개의 pairedread 인스턴스를 만듭니다. 그러나 스크립트는 전혀 기다리지 않고 "Done..."즉시 인쇄하고 하위 프로세스가 백그라운드에서 실행되는 동안 반환됩니다.

내가 뭐 놓친 거 없니? 스크립트를 계속 진행하기 전에 하위 프로세스가 완료될 때까지 기다릴 수 없는 이유는 무엇입니까?

답변1

(...)파이프 및 추가 옵션 으로 인해 이러한 프로세스를 서브셸에서 시작하기 때문에 wait대기할 하위 프로세스가 있는지 알 수 없습니다. 다음과 같은 하위 쉘이 필요하지 않도록 루프를 다시 작성할 수 있습니다.

while read DIR; do
    echo "reading..."
    test -r "$DIR"/*_1.gz -a -r "$DIR"/*_2.gz || continue
    pairedread $DIR &
done < <(find . -type d -print)

대기는 현재 프로세스의 하위 프로세스에 대해서만 알고 있습니다. 이를 사용하면 |측면의 stdin/stdout을 함께 연결하는 구성 요소의 하위 쉘이 생성됩니다. 서브셸에서 시작된 모든 프로세스는 "최상위" 프로세스의 하위 프로세스가 아니므로 wait이를 인식하지 못합니다.

pairedread()따라서 이 경우 구문을 사용하여 하위 쉘에서 명시적으로 시작하고 파이프의 루프 블록 내부에서 발생함으로써 방해를 받습니다.while

파이프를 피하고 명시적인 서브셸을 제거하여 해당 블록을 다시 작성하여 wait하위 프로세스에 대해 외부에 알려 예상한 대로 수행되도록 합니다.

답변2

@Eric이 지적했듯이 프로세스를 기다리려면 명령을 하위 쉘링하는 대신 파이프 외부에서 백그라운드로 처리해야 합니다.

이중 포크: 최소 두 번 포크하면 해당 프로세스는 고아 프로세스가 되고 init 프로세스는 해당 프로세스의 상위 프로세스가 됩니다.

코드: 세 가지 포크(파이프, 서브쉘 및 백그라운드)를 수행하므로 init 프로세스는 새로 시작된 프로세스의 상위 프로세스가 되며 wait는 기다릴 수만 있기 때문에 기다릴 수 없습니다.내 자신의자식 프로세스.

관련 정보