it-swarm.com.de

Anhalten eines Bash-Skripts, bis die vorherigen Befehle abgeschlossen sind

Ich habe ein Bash-Skript, das wie folgt aussieht:

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

Ich möchte eine weitere for-Schleife nach der ersten erstellen, um für weitere 30 fortzufahren. Zum Beispiel

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

Ich möchte, dass der erste Satz von Jobs beendet wird, bevor der neue Satz gestartet wird. Aber aufgrund der Nohup scheinen sie alle gleichzeitig ausgeführt zu werden.

Ich habe Nohup, weil ich mich remote bei meinem Server anmelde und dort die Jobs starte und dann meine Bash schließe. Gibt es eine alternative Lösung?

21
masfenix

Verwenden Sie dazu den Befehl wait. Sie können entweder alle untergeordneten Prozess-IDs erfassen und speziell auf sie warten, oder wenn dies die einzigen Hintergrundprozesse sind, die Ihr Skript erstellt, können Sie einfach wait ohne Argument aufrufen. Zum Beispiel:

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

Ein paar Punkte:

  • Wenn Ihr Ziel mit Nohup darin besteht, zu verhindern, dass ein Remote-Shell-Exit Ihre Arbeitsprozesse beendet, sollten Sie Nohup für das Skript selbst verwenden, nicht für die einzelnen Arbeitsprozesse, die es erstellt.

  • Wie bereits erläutert hier , verhindert Nohup nur, dass Prozesse SIGHUP empfangen und mit dem Terminal interagieren, unterbricht jedoch nicht die Beziehung zwischen der Shell und ihren untergeordneten Prozessen.

  • Aufgrund des obigen Punktes, mit oder ohne Nohup, bewirkt eine einfache wait zwischen den beiden for Schleifen, dass die zweite for schließlich nur ausgeführt wird Untergeordnete Prozesse, die mit dem ersten for gestartet wurden, wurden beendet.

  • Mit einem einfachen wait:

    auf alle derzeit aktiven untergeordneten Prozesse wird gewartet, und der Rückgabestatus ist Null.

  • Wenn Sie das zweite for nur ausführen müssen, wenn im ersten keine Fehler aufgetreten sind, müssen Sie jede Worker-PID mit $! und übergebe sie alle an wait:

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