mini|OpenBSD ksh Die Kornshell (Eigenschreibweise KornShell, auch als ksh, ksh86, ksh88 und ksh93 bezeichnet) ist ein von David Korn entwickelter Kommandozeileninterpreter wie auch die Beschreibung der Skriptsprache, welche durch diesen Interpreter implementiert wird. Ursprünglich für UNIX geschrieben finden sich heute Implementierungen nicht nur für UNIX-ähnliche Systeme, sondern auch für Windows und AmigaOS.

Die Sprachbeschreibung selbst ist gemeinfrei, jedoch nicht jede Implementierung. Der originale Quelltext der ksh93 ist seit 2000 (bzw. 2005, siehe Geschichte) ebenfalls gemeinfrei.

Die KornShell (in der Version von 1988) bildete die Grundlage für die POSIX-Shell-Spezifikation und erfüllt den POSIX2-Standard. Sie ist vollständig abwärtskompatibel mit der Bourne-Shell (sh) und übernimmt viele Neuerungen der C-Shell (csh).

Geschichte Die KornShell – so die durch ihren Autor geprägte Schreibung – wurde Anfang der 1980er Jahre von David Korn bei den Bell Labs der AT&T entwickelt und bei der USENIX-Konferenz am 14. Juli 1983 vorgestellt.David Korn: KSH – A Shell Programming Language. USENIX Conference Proceedings, Toronto, Ont. Summer 1983, S. 191–202. Sie basierte ursprünglich auf einem Formularinterpreter, an dem David Korn mitgearbeitet hatte. Dessen Syntax wurde auf Basis der Bourne Shell konzipiert, unterschied sich von dieser aber durch wesentliche Verbesserungen: Job Control, eine der C Shell nachempfundene Command History und Command Aliasing.

ksh86 Die neue Shell fand bei den Mitarbeitern von AT&T schnell Verbreitung, so dass sie schnell zur dortigen De-facto-Standardshell wurde. Da immer mehr Entwickler, die das Unternehmen verließen, nach der Verfügbarkeit außerhalb AT&Ts fragten, wurde die Shell schließlich als Teil des UNIX System Toolchests gegen Gebühr freigegeben. Die ksh86 war eine der ersten so veröffentlichten Versionen und diente unter anderem als Vorbild für die Shell früher Versionen von QNX.

ksh88 Die Nachfolgeversion ksh88 wurde rasch zum Erfolg und wird heute noch von vielen Anbietern von Unix-Systemen ausgeliefert: HP-UX etwa hat eine eigene Version als Default-Shell, ebenso wird AIX (ab Version 4) mit einer originalen ksh88 als Default-Shell ausgeliefert. Ende der 1980er-Jahre wurde die Spezifikation ksh88 festgelegt, welche die Grundlage für die Beschreibung des Command Interpreters im POSIX-Standard bildete und im Wesentlichen mit dieser identisch ist. Die Rechte an der ksh88 liegen bei AT&T sowie bei Novell.

ksh93 1993 erfolgte eine grundlegende Überarbeitung der Shell wie auch ihrer Skriptsprache. Diese neue Spezifikation (bzw. Implementierungen, die ihr folgen) wird als ksh93 bezeichnet. Einzelne Versionen werden dabei durch angehängte Buchstaben gekennzeichnet, so ist etwa die aktuelle Version ksh93u+, welche der Version ksh93u, ksh93t+ und deren Vorgängerin ksh93t folgte.

Bis zum Jahr 2000 war die KornShell proprietäre Software, die Rechte lagen bei AT&T und Lucent Technologies. 2000 wurde schließlich der Quellcode veröffentlicht, erst unter einer AT&T-eigenen Version einer gemeinfreien Lizenz, ab Version ksh93q (2005) unter der Common Public License.

Die KornShell und ihr Umfeld Unterschiede zu und Gemeinsamkeiten mit anderen Shells Commandline Editing, File Name Completion Eine der wichtigsten Änderungen gegenüber ihrer Vorgängerin, der Bourne-Shell, war die Möglichkeit, die eingegebene Kommandozeile zu wiederholen, beziehungsweise, vor dem erneuten Ausführen zu verändern. Diese Funktion wurde aus der C Shell Bill Joys übernommen, aber gegenüber dieser wesentlich ausgebaut; in der ksh standen von Beginn an drei Editiermodi zur Verfügung, die alle das Verhalten gängiger Editoren nachahmten: vi, Emacs und XEmacs.

Ebenfalls neu war die Möglichkeit, Dateinamen automatisch vervollständigen oder sich zu einem unvollständig eingegebenen Dateinamen während der Kommandoeingabe eine Liste aller passenden Dateien anzeigen zu lassen.

