Bash, 특정 백그라운드 프로세스를 실행하고 다른 프로세스를 기다리는 방법은 무엇입니까?

Bash, 특정 백그라운드 프로세스를 실행하고 다른 프로세스를 기다리는 방법은 무엇입니까?

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이 두 프로세스를 기다릴 수 있습니까?somethingElsesomething

답변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-910개 파일 및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를 확인하고 기다리세요.

관련 정보