Die „while read“-Schleife des Bash-Skripts verursacht beim Ausführen mit GNU Parallel den Fehler „Broken Pipe“

Die „while read“-Schleife des Bash-Skripts verursacht beim Ausführen mit GNU Parallel den Fehler „Broken Pipe“

Laut der GNU Parallel-Mailingliste handelt es sich hierbei nicht um ein GNU Parallel-spezifisches Problem. Sie haben mir vorgeschlagen, mein Problem hier zu posten.

Der Fehler, den ich bekomme, ist ein „Broken Pipe“-Fehler, aber ich denke, ich sollte zuerst den Kontext meines Problems und die Ursache dieses Fehlers erklären. Er tritt auf, wenn ich versuche, ein beliebiges Bash-Skript zu verwenden, das eine „while read“-Schleife in GNU Parallel enthält.

Ich habe ein einfaches Bash-Skript wie dieses:

#!/bin/bash
# linkcheck.sh

while read domain
do
host "$domain"
done

Angenommen, ich möchte eine große Liste (sagen wir 250 MB) einspeisen.

cat urllist | ./linkcheck.sh

Das Ausführen des Host-Befehls auf URLs im Umfang von 250 MB ist ziemlich langsam. Um die Dinge zu beschleunigen, möchte ich die Eingabe vor dem Weiterleiten in Blöcke aufteilen und dann mehrere Jobs parallel ausführen. GNU Parallel ist dazu in der Lage.

cat urllist | parallel --pipe -j0 parallel ./linkcheck.sh {}

{} wird zeilenweise durch den Inhalt der URL-Liste ersetzt. Nehmen wir an, dass die Standardkonfiguration meines Systems in der Lage ist, etwa 500 Jobs pro Instanz von Parallel auszuführen. Um diese Einschränkung zu umgehen, können wir Parallel selbst parallelisieren:

cat urllist | parallel -j10 --pipe parallel -j0 ./linkcheck.sh {}

Dadurch werden etwa 5000 Jobs ausgeführt. Leider wird auch der Fehler „gebrochenes Rohr“ auftreten.(Bash-FAQ). Das Skript funktioniert jedoch, wenn ich die while read-Schleife entferne und die Eingabe direkt von dem nehme, was in {} eingespeist wird, z. B.

#!/bin/bash
# linkchecker.sh

domain="$1"
host "$1"

Warum funktioniert es nicht mit einer While-Leseschleife? Ist es sicher, einfach das SIGPIPE-Signal auszuschalten, um die Meldung „Broken Pipe“ zu stoppen, oder hat das Nebenwirkungen wie Datenbeschädigung?

Danke fürs Lesen.

Antwort1

Also,

cat-URL-Liste | parallel --pipe -j0 parallel ./linkcheck.sh {}

richtig funktionieren? Ich glaube, ein Teil Ihres Problems könnte sein, dass Sie das zweite ausgelassen haben --pipe, wie in

cat-URL-Liste | parallel -j10 --pipe parallel -j0--Rohr./linkcheck.sh {}

 


Übrigens, du brauchst nie zu sagen

Katzeeine_Datei|irgendein_Befehl

Sie können dies jederzeit ändern in

irgendein_Befehl<eine_Datei

Dies führt zu einem Prozess weniger (und einer Pipe weniger). (Die Verwendung kann sinnvoll/notwendig sein, catwenn Sie mehrere Eingabedateien haben.)

Antwort2

Mir scheint, dass der Fehler aufgrund eines schlechten Race-Zustands auftreten kann, und zwar aufgrund des Zeitfensters zwischen dem Forking eines untergeordneten Elements, um eine weitere Kopie von linkcheck.sh auszuführen, während die Pipe noch geöffnet ist, und dem Zeitpunkt, an dem das untergeordnete Element tatsächlich versucht zu lesen. In diesem Zeitfenster hat eine andere Kopie EOF gelesen und die Pipe wurde geschlossen.

verwandte Informationen