Vorlesung "UNIX"

von Prof. Jürgen Plate

3. Einige Kommandos

In diesem Kapitel wird eine Reihe wichtiger UNIX-Kommandos besprochen. Wie so oft, liegt hier der Nutzen in der Beschränkung. Weitere Kommandos kann sich nach Kenntnis des "Grundwortschatzes" jeder selbst aneignen. Es gibt für fast jeden Zweck schon passende UNIX-Kommandos. Denken Sie daran, bevor Sie anfangen selbst etwas zu programmieren. Es werden hier auch nicht alle Kommandos aus der Vorlesung beschrieben. Zunächst aber ein etwas "seltsames" Kommando.

:(Doppelpunkt)
Der Doppelpunkt ist das leere Kommando der Unix-Shell. Es liefert immer "true" zurück und hat keine Wirkung. Es werden jedoch alle Shell-Ersetzungen der nach dem Doppelpunkt angegebenen Kommandos durchgeführt. Es eignet sich daher auch zum Testen von Shell-Skripts.

3.1 Kommandos zur Steuerung der Zugriffsberechtigung

Die Zgriffsberechtigungen wurde in Kapitel 1 besprochen; hier nun die Kommandos zum Setzen und Rücksetzen der Schutzbits. Die Bits UID und GID nehmen übrigens eine Sonderstellung ein - sobald eine Datei an einen anderen Benutzer übertragen wird, werden sie zur Sicherheit automatisch gelöscht. Bei den folgenden Kommandos erfolgen die Eingaben oktal (d. h. zur Basis 8). Das ist deshalb sinnvoll, weil es jeweils 3 Schutzbits für jede Benutzerklasse (Eigentümer, Gruppe, Andere) gibt, die sich zu einer Oktalstelle zusammenfassen lassen.

chmod Modus Dateiliste

Kommando zum Einstellen der Zugriffsrechte einer Datei, wobei zwei Modi existieren, symbolisch oder direkt.

Symbolischer Modus: = Bereich Operand Berechtigung

Bereich u   Eigentümer (user)
g   Gruppe (group)
o   Übrige Benutzer (others)
keine Angabe = ugo
Operand +   Recht hinzufügen
-   Recht wegnehmen
=   Recht absolut setzen
Berechtigung r   Read
w   Write
x   eXecute
s   UID/GID (je nachdem, ob u+s oder g+s)
t   Sticky Bit (ohne Angabe von ugo)

Beispiele:

chmod +xAusführungsrecht für alle hinzufügen
chmod go-w dat2Schreibrecht nur noch für User
chmod g+rwx dat3Volle Rechte für Gruppe
chmod ugo-rwx dat4Allen alle Rechte entziehen
chmod +t verz1Sticky-Bit von verz1 setzen
chmod u+s admintoolSUID-Bit setzen

Direktmodus: Modus = Oktalzahl (3 - 4 Stellen)
Für user, group und others wird jeweils eine Oktalzahl angegeben, welche die jeweiligen Rechte wiedergibt. Dabei gilt folgende Wertigkeit:

read4
write2
execute1

Falls die Zugriffsrechte SUID (4), SGID (2) und STICKY (1) vergeben werden sollen, kommt vorne noch eine vierte Stelle hinzu. Die Anwendung dieses Modus zeigen die folgenden Beispiele:

 UserGroupOthers
chmod 754 dat1 rwxr-x r--
chmod 740 dat2rwx r-- ---
chmod 440 wichtig r--r-- ---
chmod 000 geheim --- --- ---
chmod 4711 systoolrws--x --x

umask Modus

Dieses Kommando vereinbart eine Standardeinstellung der Dateirechte für alle Dateien, die nach Aufruf von umask erzeugt werden - man braucht also nicht jedesmal des chmod-Kommando aufrufen, wenn einen Datei kreiert wurde. Auf bestehende Dateien hat das Kommando keinen Einfluß. Bedauerlicherweise ist der dreistellige Zahlenwert (für User, Group und Others) genau das Komplement der Angabe von chmod, d. h. hier wird festgelegt, welches Bit nicht gesetzt werden soll (für den Anfänger eine Pest!). Stellen Sie sich einfach vor, sie ziehen den Wert des umask-Modus vom Maximalwert 777 ab. Sie erhalten dann die Zugriffsrechte. Beispiele:

umask 022   7 7 7
- 0 2 2
= 7 5 5
rwx r-x r-x
umask 027   7 7 7
- 0 2 7
= 7 5 0
rwx r-x ---
umask 177   7 7 7
- 0 7 7
= 6 0 0
rwx --- ---

chown Username Dateiliste

Übertragen einer Datei an einen anderen Benutzer. Der Benutzer wird vollständiger Eigentümer der Datei. Der alte Eigentümer verliert sie. Beispiel:

chown markus dat1

Datei dat1 wird an markus übertragen

chgrp Gruppe Dateiliste

Ändern der Gruppenzugehörigkeit einer Datei. Es kann entweder die Gruppennummer oder der Gruppenname angegeben werden.

3.2 Dateidienste

cat[-usvte] datei [datei]

(concatenate) Lesen der angegebenen Dateien und Kopieren auf die Standardausgabe. Zusammenkopieren mehrerer Dateien oder Ansehen der Dateien. Optionen:

-e $-Zeichen am Ende der Zeile ausgeben
-s (silent) Keine Fehlermeldung bei nicht existierenden Dateien
-t Tabulatoren als "^I" ausgeben
-v Nicht druckbare Zeichen als "^Z" ausgeben, wobei Z der ASCII-Wert des Zeichens + 64 ist (SOH = ^A, usw.)
-u ungepufferte Ausgabe

Beispiele:

cat dat1gibt dat1 auf dem Bildschirm aus
cat dat1 dat2 > dat3 kopiert dat1+dat2 auf dat3

cd [directory]

