pause et bash-skript til forrige kommandoer er ferdig

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

  • Søk i manualen for wait innebygd.

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 nohup er å forhindre at en ekstern skallutgang dreper arbeidsprosessene dine, bør du bruke nohup på selve skriptet, ikke på de individuelle arbeidsprosessene det oppretter.

  • Som forklart her , nohup hindrer 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 enkel wait mellom de to for løkkene vil føre til at den andre for skal bare utføres etter at alle underordnede prosesser startet av den første for er avsluttet.

  • Med en enkel wait:

    alle nåværende aktive underordnede prosesser ventes, og returstatusen er null.

  • Hvis du trenger å kjøre den andre for bare hvis det ikke var noen feil i den første , så må du lagre hver arbeider PID med $!, og sende dem alle til wait:

    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 R eller cc1plus i top -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.
  • wait får bash til å vente på bakgrunnsjobbene det skapte selv, ingenting annet. Det kan være forvirring her – disse for sløyfene, lagret du dem i en fil og påkalte dem som et skript (det jeg antok på grunn av ##script linje), eller skriver du dem for hånd i terminalen?
  • Jeg gjorde cat file.txt | while og pidsene ble ikke satt utenfor løkken så ventekommandoen så en tom $pids streng. hvorfor dette skjer blir diskutert på serverfault.com/q/259339 . lett fikset som while ... < files.txt som 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 top viser enten R noen ganger eller cc1plus.
  • I så fall må du finne en fellesnevner som vises i ps -ef -listen. Eller registrer PID til en variabel (helst en matrise) etter hver nohup -kommando ved echo ${!} og se etter denne gruppen av PIDer. Når alle forsvinner, kan du gå videre til den andre for loop

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *