(bash) 스크립트 A, 스크립트 B를 기다리지 만 자식 프로세스는 아님


9

그래서 나는 scriptA를 가지고 있습니다 :

ssh server1 -- scriptB &
ssh server2 -- scriptB &
ssh server3 -- scriptB &
wait
otherstuffhappens

ScriptB는 다음을 수행합니다.

rsync -av /important/stuff/. remoteserver:/remote/dir/.
rsync -av /not/so/important/stuff/. remoteserver:/remote/dir/. &
exit

필자가 원하는 결과는 scriptA가 scriptB의 모든 인스턴스가 완료되기를 기다렸다가 현재 진행하고 있지만 중요하지 않은 것들의 백그라운드 동기화를 기다리는 것입니다. 이것들은 내가 기다리고 싶지 않은 더 큰 파일입니다.

nohup, disown 및 &의 차이점을 읽고 다른 조합을 시도했지만 원하는 결과를 얻지 못했습니다.

이 시점에서 나는 꽤 충격을 받았습니다. 도움을 주시면 감사하겠습니다!

답변:


15

여기서 문제 sshd는 파이프에서 파일 끝 을 기다리는 것이 명령의 stdout (어떤 이유로 stderr가 아니라 적어도 테스트중인 버전에서)을 읽는 것입니다. 그리고 백그라운드 작업은 해당 파이프에 fd를 상속합니다.

따라서이 문제를 해결하려면 해당 백그라운드 rsync명령 의 출력 을 일부 파일로 리디렉션 하거나 /dev/null신경 쓰지 않는 경우 리디렉션하십시오 . sshd가 해당 파이프를 기다리지 않더라도 sshd종료 후에 파이프가 끊어 지므로 rsyncstderr에 쓰려고하면 종료 되므로 stderr를 경로 재지 정해야 합니다.

그래서:

rsync ... > /dev/null 2>&1 &

비교:

$ time ssh localhost 'sleep 2 &'
ssh localhost 'sleep 2 &'  0.05s user 0.00s system 2% cpu 2.365 total
$ time ssh localhost 'sleep 2 > /dev/null &'
ssh localhost 'sleep 2 > /dev/null &'  0.04s user 0.00s system 12% cpu 0.349 total

과:

$ ssh localhost '(sleep 1; ls /x; echo "$?" > out) > /dev/null &'; sleep 2; cat out
141  # ls by killed with SIGPIPE upon writing the error message
$ ssh localhost '(sleep 1; ls /x; echo "$?" > out) > /dev/null 2>&1 &'; sleep 2; cat out
2    # ls exited normally after writing the error on /dev/null instead
     # of a broken pipe

4

둘 다의 부모 인 스크립트를 작성하면 둘 다 쉽게 제어 할 수 있습니다 . 또는 두 채널 사이에 통신 채널을 설정하십시오 .

특정 백그라운드 작업을 구체적으로 무시하기 위해 PID ( $!마지막 백그라운드 작업 PID)를 캡처하고 wait $pid해당 작업이 완료 될 때까지 기다릴 수 있습니다.


3

문제 -fssh해결하기 위한 플래그 입니다. 에 테스트 :

#!/bin/sh -e
echo $$_script__begin
( echo sleeping; sleep 2; echo slept )&
echo $$_script__end

로 실행하면 표시 ssh localhost ./script될 때까지 기다립니다 slept. 로 -f플래그, 그것은에 종료 echo $$_script__end하고 slept나중에 후 배경에 표시 ssh명령이 돌아왔다.


2

이것은 OpenSSH 서버의 알려진 문제이며 업스트림 bugzilla # 2071에 설명되어 있습니다. 이 버그에서 OpenSSH 쪽이나 스크립트에 대한 몇 가지 해결 방법이 제안되었습니다.

이 스크립트의 출력을 기다릴하려는 경우를 추가해야 wait하기 전에 exitscriptB도.

출력에 신경 쓰지 않으면에 약간의 변형 nohup및 IO 리디렉션을 사용 /dev/null하면 문제가 같은 방식으로 해결됩니다.


1

당신은 이것을 시도 할 수 있습니다. $!가장 최근에 실행 된 백그라운드 파이프 라인 / 프로세스의 프로세스 ID를 포함하는 기본 셸 변수입니다.

command1 &
lpid1=$!

command2 &
lpid2=$!

command3 &
lpid=$!

wait $lpid1  # waits for only the process with PID lpid1  to complete. 

export변수 등 을 사용하여 스크립트에 따라 이것을 사용해야합니다.


1

B는 자체 백그라운드 프로세스를 기다릴 필요가 있습니다.

rsync -av /important/stuff/. remoteserver:/remote/dir/.
rsync -av /not/so/important/stuff/. remoteserver:/remote/dir/. &
wait
exit

이 시점에서 백그라운드에서 두 번째 rsync를 실행하지 않고 wait완전히 사용하지 않을 수도 있습니다. 내가 할 의미 영업 이익이 모두 실행 된 것 같은데요하지만 rsync그들을 배경 처리 의미 병렬 프로세스, 둘 다 (함께 &) 한 후 사용하여 wait. 어쨌든 이것이 문제를 해결하는 가장 간단한 방법이며 질문의 정보를 기반으로 선택한 방법이라는 데 동의합니다.
David Z
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.