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
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 yksinkertainenwait
aiheuttaa toisenfor
suoritetaan vasta sen jälkeen, kun kaikki ensimmäisetfor
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 osoitteeseenwait
: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
taicc1plus
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
saabash
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ää jokoR
joskus taicc1plus
. - Siinä tapauksessa sinun on löydettävä yhteinen nimittäjä, joka näkyy
ps -ef
-luettelossa. Tai tallenna jokaisennohup
-komennon jälkeen PID muuttujaan (mieluiten matriisiin)echo ${!}
-toiminnolla ja tarkista, onko tässä PID-ryhmässä. Kun ne kaikki katoavat, voit siirtyä toiseenfor
-silmukkaan
wait
-ohjelmaa.