Jeg har et bash-script, der ligner følgende:
##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 gerne oprette en anden til loop efter den første for at fortsætte til en anden 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 vil gerne have det første sæt job, der er afsluttet, før du starter det nye sæt. Men på grund af nohup
ser det ud til, at de alle køres samtidigt.
Jeg har nohup
, fordi jeg logger eksternt på min server og starter jobbet der og lukker derefter min bash. Er der en alternativ løsning?
Kommentarer
Svar
Du vil gerne bruge kommandoen wait
til gør dette for dig. Du kan enten fange alle børnene behandle ider og vente på dem specifikt, eller hvis de er de eneste baggrundsprocesser, som dit script opretter, kan du bare ringe til wait
uden 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
Et par punkter:
-
Hvis dit mål med
nohup
er at forhindre, at en ekstern shelludgang dræber dine medarbejderprocesser, skal du brugenohup
på selve scriptet, ikke på de individuelle medarbejderprocesser, det opretter. -
Som forklaret her ,
nohup
forhindrer kun processer i at modtage SIGHUP og fra at interagere med terminalen, men det bryder ikke forholdet mellem skallen og dens underordnede processer. -
På grund af ovenstående punkt med eller uden
nohup
, en simpelwait
mellem de tofor
sløjfer forårsager den andenfor
skal kun udføres, efter at alle underordnede processer startet af den førstefor
er afsluttet. -
Med en simpel
wait
:der ventes på alle aktuelt aktive underordnede processer, og returstatus er nul.
-
Hvis du kun skal køre den anden
for
hvis der ikke var nogen fejl i den første , så skal du gemme hver arbejdstagers PID med$!
og videregive 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 job, der kører på serveren. Så jeg ' vil kun vente på min batch .. de er R-scripts, så de køres under
R
ellercc1plus
itop
kommandoen - Også jeg ' vil gerne bruge nohup inde at køre alle kommandoerne i " parallelt ". dybest set er dette simuleringer til et videnskabeligt program. Jeg vil køre 180 simuleringer i alt, men i batches på 60. Tælleren skal også gå fra 1 til 180. Hvis jeg gør dem en ad gangen, vil det tage for lang tid.
-
wait
fårbash
til at vente på de baggrundsjob, som det skabte selv, intet andet. Der kan være en vis forvirring her – dissefor
sløjfer, gemte du dem i en fil og påkaldte dem som et script (hvad jeg antog på grund af##script
linje), eller skriver du dem manuelt i terminalen? - Jeg lavede
cat file.txt | while
og pidserne blev ikke sat uden for sløjfen så ventekommandoen så en tom$pids
streng. hvorfor dette sker diskuteres på serverfault.com/q/259339 . let fast somwhile ... < files.txt
som svaret på serverfault.com/a/259346 - Bare nysgerrig hvad er formålet med + tegn med pids-variablen?
Svar
Brug fg
indbygget. Det venter, indtil baggrundsprocesser er færdige.
Prøv help fg
for detaljer.
Kommentarer
- Et script kører uden jobkontrol.
Svar
Hvis du indsætter noget i retning af følgende kodesegment imellem dine to for
sløjfer, kan det hjælpe.
flag=0 while [ flag -eq 0 ] do ps -ef | grep "Rscript --vanilla" | grep -v grep > /dev/null flag=${?} sleep 10 done
Selvfølgelig, hvis din applikation Rscript
har en chance for ikke at fuldføre og dvæle rundt, din anden for loop har muligvis ikke en chance for at løbe. Kodesegmentet ovenfor antager, at alle processer med identifikatoren Rscript --vanilla
fuldføres og forsvinder korrekt. Uden at vide, hvad din ansøgning gør, og hvordan den kører, er jeg nødt til at stole på denne antagelse.
REDIGER
På baggrund af kommentarerne passer dette bedre dine behov. (den inkluderer din originale kode samt kontrollogik for færdiggørelse)
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
- Processen navn i
top
viser entenR
undertiden ellercc1plus
. - I så fald skal du finde en fællesnævner, der vises i
ps -ef
-listen. Eller efter hvernohup
-kommando skal du registrere PID til en variabel (helst en matrix) ved atecho ${!}
og kontrollere for denne gruppe af PIDer. Når de alle forsvinder, kan du gå videre til den andenfor
loop
wait
indbygget.