Jeg har et bash-skript som ser slik ut:
##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
Jeg vil lage en annen for loop etter den første for å fortsette for en annen 30. For eksempel
##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
Jeg ønsker for det første settet med jobber som er ferdig før du starter det nye settet. Men på grunn av nohup ser det ut til at de alle kjøres samtidig.
Jeg har nohup fordi jeg logger på serveren min eksternt og starter jobbene der og lukker deretter bash. Finnes det en alternativ løsning?
Kommentarer
Svar
Du vil bruke kommandoen wait til gjør dette for deg. Du kan enten fange alle barna behandle ID-er og vente på dem spesifikt, eller hvis det er de eneste bakgrunnsprosessene skriptet ditt oppretter, kan du bare ringe wait uten argument. For eksempel:
#!/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"
Svar
Noen få punkter:
-
Hvis målet ditt med
nohuper å forhindre at en ekstern skallutgang dreper arbeidsprosessene dine, bør du brukenohuppå selve skriptet, ikke på de individuelle arbeidsprosessene det oppretter. -
Som forklart her ,
nohuphindrer bare prosesser i å motta SIGHUP og fra å samhandle med terminalen, men det bryter ikke forholdet mellom skallet og dets barneprosesser. -
På grunn av punktet ovenfor, med eller uten
nohup, en enkelwaitmellom de toforløkkene vil føre til at den andreforskal bare utføres etter at alle underordnede prosesser startet av den førsteforer avsluttet. -
Med en enkel
wait:alle nåværende aktive underordnede prosesser ventes, og returstatusen er null.
-
Hvis du trenger å kjøre den andre
forbare hvis det ikke var noen feil i den første , så må du lagre hver arbeider PID med$!, og sende dem alle tilwait:pids= for ... worker ... & pids+=" $!" done wait $pids || { echo "there were errors" >&2; exit 1; }
Kommentarer
- Der cou Det ville være andre jobber som kjører på serveren. Så jeg ' vil bare vente på batchen min .. de er R-skript så de kjøres under
Rellercc1plusitop-kommandoen - Også jeg ' vil bruke nohup inni å kjøre alle kommandoene i " parallelt ". i utgangspunktet er dette simuleringer for et vitenskapelig program. Jeg vil kjøre 180 simuleringer totalt, men i batcher på 60. Telleren må også gå fra 1 til 180. Hvis jeg gjør dem om gangen, vil det ta for lang tid.
-
waitfårbashtil å vente på bakgrunnsjobbene det skapte selv, ingenting annet. Det kan være forvirring her – disseforsløyfene, lagret du dem i en fil og påkalte dem som et skript (det jeg antok på grunn av##scriptlinje), eller skriver du dem for hånd i terminalen? - Jeg gjorde
cat file.txt | whileog pidsene ble ikke satt utenfor løkken så ventekommandoen så en tom$pidsstreng. hvorfor dette skjer blir diskutert på serverfault.com/q/259339 . lett fikset somwhile ... < files.txtsom svaret på serverfault.com/a/259346 - Bare nysgjerrig hva er hensikten med + tegn med pids-variabel?
Svar
Bruk fg innebygd. Den venter til bakgrunnsprosesser er ferdig.
Prøv help fg for detaljer.
Kommentarer
- Et skript kjører uten jobbkontroll.
Svar
Hvis du setter inn noe som følgende kodesegment mellom de to for sløyfene, kan det hjelpe.
flag=0 while [ flag -eq 0 ] do ps -ef | grep "Rscript --vanilla" | grep -v grep > /dev/null flag=${?} sleep 10 done
Selvfølgelig, hvis søknaden din Rscript har en sjanse til å ikke fullføre vellykket og dvele rundt, din andre for loop har kanskje ikke sjansen til å løpe. Kodesegmentet ovenfor forutsetter at alle prosesser med identifikatoren Rscript --vanilla vil fullføres og forsvinne ordentlig. Uten å vite hva søknaden din gjør og hvordan den kjører, må jeg stole på denne antagelsen.
REDIGER
I lys av kommentarene vil dette bedre passe dine behov. (den inkluderer den opprinnelige koden samt logikk for fullføringskontroll)
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
Kommentarer
- Prosessen navn i
topviser entenRnoen ganger ellercc1plus. - I så fall må du finne en fellesnevner som vises i
ps -ef-listen. Eller registrer PID til en variabel (helst en matrise) etter hvernohup-kommando vedecho ${!}og se etter denne gruppen av PIDer. Når alle forsvinner, kan du gå videre til den andreforloop
waitinnebygd.