wait
또 다른 제어 &
흐름 문제 가 있습니다 &&
.
다음과 같은 스크립트가 있고 동시에 가능한 많은 작업을 수행하고 싶다고 가정해 보겠습니다.
# may take some hours
something InputA > IrrelevantA &
something InputB > IrrelevantB &
# may take an hour
(
somethingElse InputA > OutputA &
somethingElse InputB > OutputB &
)&& combine OutputA OutputB > Result
...morestuff
질문 1: 스크립트에서는 combine
두 프로세스가 somethingElse
모두 계속되는 동안 두 프로세스가 모두 완료될 때 까지 기다리나요 something
?
질문 2: 그렇지 않은 경우(제 생각으로는 그럴 것 같지 않습니다) 위의 프로세스가 백그라운드에서 계속 실행되는 동안 어떻게 combine
이 두 프로세스를 기다릴 수 있습니까?somethingElse
something
답변1
귀하의 예에서 combine
명령은 하위 쉘이 종료된 직후에 실행됩니다(마지막 백그라운드 프로세스가 오류 없이 시작되었다고 가정). 명령이 없으므로 wait
작업이 시작되자마자 서브쉘이 종료됩니다.
둘 이상의 동시 백그라운드 프로세스의 반환 값을 기반으로 명령을 실행하려면 임시 파일을 반환 값으로 사용하는 것 외에는 다른 방법이 없습니다. wait
반환 값만 반환할 수 있기 때문입니다.하나대기 중인 프로세스 수입니다. 또한 백그라운드 프로세스는 반환 값을 얻기 위해 하위 셸에서 실행되어야 하므로 변수에 저장할 수 없습니다. 다음을 수행할 수 있습니다.
something InputA >IrrelevantA &
something InputB >IrrelevantB &
tmp1=$(mktemp)
tmp2=$(mktemp)
( somethingElse InputA >OutputA; echo $? >"$tmp1" ) &
proc1=$!
( somethingElse InputB >OutputB; echo $? >"$tmp2" ) &
proc2=$!
wait "$proc1" "$proc2"
read ret1 <"$tmp1"
read ret2 <"$tmp2"
[ "$ret1" = 0 && "ret2" = 0 ] && combine OutputA OutputB >Result
rm "$tmp1" "$tmp2"
반환 값에 별로 관심이 없다면 작업을 정상적으로 시작하고 다음을 사용할 수 있습니다 wait
.
something InputA >IrrelevantA &
something InputB >IrrelevantB &
somethingElse InputA >OutputA &
proc1=$!
somethingElse InputB >OutputB &
proc2=$!
wait "$proc1" "$proc2"
combine OutputA OutputB >Result
답변2
wait
다음 명령을 사용할 수 있습니다 .
(echo starting & sleep 10 & wait) && echo done
"Start" 줄이 즉시 발생하고 "Finish" 줄이 10초 동안 기다리는 것을 볼 수 있습니다.
답변3
OutputA
특히 파일을 저장할 필요가 없고 그게 OutputB
전부인 경우 프로세스 교체가 더 효율적일까요 Result
? 디스크에 쓸 때 I/O, 파일 저장이 느리고 속도 제한 단계일 수 있는 경우 이것이 특별한 시간 절약이 OutputA
될까요 OutputB
?
combine <(somethingElse InputA) <(somethingElse InputB) > Result
<(..here..)
프로세스 대체를 사용하면 출력을 파일에 저장한 다음 "결합" 단계에서 입력으로 읽는 대신 명령을 넣을 수 있습니다 .
메모리는 한계가 있고 메모리의 크기가 메모리의 용량을 outputA
초과하면 전체 목적을 무효화합니까?outputB
combine
시작하기 전에 두 프로세스가 모두 완료될 때까지 기다리 나요 ?
답변4
나는 실제로 다른 답변에서 그러한 일이 어떻게 수행되는지 정확하게 보여줍니다.여기. 이 답변은 백그라운드 프로세스가 2개의 로그를 유지하는지 확인하는 것에 관한 것이므로 10개의 로그로 설명했습니다.
데모 스크립트
cat <<-\DEMO >|${s=/tmp/script}
printf 'tty is %s\nparent pid is %s\npid is pid=%s\n' \
"$(tty)" "$PPID" "$$"
exec 1>&2 ; nums=$(seq 0 9)
rm ${files=$(printf "/tmp/file%s\n" $nums)}
for n in $nums ; do { for f in $files ; do
echo "Line $n" >>"$f" ; done
sleep 1 ; } ; done
#END
DEMO
데모 실행
s=/tmp/script ;chmod +x $s ;info="$(($s &)2>&- &)"
echo "$info" ; pid="${info##*=}" ; echo
while ps -p $pid >/dev/null ; do sleep 3 ; done
for f in /tmp/file[0-9] ; do
printf 'path : %s\tline count : %s\n' \
$f $(<$f wc -l)
done
산출:
tty is not a tty
parent pid is 1
pid is 12123
path : /tmp/file0 line count : 10
path : /tmp/file1 line count : 10
path : /tmp/file2 line count : 10
path : /tmp/file3 line count : 10
path : /tmp/file4 line count : 10
path : /tmp/file5 line count : 10
path : /tmp/file6 line count : 10
path : /tmp/file7 line count : 10
path : /tmp/file8 line count : 10
path : /tmp/file9 line count : 10
위에서 증명되었습니다. 라는 파일을 빌드하고 실행합니다./tmp/script
, chmod
~의실행 파일로 제공되며 다음과 같은 형식으로 제공됩니다.&background
중 하나&backgrounded ( subshell )
.
스크립트rms /tmp/file0-9
10개 파일 및echoes
초당 하나의 행이 10명 모두에게 전달됩니다. 내가 좀 잡았어$info
거부로부터 흘러 나와 제시된다.$(command substitution). While ps
아직 보고 중$pid
캡처했는데 아직 실행 중이라는 걸 알고 있으므로sleep.
완료되면 10개 파일 모두의 행이 계산됩니다.wc.
이런 방식으로 프로세스를 호출한 후에는 원래 상위 프로세스를 자유롭게 닫을 수 있으며 계속 실행됩니다. 사실상 거부됩니다. 이는 또한 전통적인 방법을 사용할 수 없음을 의미합니다.wait
명령하고 기다려ps
~의그럼에도 불구하고 수익은 더욱 강력해야 합니다.
프로세스가 실제로 시작되었다는 점은 언급할 가치가 있다고 생각합니다.$(command substitution)
그리고printfs
내 거$info
이런 식으로 효과적으로 제어할 수 있기를 바랍니다. 하지만 일단 터미널 출력이 떨어지면exec 1>&2
( 와 동일한 서브쉘에서 닫힘 2>&-
),프로세스가 종료되고 다른 쪽에서 이를 기다려야 합니다. 특히 모든 리디렉션과 프로세스 리더에 집중할 수 있는 한 입력 파이프를 처리하는 데 사용하는 경우 두 세계 모두에서 최고입니다.
다른 모든 것은 여기서 시연을 위한 것입니다. 이를 실행하는 데 필요한 것은 최상위 스크립트와 다음뿐입니다.
info="$(($script_path &)2>&- &)"
노트:이것은 내가 보여주고 싶은 내용만을 터미널에 인쇄할 것입니다. 지적한대로$PPID,
프로세스가 터미널에 의해 거부되었으며 이 프로세스의 직계 하위 프로세스입니다.$PID 1.
두 개를 동시에 실행하고 기다리려면 수동으로 할 수 있습니다.ps
그들의 pid를 확인하고 기다리세요.