Persistente Shell-Objekte

Angesichts der Popularität objektorientierter Verfahren und Werkzeuge erscheint es verwunderlich, dass unsere heissgeliebten Kommandozeilen bisher vom Trend verschont blieben. In diesem Artikel beschreibe ich, wie man innerhalb bestehender Shells einen Hauch von Objektorientierung (OO) erreichen kann und welche Vorteile sich daraus für die tägliche Arbeit ergeben können.

Wer mit Objektorientierung bisher keine Erfahrung gesammelt hat, für den bieten die persistenten Shell-Objekte einen Einstieg in die OO-Welt fernab von komplexen Sprachen wie Java oder C++. Zur Vermeidung der länglichen Bezeichnung persistentes Shell-Objekt schreibe ich im folgenden einfach von Objekten.

Der übliche Gebrauch der Kommandozeile erfolgt anwendungsorientiert: Aus einer Menge von Werkzeugen wählt der Anwender die richtigen in der richtigen Reihenfolge für die richtigen Daten aus. In Listing 1-1 sehen Sie eine solche Abfolge von Kommandos zum Drucken eines TeX-Dokuments. Das Eintippen solcher Kommandofolgen ist aus Sicht des Anwenders nicht produktiv und mangels weltweit einheitlicher bzw. leicht zu modifizierender Voreinstellungen ist die volle Breite der Detailskenntnisse über die beteiligten Werkzeuge notwendig. 1670 verschiedene sind es beispielweise auf meinem System; nicht gezählt die ausserhalb des Suchpfades $PATH. Für die von mir am häufigsten verwendeten Anwendungen kenne ich die Abhängigkeiten, für den Rest muss ich die Zusammenhänge bei Bedarf mühsam herausfinden.

latex  mein_paper.tex
dvips  mein_paper.dvi
gs     -q -dSAFER -dNOPAUSE -r600 -sDEVICE=ljet4 -sPAPERSIZE=a4 \
       -sOutputFile="mein_paper.pcl" mein_paper.ps quit.ps
lpr    -h -Plindgren mein_paper.pcl

Listing 1-1: Kommandos zum Drucken eines TeX-Dokuments

Eine übliche Strategie zur Vereinfachung der Situation ist die Verwendung eines Makefiles, welches die obigen Kommandos hinter einfachen Namen wie dvi, postscript und print verbirgt. Im Makefile können Abhängigkeiten definiert werden, so dass beim Aufruf von "make print" automatisch alle notwendigen Kommandos ausgeführt werden. Allerdings muss der Anwender nun zusätzlich die Syntax von Makefiles erlernen, um Änderungen anbringen zu können. Mit Makefiles verhält es sich in diesem Zusammenhäng wie mit den Werkzeugen crontab oder edquota: anstelle einer eindeutig definierten Schnittstelle tritt eine mehr oder weniger eindeutig definierte Syntax in Form eines Textes. Die Syntax einer Datei ist aber niemals eine Schnittstelle, ansonsten wäre /dev/sda die Schnittstelle zum Kopieren von Dateien und der Entwicklungsaufwand für cp könnte gespart werden.

Den vielleicht nächsten Schritt in der Evolution bringen die Objekte. Mit Objekten ist man nicht mehr auf die Namen make und Makefile festgelegt, sondern das Objekt erhält bei seiner Erzeugung einen fast frei wählbaren Namen. Die weitere Verwendung des Objekts erfolgt fast wie bei den Makefiles und ist anhand eines Beispiels in Listing 1-2 wiedergegeben. Die Erzeugung des neuen Objekts mein_paper geschieht in diesem Fall durch das Clonen eines bereits bestehenden Objekts mit Namen altes_paper.

Das Ergebnis erscheint auf den ersten Blick eine Augenwischerei zu sein, weil sich scheinbar nur die Reihenfolge von Wörtern geändert hat: Aus "latex mein_paper" wird "mein_paper latex". Tatsächlich hat sich aber mehr geändert. Vorher waren Anwendungen und die zugehörigen Daten getrennt. Der Anwender musste beides in Gedanken zusammenhalten. Nun werden Anwendungen und Daten durch das Objekt zusammengehalten, d.h. der Anwender ist entlastet. Die Objekte führen zu einer Sichtweise, die problem-zentrisch ist.

sh> altes_paper clone mein_paper     # mein_paper = altes_paper->clone();