(change directory) Wechsel des Arbietsverzeichnisses. cd ohne Parameter wechselt ins Home-Directory.

cp dat1 [dat2 ... datx] directory

(copy) Kopiert eine oder mehrere Dateien in das angegebene Directory. Existiert die Datei schon im Zieldirectory, wird sie überschrieben. Existiert sie noch nicht, wird sie neu angelegt. Dateien, die mit einem Punkt beginnen, müssen explizit angegeben werden ("cp * ziel" kopiert nur diejenigen Dateien, die nicht mit einem Punkt beginnen; "cp .* ziel" kopiert alle Dateien).

ln [-fs] dat.alt dat.neu

(link) Trägt für eine bereits existierende Datei "dat.alt" ein (Hard-)Link unter dem Namen "dat.neu" ein. Die Datei ist physikalisch nur einmal vorhanden, aber unter zwei Namen ansprechbar. Beim Dateinamen wind der Link-Count auf 2 gesetzt. Beide Directoryeinträge müssen auf dem gleichen Datenträger (= Dateisystem) liegen Dateien mit mehreren Links werden erst beim Löschen des letzten Links physikalisch gelöscht. Optionen:

-f verhindert eine Nachfrage des Kommandos, falls die Datei schreibgeschützt ist.
-s erzeugt ein "Symbolisches Link". Hier wird eine Datei angelegt, die einen Verweis auf ihr Link enthält (Dateityp 'l'). Solche Links werden hauptsächlich für Verzeichnisse verwendet, sie wirken auch über die Grenzen von Dateisystemen hinweg.

Beispiele:
ln /usr/bin/ls /home/meier/bin/dir
ln -s /home/local /usr/local

mkdir Dirname

(make directory) Anlegen eines neuen Verzeichnisses, sofern der Schreibschutz des übergeordneten Verzeichnisses dies zuläßt. Voreinstellung für das Zugriffsrecht ist (umask) 755. Die Standardeinträge "." und ".." werden automatisch erzeugt. Die Zugriffsrechte lassen sich mit chmod ändern.

more

Wie cat eine weitere Möglichkeit zum Ansehen von Dateien. Jedoch stoppt hier die Ausgabe nach einer Bildschirmseite. Durch Tastendruck kann weitergeblättert oder abgebrochen werden. Außerdem kann auch im Text gesucht werden: Die Daten werden entwider über die Standardeingabe gelesen oder aus (einer) Datei(en), die als Parameter angegeben wird.

less

Wie more, jedoch erweiterter Befehlssatz und man kann auch bei Pipes zurückblättern. Siehe man-pages.

mv [-f] dat.alt dat.neu

(move) Umbenennen einer Datei unter Einbeziehung des gesamten Dateibaums. D. h. neben reiner Namensänderung auch ein Verschieben in ein anderes Verzeichnis möglich (Änderung der Verzeichniseinträge, kein Kopieren). Ist die Datei "dat.neu" bereits vorhanden, wird sie überschrieben. Liegt die Datei auf einen anderen Datenträger, wird sie physikalisch kopiert und an der alten Stelle gelöscht. Die Option -f unterdrückt eine Rückfrage bei Schreibschutz für dat.neu.

rm [-fri] Dateiliste

(remove) Löschen von Dateien und Verzeichnissen. Die angegebenen Dateien werden gelöscht. Optionen:
-i interaktiv: vor dem Löschen wird nachgefragt, ob die Datei gelöscht werden soll. Antwort "y" oder "n".
-f Löschen ohne Nachfrage bei schreibgeschützten Dateien
-r rekursives Löschen; es werden auch alle Dateien in daruterliegenden Verzeichnissen gelöscht (Diese Option ist gefährlich, wenn man nicht aufpasst!).

rmdir directory

Löschen eines leeren Verzeichnisses

3.3 Steuerung des Druckers

lp [-cdmnws] Dateiliste

Line Printer Spooler bei System V
Die angegebenen Dateien werden in die Druckerwarteschlange übergeben und dann vom Druckerspooler auf dem Drucker ausgegeben. Wird keine Datei angegeben liest lp von der Standardeingabe. Dem Druckauftrag wird eine eindeutige Auftragsnummer zugeteilt unter der er später angesprochen werden kann (siehe lpstat, cancel).
In der Regel wird nur ein Link auf die Datei(en) gesetzt. Will man sofort nach dem Aufruf von lp die Datei(en) ändern, muß eine Kopie erzeugt werden (siehe -c). Optionen:

-cEs wird eine Kopie im lp-Verzeichnis angelegt (kein Link)
-n#Es werden # Kopien ausgedruckt (z.B. -n4 für 4 Kopien) -w Nach Beendigung des Druckauftrags wird eine Meldung ans Terminal geschickt (wie bei write). Hat sich der Benutzer abgemeldet, erfolgt die Meldung per mail-Kommando.
>-ww Nach Beendigung des Druckauftrags wird eine Meldung ans Terminal geschickt (wie bei write). Hat sich der Benutzer abgemeldet, erfolgt die Meldung per mail-Kommando.
-mNach Beendigung des Druckauftrags Benachrichtigung des Benutzer per mail-Kommando.
-sDie Ausgabe der Auftragsnummer durch lp wird unterdrückt.
-d DRUCKERExplizite Angabe eines Druckers DRUCKER, falls sich mehrere Drucker im System befinden.

Beispiel: Ausgabe der Dateien vorles.kap1 und vorles.kap2 auf dem Drucker, Da die Datei weiter bearbeitet werden soll, wird eine Kopie erzeugt. Die Nachricht über Druckende soll per mail erfolgen:

lp -cm vorles.kap1 vorles.kap2

lpstat [-acdoprstuv] [Auftragsnummer]

