n개 이하의 병렬 서브쉘을 실행하는 방법

n개 이하의 병렬 서브쉘을 실행하는 방법

메인 스크립트에서 서브스크립트를 실행하려고 하는데 초과하지 않도록 하고 싶습니다.N첨자는 동시에 실행됩니다.

다음의 간단한 예에서는 이를 보여줍니다.

/dev/shm/각 첨자는 고유한 타임스탬프로 구성된 이름을 사용하여 RAM( )에 가상 파일을 생성하고 완료되면 삭제합니다.

기본 스크립트는 첨자에서 발생한 더미 파일의 수를 계산하고 /dev/shm/2개 이상의 첨자가 이미 실행 중인 경우 새 첨자를 시작하지 않습니다(시작해서는 안 됩니다).

그러나 기본 스크립트는 while 조건을 무시하고 5개의 첨자를 모두 즉시 시작하는 것 같습니다.

내 코드에 문제가 있나요?

메인스크립트.txt

#!/bin/bash
for counter in $(seq 1 5)
do
        while [ $(ls -1 /dev/shm/|grep "script044"|wc -l) -ge 2 ]
        do
                sleep 0
        done

        xterm -e "bash script044.txt" &
done

exit

script044.txt(아래첨자)

#!/bin/bash

tempfilename="script044_"$(date +%Y%m%d%H%M%S)_${RANDOM}
echo > /dev/shm/${tempfilename}

for counter in $(seq 1 $(shuf -i 10-45 -n 1))
do
        sleep 1
        printf "${counter}\r"
done

rm /dev/shm/${tempfilename}

exit

답변1

(관례 - .txt일반 텍스트 파일입니다. .sh파일은 쉘 스크립트 파일입니다.)

mainscript.txt 스크립트에 경쟁 조건이 있습니다. 특히, while 루프는 script044.txt 스크립트가 임시 파일을 생성하기 전에 다음 반복을 시작합니다. 실제로 이러한 파일이 생성되기 전에 전체 루프가 반복됩니다.

이런 종류의 일을 처리하는 보다 안정적인 방법은 임시 파일을 잊어버리고 내장 셸을 사용하는 것입니다 wait.

#!/bin/bash

pid_count=0
for counter in $(seq 1 5)
do
    xterm -e "bash script044.txt" &
    if (( ++pid_count > 2 )); then
        wait -n
        ((pid_count--))
    fi
done

하위 프로세스가 시작될 때마다 카운터가 증가합니다. 카운터가 3보다 크면 wait다음 하위 프로세스를 완료합니다. 돌아올 때 wait카운터를 감소시키고 다음 xterm을 다시 시작합니다.

script044.txt에서 tempfilename관련 줄을 모두 삭제할 수 있습니다. 더 이상 필요하지 않습니다.


@chepner가 지적했듯이 필수 -n옵션은 bash 4.3 이상에서만 사용할 수 있습니다.

답변2

목표가 셸 전용 솔루션이라면 도움이 되지 않지만 GNU Parallel은 다음 중 하나를 제공합니다.sem명령을 사용하면 이 상황을 해결하는 데 도움이 됩니다.

다음(귀하의 스크립트가 없으므로 테스트되지 않음)은 작업을 5번 실행해야 하지만 한 번에 2번만 최종 종료를 기다리면서 실행해야 합니다.

LIMIT=2
for i in {1..5}; do
    sem -j $LIMIT 'term -e "bash script044.txt"'
done
sem --wait

답변3

IPC를 원하는 것 같습니다. 매번 잠자기 상태로 반복하고 테스트하는 대신 하위 프로세스가 완료되면 알려줄 때까지 기다릴 수 있습니다. 이것이 바로 파이프의 목적입니다.

하위 프로세스가 상위 프로세스에 보고되도록 할 수 있습니다. 파이프라인을 열고 공유하세요. 작업이 끝나면 부모에게 알리기만 하면 됩니다.

sub()(  trap "echo >&9" 0
        sleep 5
)
eval    "exec 9<>"<(echo);i=0
until   [ "$((i+=1))" -gt 5 ]
do      sub & read na <&9
        date +%S:%t"$i"
done

프로세스 대체를 사용하여 열었습니다. 쉘에서 이 작업을 수행할 수 없으면 다음을 사용할 수 있습니다.

mkfifo pipe; exec 9<>pipe; rm pipe; echo >&9

이제 두 경우 모두 처음에는 echo와이어가 파이프에 삽입됩니다. 이렇게 하면 처음부터 하나의 대기 프로세스보다 앞서게 됩니다. 즉, 항상 두 개의 동시 프로세스가 실행된다는 의미입니다. 이 스크립트는 date각 호출 사이의 시간(초)을 보고합니다 sub(). 출력은 다음과 같습니다.

34: 1
39: 2
39: 3
44: 4
44: 5

거기. 이제 보시다시피 5초마다 하위 프로세스가 종료되고, 종료되면 현재 차단된 echo파이프에 대한 라인이 됩니다. find는 입력에서 개행 문자를 만나자마자 수행 중인 작업을 종료하고 다시 시작할 수 있습니다 read.read

trap완료되면 하위 프로세스가 상위 프로세스를 호출하도록 지시하는 명령을 script_044에 추가하기 만 하면 됩니다 .

답변4

새 인스턴스를 시작한 후 약간의 지연을 삽입합니다 xterm...

        xterm -e "bash script044.txt" &
        sleep 0.1

관련 정보