sh> mein_paper  cli                  # mein_paper->cli();
mein_paper> set editor emacs         # mein_paper->set->editor('emacs');
mein_paper> get editor               # mein_paper->get->editor();
emacs
mein_paper> set document /home/truemper/guugn.tex
mein_paper> quit

sh> mein_paper  edit                 # mein_paper->edit();
sh> mein_paper  papersize letter     # mein_paper->papersize('letter');
sh> mein_paper  print                # mein_paper->print();

Listing 1-2: Drucken von LaTex-Dokumenten mit Objekten

Darüber hinaus bietet das Objekt Methoden zur Anpassung der Konfiguration an die eigenen Bedürfnisse. Der Anwender kann die Objekt-spezifische Kommandozeile (command line interpreter) aufrufen, um mit weniger Tipparbeit die möglichen Einstellungen aufzulisten und zu bearbeiten (siehe Listing 1-2). Mit den individuellen Kommandozeilen wird der vormals globale Namensraum aller Anwendungen und Daten, die sich unter Unix ja nur durch das x-Bit voneinander unterscheiden, in überschaubare und logisch zusammenhängende Namensräume geteilt.

Das aktuelle Arbeitsverzeichnis (CWD) weicht dem aktuellen Arbeitsobjekt (CWO). Alt-Tab erlaubt die Wahl des am Terminal aktiven Objekts? Objekte liessen sich daher als Icons der Kommandozeile betrachten. Die hierarchisch organisierten und voneinander getrennten Kommandozeilen entsprächen den Aufklap-Menüs der Icons und Anwendungen der grafischen Oberflächen.

Wegen der ständig steigenden Zahl von Werkzeugen wird dem Schutz des Namensraums bzw. individuellen Namensräumen in Zukunft eine immer stärkere Bedeutung zukommen. Schon heute werden Komponenten wie Spiele oder die P(B|G|N)M-Sammlung in eigenen Hierarchien organisiert. Wie wird man in Zukunft Anwendungen zur Vermeidung von Namenskonflikten nennen müssen? cp_Solaris_2.7_patch-328, cp_gnu_4.0? Und dann mit wenig übersichtlicher und vom Anwender nicht konfigurierbarer Verlinkung - oder noch schlimmer: Doppelverlinkung - die gerade gewünschte Version auswählen? Zugegeben, die zugehörigen Klassen hätten auch ärgerlich lange Namen, aber die Namen der Klassen werden nur einmal bei der Erzeugung des Objekts benötigt - das ist der entscheidende Punkt.

Eine Hauptanwendung für Objekte sind die Shell-skripte des SysV-init-Konzepts. Der Aufruf der Skripte im objektorientierten Stil "apache start" oder "apache stop" ist wohlbekannt. Allerdings hat SysV die grundsätzliche Idee monolitischer Shell-skripte von BSD übernommen, so dass die init-Skripte in der Regel nur unter Vorbehalt geändert werden dürfen. Verwendet man jedoch Objekte, dann müssen diese weder mit einem Editor modifiziert werden, weil die Objekte dafür eine Schnittstelle bieten. Noch müssen die Objekte mit cp und einem Editor von der Datei init.d/skeleton abgeleitet werden, wie das zur empfohlenen Politik vieler Linux-Distributionen gehört. Sondern die Objekte werden einfach geklont (entspricht dem cp) und dann geändert (entspricht dem edieren). Und zwar mit den speziell dafür konstruierten Schnittstellen. Entweder wird ein bestehendes Objekt direkt geklont, oder das Objekt wird anhand einer Vorlage für neue Objekte, genannt Klasse, erstellt.

Die aktuelle Implementierung der Objekte ist sehr einfach gehalten. Der Name des Objekts ist ein symbolischer Link im Verzeichnis $HOME/.shobj/bin. Indem dieses Verzeichnis zum Suchpfad $PATH gehört, lassen sich Objekte wie gewöhnliche Anwendungen aufrufen. Der symbolische Link aller Objekte zeigt der Einfachheit halber auf ein gemeinsames Shell-skript namens objects-wrapper.sh, von dem der originale Name des Objekts anhand von $0 ermittelt wird. Jedes Objekt verfügt über ein eigenes Verzeichnis, in dem die (Meta-)Daten und die Methoden des Objekts abgelegt sind. Weil jede Methode z.B. als Shell-skript in einer eigenen Datei gespeichert wird, lassen sich neue Methoden sehr einfach hinzufügen - mit etwas Sorgfalt auch zu bestehenden Objekten. Man kann sagen, die Objekte setzen den Ansatz von SysV-init konsequent fort, aus monolitischen Skripten eine modulare Angelegenheit zu machen.