(Line Printer Status) Gibt den Status der mit lp abgesetzten Druckaufträge aus. Fehlt die Auftragsnummer, wird der Status aller Druckaufträge des Benutzers ausgegeben. Bei den Optionen a, c, o, p, u und v kann anschließend an die Option eine Liste von Druckern oder Druckerklassen angehängt werden. Die Information erfolgt dann nur zu den angegebenen Geräten. Fehlt die Liste, wird die Statusinformation zu allen Druckern ausgegeben. Optionen siehe man-pages. Beispiel: lpstat -u gibt den Status aller Durckaufträge des Benutzers aus.

cancel [Auftragsnummer(n)] [Druckername(n)]

Abbrechen eines mit lp gestartete Druckauftrags. Angabe von entweder Auftragsnummer(n) oder Druckername(n). Wird ein Druckername angegeben, wird der gerade auf diesem Drucker bearbeitete Auftrag abgebrochen. Werden Auftragsnummern angegeben, können auch Aufträge aus der Warteschlange gelöscht werden.

disable Druckername

Stoppen des angegebenen Druckers (z. B. um Papier nachzulegen).

enable Druckername

Erneuter Start des Druckers.

lpr Dateiliste BSD-Style Printer Spooler. Analog zu dem lp-Programm unter System V gibt es bei BSD das Programm lpr, um Dateien über den Spooler auszudrucken. Ohne weitere Optionen wird die Datei wieder zum Standarddrucker geschickt, z. B. : lpr text
Möchte man explizit angeben, auf welchem Drucker der Ausdruck erfolgen soll, verwendet man bei BSD die Option - P. Auch hier folgt direkt hinter dem "P" der Druckername, z. B.: lpr -Plaserjet3 text
Auch unter BSD gibt es meist das Programm lpstat, um sich mit der Option -s die angeschlossenen Drucker anzeigen zu lassen. Falls das nicht geht, kann man sich die Datei /etc/printcap mit more anschauen. In dieser Datei sind alle angeschlossenen Drucker mit allen für den Drucker-Spooler wichtigen Einstellungen eingetragen. Abgesehen von den Namen, unter denen ein Drucker ansprechbar sein soll, und der Zuordnung zu einer bestimmten Schnittstelle, d. h. also einer Gerätedatei /dev/lp?, können hier auch Filterprogramme und Optionen für den Ausdruck angegeben werden. Die Einstellungen kann allerdings nur der Systemverwalter ändern.
Das mehrmalige Ausdrucken einer Datei erreicht man mit -# gefolgt von der Zahl der gewünschten Kopien. Wenn das UNIX-System nach erfolgtem Ausdruck eine entsprechende Bestätigung als Mail schicken soll, steht dafür die Option -m zur Verfügung.
Anders als bei System V kopiert das lpr-Programm unter BSD standardmäßig die auszudruckenden Dateien immer automatisch in den Pufferbereich des Drucker-Spoolers. Sollen nur Verweise angelegt werden, muß man die Option -s bei lpr angeben. Das ist vor allem dann sinnvoll, wenn eine Druckdatei sehr groß ist.

lprm

Druckaufträge wieder löschen. Es erwartet als Parameter die Kennummer des Druckauftrags, der gelöscht werden soll. Leider gibt lpr beim Aufruf nicht die Kennummer aus. Dazu muß man zunächst mit lpq nachschauen, welche Aufträge in der Warteschlange stehen.

lpq

Druckerwarteschlange auflisten. Zum Beispiel: lpq -Plaserjet3. Die Ausgabe sieht dann etwa so aus:
laserjet3 is ready and printing
Rank     Owner     Job    Files                               Total Size
active   markus    3      bericht.ps                          41984 bytes
lst      plate     17     brief                               3213 bytes
Mit der Option - Plaserjet3 wird im Beispiel die Ausgabe von lpq auf den Laserdrucker eingeschränkt.

3.4 Informationsdienste

Einige Informationsdienste sind schon bekannt: who, ls, man, tty. Hier folgen einige weitere Kommandos, die den Benutzer mit Informationen versorgen:

date [mmddhhmm[yy]] [+format]

Beim Aufruf ohne Parameter werden Datum und Uhrzeit ausgegeben. Der Superuser kann mit diesem Kommando die Werte auch neu eingeben:

date mmddhhmmyy (Monat, Tag, Stunde, Minute, Jahr)
z. B.: date 10091245 (9.10., 12 Uhr 45)

Über den Parameter +format ("+"-Zeichen beachten!) kann die Ausgabe nach eigenen Wünschen gestaltet werden. Die Ausgabeformatierung erfolgt gemäß den Konventionen der Programmiersprache C (printf). Als Parameter werden verwendet:

%m: Monat (1 - 12) %D: Datum im Format mm/dd/yy
%d: Tag (1 - 31) %H: Stunde
%y: Jahr (00 - 99) %M: Minute
%n: neue Zeile %S: Sekunde
%w: Wochentag (0-6) %T: Zeit im Format HH:MM:SS
%a: Wochentag (Sun-Sat) %h: Monat (Jan-Dec)

Beispiel: Datum und Uhrzeit zweizeilig:

date '+Datum: %w, %d.%m.%y%nUhrzeit: %T'

Erstellungs- und Zugriffszeit/Datum von Dateien werden intern in Sekunden ab dem Offiziellen Geburtstag von UNIX, dem 1.1.1970, 0 Uhr UTC, gespeichert. Vor einiger Zeit habe ich mal das UNIX-Verfallsdatum ausgerechnet:
Auf 32-bit-Systemen wird time_t genau 2038-01-19 03:14:08 UTC ueberlaufen, d. h. dieses Datum hat die gleiche Darstellung wie 1970-01-01 00:00:00 UTC = (time_t) 0.

touch [-em] [mmddhhmm[yy]] Dateiliste

Setzt Datum und Uhrzeit der Datei. Parameter -m setzt die "modification time" (Voreinstellung), -a die "access time". Wird keine Zeit angegeben, nimmt touch die aktuelle Zeit (mmddhhmmyy = Monat, Tag, Stunde, Minute, Jahr).

