![이 스크립트에서 기다린 후에 모든 하위 쉘이 실행되지 않는 이유는 무엇입니까?](https://linux55.com/image/201587/%EC%9D%B4%20%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%97%90%EC%84%9C%20%EA%B8%B0%EB%8B%A4%EB%A6%B0%20%ED%9B%84%EC%97%90%20%EB%AA%A8%EB%93%A0%20%ED%95%98%EC%9C%84%20%EC%89%98%EC%9D%B4%20%EC%8B%A4%ED%96%89%EB%90%98%EC%A7%80%20%EC%95%8A%EB%8A%94%20%EC%9D%B4%EC%9C%A0%EB%8A%94%20%EB%AC%B4%EC%97%87%EC%9E%85%EB%8B%88%EA%B9%8C%3F.png)
이 스크립트에서는 모든 git 저장소를 가져옵니다.
#!/bin/bash
find / -type d -name .git 2>/dev/null |
while read gitFolder; do
if [[ $gitFolder == *"/Temp/"* ]]; then
continue;
fi
if [[ $gitFolder == *"/Trash/"* ]]; then
continue;
fi
if [[ $gitFolder == *"/opt/"* ]]; then
continue;
fi
parent=$(dirname $gitFolder);
echo "";
echo $parent;
(git -C $parent pull && echo "Got $parent") &
done
wait
echo "Got all"
wait
모든 하위 쉘을 기다리지 마십시오 git pull
.
왜 이런 일이 발생합니까? 어떻게 해결할 수 있나요?
답변1
문제는 wait
잘못된 쉘 프로세스에 의해 실행되고 있습니다. 에서는 bash
파이프라인의 각 부분이 별도의 하위 셸에서 실행됩니다. 백그라운드 작업은 while
루프를 실행하는 하위 셸 에 속합니다 . 이 하위 셸로 이동하면 wait
예상대로 작동합니다.
find ... |
{
while ...; do
...
( git -C ... && ... ) &
done
wait
}
echo 'done.'
너도 좀 갖고 있어따옴표 없는 변수.
파이프를 완전히 제거하고 대신 루프를 직접 실행합니다 find
.이렇게 하면 출력을 구문 분석할 필요가 없습니다.find
.
find / -type d -name .git \
! -path '*/Temp/*' \
! -path '*/opt/*' \
! -path '*/Trash/*' \
-exec sh -c '
for gitpath do
git -C "$gitpath"/.. pull &
done
wait' sh {} +
또는 -prune
우리가 처리하고 싶지 않은 하위 디렉터리로 이동하지 않으려면 다음을 사용하세요.
find / \( -name Temp -o -name Trash -o -name opt \) -prune -o \
-type d -name .git -exec sh -c '
for gitpath do
git -C "$gitpath"/.. pull &
done
wait' sh {} +
설명에서 언급했듯이 xargs
동시에 실행되는 프로세스 수를 더 잘 제어 할 수도 있습니다 git
. 아래에 사용된 옵션 -P
(동시 작업 수 지정)은 비표준, -0
(읽기 \0
- 구분된 경로 이름) 및 -r
(입력 없이 명령 실행 방지)입니다. 그러나 GNU xargs
와 이 유틸리티의 일부 다른 구현에는 이러한 옵션이 있습니다. 또한 조건자(출력으로 구분된 경로 이름)는 -print0
비표준이지만 일반적으로 구현됩니다.find
\0
find / \( -name Temp -o -name Trash -o -name opt \) -prune -o \
-type d -name .git -print0 |
xargs -t -0r -P 4 -I {} git -C {}/.. pull
나는 GNU가 비슷한 방식으로 사용될 수 있다고 확신 parallel
하지만 그것이 이 질문의 주요 초점이 아니기 때문에 나는 그런 사고 방식을 추구하지 않습니다.