Wie kann verhindert werden, dass XARGs die Ausgabe mehrerer Prozesse falsch zusammenführen?

17

Ich benutze xargsmit der Option --max-args=0(alternativ -P 0).

Die Ausgabe der Prozesse wird jedoch stdoutohne Rücksicht auf eine ordnungsgemäße Leitungstrennung in den Strom eingebunden . So werde ich oft mit Zeilen enden wie:

<start-of-line-1><line-2><end-of-line-1>

Da ich egrepmit ^in meinem Muster auf der gesamten xargsAusgabe verwende, ist dies mein Ergebnis durcheinander.

Gibt es eine Möglichkeit, xargsdas Schreiben der Prozessausgaben in der angegebenen Reihenfolge zu erzwingen (eine beliebige Reihenfolge, solange die Ausgabe eines Prozesses zusammenhängend ist)?

Oder eine andere Lösung?

Bearbeiten: Weitere Details zum Anwendungsfall:

Ich möchte Webseiten von verschiedenen Hosts herunterladen und analysieren. Da das Laden jeder Seite etwa eine Sekunde dauert und es ein paar Dutzend Seiten gibt, möchte ich die Anforderungen parallelisieren.

Mein Befehl hat die folgende Form:

echo -n $IPs | xargs --max-args=1 -I {} --delimiter ' ' --max-procs=0 \
wget -q -O- http://{}/somepage.html | egrep --count '^string'

Ich benutze bash und nicht so etwas wie Perl, da die Host-IPs (die $ IPs-Variable) und einige andere Daten aus einer enthaltenen bash-Datei stammen.

Christoph Wurm
quelle
Können Sie ein vollständigeres Beispiel zu Ihrer Frage geben? Es ist nicht klar, wie oder warum Sie derzeit verwenden xargs.
Caleb
Die Lösung dafür wird schwierig sein, man muss unterschiedliche Dateideskriptoren für stdouts jedes Prozesses verwenden und einen kleinen Server verwenden, um die Zeilen zu sammeln. xargsscheint keine solche Funktion zu bieten.
Stéphane Gimenez
@Caleb Los geht's, hoffe das hilft :-)
Christoph Wurm
Auf keinen Fall eine schlanke Lösung, aber vielleicht könnten Sie die makeJob-Funktion verwenden, ich denke, makedie Ausgabezeilen werden ordnungsgemäß zusammengeführt.
Stéphane Gimenez
fügt die --line-bufferedFlagge hinzu, egrepum zu helfen
iruvar

Antworten:

6

Dies sollte den Trick machen:

echo -n $IPs | xargs --max-args=1 -I {} --delimiter ' ' --max-procs=0 \
  sh -c "wget -q -O- 'http://{}/somepage.html' | egrep --count '^string'" | \
  { NUM=0; while read i; do NUM=$(($NUM + $i)); done; echo $NUM; }

Die Idee hier ist, separate Zählungen vorzunehmen und diese am Ende zu summieren. Könnte fehlschlagen, wenn die einzelnen Zählungen groß genug sind, um gemischt zu werden, aber das sollte nicht der Fall sein.

Stéphane Gimenez
quelle
14

GNU Parallel wurde speziell entwickelt, um dieses Problem zu lösen:

echo -n $IPs | parallel -d ' ' -j0 wget -q -O- http://{}/somepage.html | egrep --count '^string'

Wenn Ihre IPs in einer Datei sind, ist es noch schöner:

cat IPs | parallel -j0 wget -q -O- http://{}/somepage.html | egrep --count '^string'

Weitere Informationen finden Sie im Intro-Video: http://www.youtube.com/watch?v=OpaiGYxkSuQ

Ole Tange
quelle
2
Nettes Werkzeug! Ich wette auch, dass dir jemand sagen wird, dass die Katze sehr bald unbrauchbar ist.
Stéphane Gimenez
1
Ich kenne. Aber ich finde es einfacher zu lesen und arbeite normalerweise auf 48-Kern-Rechnern, sodass die wenigen zusätzlichen Taktzyklen für einen der inaktiven Kerne noch kein Problem darstellen.
Ole Tange
parallel wäre perfekt für den Job, wenn es in den Debian-Repositories wäre.
Christoph Wurm
1
@Legate Debian enthält den parallelBefehl von moreutils , der hier ausreicht:parallel -j99 -i sh -c 'wget -q -O- http://{}/somepage.html | egrep -c "^string"' -- $IPs
Gilles 'SO - hör auf, böse zu sein'
@Legate checkout build.opensuse.org/package/… für eine .deb-Datei und bugs.debian.org/cgi-bin/bugreport.cgi?bug=518696 für den Fehler, der behoben werden soll .
Ole Tange