df [-tfk] [Dateisystem] (Disk Free)

Liefert die Anzahl freie Blöcke und freier i-nodes des angegebenen Datenträgers. Fehlt die Angabe des Datenträgers, wird der aktuelle Datenträger verwendet. Optionen:

-t Gesamtkapazität wird mit angegeben
-f Die Angabe über i-nodes entfällt
-k Angabe in KByte statt in Blöcken

df /dev/dsk/0s1Daten über einen bestimmte Platte
df -f /usrfreie Blöcke des Dateisystems, das unter /usr eingehängt ist.

du [-arsk] [Dateiname]

(Disk Usage) Liefert die Anzahl der belegten Blöcke von Dateien und Verzeichnissen (fehlt der Dateiname, wird das aktuelle Directory untersucht). Bei Verzeichnissen werden die Blöcke der darin enthaltenen Dateien aufsummiert. Bei Link-Dateien wird nur der i-node gezählt. Es werden auch die indirekten Blöcke gezählt. Optionen:

-a (Voreinstellung) Daten für jede Datei ausgeben
-r Dateien melden, für die kein Leserecht existiert
-s Nur die Summe der belegten Blöcke ausgeben
-k Angabe in KByte statt in Blöcken

du -a dat1 Größe der Datei dat1 ausgeben
du -s /bin Summe der belegten Blöcke im Verzeichnis /bin
du -s /usr/* ausprobieren

file [-c] [-f Dateiname] [-m Dateiname] [Dateinamen]

(Determine File Type) Überprüfung der angegebenen Dateien auf ihren Inhalt (C-Programm, ASCII-Datei, ausführbares Programm, etc.). Um den Inhalt der Datei zu analysieren, verwendet das file-Kommando die Datei /etc/magic, in der Angaben über die Dateieigenschaften stehen (welche Bytes zu analysieren sind). Optionen:

-f Dateiname Die zu durchsuchenden Dateinamen stehen nicht in der Kommandozeile, sondern in der angegebenen Datei.
-m Dateiname Die Unterscheidungskriterieen stehen nicht in /etc/magic, sondern in der angegebenen Datei.

find Pfadname(n) Bedingung(en) Aktion(en)

(Find Files) Durchsuchen der Platte nach bestimmten Dateien. Dieses Kommando ist sehr mächtig und besitzt zahlreichen Optionen, welche die Bedingungen für die Dateiauswahl (= Treffer) festlegen. Die angegebenen Pfade werden rekursiv durchsucht, d.h. auch Unterverzeichnisse und Unter-Unterverzeichnisse, usw. Aufrufschema:

find Pfadname(n) Bedingung(en) Aktion(en)

Bei den nachfolgenden Optionen (= Bedingungen) steht das N für eine Zahlenangabe (ganze Zahl). Das Vorzeichen dieser Zahl bestimmt die Bedingung:

Bedingungen

Aktionen

(auch hier nur die wichtigsten):

Beispiele:

ps [adeflnptu] (Report Process Status)

Liefert Statusinformationen über die aktiven Prozesse. Ohne Angabe von Optionen wird Information zu den Prozessen ausgegeben, die vom jeweiligen Terminal aus gestartet wurden. Zu jedem Prozeß wird eine Zeile ausgegeben, die Prozeßnummer, Terminalname, verbrauchte Rechenzeit und das Kommado angibt. Für den Alltag reichen zwei Optionen:
-e Informationen über alle laufenden Prozesse ausgeben
-f Vollständige Informationen über die Prozesse ausgeben.

Beispiel: ps -efIn jeder Zeile werden folgende Informationen ausgegeben:

Anmerkung: Bei Linux erreicht man Ähnliches mit ps aux (schlimmstenfalls muss man "man ps" eingeben).

3.5 Die Kommandos stty und tput

UNIX arbeitet terminalorientiert, d. h. der Benutzer sitzt an einen wie auch immer ausgestatteten Text-Terminal. Auch der PC-Bildschirm bei Linux ist ein solches Text-Terminal. Ebenso ist ein "xterm" auf dem Grafikbildschirm nichts anderes als ein emuliertes Text-Terminal. Sobald Kontakt zu einem Terminal hergestellt ist, greift die Terminalsteuerung auf zwei Dateien zurück: /etc/ttydefs oder /etc/gettydefs, in der hauptsächlich Steuerungswerte für die Datenübertragung gespeichert sind (z. B. Baudrate, Datenformat, Handshake, etc.). Das ist natürlich nur noch dann interessant, wenn das Terminal über eine serielle Schnittstelle oder per Modem angeschlossen ist. Bei den Pseudo-Terminals, die über das Netz mit dem UMIX-Rechner verbunden sind, spielen die Inhalte der Dateien nur noch eine untergeordnete Rolle (z. B. bei der Definition einiger Steuertasten wie Backspace).

Beim Programmieren keimt recht schnell der Wunsch auf, den Bildschirm anzusteuern, z. B. den Bildschirm zu löschen, den Cursor zu positionieren etc. Es existieren verschiedene Möglichkeiten, dies zu realisieren. In den frühen Jahre von UNIX gab es zahlreiche Anbiter von Bildschirmterminals und jeds dieser Terminals wurde mit anderen Kombinationen von ASCII-Zeichen angesteuert. Selbst unter MS-DOS wurde diese Tradition noch gepflegt - in Form des ANSI-Treibers.

Welche Möglichkeiten der Bildschirmansteuerung gibt es? Ein Terminal reagiert normalerweise auf Zeichenfolgen, die vom Programm aus geschickt werden. Normale Zeichen werden als Buchstaben dargestellt, bestimmte Sonder- zeichen oder Kombinationen bewirken aber bestimmte Funktionen. Da diese Kombinationen meist bestimmte Sonderzeichen enthalten (z.B. ESCAPE), um sie von Text zu unterscheiden, werden die Steuerfolgen auch Escape-Sequenzen genannt. Wenn man nun z. B. den Bildschirm löschen möchte, dann sucht man sich im Manual des Terminals die entsprechende Sequenz für "Bildschirm löschen" heraus und schickt sie vom Programm aus an das Terminal. Weil es auch nichtdruckbare Zeichen sein können, kann es sein, daß man ihre oktale oder sedezimale Verschlüsselung angeben muß. Dazu ein Beispiel:

Bei einem VT100-Terminal ist die Sequenz für "Bildschirm löschen" die Zeichenfolge

[;H[2J

Man schickt das beispielsweise aus einem C-Programm heraus mit printf("\033[;H\033[2J") ans Terminal. Dabei ist "\033" die oktale Schreibweise für das Escape-Zeichen.

Bei bildschirmorientierten Programmen wie z. B. einem Editor muß es möglich sein, den Cursor auf dem Bildschirm frei hin und her bewegen zu können. Das geht nicht ohne weiteres, weil die Terminals dafür spezielle Steuercodes, meist ESC gefolgt von einer bestimmten Zeichenkette, erwarten. Auch Fett- oder Kursivschrift lassen sich oft über solche Steuersequenzen ein- bzw. ausschalten. Andere Funktionen sind z. B. das Löschen des gesamten Bildschirms oder bis zum Ende der Zeile. Leider sind die Steuersequenzen für die einzelnen Funktionen nicht einheitlich. Auch haben die vielen verschieden Terminals unterschiedliche Möglichkeiten.

Deshalb gibt es eine Datenbank, in der, bei BSD-UNIX in der Datei etc/termcap im Textformat und bei System V in kompilierter Form in einer Reihe von Dateien unter dem Verzeichnis /usr/lib/terminfo, die Steuersequenzen zur Bildschirmansteuerung bei verschiedenen Terminaltypen gespeichert sind. Die Termcap und Terminfo-Datenbanken sind im wesentlichen äquivalent zueinander. Der Vorteil der Termcap-Variante ist die leichte Lesbarkeit und ─nderbarkeit. Dafür kann auf die kompilierte Terminfo-Datenbank schneller zugegriffen werden.

Termcap

Je nachdem mit welchem Terminal man nun gerade arbeitet, sucht sich das UNIX-System die richtigen Steuersequenzen für dieses Terminal aus der Datenbank, wenn ein Anwendungsprogramm Funktionen wie "Bildschirm löschen" oder "Cursor nach oben" aufruft. Auf diese Art sind auch bildschirmorientierte Programme ohne Veränderung mit praktisch jedem Terminal einsatzfähig, vorausgesetzt natürlich, daß ein Termcap/Terminfo-Eintrag für das Terminal existiert. Im allgemeinen sollte das für alle gängigen Terminaltypen der Fall sein. Falls der Eintrag für ein verwendetes Terminal fehlt, können die Datenbanken auch um eigene Einträge ergänzt werden.

Der Termcap-Eintrag für das oft verwendete VT100-Terminal von DEC sieht z. B. folgendermaßen aus:

vtlO0|vt100-am|vt100am|dec vt100:\ 
     :do=^J:co#80:]i#24:c1=50\1[;H\E[2J:sf=5\ED:\ 
     :le=^H:bs:am:ce5\E[%i%d:%dH:nd=2\EEC:up=2\E[A:\          
     :ce=3\E[K:cd=50\E[J:so=2\E[7m:se=2\E[m:us=2\E[4m:ue=2\E[m:\ 
     :md=2\E[lm:mr=2\E[7m:mb=2\E[5m:me=2\E[m:is=\E[1;24r\E[24;IH:\  
     :rf=/usr/share/lib/tabset/vt100:\ 
     :rs=\E>\E[?31\E[?41\E[?51\E[?7h\E[?8h:ks=\E[?lh\E=:ke=\E[?11\E>:\ 
     :ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:kb=^H:\ 
     :ho=\E[H:kl=\EOP:k2=\EOO:k3=\EOR:k4=\EOS:pt:sr=5\EM:vt#3:xn:\ 
     :sc=\E7:rc=\E8:cs=\E[%i%d;%dr:

In der ersten Zeile stehen die Namen, unter denen dieser Termcap-Eintrag angesprochen werden kann. Danach folgen durch Doppelpunkte getrennt die zur Verfügung stehenden Funktionen und entsprechenden Steuersequenzen. Die Steuercodes, um den Cursor auf den Bildschirm bewegen, findet man beispielsweise in den ersten beiden Zeilen. do = ^J bedeutet, daß der Cursor mit CTRL-J eine Zeile nach unten, und up=2\E[A, daß er mit ESC-[A eine Zeile nach oben bewegt wird. Kombinationen mit der Control-Taste werden also in der Form ^x angegeben, wobei x ein beliebiger Buchstabe sein kann. \E ist die Umschreibung für das Escape-Zeichen. Die Zahl 2 hinter dem Gleichheitszeichen bei der Angabe der Steuersequenz für die Bewegung des Cursors nach oben hat eine besondere Bedeutung. Grundsätzlich kann bei jeder Funktion an dieser Stelle eine Wartezeit in Millisekunden angegeben werden, die nach dem Abschicken der Steuersequenz verstreichen muß, bis der UNIX-Rechner weitere Zeichen an das Terminal schicken darf. Das ist notwendig, weil die Terminals für die Verarbeitung eines Steuercodes eine bestimmte Zeit brauchen, in der alle ankommenden Zeichen im - meist sehr kleinen - internen Puffer zwischengespeichert werden müssen, bis die Verarbeitung der Steuersequenz beendet ist. Bei einer schnellen Leitung zwischen Terminal und Computer kann es so zum Verlust von Zeichen kommen, weil der interne Puffer schnell überlaufen würde, wenn das Terminal beispielsweise damit beschäftigt ist, den Bildschirminhalt zu löschen. Dieses Warten nach dem Abschicken einer Steuersequenz an das Terminal nennt man englisch Padding.

Andere Angaben in dem Termcap-Eintrag sind die Zeilen- und Spaltenzahl des Terminals in der zweiten Zeile mit den Kürzeln co#80 bzw. li#24. Sollte man tatsächlich einmal in die Verlegenheit kommen, einen Termcap-Eintrag verändern oder gar neu schreiben zu müssen, findet man weitere Informationen in den man-pages oder in weiterführender Literatur.

Auch in Programmen werden symbolische Bezeichnungen für die Terminalfunktionen verwendet, die in den entsprechenden Headerdateien der C-Bibliothek festgelegt sind. Zur Änderung der Werte in ttydefs/gettydefs dient das Kommando stty, zur Steuerung der Ausgabe kann das Kommando tput verwendet werden.

Terminfo

Mittlerweile gibt es einen Nachfolger für Termcap, die sogenannte Terminfo-Datenbank. Sie ist ziemlich ähnlich, nur daß die Datenbank hier nicht im ASCII-Format abgespeichert ist, sondern in einem Binärformat, weil das geht. Im Normalfall haben die meisten verwendeten Unix-Varianten noch beides, termcap und terminfo.

Curses

Mit termcap kann man flexible Programme schreiben, aber es könnte noch einfacher gehen. Deshalb gibt es eine weitere Bibliothek, die auf termcap aufbaut: "curses". Die curses-Bibliothek ermöglicht sämtliche Terminal-E/A-Funktionen. Zusätzliches Ziel von "curses" ist es, den Update des Bildschirms in optimaler Form durchzuführen, also möglichst schnell mit möglichst wenig Zeichen, die geschickt werden müssen.

Curses geht dabei folgendermaßen vor: es gibt einen virtuellen Bildschirm im Hauptspeicher. Ausgaben werden nun zuerst in diesem internen Speicherbereich aufgebaut. Und erst beim Aufruf der Funktion refresh() werden alle seit dem letzten refresh() angefallenen Aenderungen an den realen Bildschirm geschickt. Zusätzlich ist es möglich, den Bildschirm in Bereiche (Windows, hat aber nichts mit X Windows zu tun) einzuteilen und diese getrennt zu bearbeiten. Am Anfang gibt es für den gesamten zur Verfügung stehenden Bildschirm das vordefinierte Window stdscr.

Wie sieht ein curses-Programm aus? Hier ein Beispielprogramm, das in der Mitte des Bildschirms den String "Hello, world!" invers ausgibt.

#include 

int main(void)
  {
  char *text = "Hello, world!";

  initscr();                 /* Curses-Paket initialisieren */
  clear();			         /* Bildschirm löschen */
  move(LINES/2-1,(COLS-strlen(text))/2-1);
                             /* Cursor zur richtigen Position */
                             /* LINES und COLS sind vordefiniert */
  standout();                /* schalte auf Invers */
  printw("%s\n",text);       /* gib den Text aus */
  standend();                /* wieder auf normal */
  refresh();                 /* reale Ausgabe */
  endwin();	                 /* Ende Curses-Nutzung */
  return 0;
  }

