2010-02-14 4 views
10

Ich schreibe ein kleines Skript, das Archive im Hauptthread erstellt und nach jedem Archivieren wird ein neuer Thread erstellt, indem eine Funktion aufgerufen wird, die sich um das Hochladen dieser Archive kümmert. Der Grund für das Hochladen im Hintergrund besteht darin, dass ein anderes Archiv erstellt werden kann, während die vorherigen Archive hochgeladen werden.Bash-Threading: Warten auf das Ende aller Job-Threads funktioniert nicht?

Das Problem, das ich habe, ist am Ende des Skripts. Das heißt, der Haupt-Thread wartet nicht darauf, dass alle Upload-Threads vor dem Beenden beendet werden. Schauen Sie sich die folgenden vereinfachten Skript (I entfernt/geändert Teile des Codes nicht mit dem Problem)

function func { 
for files in /home/somewhere/ 
    do 
    echo "Uploading $1" & 
    done 
wait 
} 

find /home/some/path -type f | while read filename ; do 
    echo "Creating archive of $filename" 
    func $somevariable & 
done 

wait 

Alles ist sehr schön ausgeführt wird, bis das letzte Archiv erstellt wird, dann wird das Skript beendet, bevor alle func Threads zu beenden, viele Dateien nicht hochgeladen.

Vielen Dank für Ihre Ideen.

+0

@Andrew: welches OS verwendest du? Mir sind einige Solaris-Builds bekannt, die genau so einen Wartefehler haben. –

+0

@martin clayton: Ich benutze Ubuntu Server 9.10 – Gargauth

Antwort

11

Update: gute Punkte im Kommentar.

Also, bei einem zweiten Blick stellt sich heraus, das Problem ist die Subshell, die von der Rohrleitung an die Schleife erstellt wird. Es ist eine gute Möglichkeit, das Skript zu strukturieren, aber Sie müssen das letzte Warten in der Shell, die die Hintergrundaufgaben abgespalten.

So etwas tun, wie folgt aus:

find /home/some/path -type f | (while read filename; do 
    echo "Creating archive of $filename" 
    func $somevariable & 
    done 
    wait 
) 
+1

Danke, aber wenn ich '&' aus 'function func' entferne, würde es warten, bis die Funktion beendet ist, nein? Außerdem habe ich Upload-Funktion in Schleife, so dass 4 Archive gleichzeitig hochgeladen werden. Dafür brauche ich diese Schleife, um auch nach dem Ausführen von Upload-Befehlen fortzufahren. EDIT: Ich habe auch in der Shell-Funktion "warten". – Gargauth

+0

Danke nochmal für das Update :) Ich * denke * das hat den Trick gemacht. Ich werde noch ein paar Tests machen. – Gargauth

-1

Sie könnten eine Schleife ausführen, bis der Befehl jobs als alternative Methode nichts zurückgibt.

3

Wenn Sie wait ohne Argumente ausführen, es soll für derzeit aktive Kindprozesse warten zu vervollständigen.

Das Problem ist wahrscheinlich, dass "alle derzeit aktiven untergeordneten Prozesse" nicht das bedeuten, was Sie in diesem Zusammenhang meinen. Insbesondere wenn Sie Pipelines in einer Subshell erstellen, ist nicht ganz klar, ob auf sie in der Parent-Shell gewartet wird.

Ich vermute, dass wait eigentlich nur auf Prozesse/Pipelines wartet, die in der Ausgabe von jobs angezeigt werden. Versuchen Sie einige Experimente ...

Eine mögliche Alternative könnte sein, die Kindprozess-IDs zu erfassen und einen wait n Aufruf für jede ID zu machen.

6

Heikel! Das Problem ist, dass dieser Block

find /home/some/path -type f | while read filename ; do 
    ... 
done 

Erstellt eine Untershell. Die Jobs func $ somevariable werden in dieser Subshell erstellt. Die übergeordnete Shell sieht, dass alle Hintergrundjobs, die it erstellt wurden, beendet wurden, es verfolgt keine Hintergrundjobs, die von Subshells erstellt wurden, die es hervorbrachte.

Die einfachste Lösung ist, stattdessen Ihre Hintergrundjobs von der übergeordneten Shell zu erstellen.

while read filename ; do 
    ... 
done < <(find /home/some/path -type f) 

Nun, das schafft eine Subshell --- für den Fund --- aber der während des Block nicht mehr in einer Subshell: Sie können nicht mit einem Rohr mit einem Sub-Shell zu schaffen vermeiden.

Beachten Sie, dass das obige nur unter bash funktioniert. (Weiß nicht über ksh oder zsh, vielleicht funktioniert es auch dort. Aber es funktioniert nicht unter Asche und anderen SH-Derivaten.)

Verwandte Themen