i=0
while read M; do
((cd $DEST/cfg/puppet/modules/$M || exit 1
[ -d .git ] && echo -n "$M: " && git pull) 2>&1 | prep $(printf %04d: $i) puppet/modules/$M) &
i=$[i+1]
[ $[ i % 20 ] = 0 ] && wait
done < $(dirname "$0")/modules-puppet.txt
[ $[ i % 20 ] = 0 ] && wait
위의 bash 스니펫에서 해당 라인이 무엇을 하는지 설명해줄 수 있는 사람이 있나요 ?
답변1
이 코드는 루프에서 많은 백그라운드 작업을 생성합니다. 이러한 각 작업은 git
및 와 관련된 명령을 실행합니다 puppet
.
이러한 작업은 매우 빠르게 생성될 수 있으며 시스템에 부담을 주지 않기 위해 코드는 현재 실행 중인 모든 백그라운드 작업이 완료될 때까지 기다리기 전에 해당 작업 중 20개만 실행합니다. wait
계속하기 전에 스크립트가 모든 백그라운드 작업이 완료될 때까지 기다리게 하여 또 다른 20개의 작업을 생성하는 것은 올바른 호출입니다 .
호출 전 산술 테스트는 wait
20으로 나눌 수 있는 모든 값, 즉 에 대해 true입니다.$i
$i = 20
$i = 40
산술 확장에 사용되는 구문은 $[ ... ]
더 이상 사용되지 않으며 이제 (이식 가능하게) bash
작성되었습니다 . $(( ... ))
이 %
연산자는 일반적인 모듈로 연산자입니다.
오래된 구문을 사용하는 것 외에도 셸에는 인용 문제가 있을 수도 있습니다. 변수 확장 $DEST
및 $M
및 $i
두 명령 대체와 마찬가지로 따옴표가 누락되었습니다. 이들 중 하나라도 $IFS
(기본적으로 공백, 탭, 줄 바꿈)에 있는 문자를 포함하거나 생성하는 경우 스크립트가 실패하거나 적어도 오작동할 것으로 예상할 수 있습니다.
wait
코드에는 루프에 의해 시작된 마지막 몇 개의 작업을 적절하게 기다리기 위한 루프 이후의 최종 코드도 누락되어 있습니다. 루프가 발생한다는 것을 보장할 수 있다면 이 작업을 수행할 필요가 없습니다.언제나실행 n*20
시간(일부 정수의 경우 n
)
답변2
$[ i % 20 ]
연산 확장으로 인해 감가 상각되어 으로 대체됩니다 $(())
.
i % 20
산술 연산 "모듈로"입니다.
[ $[ i % 20 ] = 0 ]
조건문이며 표준이 아니며 더 읽기 쉬운 또 다른 구문입니다. Posix는 다음과 같습니다.
if [ "$(( i % 20 ))" -eq 0 ]
&& wait
이전 명령의 반환 코드가 0인 경우에만 실행됩니다.
[ $[ i % 20 ] = 0 ] && wait
0과 같으면 모듈러스를 테스트합니다 wait
.
내 대체 완전한 구문은 다음과 같습니다.
if [ "$(( i % 20 ))" -eq 0 ] ; then
wait
fi