Die Verwendung von Bibliotheken wie termcap oder curses hat natürlich Auswirkungen auf die Portabilität des Programms. Schon verschiedene Unix-Systeme haben verschiedene Curses-Bibliotheken.

stty [Optionen]

(set tty) Änderung der Standard-tty-Parameter. Die Einstellungen sind nur solange gültig, wie der Shellprozeß mit dem Terminal verbunden ist. Das Kommando kann alleine oder mit diversen Parametern verwendet werden. stty ohne Parameter gibt die wichtigsten Einstellungen aus; um alle Parameter zu sehen, verwendet man stty -a. Meist kann man die Wirkung der entsprechenden Option durch ein "-"-Zeichen davor umkehren (siehe Beispiel stty -echo). Weitere Info: man stty. Beispiele:

stty erase ^h
Setzen der Backspace-Funktion (in diesem Fall Control-H). Bei direkter Eingabe kann man die entsprechende Taste direkt betätigen (Steuertasten werden als zwei Zeichen "geechot", Backspace z. B. als "^h"). Bei Eingabe in Skripts mit dem vi kann man mit Ctrl-D erreichen, daß das folgende Zeichen unverändert übernommen wird. Manche Shells aktzeptieren auch die Kombination aus zwei Zeichen, "^" + Buchstabe.

