504 Stimmen

Wie führt man mehrere Programme parallel in einem Bash-Skript aus?

Ich versuche, eine .sh-Datei der viele Programme ausführt gleichzeitig

Ich habe dies versucht

prog1 
prog2

Aber das führt prog1 aus, wartet dann, bis prog1 endet und startet dann prog2...

Wie kann ich sie also parallel betreiben?

35voto

mklement0 Punkte 303096

xargs -P <n> ermöglicht die Ausführung <n> Befehle parallel.

Während -P ist eine Nicht-Standard-Option, die sowohl von der GNU- (Linux) als auch von der macOS/BSD-Implementierung unterstützt wird.

Das folgende Beispiel:

  • läuft allenfalls 3 Befehle parallel zueinander,
  • mit zusätzlichen Befehlen, die nur gestartet werden, wenn ein zuvor gestarteter Prozess beendet wird.

    time xargs -P 3 -I {} sh -c 'eval "$1"' - {} <<'EOF' sleep 1; echo 1 sleep 2; echo 2 sleep 3; echo 3 echo 4 EOF

Die Ausgabe sieht in etwa so aus:

1   # output from 1st command 
4   # output from *last* command, which started as soon as the count dropped below 3
2   # output from 2nd command
3   # output from 3rd command

real    0m3.012s
user    0m0.011s
sys 0m0.008s

Das Timing zeigt, dass die Befehle parallel ausgeführt wurden (der letzte Befehl wurde erst nach Beendigung des ersten der drei ursprünglichen Befehle gestartet, aber sehr schnell ausgeführt).

En xargs selbst kehrt nicht zurück, bevor alle Befehle beendet sind, aber Sie können ihn im Hintergrund ausführen, indem Sie ihn mit dem Steueroperator & und dann unter Verwendung der wait zu warten, bis die gesamte xargs Befehl zu beenden.

{
  xargs -P 3 -I {} sh -c 'eval "$1"' - {} <<'EOF'
sleep 1; echo 1
sleep 2; echo 2
sleep 3; echo 3
echo 4
EOF
} &

# Script execution continues here while `xargs` is running 
# in the background.
echo "Waiting for commands to finish..."

# Wait for `xargs` to finish, via special variable $!, which contains
# the PID of the most recently started background process.
wait $!

Note :

  • BSD/macOS xargs Sie müssen die Anzahl der parallel auszuführenden Befehle angeben ausdrücklich während GNU xargs ermöglicht Ihnen die Angabe -P 0 um so viele so weit wie möglich parallel zueinander.

  • Der Output der parallel laufenden Prozesse kommt an während sie erzeugt wird so wird es sein unvorhersehbar verschachtelt .

    • GNU parallel wie erwähnt in Oles Antwort (hat no sind bei den meisten Plattformen Standard), bequem serialisiert (gruppiert) die Ausgabe nach Prozessen und bietet viele weitere Funktionen.

16voto

arnaldocan Punkte 365

Hier ist eine Funktion, die ich verwende, um maximal n Prozesse parallel laufen zu lassen (n=4 in diesem Beispiel):

max_children=4

function parallel {
  local time1=$(date +"%H:%M:%S")
  local time2=""

  # for the sake of the example, I'm using $2 as a description, you may be interested in other description
  echo "starting $2 ($time1)..."
  "$@" && time2=$(date +"%H:%M:%S") && echo "finishing $2 ($time1 -- $time2)..." &

  local my_pid=$$
  local children=$(ps -eo ppid | grep -w $my_pid | wc -w)
  children=$((children-1))
  if [[ $children -ge $max_children ]]; then
    wait -n
  fi
}

parallel sleep 5
parallel sleep 6
parallel sleep 7
parallel sleep 8
parallel sleep 9
wait

Wenn max_children auf die Anzahl der Kerne gesetzt ist, wird diese Funktion versuchen, ungenutzte Kerne zu vermeiden.

15voto

fermin Punkte 596
#!/bin/bash
prog1 & 2> .errorprog1.log; prog2 & 2> .errorprog2.log

Umleitung von Fehlern in separate Protokolle.

10voto

joe Punkte 1581

Das funktioniert bei mir wunderbar ( hier gefunden ):

sh -c 'command1 & command2 & command3 & wait'

Es gibt alle Protokolle der einzelnen Befehle gemischt aus (was ich wollte), und alle werden mit Strg+c beendet.

8voto

3h4x Punkte 876

Es gibt ein sehr nützliches Programm, das nohup heißt.

     nohup - run a command immune to hangups, with output to a non-tty

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X