Mit der ksh93 wurde zusätzlich zur File Name Completion auch die Command Completion, also die Vervollständigung unvollständig angegebener, ausführbarer Dateien, eingeführt. Diese Funktion ist mit jener der bash identisch.

Behandlung von Pipelines Im Gegensatz zur bash werden Pipelines in der ksh nicht automatisch in Subshells ausgeführt. Das hat gravierende Konsequenzen für den Gültigkeitsbereich von Variablen:

#!/usr/bin/ksh

typeset -i linenum=0 typeset line="" cat /path/to/input | while read line ; do (( linenum += 1 )) done echo $linenum

exit 0

In bash würde die letzte Zeile 0 ausgeben, weil die while..done-Schleife als Bestandteil einer Pipeline in einer Subshell ausgeführt wird und $linenum deshalb nur in dieser Subshell inkrementiert wird. In einer KornShell hingegen wird die Anzahl der Zeilen in der Datei ausgegeben. Viele Nachbauten (etwa pdksh) realisieren dieses Verhalten allerdings nicht, sondern verhalten sich in dieser Hinsicht wie bash.

FPATH-Variable Seit ihren ersten Versionen verfügt die ksh über die Systemvariable FPATH, die einen Standard-Suchpfad für Dateien, welche Shell-Funktionen enthalten, definiert, analog der Variablen PATH für ausführbare Dateien. Dies ermöglicht den Aufbau von Funktionsbibliotheken, die sich ähnlich wie Shared Libraries verhalten. Dies ist ein großer Vorteil gegenüber anderen Shells, insbesondere bash, die alle zu verwendenden Funktionen bei Skriptstart einparsen muss.

Floating-Point-Unterstützung Die ksh93 verfügt zusätzlich zur gewöhnlichen Integer-Arithmetik auch über den Datentyp Floating-Point und die zugehörigen Methoden zur Bearbeitung solcher Daten.

Coprocess-Facility Eine unter den verbreiteten Shells einzigartige Funktion ist die Fähigkeit, sowohl der ksh88 wie auch ksh93, Hintergrundprozesse asynchron abzuarbeiten und dennoch über Nachrichten zu steuern – das sogenannte Coprocess Facility. Dabei wird ein Prozess zwar im Hintergrund asynchron abgearbeitet, bleibt aber mit dem Vaterprozess über zwei Datenkanäle (ausgeführt als File-Deskriptoren 4 und 5) verbunden und kann über diesen bidirektionalen Kanal gesteuert werden.

Varianten Nicht zuletzt wegen der ursprünglich lizenzbelasteten Situation wurden im Laufe der Zeit verschiedene Implementierungen der Korn Shell geschrieben, die mehr oder weniger kompatibel zur originalen Shell waren bzw. sind.

dtksh dtksh (Desktop ksh) ist eine Version der ksh93 zur Programmierung graphischer Oberflächen unter X11. Diese Version erweitert die ursprüngliche Skriptsprache um Anbindungen zum Common Desktop Environment bzw. Motif, X, Xt und tcl.

pdksh / mksh / oksh pdksh ist eine gemeinfreie Implementierung der Korn Shell, die allerdings in einigen Punkten wenig Kompatibilität aufweist (etwa werden Pipelines analog der bash und im Gegensatz zu allen ksh-Versionen in Subshells ausgeführt). Es werden die meisten Merkmale der ksh88 und einige wenige der ksh93 unterstützt. Zusätzlich bringt sie einige eigene Erweiterungen mit.

mksh ist ein pdksh-Derivat, bei dem auf einfachere Bedienbarkeit und schlanken, aber korrekten Code Wert gelegt wird. Dabei werden auch Verbesserungen von Projekten wie Debian und OpenBSD eingepflegt. Im Gegensatz zur OpenBSD-ksh ist mksh portabel und steht für verschiedene Plattformen zur Verfügung. Das Programm enthält auch viele Erweiterungen und Detailverbesserungen (zum Beispiel unbegrenzt große Arrays oder ~/.mkshrc-Unterstützung), verzichtet jedoch bewusst auf den Code aufblähende Funktionalitäten wie eine bash-artige $PS1-Syntax; auch ist es nicht als Ersatz für /bin/sh gedacht. mksh wird vom MirOS-Projekt gewartet.

oksh ist eine Linux-Portierung der OpenBSD-Variante der Korn Shell, wobei im OpenBSD-Code nur so viel Änderungen wie nötig eingepflegt werden, um ihn unter Linux kompilierbar zu machen. Diese Variante wird als Standard-Shell /bin/sh unter DeLi Linux eingesetzt.

