Schlechte Linux Tools: tcpflow & ab
Tags: linux
Kategorie Software Engineering | 4 Kommentare »
Die Linux Kommandozeile ist ein geniales Werkzeug, weil sich verschiedenste kleine Programme miteinander kombinieren lassen. Das funktioniert, weil alle Programme sich an einige wenige Regeln halten. Alle Programme? Nein, leider gibt es ein paar Ausnahmen!
Regeln für Linux Kommandozeilen-Programme
Die Programme von modernen UNIX-artigen Betriebssysteme wie Linux und MacOS basieren auf einigen wenigen Design Prinzipien, die schon in den 1970er Jahren formuliert wurden. Dazu gehört:
- Programme sollen nur eine Aufgabe lösen, diese aber perfekt.
- Programme müssen miteinander kombinierbar sein.
- Programme sollen Text verarbeiten und erzeugen.
Dahinter steckt der Gedanke einer universellen Pipes-and-Filters Architektur. Die Ausgabe eines Programms ist Text. Diese Ausgabe kann an ein anderes Programm übergeben („gepiped“) werden. Die Eingabe kann deshalb sowohl interaktiv als auch per Übergabe aus einem anderen Programm erfolgen. In Linux sieht das dann so aus:
cat datei.txt | grep bla
Das Programm „cat“ gibt den Inhalt der Datei aus. Mittels des Pipe Zeichens „|“ wird diese Ausgabe direkt an das Programm „grep“ übergeben. Dieses sucht im Zeichenstrom nach „bla“ und gibt alle Zeilen aus, die den Suchbegriff enthalten. „grep“ filtert die Ausgabe von „cat“. Da nach dem „grep“ Befehl keine weitere Pipe angegeben ist, erfolgt die Ausgabe auf der Standardausgabe, also auf dem Bildschirm.
Da sich „cat“ und „grep“ an die Design Prinzipien halten, können sie miteinander kombiniert werden, ohne dass die Entwickler eine spezielle Integration implementieren mussten.
Selbst komplexere Programme, wie der MySQL Client, halten sich an diese Prinzipien. Der folgende Befehl erstellt ein Backup der lokalen Datenbank „DB“ in Textform (MySQL CREATE und INSERT Statements) und ich leite diese Ausgabe in eine Datei, deren Name sich aus der aktuellen Uhrzeit ergibt. Die aktuelle Uhrzeit ermittel ich mit dem „date“ Programm im gewünschten Format.
mysqldump -u backup DB > backup-`date +%F-%H:%M:%S`.sql
Neben diesen klassischen Design Prinzipien gibt es noch diverse Gewohnheiten. Zu jedem Programm sollte zum Beispiel eine Manpage existieren, die das Programm dokumentiert.
Weiterhin gehe ich davon aus, dass sich ein Programm über Kommandozeilenparameter steuern lässt. Die Reihenfolge der Parameter sollte keine Rolle spielen.
ls -la
ls -al
Beide Aufrufe des Programms „ls“ liefern die gleiche Ausgabe: Es werden alle Dateien (inklusive versteckter Dateien) und Verzeichnisse sowie ihre Dateiattribute wie Zugriffsrechte angezeigt. Die Reihenfolge der Parameter spielt keine Rolle.
Leider halten sich nicht alle Programme an diese wenigen Prinzipien. Falls der geneigte Leser noch andere Negativbeispiele kennt, würde ich mich über ein Kommentar freuen.
tcpflow – Netzwerk Rekorder
Vor wenigen Tagen musste ich auf einem Rechner feststellen, dass sich im Home Verzeichnis fast 100.000 Dateien befanden. Ursache: Der Netzwerk Rekorder tcpflow gibt nicht nur jeden Request aus, sondern speichert jeden Netzwerkrequest zusätzlich in einer Datei. Standardmäßig. Ohne Vorwarnung.
Das ist unerwartet und gefährlich. Ab und zu müssen meine Kollegen und ich den Netzwerkverkehr auf einigen Rechnern überwachen, um Fehler zu analysieren. Dabei filtern wir den Netzwerkverkehr, den wir mittels tcpflow erheben, zum Beispiel nach einer bestimmten MAC Adresse, um zum Beispiel den Verkehr eines Testgeräts zu erkennen. Selbst auf einem Testserver kommen pro Stunde schnell 100.000 und mehr Requests zusammen, da neben meinem Testgerät natürlich noch viele andere Clients den Server nutzen. Dass jeder Request in eine Datei geschrieben wird, ist völlig unerwartet. Auf einem Produktionsserver könnte es leicht passieren, dass sich dadurch die Festplatte innerhalb kürzester Zeit füllt.
Mit folgenden Parametern kann man tcpflow dieses eigenartige Verhalten austreiben:
tcpflow -c -S enable_report=NO -p -i eth0 port 8084
Im Beispiel wird der Verkehr auf TCP Port 8084 überwacht, der über die Netzwerkschnittstelle „eth0“ empfangen wird. Der Parameter -c verhindert, dass tcpflow alle Requests als Dateien speichert. Der Parameter -S enable_report=NO verhindert, dass tcpflow bei jeder Ausführung eine Datei „report.xml“ erstellt. In dieser steht, mit welchen Compiler Optionen tcpflow kompiliert wurde. Wozu das gut sein soll, weiß ich nicht.
ab – Apache Benchmarking Tool
Das Apache Benchmarking Tool „ab“ ist ein geniales Werkzeug, um schnell einfache HTTP Lasttests durchzuführen.
ab -n 100 -c 10 https://www.example.com/
Im obigen Beispiel löst „ab“ insgesamt 100 HTTP GET Requests (Parameter -n) für die angegebene URL aus. Dabei werden immer 10 Requests parallel ausgeführt (Parameter -c).
In einem Fall wollte ich solch einen Lasttest über eine Stunde gegen einen internen Server ausführen. Ich benutzte zusätzlich den Parameter -t, über den ein Zeitlimit in Sekunden angegeben werden kann. Ich setzte auch eine sehr hohe Anzahl von Requests, damit „ab“ auch wirklich eine Stunde was zu tun hat.
ab -n 1000000 -c 10 -t 3600 https://...
Nach der Mittagspause musste ich leider feststellen, dass mein Test schon nach wenigen Minuten „erfolgreich“ beendet war, obwohl er noch lange nicht die 1.000.000 Requests durchgeführt hatte. Ich habe gesucht und gesucht und gesucht und bin fast verzweifelt.
Irgendwann bin ich über die Randbemerkung in der Manpage von „ab“ gestolpert, dass der Parameter -t die Anzahl der Requests auf 50.000 setzt. Das wäre nicht weiter schlimm, schließlich habe ich ja explizit 1.000.000 angegeben.
ab -t 3600 -n 1000000 -c 10 https://...
Dieser Aufruf führt zum gewünschten Ergebnis. Es kommt also auf die Reihenfolge der Parameter an. Die Parameter -t setzt einen Wert für die maximale Anzahl der Requests, den ich anschließend mit dem Parameter -n wieder überschreibe. Das ist ein völlig ungewohntes Verhalten und ich bin, wenn man die vielen Hilfegesuchen in diversen Internetforen sieht, nicht der Erste, der über dieses ungewöhnliche Verhalten von „ab“ gestolpert ist.
Wäre tcpdump eine Alternative zu tcpflow?
Beide Tools machen unterschiedliche Dinge. tcpdump zeigt alle Daten, die über die Schnittstelle gehen. tcpflow hingegen zeigt Flows, also zu einem Request die zugehörige Response. Man kann damit gerade HTTP Traffic sehr gut analysieren, weil man den Request samt HTTP Headern sieht, sowie die zugehörige Response.
Hi,
du könntest auch das bash builtin timeout benutzen. Das funktioniert dann auch für andere Kommandos falls benötigt:
#!/bin/bash
timeout SECONDS your_command
Gruß
Zu meinem Artikel passt auch jener https://danluu.com/cli-complexity/, der die zunehmende Komplexität in Form von Parametern für verschiedene Unix Kommandozeilentools über die Zeit analysiert.