stty eb
Einschalten der akustischen Fehleranzeige (error bell).

stty echo stty -echo
Echo auf dem Bildschirm ein- und ausschalten. Bei der folgenden Kommandosequenz wird die Eingabe des Paßworts auf dem Bildschirm nicht wiedergegeben.

echo "Paßwort eingeben: \c"
stty -echo
read PASS
stty echo

tput Parameter

(terminal put) Senden von Steuerbefehlen an das Terminal, wobei die "echte" Steuerinfo der terminfo-Datenbasis entnommen wird. Als Parameter dient der symbolische Name der entsprechenden Steuerfunktion. Je nach Terminaltyp sind sehr viele Steuerfunktionen möglich. Derzeit akzeptiert tput nur einen Parameter, mehrere Steuerbefehle müssen also nacheinander gegeben werden. Die in der Praxis am häufigsten gebrauchten Parameter sind:

belSignalton
blink Text auf Blinken schalten
bold Text heller darstellen (hohe intensität)
clear Bildschirm löschen,Cursor in die linke obere Ecke
crCarriage Return
cup Cursor positionieren. Hinter cup folgen Zeilennummer und Spaltennummer der Cursorposition, z. B. cup 10 40
edBildschirm von Cursorposition bis Ende löschen
elVon Cursorposition bis Zeilenende löschen
home Cursor in linke obere Ecke
ind Schirm nach oben rollen
rev Text aud Inversdarstellung schalten
ri Schirm nach unten rollen rmso Wieder auf normale Zeichendarstellung schalten

