Am un script bash care arată după cum urmează:
##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
Aș dori să creez o altă buclă de for după prima care să continue pentru încă 30. De exemplu
##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
Aș dori pentru primul set de lucrări care se termină înainte de a începe noul set. Dar din cauza nohup
se pare că toate sunt rulate simultan.
Am nohup
deoarece mă conectez de la distanță la serverul meu și încep joburile acolo și apoi închid bash-ul. Există o soluție alternativă?
Comentarii
Răspuns
Veți dori să utilizați comanda wait
faceți acest lucru pentru dvs. Puteți fie să capturați toate ID-urile procesate de copii și să le așteptați în mod specific, fie dacă acestea sunt singurele procese de fundal pe care le creează scriptul dvs., puteți apela doar wait
fără argument. De exemplu:
#!/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"
Răspuns
Câteva puncte:
-
Dacă obiectivul dvs. cu
nohup
este de a împiedica o ieșire de la distanță a shell-ului să omoare procesele lucrătorului dvs., ar trebui să utilizaținohup
pe scriptul în sine, nu pe procesele individuale ale lucrătorului pe care le creează. -
Așa cum se explică aici ,
nohup
împiedică procesele să primească SIGHUP și de la interacțiunea cu terminalul, dar nu rupe relația dintre shell și procesele sale copil. -
Din cauza punctului de mai sus, cu sau fără
nohup
, un simpluwait
între cele două buclefor
va provoca al doileafor
să fie executat numai după ce toate procesele secundare începute de primulfor
au ieșit. -
Cu un simplu
wait
:toate procesele secundare active în prezent sunt așteptate, iar starea de returnare este zero.
-
Dacă trebuie să rulați al doilea
for
numai dacă nu au existat erori în primul , atunci va trebui să salvați fiecare PID lucrător cu$!
și să le transmiteți tuturor cătrewait
:pids= for ... worker ... & pids+=" $!" done wait $pids || { echo "there were errors" >&2; exit 1; }
Comentarii
- Aș fi alte lucrări care rulează pe server. Deci, ' vreau doar să aștept lotul meu .. sunt scripturi R, deci sunt rulate sub
R
sau din comandatop
- De asemenea, îmi place să folosesc nohup în interior pentru a rula toate comenzile din " paralel ". practic acestea sunt simulări pentru un program științific. Vreau să rulez 180 de simulări în total, dar în loturi de 60. Contorul trebuie să treacă și de la 1 la 180. Dacă le fac pe rând, va dura prea mult.
-
wait
face cabash
să aștepte lucrările de fundal pe care le-a generat, nimic altceva. S-ar putea să existe o anumită confuzie aici – acestefor
bucle, le-ați salvat într-un fișier și le-ați invocat ca un script (ceea ce am presupus, din cauza >
line), sau le tastați manual în terminal?
cat file.txt | while
și pids nu a fost setat în afara buclei deci comanda de așteptare a văzut un șir $pids
gol. de ce se întâmplă acest lucru este discutat la serverfault.com/q/259339 . ușor de remediat ca while ... < files.txt
așa cum a răspuns la serverfault.com/a/259346 Răspuns
Utilizați fg
builtin. Se așteaptă până la finalizarea proceselor de fundal.
Încercați help fg
pentru detalii.
Comentarii
- Un script rulează fără controlul lucrărilor.
Răspuns
Dacă inserați ceva de genul următorului segment de cod între cele două bucle for
, ar putea fi de ajutor.
flag=0 while [ flag -eq 0 ] do ps -ef | grep "Rscript --vanilla" | grep -v grep > /dev/null flag=${?} sleep 10 done
Desigur, dacă aplicația dvs. Rscript
are șansa de a nu finaliza cu succes și de a rămâne în jur, secunda dvs. pentru buclă poate să nu aibă șansa de a rula. Segmentul de cod de mai sus presupune că toate procesele cu identificatorul Rscript --vanilla
se vor finaliza și vor dispărea corect. Fără să știu ce face și cum rulează aplicația dvs., trebuie să mă bazez pe această ipoteză.
EDIT
În lumina comentariilor, acest lucru s-ar potrivi mai bine nevoile tale. (include codul dvs. original, precum și logica de verificare a finalizării)
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
Comentarii
- Procesul numele din
top
afișează uneoriR
uneori saucc1plus
. - În acest caz, va trebui să găsiți un numitor comun, care apare în lista
ps -ef
. Sau după fiecare comandănohup
, înregistrați PID la o variabilă (de preferință o matrice) prinecho ${!}
și verificați acest grup de PID-uri. Când dispar toate, puteți trece la a doua buclăfor
wait
integrat.