pozastavení bash skriptu, dokud nebudou dokončeny předchozí příkazy

Mám bash skript, který vypadá takto:

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

Chtěl bych vytvořit další smyčku for po první, abych pokračoval dalších 30. Například

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

Chtěl bych pro první sadu úloh dokončit před spuštěním nové sady. Ale kvůli nohup se zdá, že jsou všechny spuštěny současně.

Mám nohup, protože se vzdáleně přihlásím na svůj server a spustím tam úlohy a poté zavřu bash. Existuje alternativní řešení?

Komentáře

  • Hledejte v příručce vestavěný wait.

Odpovědět

Chcete použít příkaz wait k udělejte to za vás. Můžete buď zachytit všechny podřízené ID procesů a počkat na ně konkrétně, nebo pokud jsou to jediné procesy na pozadí, které váš skript vytváří, stačí zavolat wait bez argumentu. Například:

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

Odpověď

Několik bodů:

  • Pokud je vaším cílem nohup zabránit tomu, aby vzdálený výstup shellu zabil vaše pracovní procesy, měli byste použít nohup na samotný skript, nikoli na jednotlivé pracovní procesy, které vytváří.

  • Jak je vysvětleno zde , nohup pouze brání procesům přijímat SIGHUP a od interakce s terminálem, ale nenarušuje vztah mezi shellem a jeho podřízenými procesy.

  • Kvůli výše uvedenému bodu, s nebo bez nohup, jednoduché wait mezi dvěma for smyčkami způsobí druhé for bude provedeno až poté, co budou ukončeny všechny podřízené procesy spuštěné prvními for.

  • S jednoduchým wait:

    čekají se na všechny aktuálně aktivní podřízené procesy a návratový stav je nulový.

  • Pokud potřebujete spustit druhou for, pouze pokud v první chybě nebyly žádné chyby , pak „budete muset uložit každý PID pracovníka s $! a předat je všem wait:

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

Komentáře

  • Tam cou Byly by jiné úlohy spuštěné na serveru. Takže ' chci jen počkat na svou dávku .. jsou to R skripty, takže jsou spuštěny pod R nebo cc1plus v top příkazu
  • Také <

bych rád používal nohup uvnitř spustit všechny příkazy v " paralelně ". v zásadě se jedná o simulace vědeckého programu. Chci spustit celkem 180 simulací, ale v dávkách 60. Počítadlo také musí jít od 1 do 180. Pokud je udělám po jednom, bude to trvat příliš dlouho.

  • wait způsobí, že bash počká na úlohy na pozadí, které sama vytvořila, nic jiného. Mohlo by zde dojít k určitému zmatku – tyto smyčky for, uložili jste je do souboru a vyvolali je jako skript (co jsem předpokládal kvůli ##script line), nebo je píšete ručně do terminálu?
  • dělal jsem cat file.txt | while a pids nebyl nastaven mimo smyčku příkaz čekání tedy viděl prázdný $pids řetězec. proč se to stane, je popsáno na serverfault.com/q/259339 . snadno opravitelné jako while ... < files.txt podle odpovědi na serverfault.com/a/259346
  • jen zvědavý jaký je účel znaménka + s proměnnou pids?
  • odpověď

    Použijte fg vestavěné. Čeká na dokončení procesů na pozadí.

    Podrobnosti zkuste help fg.

    Komentáře

    • Skript běží bez kontroly úlohy.

    Odpovědět

    Pokud vložíte něco jako následující segment kódu mezi vašimi dvěma for smyčkami by to mohlo pomoci.

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

    Samozřejmě, pokud vaše aplikace Rscript má šanci, že se nedokončí úspěšně a přetrvává, vaše druhá smyčka for nemusí mít šanci se spustit. Výše uvedený segment kódu předpokládá, že všechny procesy s identifikátorem Rscript --vanilla se dokončí a zmizí správně. Aniž bych věděl, co vaše aplikace dělá a jak běží, musím se na tento předpoklad spolehnout.

    EDIT

    Ve světle komentářů by to lépe vyhovovalo tvoje potřeby. (zahrnuje váš původní kód i logiku kontroly dokončení)

    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 

    Komentáře

    • Proces název v top zobrazuje buď R někdy, nebo cc1plus.
    • V takovém případě budete muset najít společného jmenovatele, který se zobrazí v seznamu ps -ef. Nebo po každém nohup příkazu nahrajte PID do proměnné (nejlépe do pole) pomocí echo ${!} a zkontrolujte tuto skupinu PID. Když všechny zmizí, můžete přejít do druhé for smyčky

    Napsat komentář

    Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *