© istockphoto.comcom/Anatolii Babii
Robuste und moderne Kommandozeilenapplikationen

Schluss mit Wegwerfskripten


So gut wie jeder Softwareentwickler kennt, nutzt und schreibt sie: Skripte und Programme auf der Kommandozeile, zum Automatisieren von alltäglich wiederkehrenden Aufgaben, eingebettet in andere Applikationen oder gar als essenzielles Tool im individuellen Workflow. Doch welchen Stellenwert räumen wir ihnen ein? Wir sollten also die Zeit nutzen und uns ein wenig mit den Grundlagen eines guten CLI-Programms beschäftigen.

Aber was sind gute Absichten allein? Erst mal muss man sich überlegen, welche Eigenschaften unsere Kommandozeilenapplikation besitzen sollen. Hierfür bietet es sich an, einen Ausflug in die Vergangenheit der Softwareentwicklung zu machen, genauer gesagt: bis zurück in die wilden Siebziger.

Die Unix-Philosophie, begründet u. a. von Ken Thompson bei Bell Labs in den Siebzigerjahren, stellt einige kulturelle Grundlagen und Regeln für das Entwickeln von minimalistischer, modularer Software auf. Programme werden als einzelne Werkzeuge betrachtet, die einfach zu nutzen und gut kombinierbar sein sollen. Dieser Ansatz wird monolithischen Vielzweckprogrammen vorgezogen.

Piping

Als Pipe bezeichnet man den Datenstrom zwischen zwei Prozessen durch einen Puffer. Genauer heißt das, dass das Ergebnis des ersten Programms als Parameter für das nächste verwendet wird. Häufig dient das zweite Programm als eine Art Filter des Outputs des ersten, muss es aber nicht. Beispielsweise könnte man auf diese Art alle Prozesse, die mit der fiktiven myapplication verwandt sind, beenden:

>> ps aux | grep myapplication | grep -v grep | awk '{print $2}' | xargs kill

Hier erhalten wir vom Programm ps eine Auflistung aller Prozesse. Die Argumente a, u und x spezifizieren hier die Art des Outputs. Diese Auflis­tung wird an das Filterprogramm grep übergeben, das nach dem String myapplication filtert. Auf diese Weise kann man in der Regel den Prozess ermitteln, der das gesuchte Programm enthält. Die dritte Anweisung filtert noch den grep-Befehl selbst aus der Liste der Prozesse aus. Nun haben wir unseren Output also auf den oder die relevanten Prozesse reduziert. Der nächste Befehl verarbeitet die einzelnen Zeilen mit dem Textverarbeitungstool awk und ermittelt so die Prozess-ID. Sie werden letztlich an das Programm xargs übergeben, das eine beliebige Anzahl an Parametern entgegennimmt und dafür sorgt, dass für jeden dieser Parameter der Befehl kill ausgeführt wird.

Komplexe Textverarbeitung kann beispielsweise durch die Programme sed oder awk erfolgen, man könnte den gepipeten Datenstrom auch direkt per mail-Command verschicken oder sich anzeigen lassen, wie viele Dateien mit der Endung .jpg im eigenen Benutzerverzeichnis liegen und wie viel Speicherplatz sie benötigen. Piping ist ein mächtiges Konzept, das es uns erlaubt, kleine Single-Purpose-Applikationen zu erstellen und uns das gewünschte Endergebnis zusammen zu komponieren. Dieses Konzept ist heutzutage auch in Microservices-basierten Architekturen oder in manch einem JavaScript-Build-Tool zu finden.

Historisch bedingt waren frühe Programme aus der Unix-Welt kommandozeilenbasiert. Hier wurden Erfahrungen gemacht und Best Practices formuliert, die heute noch ein Höchstmaß an Relevanz besitzen. Daher können sie als lehrreicher Leitfaden dienen, wenn wir überlegen, wie wir unsere wiederkehrenden Aufgaben automatisieren oder die diversen Probleme des Entwickleralltags elegant lösen möchten.

Warum eigentlich keine grafische Oberfläche?

Kommandozeilenapplikationen haben einen zugegebenermaßen vollkommen offensichtlichen, aber entscheidenden Vorteil: Sie besitzen und benötigen keine grafische Oberfläche. Das spart Entwicklungszeit und hilft dem pragmatischen Problemlöser, sich mit dem Kern der Sache auseinanderzusetzen. Die Möglichkeiten, mit dem User zu kommunizieren und zu interagieren, sind jedoch eingeschränkt. Dem Entwickler obliegt die Aufgabe das Programm benutzerfreundlich zu gestalten und nutzbar zu machen, ohne dass der Anwender erst einmal den kompletten Quelltext analysieren und interpretieren muss. Um dies zu gewährleisten, ist es wichtig, sich zu überlegen, wie der User (der man auch gerne allein selbst sein kann) mit der App interagieren soll. Interaktion und Konfiguration geschieht im Normalfall über Parameter und Flags, die man beim Aufruf des Programms auf der Kommandozeile mitgibt. Hier ergibt es Sinn, sich an bestehende Konventionen zu halten. Auf diese Art und Weise kann ein Nutzer sich intuitiv den Funktionen bedienen. Absolute No-Brainer sind hierbei die Versions- und Hilfef...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Teams

Für Firmen haben wir individuelle Teamlizenzen. Wir erstellen Ihnen gerne ein passendes Angebot.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang