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
nohupeste de a împiedica o ieșire de la distanță a shell-ului să omoare procesele lucrătorului dvs., ar trebui să utilizaținohuppe 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ă bucleforva provoca al doileaforsă fie executat numai după ce toate procesele secundare începute de primulforau 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
fornumai 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
Rsau 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.
-
waitface cabashsă aștepte lucrările de fundal pe care le-a generat, nimic altceva. S-ar putea să existe o anumită confuzie aici – acesteforbucle, 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
topafișează uneoriRuneori 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
waitintegrat.