Beispiel:

 
    tput bel
    tput bold 
    echo "\nAchtung! Alle Daten werden gelöscht!\n"
    tput rmso

3.6 Weitere Kommandos

xargs Programm [Parameter]

Das xargs-Programm fällt etwas aus dem Rahmen der übrigen in diesem Kapitel behandelten Programme. xargs übergibt alle aus der Standardeingabe gelesenen Daten einem Programm als zusätzliche Argumente. Der Programmaufruf wird einfach als Parameter von xargs angegeben. Ein Beispiel soll die Funktionsweise klarmachen:

$ Is *.txt | xargs echo Textdateien:

Hier erzeugt ls eine Liste aller Dateien mit der Endung .txt im aktuellen Verzeichnis. Das Ergebnis wird über die Pipe an xargs weitergereicht. xargs ruft echo mit den Dateinamen von ls als zusätzliche Parameter auf. Der Output ist dann:

Textdateien: kap1.txt kap2.txt kap3.txt h.txt

Durch Optionen ist es möglich, die Art der Umwandlung der Eingabe in Argumente durch xargs zu beeinflussen. Mit der Option -n <Nummer> wird eingestellt, mit wievielen Parametern das angegebene Programm aufgerufen werden soll. Fehlt der Parameter, nimmt xargs die maximal mögliche Zahl von Parametern. Je nach Anzahl der Parameter ruft xargs das angegebene Programm einmal oder mehrmal auf. Dazu ein Beispiel. Vergleich einer Reihe von Dateien nacheinander mit einer vorgegebenen Datei:

ls *.dat | xargs -n1 cmp compare Muster

Die Vergleichsdatei "Muster" wird der Reihe nach mitels cmp mit allen Dateien verglichen, die auf ".dat" enden. Die Option -n1 veranlaßt xargs, je Aufruf immer nur einen Dateinamen als zusätzliches Argument bei cmp anzufügen.
Mit der Option - i <Zeichen> ist es möglich, an einer beliebigen Stelle im Programmaufruf, auch mehrmals, anzugeben, wo die eingelesenen Argumente einzusetzen sind. In diesem Modus liest xargs jeweils ein Argument aus der Standardeingabe, ersetzt im Programmaufruf jedes Vorkommen des hinter - i angegebenen Zeichens durch dieses Argument und startet das Programm. In dem folgenden Beispiel wird das benutzt, um alle Dateien mit der Endung ".txt" in ".bak" umzubenennen.

ls *.txt | cut -d. f1 | xargs -iP mv P.txt P.bak

Das Ganze funktioniert allerdings nur, wenn die Dateien nicht noch weitere Punkte im Dateinamen haben.

wc [-lwc] [Datei(en)]

Dieses Kommando zählt Zeilen, Worte oder Zeichen in einer Datei. Wird kein Dateiname angegeben, liest wc von der Standardeingabe. Optionen:

-l Zähle Zeilen
-wZähle Worte
-cZähle Zeichen

pr [+n] [-h Header] [-ftF] [-wü] [-oü] [-lü] [Datei(en)]

(print) Ausgeben und Formatieren von Dateien. Ist keine Datei angegeben, wird von der Standardeingabe gelesen. Optionen:

+nBeginne bei Seite n der Dateien (Default: 1)
-h Kopf Definiere Seitenüberschrift (Default: Dateiname)
-fVerwende beim Seitenwechsel das Formfeed-Zeichen anstelle von Leerzeichen
-t Kopf- und Fußzeilen unterdrücken
-F Zu lange Zeilen nicht abschneiden sondern umbrechen
-w#Zeilenbreite festlegen (Default: 72)
-o# ü führende Leerzeichen vor jede Zeile setzen
-l#Seitenlänge festlegen (Default: 66). Davon gehen ab 5 Zeilen für Header und 2 Zeilen für Seiten-Nummer am Ende der Seite.

sleep zeit

Legt einen Prozeß für zeit Sekunden schlafen. Erst nach Ablauf dieser Zeit wird er wieder als "bereit" in die Warteschlange eingereiht. Anwendung in der Regel in Kommandoprozeduren (Shellskripts).

tr Ersetzungsliste

tr ist ein typischer Filter (tr = translate). Es wird benutzt, um in einer Datei bestimmte Zeichen durch andere zu ersetzen. tr liest immer von der Standardeingabe und schreibt auf die Standardausgabe. Als Parameter gibt man bei tr an, welche Zeichen durch welche anderen zu ersetzen sind. Die einfachste Variante ist, ein bestimmtes Zeichen in ein anderes umgewandelt werden soll. Dazu gibt man zunächst das zu ersetzende Zeichen und danach - durch Leerzeichen getrennt - das neue Zeichen als Parameter an. Beispiel:

tr : . < foo Ersetzt ":" durch ".".
tr abc def < foo Ersetzt "a" durch "d", "b" durch "e" und "c" durch "f".
tr a-z A-Z < foo Ersetzt Kleinbuchstaben durch Großbuchstaben.

Leider unterscheiden sich die Versionen von tr auf System V und BSD-UNIX-Varianten etwas, was die Verarbeitung dieser Zeichenfolgen anbetrifft. Bei System V müssen die Bereichs- und Wiederholungsangaben in eckigen Mammern eingeschlossen sein. Bei BSD gibt es nur Bereichsangaben, allerdings ohne Klammern. Dafür wird das letzte Zeichen der zweiten Zeichenfolge bei der ESD-Variante automatisch so oft wiederholt, bis die zweite Zeichenfolge genauso lang ist wie die erste.

cut -cSpalten [dateien]

