keskeytetään bash-komentosarja, kunnes edelliset komennot ovat valmiit

Minulla on bash-komentosarja, joka näyttää tältä:

##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 

Haluaisin luoda toisen silmukalle ensimmäisen jälkeen, jotta se jatkuu toisena. Esimerkiksi:

##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 

Haluan ensimmäiset valmiit työt ennen uuden sarjan aloittamista. Mutta nohup -kohdan vuoksi näyttää siltä, että niitä kaikkia ajetaan samanaikaisesti.

Minulla on nohup, koska kirjaudun etäpalvelimeen palvelimeen ja aloitan siellä olevat työt ja suljen sitten bashini. Onko olemassa vaihtoehtoista ratkaisua?

Kommentit

  • Hae sisäänrakennettua wait -ohjelmaa.

vastaus

Haluat käyttää komentoa wait Tee se puolestasi. Voit joko siepata kaikki lasten prosessitunnukset ja odottaa niitä erikseen, tai jos ne ovat ainoat skripin luomasi taustaprosessit, voit vain soittaa numeroon wait ilman argumenttia. Esimerkiksi:

#!/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" 

Vastaa

Muutama piste:

  • Jos tavoitteesi nohup -toiminnolla on estää kuoren etäsulku tappamasta työntekijän prosesseja, käytä nohup itse komentosarjassa, ei yksittäisissä työntekijän luomissa prosesseissa.

  • Kuten selitettiin tässä , nohup estää vain prosesseja vastaanottamasta SIGHUPia ja vuorovaikutuksesta päätelaitteen kanssa, mutta se ei riko kuoren ja sen aliprosessien välistä suhdetta.

  • Yllä olevan kohdan takia, joko , kahden for -silmukan välinen yksinkertainen wait aiheuttaa toisen for suoritetaan vasta sen jälkeen, kun kaikki ensimmäiset for käynnistämät aliprosessit ovat poistuneet.

  • Yksinkertaisella wait:

    kaikkia tällä hetkellä aktiivisia aliprosesseja odotetaan ja palautustila on nolla.

  • Jos joudut suorittamaan toisen for vain, jos ensimmäisessä ei ollut virheitä , sinun on tallennettava jokaisen työntekijän PID-tunnus $! -palvelulla ja välitettävä ne kaikille osoitteeseen wait:

    pids= for ... worker ... & pids+=" $!" done wait $pids || { echo "there were errors" >&2; exit 1; } 

Kommentit

  • Siellä on Ld ovat muita palvelimella käynnissä olevia töitä. Joten haluan odottaa vain erääni '. Ne ovat R-komentosarjoja, joten niitä ajetaan R tai cc1plus top -komennossa
  • Myös minä ' haluan käyttää sisällä nohupia suorittaa kaikki komennot " rinnakkain ". pohjimmiltaan nämä ovat tieteellisen ohjelman simulaatioita. Haluan suorittaa yhteensä 180 simulaatiota, mutta 60 erässä. Laskurin on myös oltava välillä 1 – 180. Jos teen ne yksi kerrallaan, se kestää liian kauan.
  • wait saa bash odottamaan itse synnyttämiään taustatehtäviä, ei mitään muuta. Tässä voi olla jonkin verran sekaannusta – nämä for -silmukat, tallensitko ne tiedostoon ja kutsuitko niitä komentosarjan (oletin, rivi) vai kirjoitatko ne käsin päätelaitteeseen?
  • tein cat file.txt | while eikä pids-asetusta asetettu silmukan ulkopuolelle joten odota-komento näki tyhjän merkkijonon $pids. miksi näin tapahtuu, keskustellaan osoitteessa serverfault.com/q/259339 . helppo korjata nimellä while ... < files.txt vastauksena osoitteeseen serverfault.com/a/259346
  • vain utelias mikä on + -merkin tarkoitus pids-muuttujalla?

Vastaa

Käytä fg sisäänrakennettu. Se odottaa, kunnes taustaprosessit päättyvät.

Kokeile lisätietoja kohdasta help fg.

Kommentit

  • Komentosarja toimii ilman työn hallintaa.

Vastaa

Jos lisäät jotain seuraavan koodisegmentin kaltaista kahden for -silmukan välissä, se voi auttaa.

flag=0 while [ flag -eq 0 ] do ps -ef | grep "Rscript --vanilla" | grep -v grep > /dev/null flag=${?} sleep 10 done 

Tietenkin, jos sovelluksesi Rscript on mahdollisuus olla suorittamatta onnistuneesti ja viipyä, silmukassekuntosi ei välttämättä ole mahdollisuutta juosta. Yllä olevassa koodisegmentissä oletetaan, että kaikki prosessit, joiden tunniste on Rscript --vanilla, valmistuvat ja häviävät oikein. Tietämättä mitä sovelluksesi tekee ja miten se toimii, minun on luotettava tähän oletukseen.

MUOKKAA

Kommenttien valossa tämä sopisi paremmin sinun tarpeesi. (se sisältää alkuperäisen koodisi sekä suorituksen tarkistuslogiikan)

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 

Kommentit

  • Prosessi nimi nimessä top näyttää joko R joskus tai cc1plus.
  • Siinä tapauksessa sinun on löydettävä yhteinen nimittäjä, joka näkyy ps -ef -luettelossa. Tai tallenna jokaisen nohup -komennon jälkeen PID muuttujaan (mieluiten matriisiin) echo ${!} -toiminnolla ja tarkista, onko tässä PID-ryhmässä. Kun ne kaikki katoavat, voit siirtyä toiseen for -silmukkaan

Vastaa

Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *