나는 (아직) 다른이 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
합니까?
답변
예제에서 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
답변
겠습니까 프로세스 대체 당신이 파일을 저장할 필요가 없습니다 특히,보다 효율적으로 OutputA
하고 OutputB
, 단지에 대한 관심 Result
? 특히 시간을 절약 할 파일을 저장, 당신은 디스크에 서면으로 느린 I / O가있는 경우 때문에겠습니까 OutputA
및 OutputB
속도 제한 단계가 될 수 있는가?
combine <(somethingElse InputA) <(somethingElse InputB) > Result
프로세스 대체를 사용하면 <(..here..)
출력을 파일에 저장 한 다음 “combine”단계에서 입력으로 읽는 대신 명령을 내부에 넣을 수 있습니다 .
메모리 제한, 그리고 크기 인 경우 outputA
와 outputB
더 많은 메모리에 저장할 수있는 것보다를, 그것은 전체 목적을 물리 칠 것인가?
combine
두 프로세스가 모두 완료 될 때까지 기다렸다가 실행을 시작합니까?
답변
다음 wait
명령을 사용할 수 있습니다 .
(echo starting & sleep 10 & wait) && echo done
“시작”줄이 바로 나타나는 것을 볼 수 있으며 “완료”는 10 초 동안 기다립니다.
답변
사실 이런 종류의 다른 대답 할 수있는 방법을 정확하게 보여 여기 . 그 대답은 백그라운드 프로세스로 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 개의 파일과 10 개의 echoes
줄을 1 초마다 한 줄씩 만듭니다. 사용하지 않는 $info
프로세스에서 일부 를 캡처하여 캡처 $(command substitution). While ps
에 대한 스틸 보고서를 통해 표시 $pid
합니다. 여전히 실행되고 있다는 것을 알고 sleep.
있습니다. 완료되면 10 개 파일의 행이 모두 계산됩니다.wc.
이러한 방식으로 프로세스를 호출 한 후에는 원래 상위 프로세스를 자유롭게 닫을 수 있으며 계속 트럭 킹을 계속할 수 있습니다. 이것은 또한 일반적인 wait
명령을 사용할 수는 없지만 ps
의 반환 대기는 더 강력해야합니다.
언급 할만큼 가치, 내가 생각하는 과정이 실제로 처음에 호출 될 것입니다 $(command substitution)
그리고 printfs
나는 $info
내가 효과적으로 제어 할 수 있도록 내가 할 수 있습니다. 하지만 그것의 출력 단자를 삭제 자마자 exec 1>&2
(어느 것이 서브 쉘과 같은 폐쇄되고 2>&-
), 처리는 탈출 I의 타단에 대해 주위를 기다려야한다. 모든 경로 재 지정 및 프로세스 리더에 대해 마음을 감쌀 수있는 한, 특히 파이프를 사용하여 입력 파이프를 처리하는 경우 두 가지 이점을 모두 활용하십시오.
다른 모든 것들은 여기서 시연하기위한 것입니다. 이 스크립트를 실행하기 위해 필요한 것은 다음과 같습니다.
info="$(($script_path &)2>&- &)"
참고 : 이것은 내가 보여주고 싶었던 것과 정확하게 터미널에만 인쇄합니다. $PPID,
이 프로세스에서언급했듯이이 프로세스는 터미널에서 제외되며$PID 1.
이 두 가지를 동시에 실행하고 기다리려면 ps
두 pid를 모두주고 기다릴 수 있습니다.