백그라운드 변수 할당 및 대기 명령 이해

백그라운드 변수 할당 및 대기 명령 이해

내용 man bash은 다음과 같습니다:

잠깐만요 [-fn] [ID ...]

지정된 각 하위 프로세스를 기다리고 종료 상태를 반환합니다. 각 ID는 프로세스 ID이거나 작업 사양일 수 있습니다. 작업 사양이 제공되면 해당 작업에 대한 파이프라인의 모든 프로세스가 대기됩니다. ID가 지정되지 않으면 현재 활성화된 모든 하위 프로세스가 대기되고 상태 0이 반환됩니다. -n 옵션이 제공되면 wait는 작업이 종료될 때까지 기다렸다가 종료 상태를 반환합니다.

전형적인 예는 다음과 같습니다

 command1 & command2 & command3 & wait

즉, 이 세 가지 명령은 병렬로 실행되고 모든 명령이 완료된 후에만 다음 단계가 완료됩니다.

내 문제는 다음 두 bash 스크립트의 결과에 있습니다.

#!/bin/bash
for i in 1 2 3 ; do
  a=$i
  echo "$a is $i"
done 2>/dev/null

결과:

1 is 1
2 is 2
3 is 3

내가 기대했던 것과 거의 비슷합니다. 이제 변수를 할당하는 것은 긴 과정이라고 가정하고 이를 기다립니다.

#!/bin/bash
  for i in 1 2 3 ; do
  a=$i & wait
  echo "$a is $i"
done 2>/dev/null

결과 :

3 is 1
3 is 2
3 is 3

나는 다음과 같은 이유로 혼란스러워합니다.

  1. 완료될 때까지 기다려야 하는 유일한 wait프로세스는 변수를 할당하는 것이며, 그런 다음 스크립트의 다음 단계( echo)가 실행되어야 합니다. a=3루프의 마지막 반복에서만 발생해야 합니다.
  2. 내가 아는 한, for-loops는 하위 쉘에서 실행되며 wait이를 시작한 쉘의 범위만 갖습니다. 따라서 for-loop가 완료될 때 까지 기다려서는 안 됩니다 (이것이 상위 항목이므로).
  3. 나는 echo다른 프로세스와 병렬로 실행되도록 지정하지 않았으므로 경쟁 조건을 예상하지 않았습니다.

그렇다면 a마지막 루프 반복에서 -variable은 설정되었지만 이 변수는 $i설정되지 않은 이유는 무엇입니까? wait내가 명령의 어떤 부분을 잘못 이해했나요? 이 행동은 내 기대를 완전히 뛰어넘었습니다.

5.7.0-0.bpo.2-amd64 Linux 커널을 기반으로 하는 GNU bash, 버전 5.0.3(1).

미리 설정을 해제하면 a두 번째 스크립트가 이 값을 반환하게 됩니다.

 is 1
 is 2
 is 3

즉, 변수가 설정되지 않았으며 이전 실행에서 드래그되었습니다.

답변1

for루프는 하위 쉘에서 실행되지 않습니다. 예를 들어 변수가 루프 외부에서 사용되는 경우에도 for i in 1 2 3; do a=foo; done; echo $a인쇄할 수 있습니다 . foo루프 변수의 값은 루프에 의해 할당된 마지막 값이기도 합니다(루프가 종료되면 마지막 값이 아닐 수도 있음 break).

하지만 사용& 하다명령을 서브셸에 넣은 다음 작업을 수행하면 a=$i &할당이 서브셸에서만 발생합니다. 물론 서브셸에서 할당된 값을 사용할 수도 있습니다.

예를 들어:

a=1;
{ a=2; echo "subshell: $a"; } &
echo "main: $a";
wait;
echo "after: $a"

인쇄됩니다

main: 1
subshell: 2
after: 1

유효성 검사 와 같은 작업을 수행하십시오 { a=$i; echo "$a"; } &.

백그라운드 명령이 메인 셸의 변수에 액세스(및 수정)하도록 하려면 프로세스 간의 일부 동기화가 필요하며, 이로 인해 잠재적으로 상대적으로 작은 이득을 위해 셸이 복잡해집니다.

만약 너라면하다예를 들어 백그라운드에서 장기 실행 명령을 실행하고 싶지만 출력이 필요한 경우 출력을 임시로 파일에 저장하는 것과 같은 작업을 수행해야 합니다.

tmp=$(mktemp -d)
some long process > "$tmp/a" &
another long process > "$tmp/b" &
wait
a=$(< "$tmp/a")
b=$(< "$tmp/b")
...
rm -rf "$tmp"

또는 명령을 병렬로 실행하기 위해 특별히 제작된 GNU Parallel과 같은 것을 사용하세요. parset쉘 변수에 값을 할당할 수 있는 명령 도 있습니다 .

루프의 모든 반복 3에서 이를 얻는 이유는 아마도 이전에 첫 번째 루프를 실행하고 떠났기 때문일 것입니다 . 모든 후속 할당이 하위 셸로 푸시된 후 이는 루프 전체에서 기본 셸에 유지되는 값입니다.$aa3a

관련 정보