Viele Unix-Tools, die es schon seit Urzeiten des Computers gibt, sind heutigen Softwareentwicklern und Sysadmins oft gar nicht mehr so geläufig. Daher möchte ich heute hier xargs beleuchten.
Grundlegende Benutzung
xargs ist laut Beschreibung ein Tool mit welchem man Befehlszeilen bauen und ausführen kann. Hier ein kleines Beispiel:
echo -e "1\n2\n3\n4" | xargs sleep
Der Echo-Befehl gibt die Zahlen 1 bis 4 in einer separaten Zeile aus. xargs nimmt den Inhalt aller Zeilen und hängt ihn an den Befehl sleep an. Schlussendlich wird also folgendes Ausgeführt:
sleep 1 2 3 4
Dieser Befehl wartet insgesamt 10 Sekunden und kehrt dann zurück. Will man nun aber für jeden übergebenen Parameter einen eigenen Sleep-Befehl ausführen, kann man die Anzahl der übergebenen Argumente pro Befehl beschränken:
echo -e "1\n2\n3\n4" | xargs -n 1 sleep
Jetzt werden vier sleep Prozesse gestartet, die sequentiell ablaufen. Das kann man auch gut sehen, wenn man misst, wie lange alles insgesamt dauert:
time echo -e "1\n2\n3\n4" | xargs -n 1 sleep
real 0m10.006s
user 0m0.000s
sys 0m0.004s
Parallelisierung
Und jetzt parallelisieren wir die Befehlsaufrufe. Das geht mit der Option -P. Damit können wir bestimmen, wie viele Prozesse gleichzeitig gestartet werden. Um das Beispiel einleuchtend zu machen, legen wir fest, dass 4 Prozesse gleichzeitig gestartet werden. Nach Adam Ries sollte die ganze Anweisung also nur insgesamt 4 Sekunden dauern:
time echo -e "1\n2\n3\n4" | xargs -n 1 -P 4 sleep
real 0m4.003s
user 0m0.000s
sys 0m0.000s
Funktioniert! So einfach kann man Abläufe parallelisieren
Praktischer Nutzen
Das Beispiel ist natürlich hochgradig sinnlos, weswegen es dem einen oder anderen schwer fällt, sich praktische Anwendungen dafür vorzustellen. Daher hier 2 Anwendungsfälle aus dem echten Leben:
- In unserer Firma wurden kürzlich ~1TB an PDF Daten angeliefert. Da die Qualität dieser unnötig hoch war, sollten sie für die Auslieferung via einer Webapplikation heruntergerechnet werden. Sequentiell wäre der Overhead absolut gigantisch gewesen, und die Verarbeitung hätte mehrere Tage gedauert. Parallelisiert mit 8 gleichzeitigen Prozessen war die Konvertierung in 6 Stunden gegessen:
find /daten/pdfs -name "*.pdf" -print0 | xargs -0 -n 1 -P 8 -I {} gs -q -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/ebook -dNOPAUSE -dBATCH -sOutputFile="{}" "{}"
- Es gibt eine riesige Datenmenge an CSV-Dateien, die durchsucht werden soll. grep ist dazu ein extrem effizientes Tool, allerdings per default nicht multi-threaded. Das kann man ganz simpel mit xargs simulieren. Beachtet, dass hier nicht nur 8 gleichzeitige Prozesse gestartet werden, sondern, dass jedem Prozess auch bis zu 4 Dateien übergeben werden:
find /daten/csv -name "*.csv" -print0 | xargs -0 -n 4 -P 8 grep "Suchbegriff"
Wer weitere interessante Anwendungsfälle findet, kann mir gerne einen Kommentar hinterlassen oder eine Email schreiben.