Daniel Müller FLYERALARM

CLI-Programme sind Programme, die allgemein gültigen Best Practices oder Clean-Code-Prinzipien unterliegen sollten – gerade wenn sie ein kritisches Stück Infrastruktur darstellen, beispielsweise im Deploy-Prozess oder zum Erstellen wichtiger Daten-Back-ups.

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, welche 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 Programmes 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 Auflistung wird an das Filterprogramm grep übergeben, welches nach dem String myapplication filtert. Auf diese Weise kann man in der Regel den Prozess ermitteln, welcher 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, welches 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 wieviel Speicherplatz sie benötigen. Piping ist ein mächtiges Konzept, dass es uns erlaubt, kleine Single-Purpose-Applikationen zu erstellen und uns das gewünschte Endergebnis zusammen zu komponieren. Dieses Konzept ist heutzutage auch in Microservice-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, welche 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.

Den vollständigen Artikel lesen Sie in der Ausgabe:

Entwickler Magazin 5.16 - "Vulkan: Eruption im API-Zentrum"

Alle Infos zum Heft
255239Moderne CLI-Programme schreiben
X
- Gib Deinen Standort ein -
- or -