Die Kommandozeile der Objekte wirft im Zusammenhang mit den init-Skripten auch die Frage auf, warum sich Dämonen zwecks interaktiver Kommandozeile nicht mit einem Terminal verbinden lassen. Denn die Steuerung per PID-Datei birgt potenzielle Fehler. Die üblichen Vorgehensweisen garantieren nicht, dass die Zahl in der PID-Datei nach einiger Zeit noch zu meinem Dämon gehört. Stirbt ein Dämon, dann wird die PID für andere Prozesse frei. Und schliesslich: Warum sollten sich Dämonen nicht komfortabler steuern lassen, als mit Stop-Neukonfiguration-Start?

Die abstraktere Sichtweise mit Objekten führt weg von der anwendungsorientierten Sicht, bei der die Dämonen im Mittelpunkt stehen; hin zu einer Sicht, bei der der zugehörige Dienst im Mittelpunkt steht. Wenn der telnet-Dienst gestartet sein soll, dann spielt es erstmal keine Rolle, ob der Telnet-Dämon diesen Dienst vollständig selbst übernimmt oder einen Teil des Dienst, nämlich die Portüberwachung, an den inetd-Dämon übergibt. Das ist eine Frage der Konfiguration des Telnet-Dienstes. Wir befinden uns heute noch in der Situation, in der auch die Systemverwalterin einen grossen Teil der Routinearbeit im Kopf machen muss. Individuelle Verfahren zur Automation bergen nämlich stets die Gefahr, dass Vertreterinnen oder Nachfolgerinnen nicht sofort mit den Verfahren zurechtkommen.

Sie können einen lauffähigen Prototyp der Objekte unter der URL ftp://ftp.guug.de/pub/members/truemper/shobj/ finden. Die Datei shobj.txt enthält eine kurze Installationsanleitung und eine Beschreibung der Objekte von einem anderen Standpunkt aus. Falls Sie sich für die Diskussion über die Objekte interessieren, können Sie unter http://www.guug.de/lists/ die Mailingliste shobj@guug.de abonieren.

Abschliessend erwähnt sei noch das Buch "Unix Shell Objects" von C. Jones. In diesem Buch wird die Erweiterung der Korn-Shell um klassen- und objektartige Funktionen beschrieben. Wer das Buch vollständig gelesen hat schreibe doch bitte eine Buchbesprechung für die GUUG-Nachrichten... Soweit ich das Buch verstanden habe, underscheiden sich meine "persistenten Shell-Objekte" von den Jones'chen "Unix Shell-Objekten" in folgenden Punkten:

  1. Der Lebenszyklus eines persistenten Shell-Objekts endet erst, wenn Sie es ausdrücklich zerstören, nicht etwa wenn die aktuelle Shell endet. Daher auch der Name "persistente Shell-Objekte".
  2. Bei persistenten Shell-Objekten sind die Methoden ("member functions") getrennte Anwendungen, die nur über das Objekt zugänglich sind. D.h. die Namen der Methoden sind in einem eigenen Namensraum geschützt.

Zu den Nachteilen der persistenten Shell-Objekten gehört der zum einen die durch ständige fork-Aufrufe verlangsamte Ausführungsgeschwindigkeit. Und natürlich bieten die Objekte nicht den Leistungsumfang von verbreiteten OO-Programmiersprachen wie Java oder C++. Angesichts der regelrechten Überfrachtung dieser Sprachen kann das aber auch als Vorteil angesehen werden.

Ich würde mich freuen, falls jemand die Idee der Objekte aufgreift und durch die Entwicklung einer Klassenbibliothek fortführt. Prozesse, Dateien, Anwender oder Dokumente, diese und viele andere Systemkomponenten liessen sich auch auf der Ebene der Kommandozeile elegant mit Objekten modellieren.

Winfried Trümper Winfried Trümper benutzt kein Windows, so dass er sich an Verdammungen oder Vergleichen nicht beteiligen kann. Stattdessen findet er es produktiver und interessanter, Ideen zur Weiterentwicklung von Unix aufzuzeigen, wobei nichts heilig sein darf. Sie erreichen ihn unter me@wt.xpilot.org.