다음과 같은 bash 스크립트가 있습니다.
##script #!/bin/bash rm data* rm logfile* for i in {1..30} do ## append a & if you want to run it parallel; nohup Rscript --vanilla main.R 10 100 $i &> logfile"$i" & done
첫 번째 루프 다음에 또 다른 for 루프를 만들어서 30 개 더 계속하고 싶습니다. 예를 들어
##script #!/bin/bash rm data* rm logfile* for i in {1..30} do ## append a & if you want to run it parallel; nohup Rscript --vanilla main.R 10 100 $i &> logfile"$i" & for i in {31..60} do ## append a & if you want to run it parallel; nohup Rscript --vanilla main.R 10 100 $i &> logfile"$i" & done
새 세트를 시작하기 전에 완료 할 첫 번째 작업 세트. 그러나 nohup
때문에 모두 동시에 실행되는 것 같습니다.
nohup
가 있습니다. 원격으로 서버에 로그인하여 작업을 시작한 다음 bash를 닫았 기 때문입니다. 대체 솔루션이 있습니까?
댓글
li>
답변
wait
명령을 사용하여 모든 하위 프로세스 ID를 캡처하고 구체적으로 기다릴 수 있습니다. 또는 스크립트가 생성하는 유일한 백그라운드 프로세스 인 경우 wait
를 호출 할 수 있습니다. 인수없이. 예 :
#!/bin/bash # run two processes in the background and wait for them to finish nohup sleep 3 & nohup sleep 10 & echo "This will wait until both are done" date wait date echo "Done"
Answer
몇 가지 요점 :
-
nohup
의 목표가 원격 셸 종료로 인해 작업자 프로세스가 종료되는 것을 방지하는 것이라면 스크립트 자체가 아니라 스크립트 자체에서 생성합니다. -
여기에 설명 된대로 ,
nohup
는 프로세스가 SIGHUP를 수신하지 못하도록 차단합니다. 터미널과의 상호 작용에서 벗어나지 만 셸과 하위 프로세스 간의 관계를 끊지는 않습니다. -
위의 점 때문에 , 두 개의
for
루프 사이의 간단한wait
로 인해 두 번째for
는 첫 번째for
에 의해 시작된 모든 하위 프로세스가 종료 된 후에 만 실행됩니다. -
간단한
wait
:현재 활성화 된 모든 하위 프로세스가 대기하고 반환 상태는 0입니다.
-
첫 번째 오류가없는 경우에만 두 번째
for
를 실행해야하는 경우 이면 각 작업자 PID를$!
로 저장하고 모두wait
에 전달해야합니다.pids= for ... worker ... & pids+=" $!" done wait $pids || { echo "there were errors" >&2; exit 1; }
댓글
- ld는 서버에서 실행되는 다른 작업입니다. 그래서 저는 ' 배치를 기다리기만합니다. 그들은 R 스크립트이므로
R
또는 iv id =에서 실행됩니다.top
명령의 “4700a8d421″>
wait
는 bash
가 자체 생성 한 백그라운드 작업을 기다리게합니다. 여기에 약간의 혼동이있을 수 있습니다. 이러한 for
루프, 파일에 저장하고 스크립트로 호출 했습니까 ( 줄) 또는 터미널에 직접 입력하고 있습니까? cat file.txt | while
를 수행하고 있었고 PID가 루프 외부에 설정되지 않았습니다. 그래서 wait 명령은 빈 $pids
문자열을 발견했습니다. 이 문제가 발생하는 이유는 serverfault.com/q/259339 에서 설명합니다. serverfault.com/a/259346 에서 답변 한대로 while ... < files.txt
로 쉽게 고정됩니다.
답변
내장. 백그라운드 프로세스가 완료 될 때까지 대기합니다.
자세한 내용은 help fg
를 참조하세요.
댓글
- 스크립트는 작업 제어없이 실행됩니다.
답변
다음 코드 세그먼트와 같은 것을 삽입하는 경우 두 개의 for
루프 사이에 있으면 도움이 될 수 있습니다.
flag=0 while [ flag -eq 0 ] do ps -ef | grep "Rscript --vanilla" | grep -v grep > /dev/null flag=${?} sleep 10 done
물론 애플리케이션이 Rscript
가 성공적으로 완료되지 않고 계속 남아있을 수 있으며 두 번째 for 루프가 실행되지 않을 수 있습니다. 위의 코드 세그먼트는 식별자가 Rscript --vanilla
인 모든 프로세스가 제대로 완료되고 사라진다고 가정합니다. 애플리케이션이 무엇을하고 어떻게 실행되는지 알지 못한 채이 가정에 의존해야합니다.
편집
댓글에 비추어 볼 때 이것이 더 적합합니다. 너의 요구. (원본 코드와 완료 확인 논리 포함)
for i in {1..30} do ## append a & if you want to run it parallel; nohup Rscript --vanilla main.R 10 100 $i &> logfile"$i" & pids[$i]=${!} done flag=0 while [ flag -eq 0 ] do for PID in $(echo ${pids[@]}) do flag=1 ps -ef | grep ${PID} | grep -v grep >/dev/null; r=${?} if [ ${r} -eq 0 ] then flag=0 fi done done for i in {31..60} do ## append a & if you want to run it parallel; nohup Rscript --vanilla main.R 10 100 $i &> logfile"$i" & done
댓글
- 프로세스
top
의 이름은R
또는cc1plus
를 표시합니다. - 이 경우
ps -ef
목록에 표시되는 공통 분모를 찾아야합니다. 또는 각nohup
명령 후에echo ${!}
를 사용하여 PID를 변수 (바람직하게는 배열)에 기록하고이 PID 그룹을 확인합니다. 모두 사라지면 두 번째for
루프
로 진행할 수 있습니다.
wait
내장 기능을 검색하십시오.