cut -fFelder [-dZeichen] [-s] [dateien]
Extrahieren bestimmter Spalten aus einer Datei. Werden keine Dateien angegeben, liest cut von der Standardeingabe. Die Ausgabe erfolgt auf die Standardausgabe. Optionen:

-cSpaltenDie angegebenen Spalten werden herausgenommen, dabei sind mehrere Zahlenangaben, getrennt durch Kommata möglich, ebenso Bereiche, z.B. 5-9.
-c-10,15,20,30- 1. bis 10. Spalte, Spalte 15, Spalte 20 und alles ab Spalte 30
-fFelder Angaben von Feldern durch die Feldnummern analog -c. Als Feldtrenner ist das Tabzeichen vorgegeben.
-dZeichen Vorgabe des Feldtrenners. Das Zeichen wird als Feldtrenner verwendet. z. B. -c:
-s Zeilen, in denen der Feldtrenner vorkommt, nicht ausgeben (Voreinstellung: Zeile ausgeben)

cal [[monat] jahr]

Kalender zu einem Monat oder Jahr auf der Standardausgabe ausgeben.

calendar

Minimalversion eines Terminkalenders. Sucht im aktuellen Verzeichnis nach einer Textdatei namens "calendar" und gibt alle Zeilen aus, die irgendwo das aktuelle oder morgige Datum enthalten. Datumsangabe amerikanisch: Monat, Tag (z. B. Jan 24, 1/25, January 25). Je nach Installation auch Funktion von cal implementiert.

basename string [suffix]

Extrahieren des Dateinamens aus einer Pfadangabe, die als String übergeben wird. Wird ein Suffix angegeben, wird dieser am Ende des Dateinamens entfernt. Zum Beispiel:

basename /home/plate/dings.cdings.c
basename /home/plate/dingsdings
basename $0Programmname

dirname

Extrahieren des Pfadnamens aus einer Pfadangabe, die als String übergeben wird. Beispiel: dirname /home/plate/dings.c ergibt /home/plate und dirname dingsda ergibt .

logname

Gibt den Loginnamen auf der Standardausgabe aus. Im Gegensatz zum Kommando id, das immer den aktuellen Loginnamen ausgibt, wird hier der Name des Login geliefert, auch wenn mit su die Benutzeridentität gewechselt wurde.

time [kommando]

Berechnet die Zeit, die das angegebene Kommando zur Ausführung braucht. Es werden drei Zeiten ausgegeben:

real Insgesamt verbrauchte Zeit (elapsed time)
user Im User-Modus verbrauchte Zeit
sys Im System-Modus verbrauchte Zeit (Systemdienste)

bc [-lmath]

Einfacher Taschenrechner hoher Genauigkeit. Um mit Gleitpunktzahlen zu rechnen, muß der Parameter angegeben werden. Liest Formeln von der Standardeingabe und gibt das Ergebnis auf der Standardausgabe aus. End mit EOF = CTRL-D.

last [-Zahl] [-f datei] [namen]

Ausgabe der An- und Abmeldezeiten von Usern. Optionen:

-Zahl Anzahl der Zeilen, die ausgegeben werden sollen
-f Datei Liest aus der Datei statt aus /var/adm/wtmpx
namen Benutzer- oder Terminalnamen

script [-a] [datei]

script erlaubt es, eine Terminal-Sitzung (oder einen Teil davon) auf einer Datei aufzuzeichnen. Dabei wird alles, was in dieser Zeit auf der alphanumerischen Dialogstation (oder dem xterm-Fenster bei graphischen Oberflächen) erscheint, festgehalten - auch das Eingabeecho. Ist 'datei' im Aufruf angegeben, so wird die Sitzung in dieser Datei protokolliert. Fehlt die Angabe einer Ausgabedatei, so wird in die Datei typescript des aktuellen Katalogs geschrieben. Ctrl-C (Unterbrechung) beendet die Protokollierung. Die Option -a veranlaßt script, das Protokoll an die Datei datei (oder typescript) anzuhängen, anstatt eine neue Datei zu eröffnen. script ist immer dann hilfreich, wenn alle Aktivitäten einer längeren Sitzung dauerhaft protokolliert werden sollen: z. B. bei der Fehlersuche, bei einer längeren Netzwerk-Sitzung auf einem entfernten Rechner oder beim Ausprobieren eines chat-skripts für eine PPP-Verbindung. Man kann auch eine Kommandofolge interaktiv ausprobieren und dann die richtigen Kommandozeilen aus der Protokolldatei per Editor schnell in ein Shellskript umsetzen.

3.7 Exkurs über Parameterersetzung

Es wurden mehrere Möglichkeiten vorgestellt, Prameter für ein Kommando zu erzeugen. Am Kommando find sollen alle Möglichkeiten kritisch betrachtet werden. Es geht in allen Fällen darum, bestimmte Dateien (*.txt) in allen Verzeichnissen zu suchen und die gefundenen Dateien auszudrucken.
  1. lpr `find / -name '*.txt' -print` /home/texte
    Zuerst wird das find-Kommando ausgefürt ubnd dessen Output bildet die Parameterliste des lpr-Kommandos. Nachteil: Das geht nur solange gut, solange nicht die systemspezifische Länge der Kommandozeile überschritten wird.

  2. find / -name '*.txt' -exec lpr {} /home/texte \;
    Für jede gefundene Datei wird das lpr-Kommando aufgerufen. Vorteil: Klappt immer. Nachteil: lpr wird u. U. sehr oft aufgerufen.

  3. find / -name '*.txt' -print | xargs lpr
    Das Ergebnis von find wird unter Berücksichtigung der Systembegrenzungen an lpr übergeben. Effizienteste Lösung.

    Zum Inhaltsverzeichnis Zum nächsten Abschnitt
    Copyright © FH München, FB 04, Prof. Jürgen Plate