Portierungen auf AmigaOS und Microsoft Windows SKsh ist eine Version für AmigaOS, die eine Anzahl Amiga-spezifischer Merkmale wie beispielsweise ARexx-Interoperabilität bietet.aminet.net In dieser Tradition ist die Kornshell Standard im Software Development Kit für MorphOS.

Die MKS Korn Shell ist eine weitere kommerzielle Korn Shell-Implementierung. Sie ist Bestandteil von Microsofts Windows Services for UNIX (SFU) sowie dem Subsystem für UNIX-basierte Anwendungen (SUA) der Windows Vista Enterprise und Ultimate Editionen. Dass sie erhebliche Mängel in der Kompatibilität aufweist, wurde auf einer USENIX-Konferenz drastisch festgestellt. Die sich darum rankende Anekdote (hier wiedergegeben in den Worten David Korns) ging in die Geschichte ein:

Einführung in die Scriptsprache KornShell Die KornShell war von Beginn an, insbesondere aber die ksh93, in erster Linie als Script-Interpreter und erst in zweiter Linie als interaktive Shell gedacht. Die folgende Einführung geht auf die Unterschiede zwischen ksh88 und ksh93 nur am Rande ein, sondern versucht, die Eigentümlichkeiten der Programmiersprache KornShell überhaupt herauszuarbeiten.

Kommentare Die KornShell kennt nur eine Form von Kommentar: ab dem Rautezeichen gilt alles bis zum Ende der Zeile als Kommentar, was dem // in C++ entspricht. Zeilenübergreifende Kommentare gibt es nicht.

Eine besondere Form von Kommentar ist der Shebang, der das ausführende Programm festlegt, aber dies ist eine Leistung des Kernels. Für die Shell ist dies ein Kommentar wie jeder andere auch. Soll das Rautezeichen als Literal verwendet werden, so muss es in Anführungszeichen eingeschlossen oder escapet (durch ein vorangehendes Backslash-Zeichen '\' seiner besonderen Funktion entkleidet) werden.

#!/usr/bin/ksh

# Dies ist ein Kommentar print - "Hello World." # Kommentar: führe print-Statement aus print - "#" # Doppelkreuz in Anführungszeichen wird als Zeichen interpretiert print - \# # escapetes Doppelkreuz

exit 0

Positionale und benannte Variablen, Here-Documents Variablen werden in der KornShell wie schon in der Bourne-Shell durch ein Dollarzeichen ('$') und einen in geschweifte Klammern eingeschlossenen Bezeichner angesprochen (die geschweiften Klammern können in manchen Fällen auch weggelassen werden). Bei der Zuweisung allerdings wird lediglich der Bezeichner verwendet.

#!/usr/bin/ksh

typeset variable="Hello World." # Zuweisung print - ${variable} # Verwendung der Variablen print - $variable # Verwendung, alternative Form

exit 0

Benannte Variablen entsprechen dem, was in anderen Hochsprachen als Variablen bezeichnet wird: ein Bezeichner, der einen Speicherplatz referenziert, in welchem ein Wert abgelegt sein kann. Die KornShell erfordert dabei – zum Unterschied von anderen Hochsprachen – keine formale Deklaration und verlangt auch keine explizite Typisierung. Gleichwohl kann – und soll(!), schon im Sinne der Lesbarkeit und Dokumentation – mittels des Schlüsselwortes typeset eine Deklaration samt Datentyp erfolgen, insbesondere dann, wenn dieser von String abweicht. Als Datentypen stehen zur Verfügung:

String Integer Float (nur ksh93) Compound (nur ksh93) Array

Darüber hinaus kann jede Variable, unabhängig vom Typ, als String verwendet werden. Diese Variablen zeichnen sich dadurch aus, dass sie Namen tragen, weshalb sie benannte Variablen genannt werden.

Daneben gibt es unbenannte, sogenannte positionale Variablen, die automatisch im Falle von Scripten mit den übergebenen Kommandozeilen-Parametern, im Falle von Shell-Funktionen mit den übergebenen Argumenten gefüllt werden. Sie werden mit Zahlen bezeichnet (${0}, ${1}, ${2} usw.), wobei ${0} immer den Namen des Programms bzw. der Funktion enthält.

Mit Ausnahme von $0 können positionale Variablen mit dem Keyword shift abgearbeitet werden. shift löscht den Inhalt der Variablen $1 und belegt dann $1 mit dem Wert von $2, $2 mit dem Wert von $3 .. $n-1 mit dem Wert von $n:

#!/usr/bin/ksh

print - "Name des Scripts............: ${0}" print - "Erstes übergebenes Argument : ${1}" print - "Zweites übergebenes Argument: $2" # alternativ auch ohne Klammern