Jetzt lerne ich
UNIX
Lutz Brockmann
Jetzt lerne ich
UNIX Der schnelle Einstieg in die Welt der Linux-Betriebssysteme eBook Die nicht autorisierte Weitergabe dieses eBooks an Dritte ist eine Verletzung des Urheberrechts!
Markt+Technik Verlag
Die Deutsche Bibliothek – CIP-Einheitsaufnahme Ein Titeldatensatz für diese Publikation ist bei Der Deutschen Bibliothek erhältlich.
Die Informationen in diesem Produkt werden ohne Rücksicht auf einen eventuellen Patentschutz veröffentlicht. Warennamen werden ohne Gewährleistung der freien Verwendbarkeit benutzt. Bei der Zusammenstellung von Texten und Abbildungen wurde mit größter Sorgfalt vorgegangen. Trotzdem können Fehler nicht vollständig ausgeschlossen werden. Verlag, Herausgeber und Autoren können für fehlerhafte Angaben und deren Folgen weder eine juristische Verantwortung noch irgendeine Haftung übernehmen. Für Verbesserungsvorschläge und Hinweise auf Fehler sind Verlag und Herausgeber dankbar. Alle Rechte vorbehalten, auch die der fotomechanischen Wiedergabe und der Speicherung in elektronischen Medien. Die gewerbliche Nutzung der in diesem Produkt gezeigten Modelle und Arbeiten ist nicht zulässig. Fast alle Hardware- und Softwarebezeichnungen, die in diesem Buch erwähnt werden, sind gleichzeitig auch eingetragene Warenzeichen oder sollten als solche betrachtet werden. Umwelthinweis: Dieses Buch wurde auf chlorfrei gebleichtem Papier gedruckt. Die Einschrumpffolie – zum Schutz vor Verschmutzung – ist aus umweltverträglichem und recyclingfähigem PE-Material.
10 9 8 7 6 5 4 3 2 1 04 03 02 01
ISBN 3-8272-6240-2 © 2001 by Markt+Technik Verlag, ein Imprint der Pearson Education Deutschland GmbH, Martin-Kollar-Straße 10–12, D-81829 München/Germany Alle Rechte vorbehalten Lektorat: Boris Karnikowski,
[email protected] Herstellung: Claudia Bäurle,
[email protected] Satz: text&form, Fürstenfeldbruck Einbandgestaltung: Nowak werbeagentur & medien, Pfaffenhofen Druck und Verarbeitung: Media Print, Paderborn Printed in Germany
Übersicht
Danksagung
17
Vorwort
19
Lesehinweise
21
1
Überblick
23
2
Die Entwicklung des Unix-Betriebssystems
31
3
Anmelden und Arbeiten an Unix-Systemen
37
4
Erste Schritte
43
5
Das Unix-Dateisystem
59
6
Dateiverwaltung
67
7
Das Unix-Dateisystem – ein Blick hinter die Kulissen
87
8
Weitere Kommandos
103
9
Der Unix Stream Editor
119
10
Prozessverwaltung
131
11
C-Shell und Tenex-C-Shell
149
12
Korn-Shell
181
13
Die grafische Bedienoberfläche
209
14
Networking
235
15
Datensicherung
255
16
Der Texteditor vi
275
17
Shell-Programmierung
293
18
Der Reportgenerator awk
327
19
Das kleine 1x1 der Systemverwaltung
359
Anhang: Installation von Solaris 8
389
Stichwortverzeichnis
395
5
Inhaltsverzeichnis
Danksagung
17
Vorwort
19
Lesehinweise
21
1
Überblick
23
1.1 1.2 1.3
Konzepte Aufbau Einsatzgebiete
24 26 28
2
Die Entwicklung des Unix-Betriebssystems
31
2.1 2.2 2.3
Ein kurzer geschichtlicher Überblick Standards Ausblick
31 33 35
3
Anmelden und Arbeiten an Unix-Systemen
37
3.1 3.1.1 3.1.2 3.1.3
Grundsätzliche Bedienung von X-Window-Systemen Die Maus Die Shell-Fenster Icons
38 38 39 41
4
Erste Schritte
43
4.1 4.2 4.3 4.3.1 4.3.2 4.3.3 4.3.4 4.3.5 4.3.6 4.3.7 4.3.8 4.3.9 4.3.10 4.3.11
Kommandoeingabe Online-Hilfe Grundlegende Befehle man file who uname cat more ls mail echo date passwd
44 46 48 48 49 50 50 51 51 52 52 53 54 55
7
Inhaltsverzeichnis
8
4.4 4.4.1
Aufgaben Lösungen
56 57
5
Das Unix-Dateisystem
59
5.1 5.2 5.2.1 5.2.2 5.2.3
Dateitypen Der Dateibaum Der Dateibaum von Unix System V Release 4 Navigieren im Dateibaum Das Working Directory wechseln
59 61 61 63 65
6
Dateiverwaltung
67
6.1 6.1.1 6.1.2 6.2 6.2.1 6.2.2 6.3 6.3.1 6.3.2 6.3.3 6.3.4 6.4 6.4.1 6.4.2 6.5 6.5.1
Sonderzeichen Wildcards in Dateinamen Weitere Sonderzeichen Zugriffsrechte chmod umask Kommandos zur Dateiverwaltung ls cp mv rm Kommandos zur Verzeichnisverwaltung mkdir rmdir Aufgaben Lösungen
67 68 69 70 71 73 74 74 76 77 78 80 80 80 81 82
7
Das Unix-Dateisystem – ein Blick hinter die Kulissen
87
7.1 7.2 7.3 7.3.1 7.3.2 7.3.3 7.4 7.4.1 7.4.2 7.5 7.5.1
Der interne Aufbau des Unix-Dateisystems Verzeichnisse neu betrachtet Verweise – Links Hard Links Symbolic Links Verwendungszwecke für Links Kontrolle des Speicherplatzes du df Aufgaben Lösungen
88 91 91 92 93 95 96 96 97 98 98
Inhaltsverzeichnis 8
Weitere Kommandos
103
8.1 8.1.1 8.1.2 8.2 8.2.1 8.2.2 8.2.3 8.2.4 8.3 8.3.1
Wer suchet, der findet find fgrep, grep, egrep Sortieren und Ausschneiden – Basteln mit Unix cut head tail sort Aufgaben Lösungen
103 104 108 111 111 113 113 114 116 116
9
Der Unix Stream Editor
119
9.1 9.2 9.2.1 9.2.2 9.3 9.3.1
Reguläre Ausdrücke Arbeiten mit dem sed Adressierung Sed-Kommandos Aufgaben Lösungen
119 122 122 123 130 130
10
Prozessverwaltung
131
10.1 10.1.1 10.2 10.2.1 10.3 10.4 10.5 10.5.1 10.5.2 10.5.3 10.5.4 10.5.5 10.6 10.6.1
Das Familienleben der Prozesse ps Signale an Prozesse senden kill Vordergrund- und Hintergrundprozesse Sequentielle Verkettung von Kommandos Pipes Filterprogramme wc fold tee tr Aufgaben Lösungen
131 132 133 133 135 136 137 139 139 140 141 141 143 144
11
C-Shell und Tenex-C-Shell
149
11.1 11.2 11.2.1 11.3
Die Arbeitsweise von csh und tcsh Command History history Environmentvariablen
150 152 152 154
9
Inhaltsverzeichnis
10
11.3.1 11.3.2 11.3.3 11.4 11.4.1 11.4.2 11.4.3 11.4.4 11.5 11.6 11.7 11.7.1 11.7.2 11.7.3 11.7.4 11.8 11.9 11.10 11.10.1 11.10.2 11.10.3 11.11 11.12 11.13 11.13.1 11.13.2 11.14 11.14.1
env setenv unsetenv Shell-Variablen Textvariablen set Numerische Variablen Felder aus Textvariablen Konfigurationsvariablen der csh und tcsh Quoting Alias-Namen alias Umplatzieren der Parameterliste Permanente Alias-Namen unalias Die Datei .login Die Dateien .tcshrc und .cshrc Ein-/Ausgabeumlenkung Eingabeumlenkung Ausgabeumlenkung Ausgabeumlenkung mit Fehlerkanal Subshells Von der Eingabe eines Kommandos bis zur Ausführung Prozessverwaltung der Shell bg fg Aufgaben Lösungen
154 154 155 155 155 156 156 157 158 159 161 161 162 163 163 164 164 165 166 167 168 169 170 172 173 174 174 175
12
Korn-Shell
181
12.1 12.2 12.2.1 12.2.2 12.2.3 12.3 12.4 12.5 12.5.1 12.5.2
Die Arbeitsweise der ksh Environmentvariablen env export unset Shell-Variablen Quoting Alias-Namen alias Umplatzieren der Parameterliste
182 184 185 185 185 186 186 188 188 189
Inhaltsverzeichnis 12.5.3 12.5.4 12.6 12.7 12.8 12.8.1 12.8.2 12.8.3 12.9 12.10 12.11 12.11.1 12.11.2 12.11.3 12.12 12.12.1
Permanente Alias-Namen unalias Functions Die Datei .profile Ein-/Ausgabeumlenkung Eingabeumlenkung Ausgabeumlenkung Ausgabeumlenkung mit Fehlerkanal Subshells Von der Eingabe eines Kommandos bis zur Ausführung Prozessverwaltung der Shell jobs bg fg Aufgaben Lösungen
189 189 191 192 193 194 194 195 197 198 199 199 200 201 201 202
13
Die grafische Bedienoberfläche
209
13.1 13.1.1 13.1.2 13.2 13.2.1 13.2.2 13.2.3 13.3 13.3.1 13.3.2 13.3.3 13.4 13.4.1 13.4.2 13.4.3 13.4.4 13.4.5 13.4.6 13.4.7 13.5
X-Window-Grundlagen Was ist eigentlich X-Window? Wie funktioniert X-Window? Window-Manager Der twm Der mwm Der fvwm2 Die Konfiguration von X-Window Die Datei .xinitrc Die Datei .xsession Die Datei .Xdefaults Der Standard-Desktop CDE Das CDE-Bedienpanel Das CDE-Shell-Fenster dtterm Der CDE-Standardeditor dtpad Der CDE-File-Manager dtfile Der CDE-Application-Manager Den CDE-Desktop konfigurieren Die Erweiterung der CDE-Menüs um eigene Einträge Der Linux-Standard-Desktop KDE
209 209 210 212 213 213 215 217 218 219 220 220 221 222 222 223 227 228 232 233
14
Networking
235
14.1
Grundlagen
235
11
Inhaltsverzeichnis
12
14.2 14.3 14.3.1 14.3.2 14.3.3 14.3.4 14.4 14.4.1
TCP, UDP und IP Netzdienste Bildschirmsitzungen an Remote-Rechnern Dateitransfer Informations- und Kommunikationsdienste Electronic Mail Aufgaben Lösungen
237 239 239 241 246 249 250 250
15
Datensicherung
255
15.1 15.2 15.3 15.3.1 15.3.2 15.4 15.4.1 15.4.2 15.4.3 15.5 15.5.1
Sicherungsmedien Grundlagen Archivierungsbefehle tar cpio Datenkompression Software-Kompression gzip gunzip Aufgaben Lösungen
255 256 259 260 262 266 266 268 269 270 271
16
Der Texteditor vi
275
16.1 16.2 16.2.1 16.2.2 16.2.3 16.2.4 16.2.5 16.3 16.4 16.5 16.5.1 16.5.2 16.5.3 16.6 16.7 16.7.1
Grundlagen Der Kommandomodus Cursorpositionierung Zeichen und Zeilen löschen Kommandos zurücknehmen und wiederholen Markieren und Kopieren vi-Kommandos für Fortgeschrittene Der Eingabemodus Der Statuszeilenmodus Der ex-Modus Dateikommandos Suchen und Ersetzen Unix-Kommandos Setup Aufgaben Lösungen
276 277 277 278 279 279 280 281 282 283 283 284 286 287 288 289
Inhaltsverzeichnis 293
17
Shell-Programmierung
17.1 17.2 17.2.1 17.2.2 17.2.3 17.3 17.3.1 17.3.2 17.4 17.4.1 17.4.2 17.4.3 17.4.4 17.4.5 17.4.6 17.4.7 17.4.8 17.4.9 17.4.10 17.4.11 17.5 17.5.1 17.5.2 17.5.3 17.5.4 17.5.5 17.5.6 17.5.7 17.5.8 17.6 17.6.1 17.6.2 17.6.3 17.7 17.7.1 17.7.2
Allgemeine Hinweise zur Programmierung 294 Grundlagen 295 Wie wird ein Script aufgerufen? 295 Woran erkennt die Shell ein Script? 295 Wie wird erkannt, für welche Shell ein Script geschrieben ist? 295 Variablen 296 Standardvariablen 297 Verknüpfung von Zeichenketten und Shell-Variablen 298 Spezielle Kommandos 299 basename 299 dirname 299 expr 299 Arithmetische Operatoren 300 Relationale Operatoren 300 read 301 test 301 Bedingungen für Dateien 302 Bedingungen für Strings 302 Bedingungen für ganze Zahlen 303 Logische Verknüpfungen 303 Ablaufstrukturen 304 if 304 for 305 while 306 until 307 case 307 break 308 continue 308 exit 309 Ein Muster-Script 309 Aufgabenstellung 309 Ablaufplan 310 Kodierung 311 Aufgaben 315 Beispiel-Scripts 315 Lösungen 321
18
Der Reportgenerator awk
327
18.1
Grundlagen
328
13
Inhaltsverzeichnis
14
18.2 18.3 18.3.1 18.3.2 18.3.3 18.3.4 18.3.5 18.3.6 18.4 18.4.1 18.4.2 18.4.3 18.4.4 18.4.5 18.5 18.6 18.6.1 18.6.2 18.6.3 18.6.4 18.7 18.7.1
Das awk-Programm Die Definition von Kriterien BEGIN END /muster/ /m1/,/m2/ ausdruck Kombinierte Kriterien Die Sprache der Aktionen Zuweisungen Konstanten Variablen Ablaufstrukturen Funktionen Beispiele für awk-Programme awk für Poweruser Arrays Definition von Variablen auf der Kommandozeile Funktionen selbst gemacht Pipes und Ausgabeumlenkungen Aufgaben Lösungen
329 330 330 330 331 331 331 332 334 334 335 335 336 340 344 346 346 348 348 349 351 353
19
Das kleine 1x1 der Systemverwaltung
359
19.1 19.2 19.3 19.3.1 19.3.2 19.3.3 19.3.4 19.3.5 19.4 19.5 19.5.1 19.5.2 19.5.3 19.6 19.6.1 19.6.2
Die Aufgaben des Systemverwalters Der Superuser Verwaltung von Benutzern und ihren Gruppen Das Userkonzept von Unix Das Unix-Gruppenkonzept Erweitere Rechte Gruppen anlegen Benutzer einrichten Dateisysteme ein- und abhängen Drucken unter Unix So geht’s Einen Drucker dem Spooler bekannt machen Das Drucksystem administrieren Wer boot sagt, muss auch shutdown sagen Ändern des aktuellen Run Levels Das System herunterfahren
360 360 361 361 363 365 367 368 371 375 376 378 380 383 384 385
Inhaltsverzeichnis Anhang: Installation von Solaris 8
389
Voraussetzungen Hardware-Anforderungen Installationsmedien Installation Partitionen Booten Installationsvorgang Abschlussarbeiten
389 389 390 390 390 391 391 394
Stichwortverzeichnis
395
15
Danksagung Zuerst bedanke ích mich hiermit bei den Käufern und Lesern der ersten Auflage dieses Buches. Ihnen ist es zu verdanken, dass ich die Möglichkeit hatte, eine neue überarbeitete Version zu schreiben. Ich bin kein großer Freund der Microsoft-Office-Produkte und Word bringt mich noch immer so manches Mal zur Verzweiflung. Leider konnte ich diesmal nicht auf die Dienste von Lars Franzkowiak zurückgreifen, weil dieser inzwischen fest bei yasc arbeitet und somit für den Job ausfiel. Allerdings hatte ich Glück und meine Frau Mandy hat mich diesmal bei der Formatiererei tatkräftig unterstützt. Das kommt davon, wenn man einen Computermenschen heiratet.
erstellt von ciando
Auf Seiten des Markt+Technik-Verlags hatte ich diesmal Unterstützung von zwei Mitarbeitern, die das Projekt überhaupt möglich gemacht haben. Danke Boris Karnikowski und Tobias Draxler. Besonderer Dank gebührt Sun Microsystems für die Erlaubnis, Solaris 8 für die Intel-Plattform mit dem Buch zu distributieren. Damit Sie als meine Leser Ihre Übungen auf einem wirklich professionellen Unix-System machen können, ist die private Nutzung dieser Software frei von Lizenzgebühren. Vielen Dank Herr Lankes (Sun Germany), dass Sie geholfen haben, dies zu organisieren. Weiterer Dank gilt auch diesmal Albert Nagel, der als inzwischen gestandener Unix-Schulungsreferent die eine oder andere Anmerkung beigesteuert hat. Ohne ihn hätte es keine erste, geschweige denn eine zweite Auflage gegeben.
17
Danksagung Last but not least freue ich mich, dass ich Oliver Sievers als meinen Fachlektor gewinnen konnte. Erstens hat er in den vergangenen Jahren viel positive Werbung für das Buch gemacht und zweitens habe ich in den letzten drei Jahren das eine oder andere Unix-Problemchen zusammen mit ihm gelöst. Dies und sein Know-how kommen der zweiten Auflage sicher zugute.
18
Vorwort Als ich 1984 mein Informatik-Studium an der TU Braunschweig begann, setzte mit dem System V Release 3 gerade der kommerzielle Durchbruch von Unix ein. Meine ersten Programmierpraktika aber fanden noch auf einem IBM-Großrechner unter VM/CMS statt. Mit dem Betriebssystem Unix kam ich erst zwei Jahre später in Berührung. Ich betreute damals als studentische Hilfskraft ein Programmierpraktikum, bei dem auf Siemens-PCX-10-Systemen unter SINIX gearbeitet wurde. Während der drei Jahre, die ich dieses Praktikum betreute, sammelte ich meine ersten Erfahrungen als Unix-Systemverwalter – Erfahrungen, die Dank der betreuten Studenten oft intensiver ausgefallen sind, als geplant war. Aufgrund der zumeist positiven Eindrücke beschäftigte ich mich näher mit diesem Betriebssystem. Daher habe ich sowohl Studien- als auch Diplomarbeit unter Unix geschrieben und lernte dabei die Derivate SunOS, HP-UX und IRIX kennen. Zu dieser Zeit habe ich mir dann auch mein erstes Linux vom FTP-Server der Uni auf ca. 65 Disketten gezogen und auf meinem heimischen PC installiert. 1991, nach dem Diplom in Informatik, arbeitete ich dann als Unix-SoftwareEntwickler in Braunschweig. Durch die räumliche Nähe zu Wolfsburg schloss sich eine Dozententätigkeit beim Volkswagenkonzern an. Die Bandbreite der von mir konzipierten und gehaltenen Kurse begann bei den Unix-Grundlagen und ging bis hin zur Systemverwaltung spezieller Unix-Derivate. 1997 habe ich dann mit zwei Freunden die yasc Informatik GmbH gegründet. Der Fokus dieser Firma liegt ebenfalls auf dem Unix-Sektor. So leisten wir zum Beispiel für die VW Coaching GmbH den Großteil der Unix-Ausbildung
19
Vorwort am Standort Wolfsburg und entwickeln unter verschiedenen Unix-Derivaten Software für Forschungseinrichtungen und Industrie. Seit 1999 arbeite ich hauptsächlich als Berater in Unix-Fragen für die dvg Hannover. Dort hatte ich die Chance, mein Unix-Wissen und gleichzeitig den Kontakt zu einer Reihe von Lesern meines Buches zu vertiefen. Als ich 1999 die erste Version des Buches fertig gestellt hatte, habe ich nur kurz in diesem Vorwort über die Möglichkeit einer zweiten Auflage nachgedacht und Sie als meine Leser gebeten, mir Anregungen zu senden, was in einer solchen zweiten Auflage aufgenommen werden könnte. Sie haben recht regen Gebrauch davon gemacht und so ist doch einiges neues hinzugekommen. Auch diesmal freue ich mich wieder auf den Dialog mit meinen Lesern. Ich bin immer noch unter
[email protected] zu erreichen. Nun aber viel Spaß mit der zweiten Auflage von »Jetzt lerne ich Unix«!
Braunschweig im August 2001 Lutz Brockmann
20
Lesehinweise Der folgende Inhalt ist an der praktischen Arbeit mit einem Unix-System ausgerichtet. Der Leser soll in die Lage versetzt werden, die aufgeführten Befehle auf seinem System nachzuvollziehen und die Beispiele auszuprobieren. Das Layout des Textes soll ihn darin unterstützen. Unix-Kommandos sind in einfacher Letter Gothic gesetzt.
Angaben zur Syntax von Kommandos finden Sie in Textboxen, die durch das Syntax-Icon gekennzeichnet sind. Bei den Syntaxbeschreibungen, die im Fließtext eingerückt erscheinen, werden die folgenden Konventionen eingehalten: Letter Gothic
Alle Zeichen, die unverändert in die Eingabe zu übernehmen sind, sind im Zeichensatz Letter Gothic gesetzt.
[opt]
Optionale Ausdrücke erscheinen in eckigen Klammern. Die Syntax des Kommandos ist also auch dann noch korrekt, wenn die optionalen Ausdrücke weggelassen werden.
ersetzen
Angaben, die vom Benutzer vorgegeben werden müssen (wie z.B. Dateinamen), sind kursiv ausgeführt. Wird auf diese Angaben im laufenden Text verwiesen, so sind sie dort in der gleichen Schrift gesetzt.
6
21
Lesehinweise Am Beispiel des Kommandos cp, mit dem Daten kopiert werden können, sollen die Konventionen erläutert werden:
6
cp [Optionen] Original Kopie
Für die Ausführung des Kopier-Kommandos ist immer das Befehlswort cp anzugeben. Es können Optionen, z.B. für Sicherheitsrückfragen, angegeben werden. Das Kommando kann aber auch ohne Optionen ausgeführt werden, gefolgt von zwei Dateinamen, dem Namen einer Originaldatei und dem Namen, unter dem die Kopie gespeichert werden soll. Gültige Eingaben könnten also sein:
3
UNIX-Kurs [~] 1 > cp data data.bak UNIX-Kurs [~] 2 > cp -i data data.bak
Eine ungültige Eingabe wäre:
3
UNIX-Kurs [~] 3 > cp data
Kommandos, die in Beispielen auftreten, habe ich durchlaufend nummeriert. Dies ermöglicht einen schnellen Verweis auf die einzelnen Beispielkommandos. Das Drücken von Tasten wird im Text durch Tastensymbole mit der entsprechenden Beschriftung gekennzeichnet. Das Symbol C steht für die Taste mit dem Buchstaben C. Grundsätzlich ist von Kleinbuchstaben auszugehen, es sei denn, es wird explizit davon abgewichen. Stehen zwei Tastensymbole direkt hintereinander, so sollten Sie die beiden Tasten bei Eingabe über die Tastatur gleichzeitig drücken. Das Symbol ŸC steht also für das gleichzeitige Drücken der Steuerungs-Taste (Strg- oder auch Ctrl-Taste) und der C-Taste. Ist die Shift-Taste (zum Erreichen der Großbuchstaben) zu drücken, so wird dies durch das Symbol Á angegeben.
22
KAPITEL 1
Überblick Das Unix-Betriebssystem konnte im Laufe seiner Entwicklung und Verbreitung eine umfangreiche Anhängerschaft gewinnen. Insbesondere bei EDVSpezialisten erfreut es sich besonderer Beliebtheit. Leider erschweren Defizite bei der Benutzerführung sowie die teilweise kryptische Befehlssyntax und das Fehlen einer einheitlichen grafischen Bedienoberfläche Einsteigern und Anwendern, für welche die Nutzung der Standardsoftware im Vordergrund steht, den Umgang mit dem Unix-Betriebssystem. Dies kann bis zur Ablehnung bei solchen Benutzern führen, für die das Betriebssystem zweitrangig ist. Dabei ist es gerade das Betriebssystem, welches nicht unerheblich an der Leistungsfähigkeit einer Software beteiligt ist. Die Hauptaufgabe eines Betriebssystems besteht darin, die Ressourcen eines Rechners zu verwalten und zu kontrollieren. Unter den Ressourcen versteht man dabei z.B. den Arbeitsspeicher, die Central Processing Unit (CPU), aber auch Geräte wie den Drucker oder die Tastatur. Die Strategien, mit denen ein Betriebssystem diese Aufgaben erfüllt, haben entscheidenden Einfluss auf die Stabilität und das reibungslose Zusammenspiel der Komponenten. Diese Kriterien sollten bei der Beurteilung eines Betriebssystems sehr viel stärker als der Komfort der Benutzerschnittstelle gewichtet werden. Während jedoch dem Anwender die Konzepte eines Betriebssystementwurfs in der Regel verborgen bleiben, offenbaren sich Unzulänglichkeiten in der Benutzerführung oft bereits bei den ersten Arbeitsschritten und erschweren so den Umgang mit dem System. Die Kritik am Unix-Betriebssystem basiert zumeist auf Schwierigkeiten bei der Bedienung. Deshalb an dieser Stelle meine Bitte an alle Kri-
23
KAPITEL
1
Überblick
tiker, ihre bisherigen Erfahrungen zu überdenken und vielleicht so einen neuen Zugang zur Unix-Welt zu finden.
1.1
Konzepte
Die ursprüngliche Intention der Unix-Entwickler war nicht, ein Betriebssystem für den Anwender zu schaffen. Vielmehr war Unix von Anfang an als ein Software-Entwicklungssystem für DV-Experten geplant. Die Gründe, warum es heute nicht ausschließlich in dieser Funktion benutzt wird, liegen zum einen in den leistungsfähigen Konzepten und in der Flexibilität des Systems begründet und zum anderen in den Schwächen der Systeme neueren Datums, die auch heute noch nicht das bieten, was Unix-Betriebssysteme bereits seit mehr als 15 Jahren fest im Repertoire haben. Diese Konzepte und die daraus resultierenden Konsequenzen sollen auf den folgenden Seiten vorgestellt werden. Die Hauptaufgabe eines Betriebssystems ist, das Starten von Programmen zu ermöglichen und diese zu verwalten. Ferner hat es den Zugriff der Programme auf die Hardware des Rechners wie Bildschirm, Tastatur, Festplatte usw. zu koordinieren, unabhängig davon, ob es sich bei den Programmen um einen einfachen Kopierbefehl (der evtl. selbst ein Teil des Betriebssystems ist), einen Internetbrowser oder ein komplettes CAD-System handelt. Ein in der Ausführung befindliches Programm wird Prozess oder auch Task genannt. Jedem Prozess werden zur Laufzeit verschiedene Bereiche im Arbeitsspeicher – so genannte Segmente – zur Verfügung gestellt. Ein Prozess verfügt in der Regel über ein Programmsegment, in dem die Befehle des Programms stehen (nicht veränderlich), und ein Datensegment, in dem die Variablen des Programms abgelegt sind. Der Zustand eines Prozesses wird durch den Programmzähler, der angibt, welcher Befehl als nächster bearbeitet wird, und den Inhalt des Datensegments bestimmt. Das Unix-Betriebssystem verwaltet im Gegensatz zu anderen Systemen nicht primär Systemressourcen oder Benutzer, sondern Prozesse, die bestimmten Benutzern zugeordnet sind oder die Systemressourcen kontrollieren. Aus diesem Grund wird Unix oft als prozessorientiertes Betriebssystem bezeichnet. So verwundert es auch nicht, dass auf einem Unix-Betriebssystem stets einige Prozesse laufen, um bestimmte Aufgaben des Betriebssystems wie die Prozessverwaltung und die Interpretation von Benutzereingaben zu erledigen. Unix ist ein so genanntes Multiprocessing- oder auch Multitasking-Betriebssystem. Es ist in der Lage, mehrere Prozesse gleichzeitig zu verwalten. Dabei wird dem Benutzer durch das schnelle Hin- und Herschalten zwischen den unterschiedlichen Prozessen vorgegaukelt, dass diese parallel – also gleichzeitig
24
Konzepte – ablaufen. Echte Parallelität ist aber nur auf Rechnern mit mehr als einer CPU möglich. Im Gegensatz zum kooperativen Multitasking wie unter MS Windows 3.x verwendet Unix das so genannte präemptive1 Multitasking, d.h., die Prozesse wechseln sich ohne Zutun des Benutzers in Abhängigkeit einer ihnen zugeordneten Priorität bei der Benutzung der CPU ab. Über die Vergabe des Prozessors wacht ein eigener Prozess, der so genannte Scheduler2. Dadurch, dass mehrere Prozesse quasi parallel ablaufen, ist bereits die wichtigste Voraussetzung zur Unterstützung mehrerer Benutzer (User) zur selben Zeit erfüllt. Was noch fehlt, ist die Zuordnung der Prozesse zu einzelnen Benutzern und die Gewährleistung der Unabhängigkeit der Benutzer voneinander. Dieses ist unter Unix durch die Verteilung von Zugriffsrechten und Eigentümereinträgen umgesetzt worden. Jedes Programm und jede Datei, aber auch jeder laufende Prozess haben einen Eigentümer. Damit ein Benutzer ein Programm ausführen darf, muss der Eigentümer des Programms dem Benutzer das entsprechende Zugriffsrecht eingeräumt haben. Ist das der Fall, erzeugt Unix beim Start des Programms einen Prozess, dessen Eigentümer der Benutzer ist. Das wichtigste Programm für einen Benutzer ist in einem solchen prozessorientierten System ein Programm, mit dessen Hilfe er wieder andere Programme starten kann. Diese Schnittstelle zum Benutzer nennt man Kommandointerpreter, weil Eingaben des Benutzers (die Kommandos) in Aufrufe von Programmen umgesetzt werden. Unix verfügt im Gegensatz zu Betriebssystemen wie DOS, VM/CMS, Windows NT, VMS oder BS2000 nicht über einen für alle Benutzer einheitlichen Kommandointerpreter, sondern ermöglicht den Einsatz einer ganzen Auswahl solcher Programme. Ob diese Programme eine grafische Bedienoberfläche haben oder zeichenorientiert arbeiten, spielt dabei für Unix keine Rolle. Diese Flexibilität setzt sich auch in Bezug auf andere Komponenten des Systems fort. Unix ist weitgehend hardwareunabhängig. Der Kern (engl. kernel) des Betriebssystems, in dem die Algorithmen zur Verwaltung der Ressourcen, wie Speicher, CPU und Ein-/Ausgabegeräte, und die Methoden zur Steuerung der Prozesse implementiert sind, ist bei Unix komplett in der Programmiersprache C geschrieben und enthält keine hardwarespezifischen Elemente. Da aber von jedem Betriebssystem auch Hardware-Komponenten angesteuert werden müssen, verfügt Unix über eine spezielle Zwischenschicht, in der Schnittstellen für diese Aufgabe eingebettet sind. Der Kern greift über diese Zwischenschicht mit genormten Zugriffsfunktionen auf die Hardware zu. 1. Unter Präemption wird die Abgabe von Betriebsmitteln verstanden. Dabei kann es sich z.B. um den Prozessor oder um den Speicher handeln. 2. Scheduler, engl. von schedule: Fahrplan, Zeitplan.
25
KAPITEL
1
Überblick
Dieser Hardware-Unabhängigkeit von Unix ist es zu verdanken, dass das Betriebssystem verhältnismäßig einfach auf neue Rechnerplattformen zu portieren1 ist. Auf einer neuen Hardware müssen nur die Zwischenschicht angepasst und ein Compiler2 für die Programmiersprache C implementiert werden – und Unix ist portiert. Dies ist einer der Gründe, warum im Bereich der RISC-Workstations, in dem sich seit ihrer Entstehung die Lebensdauer von Chipgenerationen erheblich verkürzt hat, Unix das meistvertretene Betriebssystem ist. Ein weiteres wichtiges Konzept des Systems ist sein hierarchisches Dateisystem. Alle Dateien werden unter Unix in Verzeichnissen abgelegt, wobei Verzeichnisse selbst auch wieder Verzeichnisse enthalten dürfen. Diese Definition führt zu einer baumartigen Hierarchie, die – selbst bei Zugriff auf mehrere Festplatten und andere Geräte – in einem gemeinsamen Oberverzeichnis aller Verzeichnisse ihren Ursprung hat. Durch diese Anordnung ist es möglich, Dateien nach bestimmten Kriterien so zu sortieren, dass sie leichter aufzufinden sind.
1.2
Aufbau
Der Aufbau des Betriebssystems Unix steht in einer engen Verbindung zu den bereits vorgestellten Konzepten. Bei Systemen wie DOS werden die meisten Befehle von einem umfangreichen Programm bearbeitet. Dadurch, dass Unix prozessorientiert arbeitet, erfolgt die Umsetzung der Befehle im Gegensatz dazu durch eine Vielzahl kleiner Programme. Aus diesem Grund ist der Kommandointerpreter auch nur ein Programm, das lediglich die Aufgabe übernimmt, initiiert durch die Eingaben des Benutzers, die vorhandenen Programme zu starten. Für den Benutzer stellt sich der Aufbau des Unix-Betriebssystems als ein Schalenkonzept dar, wobei er in der Regel nur mit der äußersten Schale direkt in Berührung kommt (Abb. 4.1). Diese äußerste Schale ist die Shell3 (so werden die Kommandointerpreter unter Unix genannt). Sie nimmt die Kommandos des Benutzers entgegen und ruft dann Programme aus der zweiten Schicht auf. Diese können Standardprogramme des Unix-Betriebssystems, (z.B. ein Kommando) oder auch Anwendungen (z.B. eine Textverarbeitung) sein. Sollte dieses Programm auf ein Gerät zugreifen müssen – letztlich müssen dies fast alle Programme, weil sie auf dem Dateisystem operieren, wel-
1. Als Portierung wird die Anpassung eines bestehenden Programms an eine neue Hard- oder Software-Umgebung bezeichnet. 2. Ein Compiler (Übersetzer) setzt eine Hochsprache wie z.B. C oder Pascal in Maschinensprache um. 3. Shell (engl.): Muschel, Muschelschale
26
Aufbau ches auf der Festplatte steht – geschieht dies durch Funktionsaufrufe, die in der dritten Schicht des Betriebssystems anzusiedeln sind. Diese Funktionen der dritten Schicht bilden die Zugriffe auf Dateien mittels Funktionen der vierten Schicht in Schreib- und Leseoperationen auf der Platte – also in Hardware-Operationen – ab.
Abb. 1.1: Schalenkonzept
Was auf den ersten Blick umständlich erscheinen mag, beinhaltet neben Portabilität und Hardware-Unabhängigkeit noch einen weiteren Vorteil: Da die Einund Ausgabegeräte als spezielle Dateien (so genannte Device Descriptors) in den Verzeichnisbaum integriert sind, wird dem Benutzer für die unterschiedlichen Geräte ein einheitliches Zugriffskonzept präsentiert. Durch diese Geräteunabhängigkeit macht es für den Benutzer keinen Unterschied, ob er die Ausgabe auf den Bildschirm oder in eine Datei schreibt oder ob er von einem Band, einer Diskette, einer Datei auf der Festplatte oder von der Tastatur liest. Dieser transparente Mechanismus1 für den Zugriff auf unterschiedliche Geräte wird von Software-Entwicklern und Benutzern gleichermaßen geschätzt, da er
27
KAPITEL
1
Überblick
die Anbindung neuer Geräte bis hin zu neuen Technologien an Unix-Betriebssysteme stark vereinfacht, ohne bestehende Strukturen zu zerstören.
1.3
Einsatzgebiete
Ein Betriebssystem als universell zu bezeichnen, klingt wenig glaubhaft, dennoch kann Unix dieses Attribut beinahe für sich in Anspruch nehmen. Allerdings ist dabei zu beachten, dass Unix eher ein Sammelbegriff als eine Bezeichnung für ein einzelnes Betriebssystem ist. Dieser Sammelbegriff steht für Systeme unterschiedlichster Ausprägung und unterschiedlichster Hersteller, deren Konzepte und Aufbau vom »Ur-Unix« von AT&T abgeleitet sind. So gibt es Unix-Betriebssysteme, die auf Großrechnern eingesetzt werden. Systeme wie z.B. das UTS von Amdahl bedienen dabei gleichzeitig Hunderte von Benutzern und sorgen für die Einhaltung der Sicherheitsbestimmungen beim Zugriff auf Daten und Programme. Die größte Verbreitung haben Unix-Betriebssysteme im Bereich der Workstations erfahren. Insbesondere im Bereich der Grafikworkstations mit ihren Mega-Pixel-Displays (mehr als 1.000x1.000 Bildpunkte) und speziellen Erweiterungen für die Unterstützung von CAD/CAM oder Animationssystemen ist Unix das dominierende Betriebssystem. Welche Leistungen mit solchen Workstations erbracht werden können, haben Kinofilme wie »Jurassic Park« oder »Independance Day« auch für den Laien eindrucksvoll unter Beweis gestellt. Die Firmen SGI, HP, Sun und IBM sind wohl die bekanntesten Anbieter in diesem Segment. Obwohl der PC schon in den frühen Tagen der Unix-Geschichte zu den unterstützten Hardware-Plattformen gehörte (Xenix hatte von allen Unix-Betriebssystemen Mitte der 80er Jahre den weitesten Verbreitungsgrad), stellt sich doch erst mit frei verfügbaren Systemen wie FreeBSD oder Linux der Erfolg im nicht kommerziellen Bereich ein. Darüber hinaus existieren Unix-Betriebssysteme, die echtzeitfähig sind, d.h., ihre Aufgaben werden innerhalb genau abgegrenzter Zeitvorgaben abgewikkelt. Solche Systeme kommen z.B. bei Kraftwerksteuerungen, Simulationsaufgaben oder Gleisregelanlagen zum Einsatz. Unix-Betriebssysteme werden dank ihrer Architektur und ihrer fortschrittlichen Konzepte auch in Zukunft stets dann gefragt sein, wenn es um Themen wie Ausfallsicherheit, komplexe Datenbankanwendungen oder rechenintensive CAD-Projekte geht. Auch wenn die Benutzerschnittstellen erst in den nächsten Jahren den gewünschten Komfort erreichen werden, gehört Unix 1. Als transparent werden Methoden bezeichnet, die dem Benutzer eine einheitliche Arbeitsweise erlauben, obwohl u.U. verschiedene Hard- oder Software-Techniken verwandt werden.
28
Einsatzgebiete heute schon zum Besten, was der Markt zu bieten hat, wenn es um eine funktionierende Speicherverwaltung oder um die Stabilität des Gesamtsystems geht.
29
KAPITEL 2
Die Entwicklung des Unix-Betriebssystems 2.1
Ein kurzer geschichtlicher Überblick
Das Betriebssystem Unix kann auf eine recht lange Geschichte zurückblicken, in deren Verlauf das System ständig erweitert und verbessert wurde. Der Startschuss für Unix fiel in den späten 60er Jahren, als sich die Bell Laboratories, eine Tochtergesellschaft des AT&T-Konzerns (der damals noch Bell hieß), und General Electric an der Entwicklung eines neuen interaktiven Betriebssystems mit dem Namen MULTICS versuchten. Der Name MULTICS steht für Multiplexed Information and Computation Service und unterstreicht, dass das geplante System multitasking- und multiuser-fähig sein sollte und dass es – im Gegensatz zu den damals noch üblichen proprietären Betriebssystemen von IBM, DEC etc. – auf mehreren verschiedenen Hardware-Systemen laufen sollte. Das Projekt wurde zwar aus verschiedenen Gründen nicht weitergeführt, aber einige MULTICS-Projektmitglieder um Ken Thompson nutzten die Erfahrungen aus diesem Projekt, um in eigener Regie und ohne Entwicklungsauftrag ein Betriebssystem für eine PDP-7 zu entwickeln. Dieses System wurde zunächst nicht unter kommerziellen Gesichtspunkten geplant und hatte in erster Linie den Ansprüchen seiner Entwickler zu genügen. Diese erste Version des Unix-Betriebssystems, von Brian Kernighan in Anspielung auf die Tatsache, dass dieses Betriebssystem nur auf einem1 Rechner lief, scherzhaft 1. Auf deutsch heißt multi viele und unus einer.
31
KAPITEL
2
Die Entwicklung des Unix-Betriebssystems
UNICS1 genannt, enthielt zwar schon wesentliche Merkmale des heutigen Unix, war aber noch komplett in Assembler2 geschrieben. Der entscheidende Schritt für den späteren Erfolg des Systems wurde 1973 nach der Portierung des Systems auf eine PDP-11/20 getan, als Dennis Ritchie und Ken Thompson den Kern des Betriebssystems in die Programmiersprache C umschrieben. Zu diesem Zeitpunkt liefen ca. zehn Rechner unter Unix. Aber diese Zahl sollte schnell wachsen. Da das neue System – im Gegensatz zu anderen Betriebssystemen dieser Zeit – fast vollständig in einer Hochsprache geschrieben worden war, konnte es wesentlich einfacher auf neue Rechnersysteme portiert werden. Trotz der zunehmenden Popularität vertrieb AT&T das System nicht unter kommerziellen Gesichtspunkten, sondern gab es zu einem nominellen Preis inklusive der Quellen an Universitäten und interessierte Firmen ab, die so »ihr« Unix portieren und erweitern konnten. Besonders hervorgetan hat sich hier die University of California in Berkeley, an der Thompson 1975 ein Forschungssemester absolvierte. Er portierte im Rahmen dieser Tätigkeit Unix auf eine PDP-11/70, unterstützt von den Studenten Bill Joy und Chuck Haley, die eine Reihe von Arbeiten erledigten und das System um bedeutende Komponenten wie den Editor ex und den eng mit ihm verknüpften vi sowie um die Netzwerkfähigkeit erweiterten. Joy, einer der späteren Mitbegründer von Sun Microsystems, stellte aus den Ergebnissen dieser Arbeit ein Softwarepaket zusammen, welches er Berkeley Software Distribution – BSD nannte. Trotz – oder vielleicht gerade wegen – der nicht kommerziellen Auslegung des Systems hielten immer neue Konzepte und Werkzeuge Einzug in Unix. So verfügte Unix Version 7, welches den »Urahn« aller heutigen Unix-Betriebssysteme darstellt, schon über eine beachtliche Funktionsvielfalt. Problematisch für die Entwicklung und Nutzung von Anwendungssoftware war der Wildwuchs an unterschiedlichen Versionen des Systems, der sich vor allem an Universitäten entwickelte. 1982 begann die Kommerzialisierung des Unix-Betriebssystems mit der Nachfolgeversion von Unix Version 7, die unter dem Namen Unix-System III von AT&T vertrieben wurde. Der Vertrieb war zunächst nicht von Erfolg gekrönt, da neben Unix-System III auch weiterhin Forschungs- und experimentelle Versionen von AT&T abgegeben wurden.
1. Brian Kernighan machte aus dem Multiplexed Information and Computation Service einen Uniplexed Information and Computation Service und kam so zu der Abkürzung UNICS. 2. Als Assembler wird die Programmiersprache bezeichnet, die sich aus den Steueranweisungen für die jeweilige CPU ergibt. Assemblerprogramme sind daher nur auf einer speziellen Hardware lauffähig.
32
Standards Erst mit den verschiedenen Releases des Unix-System V wurde weitgehend eine Abkehr von der Versionenvielfalt erreicht. Nur einige wenige »Derivate« wie BSD oder SunOS blieben eigenständig, während andere, wie DECs ULTRIX und Microsofts Xenix, in die System-V-Familie zurückkehrten. Die weiteste Verbreitung dieser Familie hat dabei das System V Release 3.2 erfahren, welches, ausgerüstet mit BSD-Erweiterungen wie ex und vi, einem integrierten Vernetzungsansatz, verbesserten Sicherheitskonzepten (Passwortdatei) und einem Paging-Mechanismus, eigentlich dem entspricht, was wir heute als Unix bezeichnen. Um auch die letzten Derivate mit der System-V-Linie zu vereinen und den gestiegenen Sicherheitsbedürfnissen der Unix-Benutzer gerecht zu werden, wurde das neueste Unix-Release unter dem Namen Unix-System V Release 4 von AT&T definiert. Um die Vereinigung der verschiedenen »Derivate« zu ermöglichen, bedurfte es neben der Adaption von Kommandos aus den unterschiedlichen Varianten auch einiger genereller Veränderungen, wie z.B. der Unterstützung unterschiedlicher Dateisysteme oder der Einführung von Erweiterungen zur Echtzeitverarbeitung.
2.2
Standards
Bedingt durch die Versionen- und Derivatenvielfalt von Unix wurde es schon recht früh notwendig, Konventionen zu schaffen, um Programme auf den unterschiedlichen Unix-Betriebssystemen benutzen zu können. Gerade die wissenschaftlichen Benutzer an den Universitäten, die in den Anfängen der UnixGeschichte die Hauptnutzer waren, hatten ein starkes Interesse daran, ihre Forschungssoftware untereinander auszutauschen. So entstand 1981 mit der Benutzervereinigung /usr/group bereits vor der ersten von AT&T kommerziell vertriebenen Unix-Version ein Gremium, das sich um einen Standard bezüglich der Portabilität von Programmen bemühte. 1985 wurde diese Gruppe unter der Schirmherrschaft des Institute for Electronical and Electronic Engineers (IEEE – gesprochen ei triple i) in das Projekt 1003 integriert. Aufgabe dieses Projekts war es, im Auftrag des American National Standards Institutes (ANSI) eine Reihe von Standards für das Betriebssystem Unix zu entwickeln. Diese Standards wurden unter dem Namen Portable Operating System Interface for Computer Environments (POSIX) zusammengefasst. Der POSIX-Standard befasst sich mit der portablen Programmierung auf Unix-Betriebssystemen und ist auch heute noch von großer Bedeutung. Wichtigster Bestandteil des POSIX-Standards ist P1003.1, die Definition der Systemschnittstelle.
33
KAPITEL
2
Die Entwicklung des Unix-Betriebssystems
Neben den Benutzern bemühte sich aber auch AT&T um die Standardisierung ihres »Produkts«. Ziel dieser Bemühungen war es, Unix als Industriestandard zu etablieren. So wurde 1983 unter dem Namen System V Interface Definition (SVID) ein Standard veröffentlicht, der festschrieb, wie sich ein Betriebssystem verhalten muss, um als System-V-kompatibel zu gelten. Neben dieser Festlegung, die in erster Linie ein portables Programmieren unter Unix ermöglichen sollte, wurden in der SVID auch wesentliche Eigenschaften festgeschrieben, die von zukünftigen Releases erfüllt werden müssen. Damit sollte die Entwicklung von Software unterstützt werden, die auch auf zukünftigen Unix-Versionen lauffähig sein würde. Mit Unix-System V Release 4 wurde auch eine neue SVID vorbereitet; allerdings ist auch dieses Unix-Release noch konform zu der ursprünglichen SVID. Während sich in den USA Benutzer und AT&T um eine Standardisierung von Unix bemühten, bildeten sich in Europa Vereinigungen von Herstellern, denen an einer möglichst weiten Verbreitung des Systems gelegen war. Die erste dieser Vereinigungen war die so genannte BISON-Gruppe (Bull, ICL, Siemens, Olivetti und Nixdorf). Später wurde dieser rein europäische Zusammenschluss durch die Aufnahme großer amerikanischer Anbieter in die Gruppe X/OPEN umgewandelt. Um die nötige Akzeptanz für eine weite Verbreitung zu erzielen, verabschiedete die X/OPEN-Gruppe Standards bis hin zu den Software-Schnittstellen für Anwenderprogramme. So wurden etwa der Native Language Support (NLS) oder das standardisierte Datensicherungsprogramm cpio von der X/OPEN-Gruppe genormt. Weiterhin trat X/ OPEN stark für den Einsatz des Fenstersystems X11 ein, welches dadurch zum »Quasistandard« für Fenstersysteme geworden ist und Konkurrenten wie NeWS und Sun View aus dem Rennen geworfen hat. X/OPEN definierte den auf der SVID und POSIX basierenden Standard Common Applications Environment (CAE) und den X Portability Guide (XPG). Mit der Konzeption von Unix-System V Release 4 hat sich unter Federführung von AT&T und Sun Microsystems die Herstellervereinigung Unix International (UI) gebildet, deren Ziel es ist, die Verbreitung des Unix-System V zu fördern. Als Antagonist zu dieser Vereinigung haben sich u. a. IBM, DEC und HP zur Open Software Foundation (OSF) zusammengeschlossen. Ziel der OSF ist die Verbreitung des OSF/1 genannten Konkurrenzsystems zum Unix-System V Release 4. Das OSF/1 basiert auf dem multiprozessorfähigen MACH-Kernel der Carnegie-Mellon University, den diese im Auftrag des Department of Defense (DoD) als Grundstein für eine zukünftige Unix-Version entwickelt hat.
34
Ausblick Im Zusammenhang mit der Entwicklung des OSF/1 hat die OSF einen Standard für die Erstellung grafischer Bedienoberflächen verabschiedet und in Form eines Widgetsets und eines zugehörigen Styleguides realisiert. Dieser OSF/Motif genannte Standard hat das von Sun entwickelte Open Look nahezu verdrängt und ist auch auf System-V-Release-4-Systemen weit verbreitet. Die aktuelle Entwicklung ist in erster Linie darauf bedacht, Unix-Systeme für neue 64-Bit-Hardware zu entwickeln und für neue Anwendungsgebiete zu erschließen. Standards beziehen sich in diesem Zusammenhang weniger auf ganze Unix-Release, sondern oft nur auf bestimmte Schnittstellen, die unterstützt werden.
2.3
Ausblick
Obwohl schon in den frühen 90er Jahren verabschiedet, bilden auch heute noch die Umsetzung der beiden Standards Unix-System V Release 4 und OSF/1 die Ziele für zukünftige Unix-Releases. Neben der verstärkten Bedeutung der Vernetzung steht immer mehr die Verbreitung von skalaren Mehrprozessor-Maschinen (im Gegensatz zu Vektorrechnern wie der CRAY-Familie) im Vordergrund. Darüber hinaus streben die Unix-Anbieter eine stärkere Objektorientierung ihrer Systeme an, die wohl mit der Abkehr von der Programmiersprache C hin zur objektorientierten Variante C++ ihren Siegeszug antreten wird. Es bleibt zu hoffen, dass Unix-Betriebssysteme auch in Zukunft auf offenen Standards aufbauen und sich nicht aufgrund von durch eine Firma definierten »Pseudostandards« ausbreiten, bei denen unabhängige Software-Entwickler und Benutzer das Nachsehen haben. Teilweise nicht dokumentierte Programmierschnittstellen, wie bei Microsoft-Betriebssystemen oft zu finden, seien hier als Negativbeispiel angeführt. Offene Standards, gepaart mit der Vielfalt an Hardware-Pattformen, die vom PC (Linux) bis zum Großrechner (UTS) reicht, haben Unix zu seinem einzigartigen Erfolg verholfen. Die Weiterführung dieser Strategie ist zwar kein Garant für das »Überleben« des Systems, hat aber bis heute dafür gesorgt, dass Unix-Betriebssysteme stets state of the art waren. Kein anderes System ist so stark mit der Weiterentwicklung der RISCTechnologie1 und der damit erzielten Leistungssteigerung verbunden, da kein anderes Betriebssystem so schnell auf neue Prozessorkonzepte umgestellt werden kann. 1. RISC bedeutet Reduced Instruction Set Code. RISC-Prozessoren zeichnen sich durch einen kleineren Befehlssatz aus, mit dem aber auch alle komplexen Operationen durchgeführt werden können. Der kleinere Befehlssatz kann auf dem Prozessor »hart verdrahtet« werden, was zu erheblichen Geschwindigkeitssteigerungen führt. Einziger Nachteil diese Architektur ist, dass die Programmdateien für RISC-Prozessoren deutlich größer sind als die für herkömmliche Prozessoren.
35
KAPITEL
2
Die Entwicklung des Unix-Betriebssystems
Zu guter Letzt hat auch eine der spektakulärsten Entwicklungen im SoftwareBereich dafür gesorgt, dass Unix-Systeme auf vergleichsweise preisgünstigen Intel-PCs Einzug in die Wohnzimmer privater Benutzer gefunden haben. Linux, ein von dem Finnen Linus Torvalds initiiertes und von einer über die ganze Welt verstreuten Entwicklergemeinschaft zu einem vollwertigen Unix ausgebautes Betriebssystem, wiederholt durch seine Entstehungsgeschichte die Erfolgsstory des »Ur-Unix«. Ohne kommerzielle Ausrichtung, allein auf die Bedürfnisse der Anwender ausgerichtet, werden von findigen Tüftlern neue Werkzeuge in das System eingebaut, wie einst von den Studenten der University of Berkeley. Der Erfolg von Linux ist nicht mehr aufzuhalten. Während in seinen Anfängen in erster Linie Studenten, Open Source-Programmierer und Individualisten zu den hauptsächlichen Nutzern zählten, gibt es heute große Mengen von kommerziell eingesetzten Linux-Systemen. Angefangen von Webservern, über DNS-Server bis hin zum Einsatz in Forschungssystemen zur Flugführung erobern Linux-Systeme immer mehr Aufgabenbereiche und glänzen dort durch ihre Stabilität, Zuverlässigkeit und Leistungsfähigkeit. Aber auch die Variabilität des Systems ist beeindruckend – neben Machbarkeitsstudien wie die xclock Linux-Armbanduhr auf der CeBIT 2001 laufen Linux-Versionen genauso auf IBM-Großrechnern wie auf PDAs. Es gibt kaum eine Hardware, die sich nicht durch eine Linux-Variante steuern lassen würde. In diesem Fahrwasser erfahren auch die anderen kommerziellen Unix-Systeme eine Renaissance. Insbesondere bei der Servertechnologie für das Internet heißt die Plattform heute mehr den je Unix.
36
KAPITEL 3
Anmelden und Arbeiten an Unix-Systemen Bevor die ersten Schritte unter Unix gemacht werden können, bedarf es zunächst einmal eines Unix-Systems zum Üben. Anders als beim PC, der wie der Name ja schon sagt ein »Persönlicher Computer« ist, bei dem man sein persönliches Exemplar vor sich hat, kann der Zugang zu einem Unix-System zwischen einer eigenen Unix-Workstation, einem ASCII- oder grafischen Terminal an einem Server-Rechner oder einem PC mit einer entsprechenden Zugangssoftware variieren. Ebenso groß wie die Bandbreite beim Zugang zu einem Unix-System ist die Art des Arbeitens auf Unix-Systemen, die nach der Anmeldung auf den Benutzer wartet. Im einfachsten, allerdings auch unkomfortabelsten Fall meldet sich der Benutzer über ein ASCII-Terminal oder eine Terminal-Emulationssoftware von einem PC aus auf einem Unix-Rechner an. Für diesen Fall benötigt er lediglich eine Benutzerkennung (auch Account genannt) und ein Passwort. In diesem einfachsten Fall erfolgt die Eingabe nur über die Tastatur und die Ausgabe nur zeichen- und zeilenweise als Text in nur einem Bildschirmfenster. Sollte Ihr Zugang zu einem Unix-System so aussehen, können Sie den Rest dieses Kapitels getrost auf einen späteren Zeitpunkt verschieben. Alle, die das Glück haben, mit einer Workstation zu arbeiten oder sich von einem grafischen Terminal aus anmelden, werden schon bei der Anmeldung mit dem Fenstersystem X-Window konfrontiert.1 Zwar ist hier das Einloggen zunächst auch nicht komplizierter als bei der ASCII-Variante, aber spätestens wenn man den ersten Befehl eingeben will, bedarf es einiger Grundkenntnisse über den Umgang mit dem Fenstersystem. Bei X-Window-Systemen erfolgt 1. Näheres dazu in Kapitel 12.
37
KAPITEL
3
Anmelden und Arbeiten an Unix-Systemen
die Eingabe über Tastatur und Maus und die Ausgabe von Text und Bildern kann in mehreren Bildschirmfenstern erfolgen.
3.1
Grundsätzliche Bedienung von X-Window-Systemen
Unter X-Window öffnet eine grafische Applikation in der Regel mindestens ein Fenster. Ein Fenster ist dabei ein rechteckiger Bereich, der vom WindowManager mit einem Rahmen umgeben wird. An diesem Rahmen sind eine Reihe von Bedienelementen angebracht, die dem Benutzer unterschiedliche Operationen mit den Fenstern ermöglichen wie z.B. Verschieben, Vergrößern und Schließen. Welche Bedienelemente in den Rahmen eines Fensters integriert sind, hängt zum einen von der Applikation und zum anderen von dem verwendeten Window-Manager ab. Der eigentliche Fensterinhalt wird durch die Applikation bestimmt, die das Fenster geöffnet hat. Der Inhalt dieser Fenster kann rein textuell, rein grafisch oder ein Mix aus beidem sein. Um eine Eingabe in einem zu einer bestimmten Applikation gehörenden Fenster zu machen, muss dieses Fenster aktiv sein. Man spricht auch davon, dass dieses Fenster den Eingabefokus hat. Je nach Einstellung des WindowManagers kann dies dadurch erreicht werden, dass das Fenster mit der Maus angeklickt wird oder sich der Mauszeiger über dem Fenster befindet.
3.1.1
Die Maus
In der Regel werden auf X-Window-Systemen Drei-Tasten-Mäuse zur Steuerung der grafischen Bedienoberfläche eingesetzt. Dabei sind die Tasten mit bestimmten Funktionen belegt, die nahezu für alle Anwendungen identisch sind. Deshalb sollen diese Funktionen hier kurz vorgestellt werden. Die linke Maustaste wird sicherlich am häufigsten benutzt werden. Sie dient zur Auswahl und Betätigung von Bedienelementen, d.h., taucht in der Bedienoberfläche einer Anwendung ein Button auf, kann der Benutzer ihn mit der linken Maustaste betätigen. Das Gleiche gilt für die Bedienelemente im Rahmen eines Shell-Fensters (s.u.). In den Shell-Fenstern dient die linke Maustaste darüber hinaus auch zur Selektion von Text (Mauszeiger platzieren, linke Maustaste drücken und mit gedrückter Taste über den zu selektierenden Text fahren). Die mittlere Maustaste wird in der Regel von Anwendungen mit Sonderfunktionen belegt. So dient sie z.B. in einem Shell-Fenster dazu, selektierten Text an der aktuellen Eingabemarke wieder einzufügen (Copy&Paste).
38
Grundsätzliche Bedienung von X-Window-Systemen Die rechte Maustaste ist die so genannte Menütaste. Mit ihr werden PopupMenüs aufgeschaltet. Welches Popup-Menü erscheint, ist von der Position des Mauszeigers oder genauer von der Anwendung, über deren Fenster er sich befindet, abhängig. Um einen Menüpunkt auszuwählen, muss der Benutzer die rechte Maustaste solange gedrückt halten, bis der Mauszeiger über dem auszuwählenden Eintrag steht. Wird die Taste dann losgelassen, wird der Menüeintrag ausgeführt. In manchen Fällen hat die rechte Maustaste auch noch andere Funktionen, z.B. im Scrollbar eines Motif-Terminalfensters, wo man durch abwechselndes Drücken der linken und rechten Maustaste vorund zurückblättern kann. Fenster und Icons werden von den meisten Window-Managern auf dem Desktop oder auch Main Window angeordnet. Dieser Bildschirmhintergrund symbolisiert einen Schreibtisch, auf dem die einzelnen Fenster wie Blätter übereinander geschichtet und verschoben werden können. Welche Funktionen hier angeboten werden, ist abhängig vom Window-Manager.
3.1.2
Die Shell-Fenster
Die wichtigste Komponente der grafischen Bedienoberfläche für den UnixBenutzer sind die so genannten Shell-Fenster. Auf den meisten Systemen wird man so genannte xterm als Shell-Fenster verwenden. Allerdings gibt es auch hier wieder Unterschiede, die entweder durch den Window-Manager oder den Hersteller bedingt sind.
Terminalemulation In jedem dieser Fenster wird ein Terminal emuliert. Sie sind also vergleichbar mit an den Rechner angeschlossenen ASCII-Terminals. Im Gegensatz zu einem ASCII-Terminal muss sich der Benutzer aber nicht in jedem Shell-Fenster erneut am Betriebssystem anmelden. Während einer Bildschirmsitzung kann der Benutzer beliebig viele solcher Shell-Fenster öffnen.1 In jedem dieser Shell-Fenster läuft eine Shell – der Kommandointerpreter des Unix-Betriebssystems. Somit können in jedem dieser Fenster Unix-Kommandos abgesetzt werden. Wie andere Fenster auch, besitzt jedes Shell-Fenster einen Fensterrahmen. Dieser Rahmen wird durch den Window-Manager erzeugt und beinhaltet eine Reihe so genannter Handles. Ein Handle ist dabei eine Schaltfläche bzw. ein Bereich des Rahmens, über den sich bestimmte Funktionen des WindowManagers für ein Fenster ausführen lassen.
1. Die Menge ist nur durch den zur Verfügung stehenden Hauptspeicher und die maximal verfügbare Anzahl von Prozessen beschränkt.
39
KAPITEL
3
Anmelden und Arbeiten an Unix-Systemen
Abb. 3.1: Shell-Fenster
Neben dem Namen der Anwendung stellt der Titlebar auch noch ein eigenes Popup-Menü zur Verfügung. In diesem Menü befinden sich Funktionen, um das Fenster zu verschieben (MOVE), es nach oben zu holen (RAISE) oder nach unten zu schieben (LOWER). Daneben werden auch die Funktionen angeboten, die über die Bedienelemente am Rahmen erreichbar sind (MAXIMIZE, ICONIFY, CLOSE und RESIZE). Der CLOSE-Knopf schließt das Fenster. Allerdings sollte diese Funktion nur in Ausnahmefällen benutzt werden, um eine Anwendung zu beenden, da sie nur das Fenster schließt, unter Umständen aber die in dem Fenster laufenden Anwendungen nicht beendet oder umgekehrt die darin laufende Anwendung abbricht (»killt«), bevor diese ihre Aufgabe richtig beendet hat. Mit dem MAXIMIZE-Knopf wird das Fenster auf die maximale Fenstergröße ausgedehnt. Diese kann manchmal auch über die Bildschirmgröße hinausgehen. Mit dem ICONIFY-Knopf wird das Fenster zu einem Sinnbild (Icon) »geschrumpft«. Sinn eines Icons ist es, die Anwendung weiterhin geöffnet zu halten, ohne dass das Fenster der Anwendung Teile des Bildschirms bedeckt. Die vier Ecken eines Shell-Fensters sind im Allgemeinen als Resize Handles ausgelegt. Über die Ecken des Fensters kann dessen Größe verändert werden. Dazu wird der Mauszeiger auf eine Ecke des Fensters bewegt und die linke Maustaste gedrückt. Wird nun mit gedrückter Maustaste der Mauszeiger bewegt, wird die Fenstergröße verändert. Die Größe wird durch einen Minimalund einen Maximalwert begrenzt, die durch die Anwendung vorgegeben sind.
40
Grundsätzliche Bedienung von X-Window-Systemen Mit dem Scrollbar kann der Bediener »im Fensterinhalt zurückblättern«, d.h., er kann die Anzeigen, die zuvor in diesem Fenster gemacht worden, aber durch neue Ausgaben aus dem Bild nach oben verschwunden (neudeutsch: »gescrolled«) sind, zurückholen.
3.1.3
Icons
1
Icons stehen für Anwendungen, deren Fenster zu Sinnbildern »geschrumpft« worden sind (iconifiziert). Die zu einem Icon gehörende Anwendung läuft noch, auch wenn durch die Iconifizierung keine Ausgaben oder Veränderungen der Bedienoberfläche mehr erkennbar sind. Deshalb sollten Anwendungen nur dann iconifiziert werden, wenn mit ihnen noch weitergearbeitet werden soll. Sonst verbrauchen sie nur Rechenzeit und Speicher. Icons werden auf dem Desktop abgelegt und bleiben solange erhalten, bis der Benutzer die zugehörige Anwendung beendet oder das Icon deiconifiziert. Abb. 3.2: Icon eines Shell-Fensters
Um das zu dem Icon gehörige ursprüngliche Fenster wiederherzustellen, kann entweder die Funktion RESTORE aus dem Popup-Menü des Icons benutzt oder ein Doppelklick mit der linken Maustaste auf das Icon ausgeführt werden.
1. Icon (engl.): Symbol, kleines Bild
41
KAPITEL 4
Erste Schritte Die ersten Schritte sind bekanntlich immer die schwersten. In diesem Kapitel sollen die ersten Gehversuche mit dem Betriebssystem Unix beschrieben und einige grundlegende Techniken vermittelt werden, die helfen, im Umgang mit Unix nicht in Bedrängnis zu geraten. Wenn Eingaben an das Unix-Betriebssystem abgeschickt werden, müssen folgende grundlegenden Eigenschaften beachtet werden: ✘ Unix geht davon aus, dass seine Benutzer wissen, was sie tun. ✘ Die Benutzerführung beschränkt sich im Wesentlichen auf Fehlermeldungen. ✘ Sicherheitsabfragen sind quasi nicht existent. ✘ Gelöschte Dateien bleiben gelöscht. Nur eine vorangegangene Datensicherung kann hier helfen. Das klingt zugegebenermaßen abschreckend und wenig sympathisch. Der Ursprung dafür liegt in der Geschichte – Unix wurde als ein »System von Software-Entwicklern für Software-Entwickler« entworfen und nicht für den Benutzer von Standardsoftware. Unix ist ein Multiuser-System und obwohl es auch auf PCs zum Einsatz kommt, bietet es stets mehreren Benutzern die Möglichkeit, gleichzeitig (z.B. über ein Local Area Network (LAN)) auf einem Rechner zu arbeiten. Damit sich die Benutzer nicht gegenseitig behindern oder (ungewollt) Daten löschen, hat jeder eine Art »Privatsphäre« auf dem Rechner, geschützt durch eine Benutzerkennung (auch Account genannt) und ein Passwort. Gehen Sie immer
43
KAPITEL
4
Erste Schritte
vorsichtig mit diesen beiden Dingen um, denn »wer Einbrechern Tür und Tor öffnet, muss sich nicht wundern, wenn er beklaut wird«. Nach der Anmeldung wird als erstes Programm für den Benutzer in der Regel ein Kommandointerpreter – die Shell – automatisch gestartet.1 Die Shell signalisiert dem Benutzer durch die Anzeige eines so genannten Prompts2 ihre Bereitschaft zur Entgegennahme von Benutzereingaben. Die als Prompt verwendete Zeichenfolge ist durch den Benutzer konfigurierbar. In dieser Unterlage sieht ein Prompt immer wie folgt aus:
3
UNIX-Kurs [~] 4 >
In den eckigen Klammern wird das aktuelle Arbeitsverzeichnis, das so genannte Working Directory, angegeben.3 Mit der Zahl werden die einzelnen Kommandos durchnummeriert. Soll der Kommandointerpreter wieder verlassen werden, was gleichbedeutend mit dem Abmelden vom System bzw. Schließen des Fensters ist, wird einfach die Zeichenfolge exit hinter dem Prompt eingegeben und das Kommando mit der Return-Taste Æ ausgelöst.
4.1
Kommandoeingabe
Nachdem nun das An- und Abmelden beherrscht wird, kann als nächster Schritt die Eingabe von Kommandos folgen. Eingaben nimmt dabei stets eine Shell entgegen. Die Shell unterscheidet generell zwischen Groß- und Kleinbuchstaben. Unix ist also ein case-sensitives Betriebssystem. Unter Unix ist ein Kommando nichts anderes als ein Programm, welches in der Sprache der jeweiligen Hardware (Maschinensprache) oder in Form eines so genannten Shell-Scripts in der Sprache des Kommandointerpreters vor-
1. Auf Rechnern mit Fenstersystemen kann das eventuell anders sein. In diesem Fall muss der Benutzer erst ein entsprechendes Fenster öffnen. 2. to prompt (engl.): einflößen, eingeben. 3. Die Tilde (~) steht für das Home Directory, das Verzeichnis, in dem sich ein Benutzer unmittelbar nach dem Anmelden befindet. Die Begriffe werden in den folgenden Abschnitten genauer erläutert.
44
Kommandoeingabe liegt. Dieses Programm ist in einer Datei abgelegt und wird über den Namen der Datei angesprochen. Das bedeutet, alle Namen von Dateien, die Programme enthalten, sind zunächst gültige Unix-Kommandos.1 Um einem Programm mitzuteilen, welche Aufgabe es zu erfüllen hat, kann der Benutzer dem Programmaufruf meist weitere Informationen hinzufügen. Diese Informationen werden nach dem Programmnamen eingegeben. Sie werden Kommandozeilenparameter oder kurz Parameter genannt. Die einzelnen Parameter werden dabei durch Leerzeichen voneinander getrennt. Mehrfache Leerzeichen oder Tabulatoren gelten wie ein einfaches Leerzeichen als Trenner zwischen den Parametern. Spezielle Parameter sind die so genannten Optionen, die im allgemeinen als erste Parameter dem Kommandonamen folgen und die, zur Unterscheidung von den Datenparametern, normalerweise mit einem führenden Minuszeichen (-) beginnen. Während in den Datenparametern z.B. Dateinamen an das Programm übergeben werden, steuern die Optionen das Verhalten des Kommandos. So kann ein Kommando mit unterschiedlichen Optionen verschiedene Aufgaben erfüllen oder verschiedene Ausgaben erzeugen. Bestehen die Optionen für ein Kommando nur aus einzelnen Zeichen und sollen mehrere Optionen gleichzeitig eingegeben werden, lassen sie sich zu Optionsblöcken zusammenfassen. Die Optionen -l und -a können dann z.B. als -la angegeben werden.
UNIX-Kurs [~] 5 > ls -l -a UNIX-Kurs [~] 6 > ls -la
3
Bei der Angabe einiger Optionen bedarf es noch zusätzlicher Parameter, um das Kommando ausführen zu können. Diese Parameter werden als Argumente bezeichnet. Argumente folgen, meist durch Leerzeichen getrennt, direkt der zugehörigen Option. Werden die Optionen zu einem Optionsblock zusammengefasst, folgen die Argumente in der Reihenfolge, in der die zugehörigen Optionen im Optionsblock auftauchen. Wurden alle Eingaben in der Kommandozeile hinter dem Prompt angegeben, so erfolgt die Ausführung durch Betätigen der Return-Taste (Æ). Vor dem Drücken der Return-Taste sind Korrekturen der Eingabezeile mit der Backspace-Taste (Ã) möglich.
1. Diese vereinfachte Sicht wird durch das Vorhandensein von Zugriffsrechten ein wenig eingeschränkt.
45
KAPITEL
4
Erste Schritte
Zusammenfassend sieht eine Kommandoeingabe unter Unix wie folgt aus:
3
UNIX-Kurs [~] 7 >
↑ Prompt
fold
-w
40
↑
↑
↑
↑
Option
Argument
Datenparameter
Kommando
beispiel.txt
Nicht für alle Programme sind Optionen, Argumente oder Datenparameter zwingend erforderlich. Es gibt Kommandos, die auch ohne Parameter sinnvolle Aufgaben erfüllen. Unter Umständen kann die Angabe von zu vielen oder zu wenigen Parametern sogar zu einem ungewollten Verhalten des Kommandos führen. Gerade weil die Anzahl der Parameter das Verhalten eines Kommandos maßgeblich beeinflussen kann, ist es nötig, einen weiteren essentiell wichtigen Mechanismus bei der Kommandoeingabe zu kennen – das Quoting. Auf diesen Mechanismus wird später detailliert eingegangen, an dieser Stelle soll zunächst eine Variante vorgestellt werden. Das Quoting nutzt die unterschiedlichen Anführungszeichen (Quotes), um Parameter, in denen ein oder mehrere Leerzeichen oder andere Sonderzeichen vorkommen, zusammenzuhalten. Sie werden damit wie eine Zeichenkette behandelt.
3
programm zwei parameter
(Ohne Quotes ist das Leerzeichen ein Trennzeichen, ...) programm "ein parameter"
(... innerhalb doppelter Anführungszeichen nicht.)
Soll also ein Leerzeichen zwischen zwei Worten in der Kommandozeile die beiden Worte nicht auch zu zwei Parametern für das Kommando machen, sind die beiden Worte mit doppelten Anführungszeichen (Double Quotes) zu umgeben.
4.2
Online-Hilfe
Die Syntax eines Kommandos ist damit generell beschrieben. Doch in Bezug auf die Vorbemerkung, dass Unix seine Benutzer nicht durch Sicherheitsabfragen vor Fehlbedienungen schützt, ist das Wissen um eine korrekte Syntax nicht hinreichend. Vielmehr muss der Benutzer wissen, was ein Kommando in Kombination mit welchen Optionen und Parametern leistet.
46
Online-Hilfe Damit sich der Benutzer nicht alle Kommandos merken oder unkomfortabel in einem Handbuch nachschlagen muss, verfügt jedes Unix-Betriebssystem über die so genannten Manual-Pages (oder kurz man-Pages). Hierbei handelt es sich um ein Online-Hilfesystem, über das die Optionen und Parameter für ein Kommando abgefragt werden können. Die entsprechende man-Page liefert eine ausführliche Beschreibung des Kommandos. Der Benutzer muss lediglich den Namen des Kommandos kennen und diesen als Parameter an das Kommando man übergeben. Falls man den Befehlsnamen nicht weiß, kann man mit der Option -k über Schlüsselwörter (engl.: keywords) nach den Befehlsnamen suchen (vgl. Kapitel 4.3).
UNIX-Kurs [~] 8 > man file
Die Ausgabe dieses Kommandos zeigt die folgende Abbildung:
3 Abb. 4.1: man-Page des Kommandos file
Eine man-Page beginnt immer mit einer Kurzbeschreibung des Kommandos. Hier wird in einem Satz (in Abb. 4.1 file – determine file type) versucht, die Wirkungsweise des Kommandos zu beschreiben.
47
KAPITEL
4
Erste Schritte
Der Kurzbeschreibung folgt die Synopsis. Diese Syntaxbeschreibung enthält eine Auflistung aller Optionen, Schreibweisen und zulässiger Parameterkombinationen. Der Synopsis schließt sich die Description an, in der die Wirkungsweise, die zu erwartenden Ausgaben und jede einzelne Option beschrieben sind. Im Abschnitt Files der man-Page stehen Verweise auf Dateien, die im Zusammenhang mit dem Kommando stehen. Unix besteht aus einer Sammlung vieler kleiner Programme mit ganz spezifischen Aufgaben, die bezüglich ihrer Aufgaben oftmals in einer engen Beziehung stehen. Im Abschnitt See also der man-Page werden Kommandos aufgeführt, die im Zusammenhang mit dem Kommando dieser man-Page stehen. Oftmals erweisen sich diese Verweise als wertvolle Hilfe, um das richtige Kommando für die zu lösende Aufgabe zu finden.
1
Bevor Sie ein unbekanntes Unix-Kommando ausführen, sollten Sie immer die zugehörige man-Page gelesen haben, um keine bösen Überraschungen zu erleben.
4.3
Grundlegende Befehle
Auch wenn es die man-Pages gibt, sollte der Benutzer über einen gewissen »Grundwortschatz« an Unix-Kommandos verfügen. Der Grundstein dafür soll in diesem Abschnitt gelegt werden.
4.3.1
man
Das Kommando man dient zur Anzeige der man-Page für ein Kommando oder zur Suche nach Kommandos. man bietet für diese beiden Aufgaben zwei unterschiedliche Syntaxvarianten an:
6 48
man [Optionen] Kommandoname/namen
Als Parameter können ein oder mehrere Kommandonamen angegeben werden. Die man-Pages werden seitenweise angezeigt. Mit der Leertaste blättern Sie auf die jeweils nächste Seite vor.
Grundlegende Befehle
man -k Schlüsselwort/worte
-k
Wird man mit der Option -k aufgerufen (k für keyword), so sind als Parameter statt Kommandonamen Schlüsselworte anzugeben.1 Tauchen diese Schlüsselworte in der Kurzbeschreibung der man-Page eines Kommandos auf, so wird die Kurzbeschreibung ausgegeben.
6
man -k ist die wichtigste Hilfe, um nach Befehlen für bestimmte Aufgaben zu
suchen.1
UNIX-Kurs [~] 9 > man -k printer banner (6) - Print large banner on printer lp (4) - Line printer devices lpc (8) - Line printer control program lpd (8) - Line printer spooler daemon lprm (1) - Remove jobs from line printer spooling queue lptest (1) - Generate lineprinter ripple pattern pac (8) - Printer/plotter accounting information printcap (5) - Printer capability data base xdpr (1) - Dump an X window directly to a printer
3
Die Nummern in den Klammern geben die »Kapitel« der Online-Dokumentation an. Für Benutzer sind in erster Linie die in Kapitel (1) enthaltenen Kommandos und die in Kapitel (5) enthalten allgemeinen Erklärungen interessant. Die anderen Kapitel sind nur für Systemprogrammierer und Systemadministratoren wichtig.
4.3.2
file
Mit dem Kommando file kann der Benutzer den Typ des Inhalts einer Datei erfragen. Er kann damit z.B. feststellen, ob es sich um eine Textdatei oder ein Programm handelt. Bevor der Inhalt einer Datei auf irgendeine Weise auf dem Bildschirm angezeigt wird, sollte auf jeden Fall durch einen Aufruf von file sichergestellt werden, dass es sich um eine Textdatei handelt!
file [Optionen] Datei/Dateien
6
1. Auf einigen Systemen wird man -k durch das Kommando apropos ersetzt.
49
KAPITEL
3
4
Erste Schritte
UNIX-Kurs [~] 10 > file abc.txt abc.txt: ascii text
4.3.3
who
Das Kommando who zeigt an, welche Benutzer zurzeit auf dem Unix-Betriebssystem arbeiten und an welchen Bildschirmen bzw. Terminals sie sitzen. Auf einigen Systemen wird zusätzlich ausgegeben, wenn die Benutzer über das Netz angemeldet sind.
6
3
who [Optionen]
Mit der speziellen Schreibweise who am I erhält der Benutzer Informationen darüber, an welchem Terminal er mit seiner aktuellen Shell arbeitet. Die wichtigsten Optionen lauten: -H
Mit dieser Option wird eine Überschrift (Header) über die Spalten der normalen Ausgabe des who gesetzt.
-a
Diese Option bewirkt die Ausgabe aller verfügbaren Informationen.
UNIX-Kurs [~] USER LINE lutz tty1 ralph tty3
4.3.4
11 > who -aH LOGIN-TIME IDLE FROM Jan 20 13:37 . Jan 20 15:44 .
uname
Das Kommando uname -a liefert Ihnen Informationen darüber, wie der Rechner heißt, an dem Sie sich angemeldet haben, und mit welcher Betriebssystemversion Sie arbeiten. Je nach Betriebssystem werden folgende Informationen angegeben: ✘ Betriebssystemname ✘ Rechnername ✘ weitere Angaben zur Version des Betriebssystems und zur Hardware (Rechnersystem, CPU)
50
Grundlegende Befehle
Ausgaben eines Silicon-Graphics-Rechners: UNIX-Kurs [~] 12 > uname -a IRIX sbfft22 6.3 12161207 IP32
3
Ausgaben unter Linux: UNIX-Kurs [~] 13 > uname -a Linux yasc 2.0.25 #5 Sat Feb 1 22:04:36 MET 1997 i586
4.3.5
cat
Das Kommando cat (concatenate) dient zur Ausgabe des Inhalts einer Datei auf dem Bildschirm. Allerdings ist hierbei Vorsicht geboten.
Nur Textdateien sollten auf dem Bildschirm ausgegeben werden!
Alle anderen Dateien könnten Steuerzeichen enthalten, welche die Einstellungen des Terminals verändern können. Um zweifelsfrei ermitteln zu können, ob es sich um eine Textdatei handelt, sollte das Kommando file benutzt werden.
cat [Optionen] Datei/Dateien
UNIX-Kurs [~] 14 > cat beispiel.txt Dies ist ein Beispiel fuer eine Text-Datei: yasc Informatik GmbH 38114 Braunschweig
4.3.6
2 6 3
more
Ein Nachteil des Kommandos cat ist, dass lange Textdateien auf dem Bildschirm am Leser nur so »vorbeirauschen« und er im Endeffekt nur die letzte Bildschirmseite des Inhalts zu sehen bekommt. Für solche langen Textdateien, die nicht in einem Editor betrachtet werden sollen, hält Unix so genannte Pager bereit. Das sind Kommandos, die Dateien bildschirmseitenweise anzeigen und erst auf die nächste Seite blättern, wenn der Benutzer auf eine ent-
51
KAPITEL
4
Erste Schritte
sprechende Taste drückt. Der gebräuchlichste dieser Pager ist more, welcher u. a. auch bei den man-Pages eingesetzt wird.
6
more [Optionen] [Datei/Dateien]
Wurde eine Datei in den Pager geladen, so blättert more bei einem Druck auf die Leertaste eine Bildschirmseite weiter. Bei einem Druck auf das q bricht more die Ausgabe ab. Bei Druck auf Æ wird eine Zeile »weitergeblättert«. Mit einem Slash »/«, gefolgt von einem Suchmuster, kann nach Worten in dem von more angezeigten Text gesucht werden.
4.3.7
ls
list – Das Kommando ls ist einer der wichtigsten Unix-Befehle. Mit ls können die Dateien im aktuellen Verzeichnis aufgelistet werden. Um die Optionen des ls zu verstehen, muss allerdings mehr Wissen über den Dateibegriff unter Unix sowie den Aufbau des Dateisystems vorhanden sein. Deshalb soll an dieser Stelle das Kommando nur kurz erwähnt werden.
6 3
ls [Optionen] [Datei/Dateien]
UNIX-Kurs [~] 15 > ls
4.3.8
mail
Über das Kommando mail kann Electronic Mail (kürzer: E-Mail) an andere Benutzer verschickt werden. Inwieweit das Mail-System genutzt werden kann, hängt davon ab, ob der Rechner in ein Netz integriert ist und ob das Mail-System auch für diese Vernetzung eingerichtet wurde. Ist der Rechner nicht für netzwerkweite oder internetweite Mail ausgelegt, kann nur Mail auf dem lokalen Rechner verschickt werden. Eine E-Mail-Adresse, über die der Empfänger für eine Nachricht angesprochen wird, setzt sich zusammen aus einer Benutzerkennung und einer so genannten Domain, die angibt, wo sich der Empfänger befindet.
52
Grundlegende Befehle
[email protected]
↑
↑
3
Benutzerkennung Domain
Eventuell können vor der Domain noch Subdomains stehen und vor diesen noch der Name eines expliziten Rechners. Häufig werden statt der Klarnamen auch einfach nur die Loginnamen als Benutzerkennung verwendet. Wird nur lokale Mail verschickt, so entfallen der Klammeraffe (»@« – wird at gesprochen) und die Domain. Das Kommando mail, gefolgt von der Angabe des Empfängers, ist zunächst mit Æ abzuschließen. Anschließend wird die zu versendende Nachricht eingegeben, die dann nach einem abschließenden Æ durch die Tastenkombination ŸD versandt wird.
mail [Optionen] Empfängeradresse
UNIX-Kurs [~] 16 > mail ralph Hallo Ralph :-)), Dies ist ein Beispiel fuer eine E-Mail mit einer lokalen Adresse.
6 3
Ciao Lutz
ŸD
Leider ist der mail-Befehl nicht auf allen Rechnersystemen zu finden. Dort werden mail-Programme wie z.B. mailx als Ersatz für mail oder das komfortablere elm verwendet.
4.3.9
1
echo
Das Kommando echo dient der Ausgabe von Zeichenketten auf dem Bildschirm. echo lässt sich sehr gut zum Testen der Funktionalität von Sonderzeichen benutzen.
53
KAPITEL
6 3
4
Erste Schritte
echo [Zeichenkette/Zeichenketten]
Leerzeichen trennen auch beim Kommando echo die einzelnen Zeichenketten. Eine Zeichenkette, die Leerzeichen enthält, muss also auch in Quotes eingeschlossen werden, wenn echo mehrere Leerzeichen in der Eingabe nicht zu einem Leerzeichen in der Ausgabe zusammenfassen soll.
UNIX-Kurs [~] 17 > echo Hallo Hallo Test mit echo
4.3.10
"Test
mit" echo
date
date zeigt das aktuelle Datum und die Uhrzeit an. Dies geschieht im amerika-
nischen Datumsformat. An dieser Stelle sei erwähnt, dass es unter Unix Kommandos gibt, die ähnlich oder genauso heißen wie DOS-Befehle, aber anders funktionieren. Da date bereits die Uhrzeit mit ausgibt, liegt die Vermutung nahe, dass das Unix-Kommando time etwas ganz anderes macht – lesen Sie auf jeden Fall zunächst die man-Page, bevor Sie es ausführen.
6
date [+Formatstring]
Das amerikanische Datumsformat ist für den nicht amerikanischen Benutzer oft schwer zu lesen. Abhilfe bietet hier die Möglichkeit von date, mittels eines Formatstrings die Ausgabe des Datums zu verändern. Da der Formatstring als ein Parameter an das date übergeben werden muss, er aber oft Leerzeichen enthält, wird er in der Regel zusammen mit dem einleitenden »+« gequotet – also in doppelte Hochkommas eingeschlossen. Der Formatstring kann aus beliebigen Zeichen und den Platzhaltern für die Datumskomponenten bestehen. Die Platzhalter bestehen immer aus einem Prozentzeichen (»%«) mit einem nachgestellten Buchstaben. Folgende Platzhalter sind unter anderen definiert:
54
%d
Tag des Monats (01-31)
%m
Monat des Jahres (01-12)
%y
die letzten beiden Stellen einer vierstelligen Jahreszahl (00-99)
%b
abgekürzter englischer Monatsname
Grundlegende Befehle
%B
ausgeschriebener englischer Monatsname
%Y
das Jahr als vierstellige Jahreszahl
%H
die Stunde im 24-Stunden-Format (00-23)
%M
die Minuten (00-59)
%S
die Sekunden (00–59)
%a
abgekürzter englischer Wochentagname
%A
ausgeschriebener englischer Wochentagname
UNIX-Kurs [~] 18 > date "+Heute ist der %d.%m.%Y" Heute ist der 24.02.1997
4.3.11
3
passwd
Mit dem Kommando passwd kann der Benutzer sein eigenes Passwort ändern. Er muss dazu sein altes Passwort kennen und eingeben. Das neue Passwort muss sich an mindestens zwei Stellen von dem alten Passwort unterscheiden und sollte zwischen sechs und acht Zeichen lang sein. Viele Systeme verlangen, dass ein Passwort mindestens zwei Sonderzeichen enthält.
UNIX-Kurs [~] 19 > passwd Enter old password: Enter new password: Re-Enter new password: Password was changed
3
Das neue Passwort muss zweimal eingegeben werden. Da es aus Sicherheitsgründen nicht auf dem Bildschirm angezeigt wird, kann es leicht zu Tippfehlern kommen, sodass dieser Sicherheitsmechanismus angebracht ist.
Gehen Sie sorgsam mit Ihrem Passwort um – behandeln Sie es wie die Geheimnummer Ihrer Euroscheckkarte oder wie Ihren Wohnungsschlüssel. Sie schützen damit nicht nur Ihre eigenen Dateien, sondern den gesamten Rechner gegen »Hacker«. Wählen Sie ein Passwort, das fremde Leute nicht leicht erraten können. Schreiben Sie Ihr Passwort niemals auf, und speichern Sie es niemals in einer Datei ab. Falls Sie Ihr Passwort vergessen sollten, kann Ihnen der Systemadministrator jederzeit ein neues Passwort einrichten.
2 55
KAPITEL
4
Erste Schritte
Übungen
4.4
Aufgaben
1. Rufen Sie die man-Page für das Kommando xterm auf und versuchen Sie, die Option zu finden, mit der sich der Titel für das Fenster einstellen lässt. Probieren Sie diese Option aus, indem Sie ein neues Fenster über den Befehl xterm mit der entsprechenden Option öffnen. 2. Rufen Sie die man-Page für das Kommando man auf. 3. Suchen Sie alle Kommandos zu dem Schlüsselwort »time«. 4. Prüfen Sie den Inhalt der folgenden Dateien mit dem Kommando file. Geben Sie dazu den Dateinamen wie hier abgedruckt in der vollen Länge an. /etc/passwd /bin/rm .login /usr
5. Was liefert Ihnen das Kommando who am I? Schlagen Sie zuerst in der entsprechenden man-Page nach. 6. Gibt es einen Unterschied in der Ausgabe der beiden folgenden Befehle? Wenn ja, dann versuchen Sie ihn zu begründen. Achten Sie bitte darauf, dass zwischen den Wörtern mehrere Leerzeichen eingegeben werden. echo "eins echo eins
zwei zwei
drei" drei
7. Versuchen Sie, mit dem Befehl date eine Ausgabe der Form Datum: 15.03.97 Zeit : 10:35:26
zu erzeugen. Den Zeilenumbruch erreichen Sie durch ein %n an der entsprechenden Stelle im Formatstring. 8. Was ist an dem folgenden Kommando falsch und warum? date +Es ist jetzt %H:%M
56
Aufgaben
4.4.1
Lösungen
1. Durch Eingabe des Kommandos UNIX-KURS [~] 1 > man xterm
erhält man die entsprechende Manual-Page für den Befehl xterm. Wie Sie dort nachlesen können, öffnet der Befehl xterm ein neues Shell-Fenster. Eine Möglichkeit, den Titel des neuen Fensters festzulegen, ist die Option -T: UNIX-KURS [~] 2 > xterm -T "Meine neue Shell"
2. Natürlich existiert auch eine Beschreibung des Hilfesystems man. Durch Eingabe von UNIX-KURS [~] 3 > man man
erhält man eine Beschreibung zur Bedienung der Manual-Pages. 3. In der Manual-Page zu dem Befehl man ist die Option -k beschrieben. Sie sorgt dafür, dass die Manual-Pages nach Schlüsselwörtern und nicht nach Kommandonamen durchsucht werden. Daher listet der Befehl UNIX-KURS [~] 4 > man -k time
alle Kommandos auf, in deren einzeiliger Kurzbeschreibung das Wort »time« vorkommt.
4. Das Kommando file untersucht, um welche Art Datei es sich handelt. Die Resultate der Untersuchung lauten: UNIX-KURS [~] 5 > file /etc/passwd /etc/passwd: ascii text UNIX-KURS [~] 6 > file /bin/rm /bin/rm: ... executable ...
Sie können dem Befehl auch gleich mehrere Dateien zur Untersuchung übergeben: UNIX-KURS [~] 7 > file .login /usr .login: ascii text /usr: directory
Eventuell existieren nicht alle in der Aufgabe angegebenen Dateien auf Ihrem eigenen Unix-System. Dann untersuchen Sie einfach eigene Dateien in Ihrem Home Directory. 5. Das Kommando who am I gibt Ihnen Auskunft darüber, wie Ihre Benutzerkennung lautet, welches Terminal Sie benutzen und wann Sie sich eingeloggt haben.
57
KAPITEL
4
Erste Schritte
6. Die Shell interpretiert ein Leerzeichen als Trenner zwischen Befehl und Optionen/Dateinamen. Folgen zwei Leerzeichen aufeinander, so fasst die Shell diese zusammen. Daher sieht die Ausgabe des Kommandos UNIX-KURS [~] 8 > echo eins
zwei
drei
wie folgt aus: eins zwei drei
Sollen die Leerzeichen mit ausgegeben werden, so müssen diese vor der Shell »versteckt« werden. Dies geschieht durch das Quoting, also das Zusammenfassen einer Zeichenkette durch Anführungszeichen: UNIX-KURS [~] 9 > echo "eins eins zwei drei
zwei
drei"
7. Das Kommando date gibt das Datum und die Uhrzeit aus. Wie die Ausgabe zu erfolgen hat, kann durch Angabe eines Formatstrings festgelegt werden. Dabei werden für die Stunden, Minuten etc. Platzhalter benutzt, die in der Manual-Page genau beschrieben sind. Die Eingabe von date "+Datum: %d.%m.%y%nZeit : %H:%M:%S"
liefert das gewünschte Ergebnis. Beachten Sie die Groß- und Kleinschreibung! 8. Es fehlen die Quotes (Anführungszeichen). Das Kommando date erwartet einen Formatstring, der die Ausgabe der Stunden und Minuten festlegt. Ohne Anführungszeichen interpretiert das Kommando jeden einzelnen Teilstring als einen Eingabeparameter. SCO Unix liefert hier sogar eine Fehlermeldung.
58
KAPITEL 5
Das Unix-Dateisystem Für den Unix-Benutzer steht der Zugriff auf die Daten im Vordergrund seiner Tätigkeiten. Da unter Unix Daten immer in Dateien abgelegt sind, muss die Organisation dieser Dateien bekannt sein. Unix verfügt hierzu über ein hierarchisches Dateisystem.
5.1
Dateitypen
Unix verwendet einen sehr allgemeinen Dateibegriff, der Benutzern, die z.B. von DOS/Windows kommen, zunächst ungewohnt erscheint. Aus diesem Grund soll diese allgemeine Definition einer Datei genauer erläutert werden. Eine Datei ist eine Sammlung von Daten in strukturierter oder unstrukturierter Form, die unter einem logischen Namen zusammengefasst werden. Unix kennt folgende Klassen von Dateien: Unter dem Begriff Plain File werden Datendateien, wie sie auch von anderen Systemen bekannt sind, aber auch Programme zusammengefasst. Da Unix keine Extensions1 zur Unterscheidung der Programme von den Datendateien fordert, ist die Einteilung in dieselbe Klasse von Dateien nicht weiter ver1. Extensions sind Erweiterungen des Dateinamens um bestimmte Endungen und in vielen Betriebssystemen üblich. Sie erleichtern die Unterscheidung der Dateitypen bis hin zur Kennzeichnung ihres Inhalts. Die Tatsache, dass Unix keine festgeschriebenen Extensions vorgibt, sollte dennoch nicht davon abhalten, Dateien mit Endungen wie z.B. .txt für Textdateien zu versehen. Manche Software-Produkte erwarten sogar bestimmte Extensions wie beispielsweise .Z für komprimierte Dateien oder .f, .c und .java für Fortran-, C- und Java-Programme.
59
KAPITEL
5
Das Unix-Dateisystem
wunderlich, führt aber bei Neueinsteigern immer wieder zu Unterscheidungsproblemen. Hier kann das Kommando file helfen. Ein Directory unterscheidet sich von einem Plain File in drei wesentlichen Eigenschaften: ✘ Die Struktur der Datei für ein Directory ist durch das Betriebssystem vorgegeben und kann nicht verändert werden. ✘ Der Inhalt eines Directorys besteht aus Dateien (genauer: Namen von Dateien und Verweise auf die Daten). ✘ Verzeichnisse können nur mit bestimmten Befehlen erzeugt und gelöscht werden. Verzeichnisse werden unter Unix zum Aufbau einer Verzeichnisstruktur benutzt. Dahinter verbirgt sich eine Art Ablagesystem. Dieses Ablagesystem ist hierarchisch aufgebaut, d.h. es gibt einen Anfangs- bzw. Einstiegspunkt, von dem aus Unterverzeichnisse, Unterunterverzeichnisse usw. abzweigen. Dieses System von Verzeichnissen ist bis zu einem gewissen Punkt genormt, kann aber verändert werden. Da jedes Verzeichnis wieder Unterverzeichnisse enthalten kann, die ihrerseits wieder Unterverzeichnisse enthalten können, entsteht eine Struktur, die aufgrund ihrer Verzweigung auch Dateibaum oder Verzeichnisbaum genannt wird. Aufgrund dieser Analogie wird der Anfangspunkt auch root (engl. für Wurzel) genannt. Neben den Daten und dem zugehörigen Ordnungssystem (Verzeichnisse) muss ein Betriebssystem auch eine Reihe von zusätzlichen Informationen verwalten. In diese Kategorie fallen z.B. die Peripheriegeräte, das Netzwerk und andere Kommunikationskanäle. Hier bietet Unix dem Benutzer eine einheitliche geräteunabhängige Schnittstelle an, die auf der allgemeinen Definition des Dateibegriffs von Unix basiert. Geräte werden durch spezielle Dateien – die so genannten Device Descriptors oder Special Files – repräsentiert, über die auf sie zugegriffen werden kann. Der Zugriff erfolgt transparent durch den Betriebssystemkern (Kernel) und die Hardware-Schnittstellen, d.h. der Zugriff auf Peripheriegeräte stellt sich für den Benutzer nicht anders dar als der Zugriff auf eine Datendatei. Unix ist bezüglich der verwendbaren Dateinamen sehr flexibel. Es lassen sich im Prinzip alle druckbaren Zeichen für Dateinamen benutzen1, zwischen Groß- und Kleinbuchstaben wird unterschieden und die Länge eines Dateinamens beträgt bis zu 256 Zeichen.
1. außer dem Schrägstrich, der Verzeichnisnamen und Dateinamen trennt
60
Der Dateibaum
Trotz dieser Flexibilität sollte der Benutzer sich selbst einige Beschränkungen für die Benennung von Dateien auferlegen. So führt die Verwendung von Sonderzeichen in Dateinamen in der Regel zu Problemen (siehe auch Wildcards) und die gemischte Groß-/Kleinschreibung wird spätestens beim Austausch von Dateien mit anderen Betriebssystemen problematisch. Außerdem sollten Dateinamen nicht mit einem Minuszeichen oder Punkt beginnen, um Verwechslungen mit Optionen oder Systemdateien zu vermeiden.
5.2
1
Der Dateibaum
Der Dateibaum des Unix System V Release 4 ist in Bezug auf seine allgemein vorhandenen Komponenten genormt, allerdings kann es durch Erweiterungen in Form von Anwendungssoftware oder durch firmeneigene Standards zur Datenhaltung Abweichungen geben. Abb. 5.1 gibt einen Überblick über den Dateibaum.
5.2.1
Der Dateibaum von Unix System V Release 4
/
Der Slash »/« steht für das so genannte Root-Directory. Das Root-Directory ist das Oberverzeichnis aller Verzeichnisse und damit auch der Einstiegspunkt in die Dateihierarchie. Von diesem Verzeichnis aus sind alle Verzeichnisse des Dateibaums durch Abstieg in der Dateihierarchie erreichbar.
/bin
In diesem Verzeichnis befinden sich Standardprogramme, die fest zum Bestand des Unix-Betriebssystems gehören.
/sbin
Dieses Verzeichnis enthält Programme, die zum Booten und Wiederherstellen des Betriebssystems gebraucht werden.
/dev
Das Verzeichnis /dev und seine Unterverzeichnisse enthalten die Special Files für die Geräte. Diese Gerätedateien werden nach ihren so genannten Major Device Numbers in Kategorien eingeteilt. In dem Unterverzeichnis /dev/term befinden sich die Dateien für Terminals, in /dev/dsk die Dateien für Festplatten (oder genauer für die Partitionen der Festplatte/platten) und in /dev/mt die Dateien für die Bandlaufwerke.
/etc
In diesem Verzeichnis befinden sich Werkzeuge zur Systemadministration und -konfiguration (z.B. die Passwortdatei oder Dateien für die Netzwerkkonfiguration).
61
KAPITEL
5
Das Unix-Dateisystem
Abb. 5.1: Der Dateibaum des Unix System V Release 4
62
/opt
Unterhalb von /opt können Zusatzanwendungen installiert werden. Auf einigen Betriebssystemen, wie z.B. Sun Solaris, werden hier auch Betriebssystemerweiterungen installiert.
/home
Die Unterverzeichnisse von /home sind zur Aufnahme der Daten der einzelnen Benutzer gedacht. Dabei hat jeder Benutzer ein eigenes Verzeichnis, sein so genanntes Home Directory.
/var
Dieser Unterbaum enthält im Wesentlichen Dateien, die zur Laufzeit eines Programmes Daten aufnehmen. Die Struktur differiert zwischen den unterschiedlichen Unix-Betriebssystemen. Das Unterverzeichnis /var/adm enthält z.B. Protokolldateien für die Rechneraktivitäten und /var/mail die Dateien für die elektronische Post der Benutzer.
Der Dateibaum
/var/spool
Dieses Verzeichnis und seine Unterverzeichnisse nehmen temporäre Dateien für den Druckerspooler (/var/spool/lp), den uucp-Spooler1 (/var/spool/uucp) und den mail-Spooler (/var/spool/mqueue) auf. Ein Spooler ist ein Warteschlangenverwalter. Solche Warteschlangen (engl. queues) werden immer dann benutzt, wenn bestimmte Dienste nicht sofort verfügbar sind, also z.B. wenn der Drucker, auf dem gedruckt werden soll, gerade belegt ist oder wenn die Mails der verschiedenen Benutzer erst einmal gesammelt werden, bevor sie verschickt werden.
/tmp
In diesem Verzeichnis werden von Programmen und Benutzern temporäre Dateien abgelegt. Der Inhalt von /tmp wird beim Booten automatisch gelöscht und in der Regel auch nicht gesichert.
/usr
Der unter /usr befindliche Dateibaum enthält für die Benutzer relevante Dateien. Häufig befinden sich /usr und seine Unterverzeichnisse auf einer eigenen Partition oder Festplatte. /usr/bin und /usr/ sbin enthalten die Standardkommandos und Benutzerprogramme, / usr/lib die Libraries zur Programmentwicklung bzw. Shared Libraries und /usr/share/man enthält in seinen Unterverzeichnissen die man-Pages.
5.2.2
Navigieren im Dateibaum1
Unix verwaltet Dateien in einem hierarchischen Dateisystem. Dabei werden die Dateien in Verzeichnisse einsortiert, um sie gezielter auffinden zu können. Wie aber können Dateien in diesem Dateisystem angesprochen werden? Wie lässt sich als Benutzer beschreiben, wo sich die Datei befindet, auf die zugegriffen werden soll? Zu diesem Zweck existiert das Konzept der Pfade. Ein Pfad ist eine Abfolge von Verzeichnisnamen, die durch ein Trennzeichen (unter Unix ist das der Slash2 »/«) abgegrenzt werden. Diese Abfolge von Verzeichnisnamen ist als eine Art Wegbeschreibung durch den Verzeichnisbaum zu verstehen. An einem aufgezeichneten Dateibaum, wie das im letzten Abschnitt für den Dateibaum des Unix System V Release 4 geschehen ist, könnte diese Wegbeschreibung verfolgt werden, indem die Kanten des Dateibaums abgefahren werden. Unix unterscheidet zwei Varianten von Pfaden. Als erstes gibt es da die absoluten Pfade. Ein absoluter Pfad beginnt stets beim Root-Directory3 (/) und beschreibt von dort aus den Weg zu einer Datei oder einem Verzeichnis. /usr/ share/man ist ein solcher absoluter Pfad, der Folgendes besagt: Die Datei man (nach Unix-Philosophie ist ja auch ein Verzeichnis eine Datei) steht in dem 1. Über das Unix-to-Unix-copy-System (uucp) können Nachrichten von einem Unix-System zu einem anderen verschickt werden. 2. Schrägstrich, nicht zu verwechseln mit dem unter DOS verwendeten Backslash »\« 3. root (engl.): Wurzel eines (Datei-)Baums
63
KAPITEL
5
Das Unix-Dateisystem
Verzeichnis mit dem Namen share. Dieses ist ein Unterverzeichnis des Verzeichnisses usr, welches seinerseits ein Unterverzeichnis des Root-Directorys / ist. Unverkennbares Anzeichen für einen absoluten Pfad ist der erste Slash »/«, mit dem der Pfad beginnt. Dieser erste Slash ist kein Trennzeichen, sondern der Name des Root-Directorys. Der absolute Pfad einer Datei ist eindeutig, d.h. es kann nur eine Datei geben, die unter diesem Pfad ansprechbar ist.
3
/–––––usr–––––share–––––man
(Verzeichnisabfolge)
/usr/share/man
(absoluter Pfad)
Bevor die zweite Variante der Pfade erläutert werden kann, muss zunächst ein weiteres Konzept des Unix-Betriebssystems vorgestellt werden, das des Working Directorys. Ist ein Benutzer an einem Unix-Betriebssystem angemeldet, läuft auf diesem System für ihn mindestens eine Shell. Jeder Shell ist ein Verzeichnis zugeordnet, auf dem sie arbeitet – das Working Directory. Dieses Verzeichnis kann von dem Benutzer während seiner Bildschirmsitzung neu gesetzt werden. Die Dateien des Working Directorys können ohne die Angabe von Pfaden nur über die Namen der Dateien angesprochen werden. Sinn dieses Konzepts ist es, Tipparbeit zu sparen, indem in das Verzeichnis »gewechselt« wird, in dem die Dateien stehen, mit denen primär gearbeitet werden soll. Wird ausgehend vom Working Directory die Lage einer Datei im Dateibaum beschrieben, so wird von einem relativen Pfad gesprochen. Relativ heißt in diesem Fall: in Abhängigkeit von der eigenen Position im Dateibaum. Durch diese Abhängigkeit wird ein relativer Pfad erst in Verbindung mit dem Working Directory eindeutig. Während ein absoluter Pfad nur in eine Richtung (vom Root-Directory weg) verläuft, kann ein relativer Pfad in beide Richtungen – auf die Wurzel zu und von der Wurzel weg – weisen. Ein solcher Weg, der über ein Oberverzeichnis (Parent Directory) führt, wird mit einem speziellen Pfadnamen (..) beschrieben. Ist zum Beispiel das Working Directory /home/lutz/src/project1, dann beschreibt der relative Pfad ../.. das Verzeichnis /home/lutz, also das Oberverzeichnis des Oberverzeichnisses des Working Directorys.
3
/home/lutz/src/project1
(Working Directory)
+ ../../..
(relativer Pfad)
= /home
64
(absoluter Pfad)
Der Dateibaum Häufig kommt der Benutzer in die Situation, den Pfad für das aktuelle Working Directory angeben zu müssen (z.B. um Dateien in das Verzeichnis, in dem er sich gerade befindet, zu kopieren). Natürlich könnte hier die lange Schreibweise mit dem absoluten Pfad benutzt werden, aber es gibt auch hier eine Kurzschreibweise als relativen Pfad – einfach einen Punkt (.). Soll z.B. eine Datei beispiel.txt aus dem Working Directory angesprochen werden, könnten synonym die Schreibweisen ./beispiel.txt (relativer Pfad) oder beispiel.txt (ohne Pfad) verwendet werden.
5.2.3
Das Working Directory wechseln
Wird für den Benutzer nach dem Anmelden eine Shell gestartet, bekommt sie ein initiales Working Directory zugeteilt. Dieses ist in der Regel das Home Directory des Benutzers. Jeder Benutzer verfügt über ein solches Verzeichnis, in dem er seine eigenen Verzeichnisse anlegen und mit entsprechenden Dateien füllen kann. Dieses Verzeichnis, das in den meisten Systemen ein Unterverzeichnis von /home ist, wird das Home Directory des Benutzers genannt. Es heißt im Allgemeinen so wie die Kennung des Benutzers (z.B. /home/meier für einen Benutzer mit der Benutzerkennung meier).
pwd print working directory – Zur Anzeige des aktuellen Working Directorys gibt es das Unix-Kommando pwd. Es gibt den absoluten Pfad des Working Directorys aus. Parameter werden keine erwartet.
UNIX-Kurs [~] 20 > pwd /home/lutz
3
cd change directory – Soll das Working Directory neu gesetzt werden, wird dazu das Kommando cd benutzt. Es erwartet einen oder keinen Parameter. Wird kein Parameter angegeben, wird das Working Directory zurück auf das Home Directory gesetzt. Wird ein Parameter angegeben, muss es ein gültiger absoluter oder relativer Pfad für ein Verzeichnis sein. Darf der Benutzer in dieses Verzeichnis wechseln, wird das Working Directory entsprechend gesetzt, sonst erscheint die Fehlermeldung permission denied.
cd [Verzeichnis]
6 65
KAPITEL
3
66
5
Das Unix-Dateisystem
UNIX-Kurs [~] 21 > cd .. UNIX-Kurs [/home] 22 > pwd /home UNIX-Kurs [/home] 23 > cd pwd /home/lutz
KAPITEL 6
Dateiverwaltung In diesem Kapitel geht es darum, den Grundwortschatz an Unix-Kommandos weiter auszubauen. Der Umgang mit Dateien und Verzeichnissen gehört zu den wichtigen Bereichen des Arbeitens unter Unix. Der Benutzer sollte die in diesem Abschnitt vorgestellten Kommandos und Regeln verinnerlichen und die wichtigsten Optionen beherrschen. Nur so lassen sich folgenschwere Fehler wie das ungewollte Löschen von Dateien vermeiden und eine akzeptable Arbeitseffektivität erzielen. Zwar gibt es im Zeitalter der grafischen Bedienoberflächen eine Reihe von Hilfswerkzeugen, mit denen die Aufgabe der Dateiverwaltung ungefährlicher und ohne Kenntnis von Unix-Kommandos vollzogen werden kann, aber wer dann plötzlich auf einem System ohne diese Werkzeuge arbeiten muss, steht »im Dunkeln«. Ein weiterer Grund für das Erlernen der Standardkommandos ist das Arbeiten über das Netzwerk, denn oft sind die grafischen Hilfswerkzeuge nicht netzwerkfähig. Außerdem lassen sich viele Aufgaben mit den umfangreichen Möglichkeiten einer Shell weit effektiver lösen als mit einem grafischen Werkzeug.
6.1
Sonderzeichen
Bevor die Kommandos zur Dateiverwaltung benutzt werden, sollte sich der Benutzer mit der Wirkungsweise einiger Sonderzeichen, den so genannten Wildcards, vertraut machen. Eine Wildcard ist ein Zeichen, das bei Eingabe von der Shell nicht als einfacher Buchstabe interpretiert wird, sondern eine Sonderbehandlung auslöst. Die Shell nimmt stets die gesamte Eingabezeile
67
KAPITEL
6
Dateiverwaltung
entgegen, untersucht sie auf das Auftreten von Wildcards und ersetzt diese, bevor der Befehl ausgeführt wird. Die meisten Wildcards wirken auf Dateinamen und dienen dazu, statt einer einzelnen Datei eine Liste von Dateien anzusprechen. Dieser Mechanismus wird von den meisten Unix-Befehlen unterstützt. Leider unterscheiden sich die Shells auch dadurch, dass sie unterschiedliche Wildcards interpretieren. Aus diesem Grund ist es nötig, die Gruppe der Nicht-Wildcards zu definieren, die auf keiner Shell eine Sonderbehandlung erfahren. Dies sind: ✘ Großbuchstaben1 ✘ Kleinbuchstaben ✘ Ziffern ✘ Bindestrich »-« und Unterstrich »_« Alle anderen Zeichen haben in der einen oder anderen Shell Sonderbedeutung und sollten deshalb auch am besten nicht für Dateinamen benutzt werden. Im Folgenden sollen die »genormten« Wildcards, die es auf jeder Shell gibt, vorgestellt werden.
6.1.1
Wildcards in Dateinamen
Die Wildcards für Dateinamen haben die Eigenschaft, nur auf vorhandenen Dateien zu arbeiten, d.h. mit ihnen können nur verkürzte Schreibweisen für Gruppen bereits vorhandener Dateien angegeben werden, aber es kann z.B. nicht definiert werden, wie das Ergebnis eines Kopiervorgangs aussehen soll. Es ist sogar dringend davon abzuraten, derartiges zu probieren, weil dies sehr schnell Datenverlust zur Folge haben kann. Weiterhin sollte beim Einsatz von Wildcards für Dateinamen bedacht werden, dass diese nur auf Dateien im Working Directory wirken, es sei denn, es werden entsprechende Pfadangaben mit in das Muster aufgenommen. ?
Das Fragezeichen steht für genau ein beliebiges Zeichen in einem Dateinamen.
*
Der Stern steht für eine beliebige Zeichenkette in einem Dateinamen. Dazu zählt auch die leere Zeichenkette. Steht der Stern als erstes Zeichen in einem Muster für einen Dateinamen, steht er nicht für Zeichenketten, deren erstes Zeichen ein Punkt ist!1
1. Als Buchstaben gelten auf Grund der amerikanischen Herkunft von Unix nur die im ASCIICode enthaltenen 26 Buchstaben A bis Z. Die deutschen Umlaute ä, ö, ü und das ß, die französischen Akzente é, è, ê und alle weiteren nationalen Zeichen können hier leider nicht verwendet werden.
68
Sonderzeichen
[ ]
Ein Ausdruck in eckigen Klammern in einem Dateinamen kann genau durch eines der Zeichen zwischen den Klammern ersetzt werden.
[A-Z]
Innerhalb eckiger Klammern können unter Verwendung des Minuszeichens auch Bereiche angegeben werden. So steht der Bereich A-Z für alle Großbuchstaben von A bis Z als eine Folge gemäß ihrer Reihenfolge im ASCII-Zeichensatz. Solche Bereiche dürfen nur innerhalb der Großbuchstaben, der Kleinbuchstaben und der Ziffern gebildet werden. Zwischen einer öffnenden und einer schließenden eckigen Klammer darf mehr als ein Bereich angegeben werden. Die Klammer selbst steht aber immer nur für genau ein Zeichen.
1. Dateien, die in ihrem Namen als erstes Zeichen einen Punkt haben, sind für system- oder applikationsspezifische Aufgaben gedacht. Damit diese Dateien nicht einfach bei der Angabe eines »*« mit in die Parameterliste eines Kommandos rutschen, sind diese speziellen Dateinamen explizit ausgenommen.
6.1.2
Weitere Sonderzeichen
Neben den Sonderzeichen, mit denen Muster für Dateinamen gebildet werden können, gibt es noch eine Reihe von Sonderzeichen, die Steuerfunktionen haben. Diese sollen an dieser Stelle zwar genannt, ihre Funktionen aber nicht näher erläutert werden. Vor der Anwendung dieser Sonderzeichen und ihrer spezifischen Funktionen steht zunächst die vollständige Beherrschung der wichtigsten Unix-Kommandos.1 ~
Die Tilde dient zur Abkürzung absoluter Pfadnamen. Durch Verwendung der Tilde kann z.B. das Home Directory des Benutzers lutz (/home/lutz) über das Kürzel ~lutz angesprochen werden. Diese verkürzte Schreibweise hat zusätzlich den Vorteil, dass sie auch auf Systemen, bei denen die Home Directories nicht unter /home liegen, richtig arbeitet. Es handelt sich also nicht um eine einfache Textersetzung. Das eigene Home Directory ist direkt über die Tilde ohne einen Namenszusatz ansprechbar.1
<,>
Umlenken der Standardein- und -ausgabe
|,;
Verketten von Kommandos
(,)
Zusammenfassen von Kommandos zu Gruppen
!,^
Arbeiten mit der Befehls-History
", ', `
Die unterschiedlichen Anführungszeichen (Quotes) ermöglichen das so genannte Quoting.
\
Der Backslash ist der so genannte Escape Character. Er sorgt dafür, dass ein Sonderzeichen, welches dem Backslash ohne Leerzeichen folgt, nicht gemäß seiner Sonderfunktion von der Shell interpretiert wird. Er macht also aus einem Sonderzeichen wieder ein »ganz normales« Textzeichen.
1. Dieser Mechanismus ist nicht in allen Kommandointerpretern implementiert.
69
KAPITEL
6 6.2
Dateiverwaltung
Zugriffsrechte
Jede Datei unter Unix verfügt über einen Satz von Zugriffsrechten. Diese Rechte legen fest, wer eine Datei lesen darf, wer sie verändern kann und wem es erlaubt ist, eine ausführbare Datei, also ein Programm oder ein Script, zu starten. Die Zugriffsrechte stehen im direkten Zusammenhang mit dem Multiuser-Konzept, da sie für den Schutz der Daten der einzelnen Benutzer sorgen. Allerdings gibt es auf jedem Unix-Betriebssystem mindestens einen Benutzer, für den die Zugriffsrechte keine Rolle spielen: Dies ist der Systemverwalter mit der Benutzerkennung root, der die Zugriffsrechte für jede Datei ändern darf. Für das Konzept der Zugriffsrechte unter Unix ist es notwendig, jede Datei einem Eigentümer zuzuordnen, der für diese Datei »verantwortlich« ist. Dieser Eigentümer der Datei hat als einziger neben dem Systemverwalter die Möglichkeit, die Zugriffsrechte »seiner« Dateien festzulegen. Die Zugriffsrechte auf eine Datei werden in den drei Kategorien Lesen, Schreiben und Ausführen für die drei unterschiedlichen Benutzerklassen Eigentümer, Gruppe und alle anderen vergeben. Neu ist hier der Begriff der Gruppe. Jeder Benutzer an einem Unix-Betriebssystem wird vom Systemverwalter in dem Augenblick, in dem er einen Account1 für den Benutzer einrichtet, in eine Gruppe eingeteilt. Sinn dieser Unterteilung in Gruppen ist es, dass sich Mitglieder eines Projekts, die in die gleiche Unix-Benutzergruppe eingetragen werden, untereinander andere Rechte auf ihre Dateien einräumen können, als sie dies für den Rest der Benutzer des Systems tun.2 Die Bedeutung der Zugriffsrechte für Datendateien und Programme (Plain Files) ist leicht erklärt: Das Leserecht gewährt der entsprechenden Benutzergruppe das Recht, sich den Inhalt einer Datei anzuschauen. Das Schreibrecht ermöglicht es ihr, den Dateiinhalt zu verändern oder zu löschen (nicht aber die Datei selbst). Programme können nur von den Benutzern gestartet werden, die zu einer der Gruppen gehören, für die das Ausführungsrecht der entsprechenden Programmdatei gesetzt ist. Während bei Plain Files die Zugriffsrechte intuitiv verständlich sind, ist dies für Verzeichnisse nicht so einfach nachvollziehbar. Die Bedeutungen der Zugriffsrechte für Verzeichnisse sind im Folgenden beschrieben. Ein Verzeichnis enthält eine Reihe von Dateien (genauer: die Namen der Dateien und Verweise auf die Daten). Lesendes Zugriffsrecht erlaubt es dem
1. Ein Account ist die Kennung, unter der sich ein Benutzer auf dem Unix-System anmelden kann. Mit der Einrichtung des Accounts wird dem Benutzer ein Home Directory zugeteilt. 2. Leider werden auf vielen Systemen riesige Sammelgruppen eingerichtet, zu denen in der Regel fast alle Benutzer gehören. Dadurch wird der Gruppenmechanismus quasi ad absurdum geführt.
70
Zugriffsrechte Benutzer, sich die Namen dieser Dateien auflisten zu lassen – also den Inhalt des Verzeichnisses zu lesen, z.B. mithilfe des Kommandos ls. Wenn ein Verzeichnis die Namen von Dateien enthält, dann bedeutet Schreiben das Verändern dieses Inhalts, also das Hinzufügen neuer Namen (durch Anlegen von Dateien) oder das Entfernen von Namen aus dem Verzeichnis (durch Löschen von Dateien).
Ob eine Datei von einem Benutzer gelöscht werden darf, entscheidet daher nicht das Zugriffsrecht auf die Datei selbst, sondern das Schreib-Zugriffsrecht auf das Verzeichnis, in dem diese Datei steht!
2
Natürlich macht es keinen Sinn, ein Verzeichnis ausführen zu wollen. Das Ausführungsrecht für ein Verzeichnis erlaubt die Ausführung eines Kommandos »auf« dem Verzeichnis. Genauer bedeutet es, dass ein Kommando mehr als nur die Namen der im Verzeichnis enthaltenen Dateien sehen darf, nämlich auch Informationen über Größe, Eigentümer, Zugriffsrechte, Daten usw. Des Weiteren bedeutet das Ausführungsrecht, dass mit cd in das Verzeichnis gewechselt werden darf. Ohne das Ausführungsrecht an einem Verzeichnis ist darüber hinaus keine Manipulation des Inhaltsverzeichnisses (Dateien hinzufügen, umbenennen oder löschen) möglich. Auch das Lesen von Dateien wird dann unterbunden.
6.2.1
chmod
change mode – Das Kommando setzt die Zugriffsrechte für eine Datei im Sinne des Unix-Dateibegriffs (also auch für Directories und Special Files). Es gibt zwei Möglichkeiten, die Zugriffsrechte einer Datei zu verändern. Die Rechte können komplett neu definiert werden. Dies geschieht durch die Angabe einer dreistelligen Oktalzahl. Jede Ziffer dieser Oktalzahl setzt sich zusammen als Summe der Wertigkeiten der Einzelrechte. Diese Wertigkeiten sind: 4 Leserecht 2 Schreibrecht 1 Ausführungsrecht 0 keine Rechte
71
KAPITEL
3
6
Dateiverwaltung
UNIX-Kurs [~] 24 chmod 640 beispiel.txt Zugriffsrechte für alle anderen Zugriffsrechte der Gruppe Zugriffsrechte des Eigentümers
In dem Beispiel werden dem Eigentümer Schreib- und Leserecht (4 + 2 = 6) und den übrigen Gruppenmitgliedern nur das Leserecht eingeräumt und allen anderen Personen jeglicher Zugriff verboten. Als Alternative zur kompletten Neudefinition können die bestehenden Rechte durch Abzug oder Hinzufügen weiterer Rechte verändert werden. Dazu muss die Benutzergruppe durch folgende Kürzel angegeben werden: u
Eigentümer (user),
g
Gruppe (group),
o
alle anderen (other),
a
alle (Eigentümer, Gruppe und alle anderen).
Außerdem ist anzugeben, ob die Rechte hinzugefügt »+« oder abgezogen »-« werden sollen und welche Rechte betroffen sind:
3
r
Lesen (read),
w
Schreiben (write),
x
Ausführen (execute).
UNIX-Kurs [~] 25 > chmod a-wx beispiel.txt
In dem Beispiel werden dem Eigentümer, der Gruppe und allen anderen (also allen: a) die Schreib- und Ausführungsrechte, sofern vorhanden, an der Datei entzogen. Dadurch ist die Datei schreibgeschützt. Möchte man diesen Schreibschutz wieder aufheben, setzt man mit dem chmod-Befehl die Zugriffsrechte wieder zurück. Die Erlaubnis, den chmod-Befehl durchzuführen, bleibt immer beim Eigentümer, selbst dann, wenn er sich selbst alle Rechte entzogen hat. Obwohl sich der Eigentümer einer Datei in Bezug auf die Zugriffsrechte in Sicherheit wiegt, da er sie jederzeit neu definieren darf, gibt es hier eine entscheidende Ausnahme: Besitzt er kein Ausführungsrecht am Working Direc-
72
Zugriffsrechte tory, darf er auch kein chmod in diesem ausführen. Dieser Fall tritt in der Regel nicht ein, da der Benutzer schon Ausführungsrechte an einem Verzeichnis besitzen muss, um es mit cd zu seinem Working Directory zu machen. Verändert er aber die Zugriffsrechte an seinem Working Directory und begeht dabei einen Fehler (statt der dreistelligen Oktalzahl wird nur eine zweistellige angegeben, die von Unix mit einer führenden Null ergänzt wird), kann die Situation eintreten, dass der Benutzer das Verzeichnis nicht mehr verlassen kann, weil er dazu das Ausführungsrecht an dem Working Directory benötigt.
Vermeiden Sie es deshalb unbedingt, die Zugriffsrechte an Ihrem Working Directory zu verändern. Ändern Sie die Zugriffsrechte für ein Verzeichnis immer aus dessen Parent Directory!
6.2.2
2
umask
Um nicht jedes Mal, wenn eine Datei angelegt wird, die Zugriffsrechte neu einstellen zu müssen, verfügt Unix über eine Defaulteinstellung für neu anzulegende Dateien. Diese Defaultrechte lauten 777 für Verzeichnisse (also Lesen, Schreiben und Ausführen für jeden) und 666 für Plain Files (Lesen und Schreiben für jeden). Da diese Einstellung nicht gerade dem entspricht, was ein sicherheitsbewusster Benutzer für sinnvoll hält, verfügt Unix über einen Mechanismus, um von diesen Defaultrechten einige »abzuziehen«. Dies geschieht durch die so genannte User File Creation Mask, die ebenfalls durch eine dreistellige Oktalzahl definiert wird. Diese Oktalzahl beschreibt, welche Rechte von den Defaultrechten abgezogen werden. So bedeutet eine User File Creation Mask von 022, dass für die Gruppe und alle anderen das Schreibrecht bei einer neuen Datei oder einem neuen Verzeichnis nicht gesetzt wird (777-022 = 755 bzw. 666-022 = 644). Die User File Creation Mask kann mit dem Kommando umask gesetzt werden. umask bekommt als einzigen Parameter die Oktalzahl, deren Ziffern genauso zusammengesetzt werden wie beim chmod.
umask [Oktalzahl]
umask ohne eine Oktalzahl als Parameter gibt die aktuelle Einstellung aus.
6 73
KAPITEL
6 6.3
Dateiverwaltung
Kommandos zur Dateiverwaltung
In diesem Abschnitt sollen Kommandos zum Auflisten, Kopieren, Umbenennen und Löschen von Dateien vorgestellt werden.
6.3.1
ls
Das Kommando ls (list) dient dem Auflisten von Dateien. ls verfügt über eine Vielzahl von Optionen, von denen hier nur einige aufgeführt werden sollen. Die allgemeine Befehlssyntax für das Kommando ls lautet wie folgt:
6
ls [Optionen] [Datei/-en]
Werden dem ls Namen von Dateien als Parameter übergeben, listet ls nur diese Dateien auf. Bei Verzeichnissen wird stets der Inhalt aufgelistet und nicht die Namen der Verzeichnisse selbst. Ohne eine Angabe von Dateien oder Verzeichnissen wird der Inhalt des Working Directory aufgelistet. Häufig benutzte Optionen für das Kommando ls sind:1 a
Mit der Option a (all) werden auch solche Dateien aufgelistet, deren Namen mit einem Punkt beginnen. Bei diesen Dateien handelt es sich in der Regel um Systemdateien, die nicht automatisch angezeigt werden sollen (siehe auch Abschnitt 6.1.1 Wildcards in Dateinamen).
F
Wird diese Option angegeben, werden an die aufgelisteten Dateinamen Zeichen zur Identifizierung der Dateitypen angehängt. Unterschieden wird in Verzeichnisse (»/«), ausführbare Plain Files (»*«) und Symbolic Links (»@«). »Normale« Plain Files erhalten kein weiteres Zeichen.
C
Mit dieser Option werden die Dateien nicht in einer Spalte untereinander, sondern in mehreren Spalten (columns) angezeigt. Das ist insbesondere dann vorteilhaft, wenn sehr viele Dateien aufgelistet werden sollen.
l
Die Auflistung erfolgt im ausführlichen (long) Format. Für jede aufgelistete Datei werden dabei neben dem Dateinamen der Dateityp, die Zugriffsrechte, der so genannte Linkcount1, der Eigentümer, die Gruppe und das Datum der letzten Veränderung (Modifikationsdatum) angezeigt.
d
Normalerweise bedeutet die Angabe eines Verzeichnisnamens, dass nicht das Verzeichnis selbst, sondern dessen Inhalt, also die darin enthaltenen Dateien und Unterverzeichnisse, gelistet werden sollen. Wird d angegeben, dann werden auch bei Verzeichnissen nur deren eigene Namen und Eigenschaften gelistet.
1. Der Linkcount ist die Anzahl der Verweise auf die Datei (siehe auch 6.3 Verweise
74
– Links).
Kommandos zur Dateiverwaltung
UNIX-Kurs [~] 26 > ls -l
3
Als Kennzeichnung des Dateityps werden im long-Format folgende Zeichen verwendet: -
Der Strich kennzeichnet ein Plain File. Ob es sich dabei um ein Programm handeln könnte, lässt sich nur an den Zugriffsrechten ablesen (x = Ausführungsrecht @ Programm).
d
Das »d« steht für Directory, kennzeichnet also ein Verzeichnis.
l
Das »l« zeigt einen Symbolic Link (einen Verweis auf eine andere Datei) an.
c ,b , p
Bei diesen drei Buchstaben handelt es sich – wie auch bei dem »l« – um Kennzeichnungen für Special Files (b = Block Device, c = Charakter Device und p = Named Pipe).
Die Zugriffsrechte werden in einem Block von neun Zeichen (drei Zeichen Eigentümerrechte, drei Zeichen Gruppenrechte und drei Zeichen Rechte für alle anderen) angegeben. Dabei stehen r
für das Vorhandensein des Leserechts (read),
w
für das gesetzte Schreibrecht (write),
x
für das Ausführungsrecht (execute) und
-
für das Fehlen eines Zugriffsrechts.
Der Bedeutung des Linkcounts soll zunächst keine Aufmerksamkeit geschenkt werden.
75
KAPITEL
6
Dateiverwaltung
Sollen die Zugriffsrechte für eine bestimmte Datei aufgelistet werden, muss die Option -l benutzt werden:
3 3
UNIX-Kurs [~] 27 > ls -l bsp.txt -rw-r--r-- 1 lutz users 76 Jan 20 13:45 bsp.txt
Die Kombination der Optionen -l und -d gibt die Zugriffsrechte für ein Directory aus (ohne die Option -d wird der Inhalt des Directorys aufgelistet):
UNIX-Kurs [~] 28 > ls -l mails -rw-r--r-- 1 lutz users 120 Jan 21 11:41 brief1.txt -rw-r--r-- 1 lutz users 80 Jan 21 23:45 brief2.txt UNIX-Kurs [~] 29 > ls -ld mails drwxr-xr-x 2 lutz users 1024 Jan 22 14:24 mails
6.3.2
cp
copy – Das Kommando cp wird zum Kopieren von Dateien benutzt. Generell gibt es zwei Syntaxvarianten von cp.
6 6
cp [Optionen] Original Kopie
Bei der einen Variante erhält cp zusätzlich zu den Optionen genau zwei Parameter, wobei der Name der Kopie noch nicht existieren muss. Das Original wird kopiert und die Kopie unter dem Namen Kopie abgelegt.
cp [Optionen] Original1 ... Originaln Verzeichnis
Bei der anderen Variante bekommt cp zusätzlich zu den Optionen mindestens zwei weitere Parameter. Der letzte Parameter muss dabei ein bereits existierendes Verzeichnis sein. Die Originale Original1 bis Originaln werden unter Beibehaltung ihres Namens in das Verzeichnis Verzeichnis kopiert. In beiden Varianten werden eventuell bereits vorhandene Zieldateien – also solche Dateien, die die gleichen Namen wie die zu erstellenden Kopien tragen und an der gleichen Stelle im Dateibaum stehen – von cp ohne Rückfrage überschrieben. Dies geschieht nur dann nicht, wenn der Anwender des Kommandos cp kein Schreibrecht an den zu überschreibenden Dateien oder dem Verzeichnis, in dem sie stehen, besitzt.
76
Kommandos zur Dateiverwaltung
UNIX-Kurs [~] 30 > cp bsp.txt bsp2.txt UNIX-Kurs [~] 31 > cp bsp*.txt /tmp
3
cp verfügt über folgende häufig benutzte Optionen:1 -i
Diese Option steht für interaktiv. Wenn eine Zieldatei existiert, die beim Kopiervorgang überschrieben werden würde, so wird bei Verwendung dieser Option vor dem Überschreiben nachgefragt.1
-r
Das r steht für rekursiv. Mit dieser Option darf ein Original auch ein Verzeichnis mit darin enthaltenen Unterverzeichnissen sein. So lassen sich Kopien von ganzen Dateibäumen anlegen. Vorsicht ist hier wegen der Menge an Daten geboten, die mit einem Befehl kopiert werden können.
-f
Eine eventuell vorhandene Zieldatei wird auf jeden Fall und ohne Rückfrage überschrieben, auch wenn kein Schreibrecht für diese existiert. Ein Schreibrecht für das Verzeichnis muss allerdings in jedem Fall vorhanden sein.
-p
Die Kopie behält die Dateiattribute des Originals. Dies kann z.B. in Bezug auf das Modifikationsdatum von Interesse sein.
Um die Gefahr des Überschreibens beim Kopieren zu minimieren, sollte stets die Option -i Verwendung finden.
6.3.3
2
mv
move – Das Kommando mv hat zwei unterschiedliche Aufgaben. Es kann sowohl zum Umbenennen von Dateien als auch zum Verschieben von Dateien im Dateibaum genutzt werden. mv verwendet für beide Aufgaben die gleichen Syntaxvarianten wie das Kommando cp:
mv [Optionen] Original Neuer_Name
In der einen Variante wird das Original in Neuer_Name umbenannt. Werden dem neuen Namen entsprechende Pfadangaben vorangestellt, findet zusätzlich zur Umbenennung auch noch eine Verschiebung statt.
6
1. Leider ist diese Option nicht auf allen Unix-Systemen vorhanden.
77
KAPITEL
6
6
Dateiverwaltung
mv [Optionen] Original1 ... Originaln Verzeichnis
In der anderen Variante werden die Dateien Original1 bis Originaln unter Beibehaltung ihres Namens in das Verzeichnis Verzeichnis verschoben. Auch hier werden bereits vorhandene Zieldateien ohne Warnung überschrieben, es sei denn, entsprechende Zugriffsrechte oder Optionen verhindern dies.
3
UNIX-Kurs [~] 32 > cd /tmp UNIX-Kurs [/tmp] 33 > mv bsp2.txt umbenannt.txt UNIX-Kurs [/tmp] 34 > mv bsp.txt umbenannt.txt /home/lutz
Folgende Optionen werden häufig im Zusammenhang mit mv benutzt:1 -i
Diese Option steht für interaktiv. Wenn eine Zieldatei existiert, die bei Umbenennung und/oder Verschiebung überschrieben werden würde, wird bei Verwendung dieser Option vor dem Überschreiben nachgefragt.1
-f
Eine eventuell vorhandene Zieldatei wird auf jeden Fall und ohne Rückfrage überschrieben, auch wenn kein Schreibrecht für diese existiert. Ein Schreibrecht für das Verzeichnis muss allerdings in jedem Fall vorhanden sein.
6.3.4
rm
remove – Das rm-Kommando ist sicherlich das »gefährlichste« aller Unix-Kommandos. Gefährlich deshalb, weil bei ihm die Eigenschaft des Unix-Betriebssystems, auf Sicherheitsabfragen zu verzichten, die fatalsten Folgen haben kann. Insbesondere im Zusammenhang mit der Wildcard »*« kann ein kleiner Tippfehler, wie z.B. ein überzähliges Leerzeichen, zu Datenverlust in erheblichem Umfang führen. Da Dateien unter Unix nicht wiederhergestellt werden können2, ist bei der Benutzung also äußerste Vorsicht geboten.
6
rm [Optionen] Datei/Dateien
1. Leider ist diese Option nicht auf allen Unix-Systemen vorhanden. 2. Ein »undelete« wie am PC gibt es nicht und wäre im allgemeinen auch gar nicht möglich, weil der freigemachte Plattenplatz meist schon durch einen anderen der vielen gleichzeitig laufenden Prozesse mit neuen Daten überschrieben worden wäre.
78
Kommandos zur Dateiverwaltung rm löscht ein oder mehrere Plain Files (und mit der entsprechenden Option
auch ganze Verzeichnisbäume). Existiert für eine Datei kein Schreibrecht, wird vor dem Löschen beim Benutzer rückgefragt. Wird die Rückfrage positiv beantwortet und existiert ein Schreibrecht für das Verzeichnis, in dem die Datei steht, wird sie gelöscht. Folgende Optionen sind verfügbar: -i
Mit Sicherheit ist -i (interaktiv) eine der sinnvollsten Optionen für das Kommando rm. Mit dieser Option erzeugt rm für jede zu löschende Datei eine Sicherheitsabfrage.
UNIX-Kurs [~] 35 > rm -i umbenannt.txt
-f
Mit dieser Option werden von rm alle Dateien, die als Parameter angegeben wurden, gnadenlos ohne Rückfrage gelöscht – sofern der Benutzer über das entsprechende Recht verfügt. Eventuell fehlende Schreibrechte bei zu löschenden Dateien finden keine Berücksichtigung mehr, nur das Schreibrecht auf das Verzeichnis wird benötigt. Unix wäre halt nicht Unix, wenn nicht auch noch das letzte bisschen Bediensicherheit zugunsten von Bediengeschwindigkeit aufgegeben würde.
-r
Diese Option wird zum Overkill-Schalter, wenn ein Tippfehler vorkommt. rm mit der Option -r löscht nämlich nicht nur Plain Files, sondern auch Verzeichnisse, die sich in der Parameterliste befinden, und alle darin enthaltenen Unterverzeichnisse und Dateien. So kann mit nur einem unbedachten Kommando alles gelöscht werden, was unterhalb des eigenen Home Directorys liegt. Benutzung auf eigene Gefahr!
3
Ein typisches Beispiel für die katastrophalen Folgen, die ein zusätzliches Leerzeichen haben kann, sind die beiden folgenden Kommandos:
UNIX-Kurs [~] 36 > rm -r *.tmp UNIX-Kurs [~] 37 > rm -r * .tmp
3
Die beiden Befehle unterscheiden sich nur durch das Leerzeichen zwischen dem * und dem .tmp. Während aber das erste Kommando alle Dateien und Verzeichnisse des Working Directorys löscht, deren Namen mit .tmp enden, löscht das zweite Kommando zuerst alle Dateien und Verzeichnisse, deren Namen nicht mit einem . beginnen (also fast alles in dem Verzeichnis), und dann noch eine Datei oder ein Verzeichnis mit dem Namen .tmp.
79
KAPITEL
2
6
Dateiverwaltung
Um die Gefährlichkeit des Kommandos rm ein wenig zu entschärfen, sollten Sie sich selbst das Schreibrecht an Ihren »wertvollsten« Dateien entziehen. So erfolgt zumindest für diese Dateien eine Sicherheitsabfrage vor dem Löschen – es sei denn, Sie operieren mit der Option -f, dann hilft nur Sorgfalt.
6.4
Kommandos zur Verzeichnisverwaltung
Obwohl Verzeichnisse nach der Unix-Datei-Philosophie auch nur Dateien sind, unterscheiden sich die Kommandos zu ihrer Handhabung doch von denen zur Bearbeitung von Plain Files. Zwar können mit mv Verzeichnisse umbenannt und auf den meisten Systemen auch im Dateibaum verschoben und mit cp und der Option -r auch ganze Verzeichnisse kopiert werden; soll aber ein leeres Verzeichnis zur Aufnahme von Dateien angelegt werden, ist hierzu ein spezielles Kommando nötig.
6.4.1
mkdir
make directory – Nach dem Kommando mkdir kann ein Name für das Dateiverzeichnis bzw. können mehrere Namen für die Dateiverzeichnisse angegeben werden, die angelegt werden sollen. Dabei darf noch keiner der Namen an ein anderes Verzeichnis oder an ein Plain File vergeben sein. Ist das doch der Fall, wird dieses Verzeichnis nicht angelegt. mkdir überschreibt nie!
3
UNIX-Kurs [~] 38 > mkdir directory
6.4.2
rmdir
remove directory – Während mit mkdir Verzeichnisse angelegt werden, werden sie mit rmdir wieder gelöscht. Voraussetzung für eine erfolgreiche Löschung ist, dass das Verzeichnis vollständig leer ist – also keine Dateien mehr enthält und von keinem Benutzer mehr als Working Directory benutzt wird.1
1. Letzteres wird leider von einigen Unix-Systemen (z.B. ULTRIX) nicht so genau genommen. Hier können Verzeichnisse gelöscht werden, die noch als Working Directories dienen. Dies hat zur Folge, dass der betroffene Benutzer in der Shell, mit der er sich in diesem Verzeichnis befindet, keine cd-Kommandos mehr absetzen und auch sonst nur noch sehr eingeschränkt arbeiten kann.
80
Aufgaben
UNIX-Kurs [~] 39 > rmdir directory
3
Übungen
6.5
Aufgaben
1. Geben Sie zwei cd-Kommandos an, um von Ihrem Home Directory in das Root-Directory zu wechseln – einmal mit einem absoluten Pfad und einmal mit einem relativen Pfad. 2. Bilden Sie ein ls-Kommando, das Ihnen alle Dateien aus Ihrem Home Directory auflistet – auch jene, deren Namen mit einem Punkt beginnen. 3. Lassen Sie sich die Zugriffsrechte an Ihrem Home Directory ausgeben. Nennen Sie mindestens zwei verschiedene Möglichkeiten, dies zu tun. 4. Legen Sie ein neues Verzeichnis mit dem Namen ueb_4 in Ihrem Home Directory an und wechseln Sie in dieses Verzeichnis. 5. Kopieren Sie die Datei /etc/passwd in Ihr Working Directory. Geben Sie den cp-Befehl ausschließlich mit absoluten Pfaden an. 6. Kopieren Sie die Datei /etc/group in Ihr Working Directory. Geben Sie den cp-Befehl ausschließlich mit relativen Pfaden an. 7. Gibt es einen einzelnen Befehl, um die beiden Dateien mit der Endung .old zu versehen? Begründen Sie Ihre Antwort. 8. Entziehen Sie sich selbst das Ausführungsrecht an dem Verzeichnis ueb_4. Welche Konsequenzen hat das für ein cd in das Verzeichnis und welche Konsequenzen hat es für unterschiedliche ls-Kommandos (ls -l, ls -a und ls) auf das Verzeichnis? 9. Wechseln Sie in das Unterverzeichnis ueb_4 und entziehen Sie sich das Schreibrecht an den beiden Dateien group und passwd. Was passiert, wenn Sie nun versuchen, die beiden Dateien zu löschen?
81
KAPITEL
6 6.5.1
Dateiverwaltung
Lösungen
1. Ein absoluter Pfad beginnt immer mit dem Zeichen »/«. Dieser Schrägstrich – im Englischen »slash« genannt – steht ja für das Root-Verzeichnis. Der erste Teil der Aufgabe ist also mit folgender Eingabe erledigt: UNIX-KURS [~] 10 > cd / UNIX-KURS [/] 11 >
Soll mit Angabe von relativen Pfaden in das Root-Directory gewechselt werden, muss zunächst geklärt werden, wie viele Ebenen Ihr Home Directory vom Root-Directory entfernt ist. Das Kommando pwd gibt Ihnen den Pfad des aktuellen Directorys an. Wechseln Sie zunächst mit dem Kommando cd wieder in Ihr Home Directory und geben Sie anschließend den Befehl pwd ein. UNIX-KURS [/] 12 > cd UNIX-KURS [~] 13 > pwd /home/lutz
In diesem Beispiel gibt es im Root-Directory ein Verzeichnis mit dem Namen home. Dort wiederum existiert ein Verzeichnis – das Home Directory des Benutzers lutz – mit dem Namen lutz. Durch Eingabe von cd .. wechseln wir also aus unserem Home Directory in das Verzeichnis mit dem Namen home. Und von dort gelangen wir durch eine erneute Eingabe von cd .. in das Root-Directory. Diese zwei Schritte können wir natürlich auch zusammenfassen: UNIX-KURS [~] 14 > cd ../.. UNIX-KURS [/] 15 >
2. Die Option -a sorgt dafür, dass alle Dateien aufgelistet werden, auch solche, die normalerweise unsichtbar sind, da sie mit einem Punkt beginnen. UNIX-KURS [~] 16 > ls -a
Dateien, die mit einem Punkt beginnen, erfüllen systemspezifische Aufgaben. Daher ist es sinnvoll, diese dem Benutzer nicht immer anzuzeigen. 3. Eine Möglichkeit, sich die Zugriffsrechte für das eigene Home Directory anzeigen zu lassen, ist: UNIX-KURS [~] 17 > cd UNIX-KURS [~] 17 > ls -ld .
Durch die Option -l werden die Zugriffsrechte für die Datei ».« angezeigt. Der Punkt steht wie immer für das Working Directory. Da wir zuvor mit cd in das Home Directory gewechselt sind, repräsentiert er in diesem Fall dasselbe. Durch die Option -d werden die Zugriffsrechte nun nicht für die im Home Directory liegenden Dateien und Unterverzeichnisse, sondern für das Home Directory selbst angezeigt. Der Punkt kann bei dem Befehl-
82
Aufgaben saufruf auch weggelassen werden, da der Befehl ls standardmäßig auf dem aktuellen Verzeichnis aufsetzt. Eine weitere – allerdings weniger komfortable – Möglichkeit bietet der folgende Befehl: UNIX-KURS [~] 18 > ls -la
Durch die Option -a werden auch Dateien mit einem Punkt angezeigt. Unter diesen Dateien befindet sich auch der ».«, welcher für das Working Directory (hier unser Home Directory) steht. Durch die Option -l werden die Angaben im »long format« ausgegeben. Dabei werden auch die Zugriffsrechte mit angezeigt. Eine weitere Möglichkeit besteht darin, in das über dem Home Directory liegende Verzeichnis zu wechseln und sich dort die Rechte für dieses anzeigen zu lassen: UNIX-KURS [~] 19 > cd .. UNIX-KURS [/home] 20 > ls -l
Da im Verzeichnis /home unter Umständen sehr viele Benutzer ihre Home Directories haben, ist es auch hier wieder sinnvoll, mit der Option -d das eigene Home Directory zu spezifizieren: UNIX-KURS [/home] 21> ls -ld lutz
4. Zunächst müssen wir wieder in unser Home Directory wechseln: UNIX-KURS [~] 22 > cd
Ein neues Directory wird durch den Befehl UNIX-KURS [~] 23 > mkdir ueb_4
angelegt. In dieses Directory wechseln wir durch Eingabe von: UNIX-KURS [~] 24 > cd ueb_4
5. Der Kopierbefehl cp verlangt als Eingabe eine Quelle und ein Ziel. Quelle und Ziel können jeweils als absoluter oder als relativer Pfad angegeben werden. In der Praxis ist es oft am elegantesten, beide Formen zu mischen. Hier sehen Sie nun die Variante mit ausschließlich absoluten Pfaden: UNIX-KURS [ueb_4] 25 > cp /etc/passwd /home/lutz/ueb_4
Die Datei /etc/passwd wird in das Verzeichnis ueb_4 kopiert. Natürlich kann auf Ihrem Rechner die Zielpfadangabe anders lauten, statt /home/ UNIX-Kurs müssen Sie Ihren Home Directory-Pfad einsetzen. Da Ihr
83
KAPITEL
6
Dateiverwaltung
Home Directory-Pfad durch die Tilde (~) abgekürzt wird, können Sie aber auch schreiben: UNIX-KURS [ueb_4] 26 > cp /etc/passwd ~/ueb_4
6. Will man mit relativen Pfaden arbeiten, muss man sich zunächst bis zum Root-Directory zurückhangeln (../../..) und von dort aus wieder in das Verzeichnis /etc wechseln, um die Quelldatei group zu finden. Das Ziel ist in unserem Beispiel das Verzeichnis, in dem wir uns gerade befinden. Es kann daher sehr bequem durch Eingabe eines Punktes als Zielverzeichnis ausgewählt werden: UNIX-KURS [ueb_4] 27 > cp ../../../etc/group .
7. Nein! Der move-Befehl kann immer nur genau ein Ziel haben, es müssen also beide Dateien einzeln umbenannt werden. Vielleicht hatten Sie die Idee, folgenden Befehl auszuprobieren: UNIX-KURS [ueb_4] 28 > mv * *.old
Was aber passiert dabei? Bevor der Unix-Befehl mv ausgeführt wird, ersetzt der Kommandointerpreter die Wildcards. Das Zeichen * wird durch alle Dateinamen im aktuellen Verzeichnis ersetzt, die nicht mit einem Punkt beginnen, hier also durch die Dateinamen group und passwd. Die Zeichenkette *.old wird durch alle Dateinamen im aktuellen Verzeichnis mit der Endung .old ersetzt. In unserem Beispiel gibt es keinen solchen Dateinamen. Der Kommandointerpreter sorgt deshalb für die Ausführung folgenden Befehls: mv group passwd
Die Datei group erhält also den neuen Namen passwd. Die bereits existierende Datei mit diesem Namen wird dadurch gelöscht. Sie haben deshalb nach Ausführung des Befehls nur noch eine Datei in ihrem aktuellen Verzeichnis. Und diese hat auch noch den falschen Namen! Natürlich können Sie auch unter Unix mehrere Dateien auf einen Schlag umbenennen. Dazu müssen Sie aber die Programmiersprache der jeweiligen Shell oder die Möglichkeiten des Editors vi nutzen. 8. Das Ändern der Zugriffsrechte erledigt das Kommando chmod. Bitte die Zugriffsrechte nie für das aktuelle Working Directory ändern! Für diese Aufgabe heißt es also zunächst, in das Home Directory zu wechseln und nicht im Directory ueb_4 stehen zu bleiben. UNIX-KURS [ueb_4] 28 > cd UNIX-KURS [~] 29 > chmod u-x ueb_4
Durch Absetzen dieses Befehls haben wir als der Eigentümer/User (u) nun kein (-) Ausführungsrecht (x) mehr an dem Directory ueb_4.
84
Aufgaben Dies heißt konkret, dass es nun nicht mehr möglich ist, mit dem cd-Befehl in das Directory ueb_4 zu wechseln. Aber auch der ls-Befehl funktioniert nicht mehr uneingeschränkt. Ein einfaches ls ueb_4 ohne Optionen liefert nach wie vor die Namen der Dateien innerhalb des Directorys ueb_4; es wird lediglich lesend auf das Directory ueb_4 zugegriffen. Ein ls -l funktioniert jedoch nicht mehr, da der Befehl auf dem Verzeichnis ausgeführt werden muss, was durch das fehlende Ausführungsrecht (x) verboten ist. Probieren Sie ruhig noch einige andere Optionen des ls-Befehls aus. Um die nächste Aufgabe lösen zu können, müssen wir nun wieder die Ausführungsrechte zurücksetzen: UNIX-KURS [~] 30 > chmod u+x ueb_4
9. In den Aufgaben 5 und 6 haben wir die Dateien passwd und group in das Verzeichnis ueb_4 kopiert. Wir wollen nun das Schreibrecht an diesen beiden Dateien verändern. Dazu wechseln wir in das Verzeichnis ueb_4: UNIX-KURS [~] 31 > cd ueb_4
Wieder benutzen wir den chmod-Befehl: Wir als User (u) wollen kein (-) Schreibrecht (w) an den beiden Dateien mehr haben. UNIX-KURS [ueb_4] 32 > chmod u-w group passwd
Wahrscheinlich waren Sie in Versuchung, den Befehl zweimal abzusetzen, für jede Datei einzeln. Aber wie Sie sehen, können die zu verändernden Dateien hintereinander angegeben werden. Was passiert nun, wenn man versucht, diese beiden Dateien zu löschen? UNIX-KURS [ueb_4] 33 > rm group passwd rm: group: 444 mode Remove? yes/no [no]
Das System meldet, dass die Datei group das Zugriffsrecht 444 (nur Leserecht für den Eigentümer, die Gruppe und alle anderen) besitzt. Dies ist jedoch nur als Warnung aufzufassen und mit der Eingabe von yes wird die Datei gnadenlos gelöscht, obwohl wir kein Schreib-Zugriffsrecht an ihr haben. Sie erinnern sich: Der Schreibschutz wird nicht durch das Schreib-Zugriffsrecht an der Datei selbst, sondern durch das Schreib-Zugriffsrecht des Verzeichnisses, in dem die Datei steht, festgelegt. Die gleiche Rückfrage erhalten Sie für die Datei passwd.
85
KAPITEL 7
Das Unix-Dateisystem – ein Blick hinter die Kulissen Einige der Unix-Konzepte für Dateien muten auf den ersten Blick ein wenig unkonventionell an. Das liegt aber nicht daran, dass die Entwickler dieses Systems umständlich gedacht haben, sondern am Unix-Dateisystem selbst. Was genau aber ist ein solches Dateisystem und wie ist es aufgebaut? Aufgabe des Dateisystems ist es, die Daten der Benutzer in Form von Dateien (also logischen Einheiten) geordnet zu speichern. Physikalisch geschieht das in der Regel auf Festplatten. Eine Festplatte ist unterteilt in Spuren, jede Spur ist ihrerseits unterteilt in Sektoren und jeder Sektor besteht wieder aus Blöcken. Jeder Block schließlich enthält eine bestimmte Anzahl Bytes. Vereinfacht lässt sich also eine Festplatte als Speicher betrachten, in dem eine bestimmte Anzahl von Bytes hintereinander angeordnet sind. Um nun Dateien in diesem Speicher ablegen zu können, muss festgelegt werden, welche Bytes zu einer Datei gehören. Und um dann noch ein hierarchisches Dateisystem zur Ordnung der Dateien anzulegen, bedarf es spezieller Dateien – nämlich der Verzeichnisse –, mit deren Hilfe sich die einzelnen Dateien zusammenfassen lassen.
87
KAPITEL
7
Das Unix-Dateisystem – ein Blick hinter die Kulissen
Abb. 7.1: Aufbau einer Festplatte
7.1
Der interne Aufbau des Unix-Dateisystems
In diesem Kapitel wird beschrieben, wie die Verwaltung der Daten für die Dateien im Unix-Dateisystem funktioniert und welcher Nutzen aus diesen Konzepten gezogen werden kann. Wichtigste Komponente für diese Aufgabe sind die so genannten i-nodes (am besten als »Informationsknoten« ins Deutsche übersetzt). Ein i-node beschreibt, welche Bytes zu einer Datei gehören, und enthält alle weiteren Informationen über die Datei (Größe, Zugriffsrechte, Typ, Eigentümer, Gruppe usw.) mit Ausnahme des vom Benutzer vergebenen Dateinamens.1 Da die Adressierung jedes einzelnen Bytes zu aufwändig wäre, werden im i-node nur Blöcke adressiert. Je nach Unix-Betriebssystem umfasst ein Block entweder 512 oder 1.024 Byte2. Den Aufbau eines solchen i-node veranschaulicht Abb. 7.2.
1. Der Name wird im Verzeichnis gespeichert, siehe folgendes Kapitel. 2. Neuere Unix-Betriebssysteme können auch größere Blöcke haben, um sehr große Dateien speichern zu können. So sind 2048 oder 4096 Byte durchaus gebräuchlich.
88
Der interne Aufbau des Unix-Dateisystems Abb. 7.2: Aufbau eines i-node
Auf die ersten zehn Datenblöcke wird im i-node direkt verwiesen, damit der Zugriff auf kleine Dateien schnell erfolgen kann. Klein heißt dabei je nach Größe eines Blocks kleiner als fünf KByte (= 10´512 Byte) oder kleiner als zehn KByte (= 10´1.024 Byte). Bei größeren Dateien werden die Verweise auf weitere Datenblöcke selbst wieder in Datenblöcken, den so genannten Indirektionsblöcken, gespeichert. Im entsprechenden i-node werden dann nur die Verweise auf die Indirektionsblöcke gespeichert. Nur der Indirektionsblock 1 enthält direkte Verweise auf Datenblöcke, die zur Datei gehören. Der Indirektionsblock 2 enthält wiederum nur Verweise auf weitere Indirektionsblöcke, die dann erst auf Datenblöcke der Datei verweisen (doppelte Indirektion). Der Indirektionsblock 3 ist für dreifache Indirektion vorgesehen. In Abb. 7.3, die dieses Prinzip verdeutlichen soll, sind die Datenblöcke mit Block n bezeichnet.
89
KAPITEL
7
Das Unix-Dateisystem – ein Blick hinter die Kulissen
Abb. 7.3: Aufbau der Indirektionsblöcke
Somit können mit dem Verweis auf den ersten Indirektionsblock 128 (bei einer Blockgröße von 1.024 Byte 256) Datenblöcke adressiert werden, mit dem Verweis auf den zweiten Indirektionsblock 1282 und mit dem Verweis auf den dritten Indirektionsblock 1283 Blöcke. Das ergibt zusammen 2.113.674 Blöcke à 512 Byte » 1 GByte. Dieser Aufbau der Indirektionsblöcke legt somit für ein Unix-Dateisystem auch die maximale Größe einer Datei fest. Bei einer Blockgröße von 1 KByte erhöht sie sich auf etwa 16 GByte. Jeder i-node hat eine eindeutige Nummer innerhalb des Dateisystems, zu dem er gehört. Die Blöcke für die i-nodes und die Blöcke für die Daten und Indirektionen werden in unterschiedlichen Speicherbereichen der Partition abgelegt. Dabei wird der Bereich für die i-nodes bei der Einrichtung des Dateisystems vom Gesamtspeicher der Partition abgezogen. Im Gegensatz zu DOS, dessen FAT-Dateisystem versucht, alle Daten einer Datei in aufeinander folgenden Speicherstellen abzulegen, spielen derartige Strategien unter Unix nur eine untergeordnete Rolle. Kann unter DOS kein ausreichend großer zusammenhängender Speicherbereich gefunden werden, wird die Datei aufgeteilt und die Teile werden über Verweise am Ende der einzelnen Bestandteile verkettet. Dieses Verhalten führt auf stark fragmentierten oder annähernd vollen Platten zu einem sehr ungünstigen Zugriffsverhalten, da die Ketten aus Speicherbereichen sehr lang werden können. Unter Unix
90
Verweise – Links reglementiert aufgrund des oben beschriebenen Konzepts lediglich die Geschwindigkeit der Platte die Zugriffszeiten, nicht aber der Füllungsgrad.
7.2
Verzeichnisse neu betrachtet
Mit dem Vorwissen über den Aufbau des Dateisystems unter Unix und der Organisation der Dateien darin kann nun der Begriff des Verzeichnisses neu betrachtet werden. Im Prinzip ist ein Verzeichnis nichts anderes als eine Tabelle, über die Dateinamen mit den zugehörigen i-node-Nummern verknüpft werden. Diese Tabelle wird ebenfalls in Form einer Datei gespeichert, deren Name über das Oberverzeichnis einer i-node-Nummer zugeordnet ist. Die Unix-Philosophie, nach der Verzeichnisse auch »nur« Dateien sind, leitet sich aus diesem Aufbau ab. Abb. 7.4: Innenansicht eines Verzeichnisses
Unix selbst verwaltet die Dateien intern unhierarchisch nur über die i-nodeNummern. Erst durch die Vergabe von Pseudonymen in Form von Dateinamen für diese Nummern durch den Benutzer und die Verwaltung dieser Namen über spezielle Verzeichnisdateien entsteht der bekannte Dateibaum.
7.3
Verweise – Links
Der Aufbau von Verzeichnissen als Tabelle eröffnet auf einfache Weise die Möglichkeit, unterschiedliche Namen für ein und dieselbe i-node-Nummer zu vergeben. Über jeden dieser Namen sind dieselben Daten ansprechbar, weil sie stellvertretend für die gleiche i-node-Nummer stehen. Unter Unix wird ein solches »Pseudonym« für eine i-node-Nummer Hard Link genannt.
91
KAPITEL
7 7.3.1
Das Unix-Dateisystem – ein Blick hinter die Kulissen
Hard Links
Die Anzahl der existierenden Hard Links auf eine Datei wird in dem i-node der Datei als Linkcount gespeichert. Dieser Zähler (count) zählt die Anzahl der Namen/Links, die für ein und dieselbe i-node-Nummer existieren. Wird z.B. mit dem Kommando rm ein Name aus einem Verzeichnis gelöscht, so wird der Linkcount des i-node, auf den dieser Name verwiesen hat, um eins verringert. Erst wenn der Linkcount den Wert Null erreicht hat, wird der Inhalt des zugehörigen i-node gelöscht. Die Hard Links für eine Datei haben je nach Dateityp unterschiedliche Bedeutungen. So wird der Aufbau der Pfade unter Unix ebenfalls über die Verwendung von Hard Links realisiert. Die beiden speziellen Pfadnamen . und .. bei den relativen Pfaden sind solche Hard Links. Wird der Inhalt eines Verzeichnisses mit ls -a aufgelistet, wird auch immer ein Eintrag . und ein Eintrag .. zu finden sein. Dabei ist . ein Pseudonym – also ein Hard Link – für die i-node-Nummer des Working Directoryss und .. ein Pseudonym für die des Oberverzeichnisses (Parent Directory) des Working Directorys.
1
Da die gesamte Navigation im Dateibaum mit cd auf diesen Links basiert, darf der Benutzer selbst keine Hard Links auf Verzeichnisse anlegen.
Anders ist das bei den »normalen« Dateien. Für ein Plain File darf der Benutzer Hard Links anlegen. Wichtig dabei sind zwei Dinge: 1. Die Daten der Datei werden nicht dupliziert, denn es wird ja nur ein zweiter Name für sie vergeben, d.h. Änderungen an den Daten können über beide Namen vollzogen werden und sind, da die Daten nur einmal über den i-node verwaltet werden, anschließend wieder über beide Namen verfügbar. 2. i-node-Nummern sind nur innerhalb eines Dateisystems eindeutig. Ein Unix-Dateibaum kann aber aus mehreren Dateisystemen bestehen. Dabei gilt die Regel, dass pro Partition der Platte (bzw. Platten), auf die vom Benutzer zugegriffen werden kann, ein Dateisystem existiert. Hard Links funktionieren damit nur innerhalb des gleichen Dateisystems. Das Kommando ls -l bestimmt den belegten Speicher (total) bei der Verwendung von Hard Links nicht korrekt, da die Hard Links jeweils wie eine eigene Datei mitgezählt werden. Abhilfe hierfür schafft das Kommando du, das nachfolgend in diesem Kapitel vorgestellt wird.
92
Verweise – Links
ln link – Unter Berücksichtigung dieser Rahmenbedingungen kann der Benutzer mit dem Kommando ln selbst Links anlegen. Die Aufrufsyntax ist dabei ähnlich der des Kommandos cp; sie existiert ebenso in zwei Varianten:
ln [Optionen] Original Link
In dieser Variante wird für ein Original ein Hard Link angelegt. Der Begriff des Originals soll in diesem Fall als ein bereits vorhandenes Pseudonym für eine i-node-Nummer verstanden werden. Voraussetzung für das Anlegen des Hard Links ist eine Schreibberechtigung in dem Verzeichnis, in dem der Link eingetragen werden soll.
ln [Optionen] Original1 ... Originaln Verzeichnis
In der zweiten Variante wird für n Originale in einem Verzeichnis jeweils ein Hard Link unter dem Namen des jeweiligen Originals angelegt. Klar ist, dass das Verzeichnis des Originals und das Zielverzeichnis für den Hard Link unterschiedlich sein müssen, da Namen innerhalb eines Verzeichnisses eindeutig sein müssen.
7.3.2
6 6
Symbolic Links
Aufgrund der Einschränkungen, denen die Hard Links unterliegen, gibt es eine zweite Art von Verweisen über das Kommando ln, die so genannten Soft oder auch Symbolic Links. Im Gegensatz zu den Hard Links wird bei diesen Links der Verweis nicht direkt (»hart«) über die i-node-Nummer angelegt, sondern indirekt (»symbolisch«) über Pfadnamen realisiert. Bei einem Symbolic Link wird eine Datei mit einem eigenen i-node angelegt, deren Daten aber nur aus dem Pfad der Datei bestehen, auf die der Link verweist. Dadurch, dass mit dem Pfad operiert wird, existiert keine Bindung mehr an das Dateisystem und auch Verweise auf Verzeichnisse sind damit möglich. Die Dateien für die Symbolic Links haben einen speziellen Dateityp, der bei einem ls -l mit l angegeben wird. -s
Symbolic Links werden mit der Option -s des Kommandos ln erzeugt. Die Syntax ist bis auf die Option identisch mit der zur Erzeugung von Hard Links.
93
KAPITEL
6 3
7
Das Unix-Dateisystem – ein Blick hinter die Kulissen
ln -s [Optionen] Original Link ln -s [Optionen] Original1 ... Originaln Verzeichnis
UNIX-Kurs [~] 40 > UNIX-Kurs [~] 41 > UNIX-Kurs [~] 42 > -rw-r--r-- 2 lutz -rw-r--r-- 2 lutz lrw-r--r-- 1 lutz -> beispiel.txt
ln beispiel.txt beispiel.hard ln -s beispiel.txt beispiel.soft ls -l beispiel.* users 67 Jan 22 14:28 beispiel.txt users 67 Jan 22 14:28 beispiel.hard users 12 Jan 26 16:13 beispiel.soft
Nach diesen beiden Befehlen sieht die Innenansicht des Verzeichnisses aus Abb. 7.4 wie folgt aus: Abb. 7.5: Innenansicht eines Verzeichnisses mit Links
Dass tatsächlich die gleichen i-node-Nummern verwendet werden, kann mit dem Kommando ls -i überprüft werden, welches zu den Dateinamen die entsprechenden i-node-Nummern ausgibt.
1
Bei der Benutzung von Symbolic Links muss beachtet werden, dass die Datei, auf die der Link verweist, eventuell gar nicht existiert. Dafür gibt es mehrere Gründe: ✘ ln prüft bei der Erstellung eines Symbolic Links nicht, ob das Original existiert, sondern legt nur eine Datei vom Typ Link an und speichert in ihr den angegebenen Pfad.
94
Verweise – Links ✘ Da der Verweis über einen Symbolic Link nur in eine Richtung definiert ist (vom Link zum Original), können Links bei einer Umbenennung oder Löschung des Originals ungültig werden, ohne dass dies bemerkt wird. ✘ Wurde der Symbolic Link mit einem relativen Pfad erzeugt und wird er dann mit mv im Dateibaum verschoben, stimmt der relative Pfad meist nicht mehr und der Link zeigt in die Leere. ✘ In die Leere zeigende Links können, unabhängig ob sie mit einem relativen oder absoluten Pfad angelegt wurden, aber auch einen Vorteil haben: Wenn das Original-File mit rm gelöscht wurde und später neu (unter demselben Namen) angelegt wird, bleibt der Symbolic Link gültig und zeigt automatisch auf die neue Version.
7.3.3
Verwendungszwecke für Links
Nach Erklärung der Zusammenhänge zwischen Links, Dateien und Verzeichnissen stellt sich die Frage, wo die Einsatzgebiete für die Links liegen. Hard Links auf Verzeichnisse sind, wie bereits erläutert, wesentlicher Bestandteil beim Aufbau der Verzeichnishierarchie. Hard Links auf andere Dateien werden z.B. dazu eingesetzt, um kryptische Namen von Device Descriptors (Gerätedateien) in verständliche Namen umzusetzen. So wird häufig von Systemverwaltern im Verzeichnis /dev ein Link mit dem Namen tape auf den Device Descriptor für das Bandlaufwerk angelegt. Ein weiteres Beispiel für den Einsatz von Hard Links könnte ein CAD-System sein, welches unterhalb des Home Directorys des Benutzers ein Verzeichnis mit Standardbauteilen erwartet, die aber nicht vom Benutzer geändert werden dürfen. Anstatt die Dateien für die Bauteile zu kopieren und somit die Pflege zu komplizieren und Plattenplatz zu verschwenden, können Hard Links auf diese Standardbauteile hergestellt werden. Ein »Abfallprodukt« dieser Strategie ist, dass jede Änderung, die der Verwalter an den Standardbauteilen vornimmt, sofort allen Benutzern zugänglich ist. Symbolic Links werden in erster Linie zum Verweis auf Verzeichnisse eingesetzt. Programmen lässt sich mit dieser Art der Links eine Verzeichnisstruktur vorgaukeln, die das Programm erwartet, die aber nicht wirklich aufgebaut werden kann. Häufig muss zu diesem »Notnagel« gegriffen werden, wenn die Kapazitäten einer Partition erschöpft sind, aber das Betriebssystem oder ein Programm in einem Verzeichnis, das auf dieser Partition liegt, Daten ablegen will. Besonders interessant ist der Einsatz von Symbolic Links in Verbindung mit dem NFS (Network File System). Durch den symbolischen Verweis über den Pfad können auch Verweise auf Dateien angelegt werden, die auf der Platte
95
KAPITEL
7
Das Unix-Dateisystem – ein Blick hinter die Kulissen
eines anderen Rechners liegen. Der Benutzer kann sie aber über den Link ansprechen, als wären sie lokal.
7.4
Kontrolle des Speicherplatzes
7.4.1
du
Das Kommando du (disk usage) bestimmt die Anzahl der Blöcke (je nach Größe 512 oder 1.024 Byte), die ein Verzeichnis mit allen darin befindlichen Dateien und Unterverzeichnissen belegt. Im Gegensatz zum Kommando ls -l trägt das du auch dem Vorhandensein von Hard Links Rechnung, sodass wirklich die exakte Menge an Blöcken ermittelt wird.
6
3
96
du [Optionen] [Verzeichnisse]
Wird du ohne Parameter aufgerufen, bestimmt es den Speicherverbrauch des Working Directorys. Werden einzelne Verzeichnisse angegeben, bestimmt du deren Speicherverbrauch und gibt für jedes Verzeichnis und jede Datei eine einzelne Zeile aus. du verfügt über folgende Optionen: -s
Durch diese Option wird du veranlasst, nur die Summe des Speicherverbrauchs zu drucken, anstatt für jedes Verzeichnis und jede Datei eine Zeile auszugeben.
-k
Auf einigen Unix-Betriebssystemen mit einer Block-Größe von 512 Byte existiert -k als weitere Option. Mit dieser Option rechnet das Kommando Blöcke in KByte um.
-a
Nicht nur die Verzeichnisse, sondern auch alle darin enthaltenen Dateien, werden mit ihrer Plattenbelegung gelistet.
UNIX-Kurs [~] 43 > du 5216 ./tmp 1 ./src 1 ./projects 5218 .
Kontrolle des Speicherplatzes
7.4.2
df
Das Kommando df (disk free) bestimmt den freien Speicherplatz im Unix-Dateibaum in Blöcken. Genutzter und freier Speicherplatz werden getrennt nach Festplattenpartitionen angegeben.
df [-k]
Bei Angabe der Option -k erfolgt die Ausgabe in KByte anstatt in Blöcken.
UNIX-Kurs [~] 44 > df -k Filesystem Type kbytes use avail %use Mounted on /dev/root xfs 4253360 2801664 1451696 66 / /dev/dsk/dks0d2s7 xfs 8884562 965329 7919233 11 /home
2 3
In dem Beispiel wird der Unix-Dateibaum auf zwei Festplatten gelagert. Alle Dateien und Verzeichnisse unterhalb des Verzeichnisses /home liegen auf einer zweiten Festplatte, die am SCSI-Controller 0 mit der SCSI-ID 2 angeschlossen und zu 11% belegt ist. In manchen Unix-Systemen erhält man diese Liste (mit den Größenangaben in KByte) mit dem Befehl bdf, das ist die Berkeley-Version des df-Befehls; df gibt dagegen Blöcke und i-nodes (AT&T-Version des df-Befehls) an.
97
KAPITEL
7
Das Unix-Dateisystem – ein Blick hinter die Kulissen
Übungen
7.5
Aufgaben
1. Legen Sie ein Unterverzeichnis mit dem Namen uebung_1 in Ihrem Home Directory an und wechseln Sie in dieses Verzeichnis. 2. Kopieren Sie die Datei /bin/ls in Ihr Working Directory und legen Sie dann ein Unterverzeichnis links in Ihrem Working Directory an. 3. Wechseln Sie in das Verzeichnis links und legen Sie dort einen Hard Link mit dem Namen ls_hard und einen Symbolic Link mit dem Namen ls_symbolic auf die Datei ~/uebung_1/ls an. 4. Vergleichen Sie die beiden entstandenen Dateien anhand der Ausgabe von ls -l in Ihrem Working Directory. Welche Unterschiede gibt es? 5. Vergleichen Sie die i-node-Nummern von ~/uebung_1/ls
und
~/
und
~/
uebung_1/links/ls_hard.
6. Vergleichen Sie die i-node-Nummern von ~/uebung_1/ls uebung_1/links/ls_symbolic.
7. Was passiert, wenn Sie versuchen ls_hard und ls_symbolic auszuführen? 8. Löschen Sie ~/uebung_1/ls und wiederholen Sie die Ausführung von ls_hard und ls_symbolic. Was passiert?
7.5.1
Lösungen
1. Wechseln Sie gegebenenfalls mit dem Befehl cd (ohne Parameter-Angabe) in Ihr Home Directory. Ein neues Verzeichnis wird durch den Befehl mkdir erzeugt. UNIX-KURS [~] 34 > mkdir uebung_1
In das Verzeichnis wechseln wir nun durch Eingabe von: UNIX-KURS [~] 35 > cd uebung_1 UNIX-KURS [uebung_1] 9 >
2. Die Datei /bin/ls soll in mein Working Directory (also das Verzeichnis, in dem ich mich gerade befinde: uebung_1) kopiert werden. UNIX-KURS [uebung_1] 36 > cp /bin/ls .
Es wird die Datei /bin/ls in das aktuelle Verzeichnis (der Punkt) kopiert.
98
Aufgaben Nun soll noch in meinem Working Directory uebung_1 ein weiteres Verzeichnis mit dem Namen links angelegt werden: UNIX-KURS [uebung_1] 37 > mkdir links
3. Zunächst wechseln wir von uebung_1 in das Unterverzeichnis links. UNIX-KURS [uebung_1] 38 > cd links
Der Befehl ln ist zuständig für die Erzeugung von Links. Ohne Optionsangabe wird ein Hard Link erzeugt. Die Option -s erzeugt einen Symbolic Link (oft auch Soft Link genannt). Um einen Hard Link auf die Datei ~/ uebung_1/ls zu erzeugen, geben wir Folgendes ein: UNIX-KURS [links] 39 > ln ~/uebung_1/ls ls_hard
Und nun noch der Symbolic Link: UNIX-KURS [links] 40 > ln -s ../ls ls_symbolic
Es bleibt Ihnen überlassen, ob Sie die Pfadangabe auf die zu linkende Datei absolut oder relativ angeben. Allerdings werden Sie in Aufgabe 4 feststellen, dass dies später durchaus Auswirkungen haben kann. 4. Wir wollen uns nun die beiden erzeugten Links etwas genauer anschauen, dazu geben wir folgendes Kommando ein: UNIX-KURS [links] 41 > ls –l -rwxr-xr-x 2 UNIX user 29.604 Jan 5 13:14 ls_hard lrwxr-xr-x 1 UNIX user 5 Jan 5 13:16 ls_symbolic -> ../ ls
Gleich in der ersten Spalte sehen wir einen Unterschied. Der Hard Link ist ein Plain File (gekennzeichnet durch den -), während der Symbolic Link mit einem l gekennzeichnet ist. Des Weiteren unterscheiden sich die beiden Links durch die Größe des Linkcounts, ls_hard hat den Linkcount 2 (denn es existieren nun zwei Namen für ein und dieselbe physikalisch existierende Datei). Noch deutlicher wird der Unterschied, wenn man sich die Größe der Dateien ansieht. In diesem Beispiel hat der Hard Link die Größe 29.604 Byte (dies ist genau die gleiche Größe wie bei der Originaldatei, denn Hard Link und Original verweisen auf die gleiche i-node). Der Symbolic Link hat eine Größe von fünf Byte. In der Datei wird nur ein Pfad gespeichert: ../ls Und »Punkt«, »Punkt«, »Schrägstrich«, »l« und »s« sind genau fünf Zeichen ...
99
KAPITEL
1
7
Das Unix-Dateisystem – ein Blick hinter die Kulissen
Dieser Pfad ist relativ. Wenn Sie also die Datei ls_symbolic in ein anderes Verzeichnis verschieben, wird die Datei ls nicht mehr gefunden.
Um dies zu verhindern, sollten Sie Symbolic Links immer mit absoluten Pfaden anlegen (ln -s ~/uebung_1/ls ls_symbolic). Dadurch wird der absolute Pfad im Symbolic Link abgespeichert und das Original wird auch dann noch angesprochen, falls der Symbolic Link verschoben werden sollte. 5. Gibt man den ls-Befehl mit der Option -i an, so werden die i-node-Nummern der Dateien mit ausgegeben. UNIX-KURS [links] 42 > ls -i ~uebung_1/ls ls_hard 264598 /home/UNIX-Kurs/uebung_1/ls 264598 ls_hard
Wie Sie sehen, sind die beiden i-node-Nummern gleich. Auf der Festplatte existiert eine Datei mit der Nummer 264598 und diese Datei hat zwei Namen: einmal ~/uebung_1/ls und einmal ~/uebung_1/links/ls_hard. Durch den Befehl ln wurde also keine Kopie angelegt. Man kann nun nicht einmal mehr sagen, was das Original, und was der Link war. Beide verweisen auf die gleiche i-node-Nummer, also werden auch die gleichen Daten angezeigt. Die beiden Namen sind synonym. 6. Schauen wir uns nun noch die i-node-Nummer des Symbolic Links an: UNIX-KURS [links] 43 > ls -i ~uebung_1/ls ls_symbolic 264598 /home/UNIX-Kurs/uebung_1/ls 5095461 ls_symbolic
Wie Sie sehen, sind die beiden i-node-Nummern verschieden. Klar, denn der Inhalt der Datei ls_symbolic besteht ja nur aus einem Pfadnamen. 7. Beide Links verweisen auf ein executable. Rufen wir beide auf, so passiert Folgendes: UNIX-KURS [links] 44 > ./ls_hard ls_hard ls_symbolic UNIX-KURS [links] 45 > ./ls_symbolic ls_hard ls_symbolic
Offensichtlich wird durch den Aufruf der Inhalt des Working Directorys angezeigt. Sie merken schon: Die Ursprungsdatei, die wir in Aufgabe 2 kopierten und dann mit den beiden Links versahen, ist nichts weiter als das Programm, das uns den Unix-Befehl ls zur Verfügung stellt. Vielleicht wundern Sie sich, dass wir vor dem Link noch den Pfad (./) angegeben
100
Aufgaben haben. Diese Angabe soll sicherstellen, dass das Programm im aktuellen Verzeichnis aufgerufen wird. 8. Löschen wir nun die Datei ~/uebung_1/ls. UNIX-KURS [links] 46 > rm ~/uebung_1/ls
Rufen wir erneut ls_hard auf, so wird wieder der Inhalt des Verzeichnisses ausgegeben. UNIX-KURS [links] 47 > ./ls_hard ls_hard ls_symbolic
Die Datei ~/uebung_1/ls existiert zwar nicht mehr, aber ls_hard hat ja die gleiche i-node-Nummer, also die Beschreibung einer Datei auf der Festplatte. Und die existiert noch. Anmerkung für Fortgeschrittene: Der Linkcount ist jetzt nicht mehr 2, sondern nur noch 1. Rufen wir nun ls_symbolic auf: UNIX-KURS [links] 48 > ./ls_symbolic ls_symbolic: Command not found.
Wir bekommen die Fehlermeldung, dass die Datei nicht gefunden wurde. Klar, die Datei ls_symbolic beschreibt nur einen Pfad. Und dieser Pfad führt zu keinem Ziel, denn das Ziel – die Datei ls im Ordner uebung_1 – haben wir ja gerade gelöscht.
101
KAPITEL 8
Weitere Kommandos Neben den Grundbefehlen für das Anlegen, Kopieren, Umbenennen und Löschen von Dateien bietet Unix eine ganze Reihe weiterer Befehle an. Die Möglichkeiten, die sich durch diese Befehle und ihre Kombination ergeben, unterstreichen den Charakter von Unix als »offenes System«. Der Begriff des offenen Systems ist so zu verstehen, dass zunächst jeder im System fast alles anschauen und erforschen darf und auch durch entsprechende Befehle darin unterstützt wird. Was sich für Systemadministratoren zunächst wie ein Horrorszenario anhört, führt im Arbeitsalltag kundiger Unix-Anwender oft zu erstaunlicher Produktivität. Um vom Anfänger zum kundigen Unix-Anwender aufzusteigen, bedarf es zwar mehr – in erster Linie vielen Trainings – als nur der Kenntnis der unterschiedlichen Kommandos, doch ohne die eine oder andere Anregung verliert der Benutzer sehr leicht die Übersicht. Aus diesem Grund soll dieses Kapitel einige Unix-Kommandos vorstellen, die in vielen Situationen gute Dienste leisten können.
8.1
Wer suchet, der findet
Die Suchkommandos unter Unix sind sehr flexibel – so flexibel, dass selbst dann Unterstützung durch die Kommandos gewährt wird, wenn der Benutzer nur ungenaue Vorstellungen von dem hat, was er sucht. Erreicht wird die Formulierung solcher »unscharfer Vorstellungen« durch die Definition von Suchmustern, die ähnlich der Suchmuster für Dateinamen in der Shell über Wildcards gebildet werden. Viele der dabei verwendeten Wildcards haben auch in der Shell eine Bedeutung, die allerdings in diesem Verwendungsfall nicht zur Geltung kommen soll. Es gibt zwei Möglichkeiten, diese Sonderzeichen vor
103
KAPITEL
8
Weitere Kommandos
der Shell zu verbergen, d.h. ihre Auswertung durch den Kommandointerpreter zu verhindern. Der Escape Character »\« versteckt das nachfolgende Zeichen vor der Shell. Alternativ können Zeichenketten durch doppelte oder einfache Anführungszeichen (" oder ') eingeschlossen werden. Sämtliche enthaltene Wildcards verlieren dann für den Kommandointerpreter ihre Sonderbedeutung, vgl. Abschnitt 9.6.
3
*.txt
Die Shell interpretiert den »*« und versucht, eine Liste von Dateinamen zu finden.
"*.txt"
Der »*« wird von der Shell in seiner Sonderbedeutung nicht wahrgenommen, sondern bleibt ein Teil des Parameters, der an das Programm übergeben wird.
8.1.1
find
Auch in einem hierarchischen Dateisystem passiert es nahezu jedem Benutzer irgendwann, dass er eine Datei »verlegt« oder die Datenbestände eines Kollegen sichten muss, ohne dessen Ordnungsprinzip zu kennen. Für derartige Aufgaben (und noch viele weitere) gibt es das Kommando find – eines der mächtigsten Unix-Kommandos überhaupt. find ist das Hilfsmittel, wenn es darum geht, Dateien nach den unterschiedlichsten Kriterien zu suchen und ihre Position im Dateibaum anzuzeigen. Leider wird der Einsatz von find durch eine Abweichung von der Standard-Kommandosyntax ein wenig getrübt, was dann auch bei vielen Benutzern zu Fehlbedienungen führt. Deshalb folgt an dieser Stelle ein kurze Erläuterung des Grundaufbaus eines find-Kommandos.
6
find Startverzeichnis [Suchkriterien] Aktion
Prinzipiell sucht find immer unterhalb eines Startverzeichnisses nach einer Datei. Alle Unterverzeichnisse und deren Unterverzeichnisse usw. des Startverzeichnisses werden durchsucht. Das Startverzeichnis kann als absoluter oder als relativer Pfad angegeben werden. Die Suchkriterien beschreiben, welche Art(en) von Datei(en) gesucht werden. Die Suchkriterien werden durch die Optionen des find festgelegt. Diese bestehen – im Gegensatz zur Unix-Standard-Kommandosyntax – nicht nur aus einem Buchstaben und können auch nicht zu Optionsblöcken zusammengefasst werden. Werden keine Suchkriterien vereinbart, liefert find als Ergebnis jede Datei unterhalb des Startverzeichnisses, die es findet.
104
Wer suchet, der findet Im Folgenden werden einige Suchkriterien vorgestellt. -name
Es wird nach Dateien mit einem bestimmten Namen gesucht. Im Namen sind auch Wildcards erlaubt, die allerdings mit einem »\« maskiert oder durch Quotes eingerahmt werden müssen.
-name "*.c"
steht für alle Dateien mit der Endung .c.
-user
Es wird nach Dateien gesucht, die einem bestimmten Eigentümer gehören. Diese Option ist insbesondere bei Systemverwaltern beliebt, die ihre Systeme nach »Hinterlassenschaften« ausgeschiedener Benutzer durchsuchen müssen.
-user meier
steht für alle Dateien, die dem Benutzer mit der Benutzerkennung meier gehören.
-inum
Mit dieser Option wird nach Links auf eine bestimmte inode-Nummer gesucht. Diese Option macht nur dann Sinn, wenn die zugehörige Datei einen Linkcount größer als 1 hat.
-inum 32112
sucht nach allen Links auf die i-node-Nummer 32112.
-atime
Diese Option ermöglicht eine Suche in Abhängigkeit von der Zeit des letzten Zugriffs.
-ctime
Diese Option ermöglicht eine Suche in Abhängigkeit der Zeit der letzten Attributänderung – also z.B. einer Veränderung der Zugriffsrechte.
-mtime
Mit -mtime suchen Sie abhängig von der Modifikationszeit.
1 1 1
Die Zeit wird dabei in Tagen spezifiziert. Die Tageszahlen können mit einem Vorzeichen versehen werden (5 bedeutet genau fünf Tage, -5 bedeutet vor weniger als fünf Tagen und +5 bedeutet vor mehr als fünf Tagen).
-mtime -8
sucht nach Dateien, die vor weniger als acht Tagen – also in der letzten Woche – verändert worden sind.
1 105
KAPITEL
8 -newer
1
Weitere Kommandos Mit dieser Option suchen Sie nach solchen Dateien, die ein neueres Modifikationsdatum tragen als eine bestimmte andere Datei. Zwar kann bei dieser Form der Suche nur in Abhängigkeit von der Veränderungszeit gesucht werden, dafür werden aber selbst die Minuten und Sekunden zum Vergleich herangezogen.
-newer backup.log
-type
Mit diesem Suchkriterium kann nach Dateien eines bestimmten Dateityps gesucht werden. Es wird zwischen den Dateitypen unterschieden, die auch ls -l anzeigt – also jenen, die im i-node eingetragen werden.1 Dies sind: f d l c, b, p
1
-type d
sucht nach Dateien, die ein neueres Modifikationsdatum als die Datei backup.log tragen.
Plain File Directory Symbolic Link Device Descriptors
sucht nur nach Directories.
Die oben aufgelisteten Suchkriterien sind nur ein kleiner Auszug aus den Möglichkeiten des find-Kommandos. Durch die Kombination mehrerer Suchkriterien können Sie sehr gezielt nach bestimmten Dateien suchen. Für eine Aktion bietet find zwei Varianten an: 1. Ausgabe der Namen und Pfade der gefundenen Dateien. Wurde das Startverzeichnis als relativer Pfad angegeben, werden auch die gefundenen Dateien mit relativen Pfaden ausgegeben. Wurde das Startverzeichnis durch einen absoluten Pfad beschrieben, erfolgt auch die Ausgabe mit absoluten Pfaden. 2. Ausführung eines Unix-Kommandos für jede gefundene Datei. Es sollten hier nur solche Unix-Kommandos verwendet werden, die den Namen einer Datei als Parameter erwarten.
1. Bei der Klassifizierung durch das Kommando file werden weitere Informationen herangezogen.
106
Wer suchet, der findet Die beiden Varianten werden durch folgende Optionen angesprochen: -print
Dies ist die Standardaktion. Die Namen der Dateien, die die Suchkriterien erfüllen, werden ausgegeben. Obwohl einige Unix-Betriebssysteme das Weglassen dieser Option erlauben, sollten Sie sich angewöhnen, immer eine Aktion – also im Standardfall -print – zu spezifizieren. Auf einigen Systemen existieren auch noch Varianten für -print, um die Ausgabe anders zu formatieren.
UNIX-Kurs [~] 45 > find ~ -name wo_bloss -print /home/lutz/src/wo_bloss UNIX-Kurs [~] 46 > find . -print ./. ./.. ./a ./beispiel.txt ./src ./src/wo_bloss . . .
3
Im ersten Beispiel wird das gesamte Home Directory nach der Datei wo_bloss durchsucht. Das Ergebnis wird als absoluter Pfad angezeigt, da ~ als Abkürzung für den absoluten Pfad des eigenen Home Directorys benutzt wird. Im zweiten Beispiel zeigt Ihnen find alle Dateien, die unter dem Working Directory liegen, mit relativen Pfaden an. -exec
Diese Aktion bewirkt, dass für alle Dateien, die die Suchkriterien erfüllen, ein Kommando ausgeführt wird. Das Kommando sollte den Namen einer Datei als Übergabeparameter erwarten. Statt eines konkreten Namens wird bei der Verwendung von exec der Platzhalter {} an die Stelle geschrieben, an der normalerweise der Dateiname stünde. Das Ende des Kommandos wird durch \; angezeigt. Die komplette Syntax für das -exec lautet also: -exec kommando [optionen] {} \;
107
KAPITEL
3
8
Weitere Kommandos
UNIX-Kurs [~] 47 > find src -name "*.c" -exec ls -l {} \; UNIX-Kurs [~] 48 > find / -name core -exec rm -i {} \;
Im ersten Beispiel werden alle Dateien mit der Endung *.c, die unterhalb des Verzeichnisses src liegen, durch das Kommando ls -l angezeigt. Das zweite Beispiel löscht (nach Rückfrage) im gesamten Unix-Dateibaum alle Dateien mit dem Namen core. Häufig geht es bei der Suche nach Dateien nicht nur um »Äußerlichkeiten«, die sich durch die Suchkriterien des find abdecken lassen, sondern um die Inhalte von Dateien. Auch hier bietet Unix Hilfswerkzeuge an, die ähnlich mächtig wie find sind, dafür aber auch ähnlich kryptisch in der Bedienung.
8.1.2
fgrep, grep, egrep
Für die Suche in Dateiinhalten stellt Unix die Familie der grep-Kommandos zur Verfügung. Alle drei Mitglieder dieser Familie machen im Prinzip das gleiche: Sie suchen nach bestimmten Zeichenketten im Inhalt von Dateien und geben die Zeilen der Dateien aus, die die Zeichenkette enthalten. Lediglich die Angabe der Zeichenketten, einige Optionen und die damit verbundene Variabilität bei der Suche unterscheiden die drei Kandidaten. Die größte Flexibilität bei der Formulierung der Suchmuster bietet das Kommando egrep. Es ist in der Lage, nach so genannten regulären Ausdrücken zu suchen. Ein regulärer Ausdruck ist eine Zeichenkette, die spezielle Metazeichen enthält, mit denen bestimmte Muster beschrieben werden können. Da reguläre Ausdrücke sehr viel mit dem umfangreichen und komplizierten Gebiet der Grammatiken (als Fachbegriff der Informatik) zu tun haben, kann an dieser Stelle nur eine minimale Einführung gegeben werden. Ein regulärer Ausdruck besteht aus einer Abfolge von Mustern. Im einfachsten Fall ist dies eine Zeichenkette aus einem oder mehreren Zeichen ohne Sonderbedeutung, wobei jedes Zeichen selbst ein Muster ist.
108
Wer suchet, der findet
( )
Werden Muster durch runde Klammern umschlossen, bilden sie wieder ein neues Muster.
*, +
Wiederholungsfaktoren wie »*« oder »+« zeigen an, dass das vor ihnen stehende Muster mehrfach auftauchen kann. Dabei bedeutet »+« mindestens einmal oder mehrmals, »*« mehrmals, aber auch keinmal.1
|
Werden Muster durch »|« getrennt, bedeutet dies ein logisches »Oder«, d.h. an dieser Stelle kann eines der durch »|« getrennten Muster stehen.
[ ]
Die eckigen Klammern sind ein Sonderfall der Oder-Verknüpfung von Mustern. Wenn alle Muster nur ein Zeichen lang sind, kann die Schreibweise mit der Trennung durch »|« dadurch ersetzt werden, dass die Zeichen hintereinander, umgeben von eckigen Klammern geschrieben werden.
.
Der Punkt steht als Platzhalter für ein beliebiges Zeichen.
^
Das »Dach« am Anfang eines Musters bedeutet »am Anfang der Zeile«.
$
Das Dollarzeichen am Ende eines Musters bedeutet »am Ende der Zeile«.
\
Wie auch schon unter der Shell, dient der Backslash »\« als Escape Character, der Metazeichen von ihrer Sonderfunktion befreit.
Der Ausdruck a.*b steht für alle Zeichenfolgen, die mit einem a beginnen und mit einem b enden.1 Der Ausdruck [a-zA-Z].*\.de steht für alle Zeichenfolgen, die mit einem Buchstaben beginnen und mit .de enden.
1
Der Ausdruck [Uu][Nn][Ii][Xx](-|( +))[Kk]urs würde die unterschiedlichsten Schreibweisen für UNIX-Kurs abdecken, u.a. folgende: unix kurs, unix
kurs, Unix-Kurs, UNIX-Kurs, ...
Während egrep den vollen Umfang möglicher Regeln zur Bildung von regulären Ausdrücken beherrscht, beschränkt sich grep nur auf die Interpretation von »+«, »*«, »\«, ».«, »^«, »$« und »[]«. fgrep behandelt alle Sonderzeichen wie Buchstaben – also ohne Sonderbedeutung.
Die allgemeine Aufrufsyntax für ein grep-Kommando lautet:
1.
.* bedeutet also eine beliebige Zeichenfolge – auch die leere Folge. .+ bedeutet hingegen eine beliebige Zeichenfolge, aber mindestens ein Zeichen.
109
KAPITEL
6
3
8
Weitere Kommandos
grep [Optionen] Suchmuster Datei/Dateien
Da viele der Metazeichen zur Bildung eines regulären Ausdrucks auch unter der Shell Wildcards sind und die Shell jede Wildcard, die ungequotet auf der Kommandozeile eingegeben wird, interpretiert, sollten Sie immer Quotes um das Suchmuster für eines der drei grep-Kommandos setzen. Folgende Optionen sind verfügbar: -c
Mit dieser Option werden nicht die Zeilen ausgegeben, in denen das Muster gefunden wird, sondern die Anzahl der Zeilen, in denen das Muster gefunden wurde, wird gezählt (count) und als Ergebnis ausgegeben.
-n
Diese Option sorgt dafür, dass vor jeder Zeile, die eine Fundstelle enthält, die Zeilennummer (number) zusätzlich zur Zeile ausgegeben wird.
-l
Statt jede Zeile auszugeben, in der das Muster vorkommt, werden nur die Namen der Dateien (list) ausgegeben, in denen das Muster mindestens einmal vorkommt.
-v
Diese Option invertiert die Suchaussage. Es werden nur solche Zeilen als Treffer gewertet, die das Muster nicht enthalten.
-i
Mit dieser Option ignoriert grep die Groß-/Kleinschreibung.
-e
Der Option -e muss direkt das Suchmuster folgen. Sie dient dazu, Suchmuster, die mit einem Minuszeichen (-) beginnen, für grep von den Optionen unterscheidbar zu machen.
UNIX-Kurs [~] 49 > grep -c yasc beispiel.txt 1 UNIX-Kurs [~] 50 > grep "^lutz:" /etc/passwd lutz:HhgskJkal:501:30:Lutz Brockmann:/home/lutz:/bin/tcsh
Das erste Beispiel zählt, wie oft die Zeichenkette »yasc« in der Datei beispiel.txt vorkommt und gibt die Anzahl aus (hier 1). Das zweite Beispiel sucht den Eintrag für den Benutzer lutz aus der Passwortdatei (/etc/passwd) heraus. Damit nicht auch Zeilen gefunden werden, in denen lutz nicht als Benutzername auftaucht (also nicht am Zeilenanfang steht) oder lutz nur ein Teil des Benutzernamens ist (z.B. lutz2 oder lutzb), wurde das Suchmuster als »^lutz:« definiert. »^« steht für den Zeilenanfang; der Doppelpunkt »:« ist das Trennzeichen zwischen den einzelnen Feldern der /etc/ passwd (vgl. auch Abschnitt 8.2, Kommando cut).
110
Sortieren und Ausschneiden
8.2
Sortieren und Ausschneiden – Basteln mit Unix
Um sich den Inhalt einer Textdatei anzuschauen, wird von den meisten Benutzern ein Texteditor bevorzugt, weil mit einem solchen Werkzeug komfortabel durch den Text gescrollt werden kann. Beschränkt sich das Interesse des Benutzers jedoch nur auf Teilaspekte oder wünscht er sich eine andere Sortierung des Inhalts, ist bei vielen Editoren das Ende der Fähigkeiten erreicht. Für derartige Anwendungsfälle bietet Unix eine Auswahl von Hilfswerkzeugen an, um den Inhalt von Dateien entsprechend aufzubereiten. Das Ergebnis der Aufbereitung wird auf den Bildschirm ausgegeben, während die Originaldatei stets unverändert bleibt. Das Bearbeitungsergebnis lässt sich z.B. wieder in eine Datei schreiben, die dann mit dem bevorzugten Editor angeschaut werden kann. Dieses Kapitel stellt fünf Werkzeuge zur Aufbereitung von Dateiinhalten vor.
8.2.1
cut
Erster Kandidat im Fünferreigen ist das cut (engl. für schneiden). Es macht seinem Namen alle Ehre – es schneidet bestimmte Teile aus dem Inhalt einer Datei heraus. cut arbeitet zeilenweise, indem es aus jeder Zeile einen bestimmten Bereich herausschneidet und ihn ausgibt. cut kennt zwei verschiedene Varianten, solche Bereiche zu definieren: ✘ Definition über Zeichenbereiche, z.B. »von Zeichen 3 bis Zeichen 15 jeder Zeile« ✘ Definition über Felder. cut geht davon aus, dass zwischen zwei Feldern ein Feldtrennzeichen steht, und umgekehrt, dass zwischen Feldtrennzeichen ein Feld steht.1 Unter dieser Voraussetzung können dann ebenfalls Bereiche gebildet werden, durch die z.B. die Felder 1, 2 und 5 jeder Zeile angesprochen werden können. Die Syntax für das Kommando cut lautet wie folgt:
cut Bereichsdefinition [Datei/Dateien]
6
1. Dieses Verhalten führt oftmals zu ungewollten Ergebnissen, wenn z.B. als Trennzeichen das Leerzeichen benutzt wird und cut Folgen von Leerzeichen nicht als einen Trenner auffasst.
111
KAPITEL
8
Weitere Kommandos
Zur Definition der Bereiche verfügt cut über folgende Optionen: -c
3
3
Mit dieser Option wird ein Zeichenbereich definiert. Die Bereichsangabe folgt dem -c ohne trennendes Leerzeichen und kann sich aus mehreren Bereichen zusammensetzen. Die einzelnen Bereiche dürfen sich nicht überlappen und werden durch Kommata getrennt angegeben. Folgende Formen von Bereichen sind erlaubt: 5
Nur ein Zeichen (hier das fünfte jeder Zeile)
-10
Vom Anfang der Zeile bis zum zehnten Zeichen inklusive
20-
Vom zwanzigsten Zeichen bis zum Ende der Zeile
3-7
Vom dritten bis zum siebten Zeichen der Zeile
UNIX-Kurs [~] 51 > cut -c-10,25- geburtstage.txt
Dieser Befehl schneidet aus jeder Zeile der Datei geburtstage.txt die ersten zehn Zeichen und alle Zeichen vom 25. bis zum Ende der Zeile aus. -f
Diese Option dient der Angabe von Feldbereichen. Die Schreibweise entspricht der der Zeichenbereiche bis auf den Unterschied, dass statt Zeichen Felder definiert werden. Der Default-Feldtrenner ist das Tabulatorzeichen.
-d
Mit dieser Option kann ein neuer Feldtrenner festgelegt werden. Das Zeichen, das als Feldtrenner dienen soll, wird direkt nach der Option ohne trennendes Leerzeichen eingegeben. (Sonderfall: Um ein Leerzeichen als Trennzeichen zu definieren, kann z.B. "-d " eingegeben werden).
UNIX-Kurs [~] 52 > cut -d: -f1,5,6 /etc/passwd
Dieser Befehl schneidet die Felder 1, 5 und 6 jeder Zeile in der Datei /etc/ passwd aus. Diese Datei ist die Passwortdatei des Unix-Betriebssystems. Sie enthält für jeden Benutzer eine Zeile, die in sieben Felder (Loginname, verschlüsseltes Passwort1, Benutzernummer, Gruppennummer, Kommentar, Home Directory und Shell) unterteilt ist. Die Felder werden durch Doppelpunkte getrennt (deshalb wird der Feldtrenner mit -d: vereinbart).
1. Auf vielen Systemen sind die Passwörter in der Datei /etc/shadow eingetragen. Die Passwortdatei enthält dann an dieser Stelle im allgemeinen nur ein x.
112
Sortieren und Ausschneiden
8.2.2
head
Eine Reihe von Dateien, z.B. CAD-Dateien oder Programmquellen, enthalten wichtige Informationen in einem so genannten Kopfteil (engl. Header). Dieser Header einer Datei wird meist dazu genutzt, Informationen über den Erzeuger (dies kann eine Person oder ein Programm sein), die Versionsnummer und den nachfolgenden Inhalt der Datei aufzunehmen. Oftmals ist dieser Header nicht länger als zehn Zeilen, was das Laden einer viele Megabyte großen CAD-Datei in einen Editor unsinnig macht, wenn man nur an diesen Informationen interessiert ist. Für derartige Anwendungsfälle gibt es das Kommando head. Mit head können die ersten n Zeilen einer Datei auf dem Bildschirm ausgegeben werden. Natürlich sollte auch hier zuerst mit dem Kommando file überprüft werden, ob es sich überhaupt um eine Textdatei handelt.
head [Optionen] [Datei/Dateien]
Die Anzahl der Zeilen, die head vom Anfang der Datei ausgeben soll, wird als Option übergeben. So steht z.B. -12 für die ersten zwölf Zeilen und -25 für die ersten 25 Zeilen. Wird die Anzahl nicht über diese Option festgelegt, werden als Default die ersten zehn Zeilen ausgegeben.
UNIX-Kurs [~] 53 > head -25 main.c
Dieses Beispiel gibt die ersten 25 Zeilen der Datei main.c aus.
8.2.3
6 3
tail
Was bei manchen Dateien den Anfang für den Benutzer interessant macht, steht bei anderen Dateien am Ende. Auch hier wäre das Laden einer solchen Datei in einen Texteditor nur die zweite Wahl für die Lösung des Problems. Ähnlich wie das head die ersten n Zeilen einer Datei ausgibt, gibt tail die letzten n Zeilen einer Datei aus.
tail [Optionen] [Datei/Dateien]
Auch tail nimmt wie head die Anzahl der auszugebenden Zeilen über eine Option entgegen. Der Default ist ebenfalls zehn Zeilen lang, wenn keine Angabe erfolgt.
6 113
KAPITEL
8
Weitere Kommandos
Wird vor die Option zur Zeilenangabe beim tail statt eines »-« ein »+« geschrieben, bedeutet dies, dass der Dateiinhalt ab dieser Zeile bis zum Ende der Datei ausgegeben werden soll. -f
3
Mit der Option -f wird das Kommando tail nicht beendet, sobald es die letzten n Zeilen der Datei ausgegeben hat (was das Standardverhalten ist), sondern es bleibt in »Wartestellung« und gibt, sobald neue Zeilen an eine Datei angefügt werden, diese auf dem Bildschirm aus. Diese Option kommt in erster Linie bei der Überwachung so genannter Log-Dateien, in denen die Ergebnisse laufender Prozesse protokolliert werden, zum Einsatz.
UNIX-Kurs [~] 54 > tail -20 /var/adm/SYSLOG
Dieses Kommando gibt die letzten 20 Zeilen der SYSLOG-Datei aus. In dieser Datei werden unter dem Unix-Betriebssystem IRIX von Silicon Graphics »Vorkommnisse« wie Lesefehler auf der Platte, Einlogvorgänge von Benutzern, Probleme mit Geräten am SCSI-Bus usw. protokolliert. Zuständig für diese Aufgaben ist der syslogd, ein so genannter Dämonenprozess, der permanent läuft.1
8.2.4
sort
Bei dem Kommando sort ist der Name Programm. Es sortiert die Zeilen von Dateien nach unterschiedlichen Kriterien. Verwendet wird dabei der Quicksort-Algorithmus, der sich durch sein gutes Zeitverhalten auszeichnet. Werden keine Optionen verwendet, die andere Sortierkriterien festlegen, sortiert sort über die ganze Zeile. Die Festlegung eines Sortierkriteriums erfolgt so ähnlich wie die Bereichsangabe beim cut. Auch sort bietet neben der Möglichkeit, einen bestimmten Zeichenbereich zum Sortierschlüssel zu machen, die Festlegung eines Feldbereichs an.
6
sort [Optionen] [Datei/Dateien]
sort verfügt über eine erstaunliche Menge von Optionen, um das Sortierver-
halten zu beeinflussen. Da eine vollständige Aufzählung und Erläuterung höchstens die Ermüdung des Lesers zur Folge hätte, sei an dieser Stelle auf
1. Nicht auf allen Unix-Systemen steht die SYSLOG-Datei in dem Verzeichnis /var/adm. Die man-Page zum syslogd hilft hier oft bei der Suche.
114
Sortieren und Ausschneiden die man-Page verwiesen. Die nun folgenden Optionen sind die gebräuchlichsten.1 -f
sort unterscheidet beim Vergleich nicht zwischen Groß- und Kleinbuchstaben.
-n
Diese Option sorgt für eine Sortierung von Ziffernfolgen nach ihrem numerischen Wert. Führende Leerzeichen werden ignoriert und das Minuszeichen (-) wird als Vorzeichen interpretiert.
-r
Die Sortierreihenfolge wird umgedreht, d.h. die (nach der ASCII-Tabelle) alphanumerisch letzte Zeile wird also als erste ausgegeben.
-d
Die Sortierung erfolgt alphabetisch (und nicht nach der ASCII-Tabelle).
-u
Über diese Option sorgen Sie dafür, dass aus dem Ergebnis des Sortiervorgangs doppelte Zeilen entfernt werden.
-t
Der Option -t folgt der Feldtrenner. Dieser ist zur Festlegung der Felder für die Definition des Sortierschlüssels gedacht. Default für den Feldtrenner ist der Leerstring zwischen einem Leerzeichen und einem Nichtleerzeichen. Das heißt, dass führende Leerzeichen mit zu einem Feld gehören, aber trotzdem die Feldgrenzen an den Leerzeichen festgemacht werden. Dieser Default soll es ermöglichen, auch solche Dateien korrekt zu sortieren, in denen Felder rechtsbündig formatiert sind.
-k n[,m]
Mit dieser Option wird ein Sortierschlüssel festgelegt, der mit Feld n beginnt und mit Feld m endet. Wird kein abschließendes Feld angegeben, so endet der Sortierschlüssel am Zeilenende. Die Option kann mehrfach angegeben werden, so bewirkt z.B. -k 4,4 -k 8,8 eine Sortierung nach dem vierten – und bei gleichem vierten Feldinhalt – nach dem achten Feld.1
-o
Nach dieser Option wird, durch ein Leerzeichen getrennt, der Name der Datei angegeben, in der das Ergebnis des Sortiervorgangs abgelegt werden soll.
UNIX-Kurs [~] 55 > sort -t: -o passwd.sort -k 5,5 /etc/passwd
Dieses Beispiel sortiert die Zeilen der Datei /etc/passwd. Das Sortierkriterium ist das fünfte Feld der Datei (dies enthält in der Regel den vollen Namen des Benutzers). Das Ergebnis wird in die Datei passwd.sort geschrieben.
3
1. Nicht bei allen Unix-Derivaten muss der Option -k ein Leerzeichen folgen.
115
KAPITEL
8
Weitere Kommandos
Übungen
8.3
Aufgaben
1. Formulieren Sie einen find-Befehl, der Ihnen alle Plain Files unterhalb des Home Directorys ausgibt. 2. Verändern Sie die Lösung von 1.) so, dass nur noch solche Plain Files aufgelistet werden, die in den letzen fünf Tagen verändert worden sind. 3. Verändern Sie die Lösung von 2.) so, dass für alle gefundenen Dateien das Kommando ls -l ausgeführt wird. 4. Suchen Sie mithilfe eines grep-Kommandos die Zeile für Ihre Benutzerkennung aus der Datei /etc/passwd heraus. 5. Geben Sie das erste und das dritte Feld aller Zeilen aus der Datei /etc/ group aus. Die Felder sind durch einen Doppelpunkt getrennt. 6. Sortieren Sie die Zeilen der Datei /etc/passwd nach den Benutzernummern. Diese stehen im dritten Feld. Die Felder sind durch Doppelpunkte getrennt. Die Sortierung soll numerisch erfolgen.
8.3.1
Lösungen
1. Der find-Befehl ermöglicht die Suche nach bestimmten Dateitypen, indem man als Suchkriterium -type angibt. Um welchen Dateityp es sich dabei handeln soll, wird hinter -type angegeben. Die Angabe f steht für Plain Files. Damit die gefundenen Dateinamen auf dem Bildschirm ausgegeben werden, gibt man als Aktion -print an: UNIX-KURS [~] 33 > find . -type f -print
Beachten Sie den Punkt. Der find-Befehl muss wissen, in welchem Verzeichnis er die Suche beginnen soll. Und da wir uns gerade in unserem Home Directory befinden, repräsentiert der Punkt dieses auch. Da der Punkt eine relative Pfadangabe ist, werden auch die Suchergebnisse in relativen Pfaden angegeben! Möchten Sie hingegen absolute Pfadangaben in den Suchergebnissen sehen, so müssen Sie das Startverzeichnis ebenfalls absolut angeben. In unserem Beispiel könnte man zu diesem Zweck den Punkt durch die Tilde (~) ersetzen, denn diese steht ja als Platzhalter für den absoluten Pfad unseres Home Directorys. 2. Wir können auch mehrere Suchkriterien angeben. Als Ergebnis bekommen wir die Dateien, die alle Suchkriterien erfüllen.
116
Aufgaben Gesucht sind alle Plain Files, die innerhalb der letzten fünf Tage verändert worden sind. Der find-Befehl muss daher lauten: UNIX-KURS [~] 34 > find . -type f -mtime -6 -print
Die Option -mtime ermöglicht die Suche nach dem Modifikationsdatum. Die Angabe -mtime –6 betrifft alle Dateien, die vor weniger als sechs Tagen geändert wurden. Und »vor weniger als sechs Tagen« entspricht dem in der Aufgabe gestellten »in den letzten fünf Tagen«. 3. Soll für jede gefundene Datei ein Kommando ausgeführt werden, so ermöglicht dies der find-Befehl durch die Aktion -exec. -exec und \; bilden dabei eine Art »Klammer«. Innerhalb dieser Klammer steht das Kommando, welches für die Suchergebnisse ausgeführt werden soll. UNIX-KURS [~] 34 > find . -type f -mtime -6 -exec ls -l {} \;
Die geschweiften Klammern stehen als Platzhalter für die Dateinamen, die der find-Befehl an das Kommando ls -l übergibt, also all jene Dateien, die die vorangegangenen Suchkriterien erfüllen. 4. In der Datei /etc/passwd sind alle Benutzer, die sich auf Ihrem Unix-System anmelden dürfen, aufgelistet. Sie können sich die Datei erst einmal mit dem Befehl more /etc/passwd anschauen. Neben der Benutzerkennung, die als erstes Feld aufgeführt ist, sind dort auch Angaben über Ihre Gruppe, Ihr Passwort (natürlich verschlüsselt), die Lage Ihres Home Directorys usw. angegeben. Diese Datei kann recht lang sein und es wäre sehr mühselig, auf dem Bildschirm alle Zeilen nach Ihrer Benutzerkennung zu durchsuchen. Da kommt das grep-Kommando wie gerufen: Es schneidet alle Zeilen – die einen gewissen Suchbegriff enthalten – aus. UNIX-KURS [~] 35 > grep "^unix:" /etc/passwd
In diesem Beispiel lautet die Benutzerkennung unix. Sie müssen natürlich an dieser Stelle Ihre eigene Benutzerkennung eintragen ... Die Felder innerhalb der Datei passwd sind durch Doppelpunkte voneinander getrennt. Wir haben in dem Beispiel den Doppelpunkt mit angegeben, um sicherzustellen, dass die Benutzerkennung unix nach dem x auch wirklich aufhört. Denn dann folgt ein neues Feld und damit der Doppelpunkt. Lässt man diesen weg, so wird auch die Zeile eines Benutzers mit der Kennung unixen angezeigt.
117
KAPITEL
8
Weitere Kommandos
Das kleine Dach ^ vor dem Suchwort stellt sicher, dass sich dieses am Anfang der Zeile befindet. Wir möchten ja nur nach der Benutzerkennung suchen und die steht jeweils im ersten Feld. 5. In der Datei /etc/group sind alle Gruppennamen (1. Feld) und ihre Gruppennummer (3. Feld) aufgeführt. Die Felder dieser Datei sind durch Doppelpunkte voneinander getrennt. Um Bereiche aus Zeilen auszuschneiden, bietet Unix den Befehl cut an. UNIX-KURS [~] 36 > cut -d: -f1,3 /etc/group
Durch die Option -f wird festgelegt, dass nicht Zeichenbereiche – also z.B. 10. bis 25. Zeichen einer Zeile –, sondern ganze Felder ausgeschnitten werden sollen. -f1,3 heißt also: das erste und dritte Feld jeder Zeile. Der Default-Feldtrenner für das cut-Kommando ist das Tabulatorzeichen. Die Datei /etc/group benutzt als Feldtrenner jedoch den Doppelpunkt. Der Doppelpunkt muss daher mit der Option -d explizit als Feldtrenner angegeben werden. 6. In dieser Aufgabe soll die schon bekannte Datei /etc/passwd nach den Benutzernummern sortiert werden. Die Benutzernummern stehen im dritten Feld. Durch die Option -t: wird festgelegt, dass der Trenner zwischen den einzelnen Feldern nicht die defaultmäßig eingestellte Leerzeichenfolge, sondern der Doppelpunkt sein soll. UNIX-KURS [~] 37 > sort -t: -k 3,3 -n /etc/passwd
Die Option -k legt den Sortierschlüssel fest. Hier soll also nach dem dritten Feld (-k3,3: Starte bei 3, Ende bei 3) sortiert werden. Letztendlich sorgt die Option -n dafür, daß numerisch sortiert werden soll. Bei einer alphanumerischen Sortierung ist nämlich eine »20« größer als eine »100«, da der erste »Buchstabe« 2 ja größer ist als der erste »Buchstabe« von »100«.
118
KAPITEL 9
Der Unix Stream Editor Oftmals ist es mit dem Sortieren des Inhalts einer Datei nicht getan – da müssen bestimmte Inhalte durch andere ersetzt, Zeilen und Worte gelöscht oder eingefügt werden. All das könnte man natürlich mit einem Texteditor ohne Probleme »von Hand« machen, aber bei bestimmten Dateien wie z.B. Template-Dateien1 möchte man solche Aufgaben gerne automatisieren. Unix wäre nicht Unix, wenn es nicht auch hier Unterstützung durch ein entsprechendes Utility gäbe. Der so genannte Stream Editor sed ist in der Lage, derartige Veränderungen am Inhalt von Dateien vorzunehmen. Dabei bleibt die Ursprungsdatei unverändert, denn der sed bearbeitet nämlich nicht die Datei selbst, sondern nur den »Datenstrom«, welchen er aus der Datei liest. Der sed wird aufgrund dieser Eigenschaft gerne von Shell-Script-Programmierern verwendet.
9.1
Reguläre Ausdrücke
In der ersten Auflage dieses Buches wurde der sed nur recht stiefmütterlich als Unterabschnitt zu den Filterprogrammen behandelt. Aufgrund des Feedbacks einiger Leser habe ich mich entschlossen, in der zweiten Auflage dem sed ein 1. Unter einer Template-Datei versteht man eine Art Vorlage. So etwas wird vielfach bei der Programmierung verwendet, um einheitliche Header für Quelldateien eines Projekts zu erhalten. Alle vorgegebenen Felder werden in einer Template-Datei hinterlegt, und der jeweilige Autor ersetzt z.B. nur bestimmte Platzhalter durch seine individuellen Angaben.
119
KAPITEL
9
Der Unix Stream Editor
eigenes Kapitel zu widmen. Eine logische Konsequenz davon ist es, auch auf die Verwendung von regulären Ausdrücken stärker einzugehen. Ein erster Eindruck von den regulären Ausdrücken wurde bereits im Abschnitt über das Kommando egrep vermittelt. Nochmal zur Wiederholung: Ein regulärer Ausdruck ist eine allgemeine Beschreibung für den Aufbau von Zeichenketten. Dabei werden variable Teile der Zeichenkette durch Platzhalter in Form von Metazeichen beschrieben. Man spricht dabei von einer Abfolge von Mustern, wobei ein Muster entweder konstant (also ein fester String, der in der gesuchten Zeichenkette exakt so vorkommt) oder variabel sein kann. Folgende Metazeichen werden dabei eingesetzt: ( )
Werden Muster durch runde Klammern umschlossen, bilden sie wieder ein neues Muster.
*, +
Wiederholungsfaktoren wie »*« oder »+« zeigen an, dass das vor ihnen stehende Muster mehrfach auftauchen kann. Dabei bedeutet »+« mindestens einmal oder mehrmals, »*« mehrmals, aber auch keinmal.1
|
Werden Muster durch »|« getrennt, bedeutet dies ein logisches »Oder«, d.h. an dieser Stelle kann eines der durch »|« getrennten Muster stehen.
[ ]
Die eckigen Klammern sind ein Sonderfall der Oder-Verknüpfung von Mustern. Wenn alle Muster nur ein Zeichen lang sind, kann die Schreibweise mit der Trennung durch »|« dadurch ersetzt werden, dass die Zeichen hintereinander, umgeben von eckigen Klammern, geschrieben werden.
.
Der Punkt steht als Platzhalter für ein beliebiges Zeichen.
^
Das »Dach« am Anfang eines Musters bedeutet »am Anfang der Zeile«.
$
Das Dollarzeichen am Ende eines Musters bedeutet »am Ende der Zeile«.
\
Wie auch schon unter der Shell dient der Backslash »\« als Escape Character, der Metazeichen von ihrer Sonderfunktion befreit.
{n,m}
Wird ein solcher Ausdruck in geschweiften Klammern einem Buchstaben nachgestellt (das kann auch ein Platzhalter wie der Punkt ».« sein), werden n bis m Wiederholungen des Buchstabens als Treffer für den Ausdruck gewertet.
1.
.* bedeutet also eine beliebige Zeichenfolge – auch die leere Folge. .+ bedeutet hingegen eine beliebige Zeichenfolge, aber mindestens ein Zeichen.
120
Reguläre Ausdrücke 1
Der Vorteil einer solchen allgemeinen Beschreibungssprache für das Aussehen von Zeichenketten ist, dass sich neben der Beschreibung von exakten Zeichenketten wie z.B. Dies ist eine Zeichenkette\.
auch unscharfe Beschreibungen für den gleichen Suchbegriff erstellen lassen, wie z.B. in der Form: Die Zeichenkette muss mit einem Großbuchstaben beginnen, dann muss die Zeichenkette ist enthalten sein und anschließend die Zeichenkette kette und das Ganze muss auf einen Punkt enden. Als regulärer Ausdruck formuliert sähe das dann wie folgt aus: [A-Z].*ist.*kette.*\.
Bei beiden Beispielen muss zuerst einmal auf den abschließenden Punkt (».«) hingewiesen werden, der durch einen Backslash »\« maskiert wird, um ihn nicht als Metazeichen zu verwenden. Ansonsten enthält der erste Ausdruck keine weiteren Metazeichen und schreibt somit das Aussehen der Zeichenkette exakt vor. Im zweiten Ausdruck wird durch die Kombination [A-Z] die Vorschrift, dass der Satz mit einem Großbuchstaben beginnen soll, abgebildet. Nach diesem Großbuchstaben darf eine beliebige Zeichenkette folgen (.*) dann das Wort ist, ebenfalls wieder gefolgt von einer beliebigen Zeichenkette (.*) gefolgt von dem Wort kette, gefolgt von einer beliebigen Zeichenkette (.*) und abgeschlossen durch einen Punkt (\.). Der zweite reguläre Ausdruck würde aber auch für den Satz Christian verschenkt eine Perlenkette.
einen Treffer ergeben. Wie man an diesem Beispiel sieht, können die Ergebnisse, die auf einen regulären Ausdruck zutreffen, sehr unterschiedlich aussehen. Die Unterschiede in den Ergebnissen nehmen mit der Anzahl an variablen Mustern zu. Aus diesem Grund sollte man, bevor man einen regulären Ausdruck konstruiert, sehr genau überlegen, welche Treffer man erzielen will und welche nicht. Oft kann man aber auch einen regulären Ausdruck variabler und somit kürzer formulieren, weil man die Daten, auf die er angewandt wird, sehr genau kennt und bestimmte mögliche Treffer von vorne herein ausschließen kann.
1.
.* bedeutet also eine beliebige Zeichenfolge – auch die leere Folge. .+ bedeutet hingegen eine beliebige Zeichenfolge, aber mindestens ein Zeichen.
121
KAPITEL
9 9.2
Der Unix Stream Editor
Arbeiten mit dem sed
Fast alle Editierfunktionen können zwar über die Kommandozeile eingegeben werden, wenn aber viele oder umfangreiche Änderungen zu machen sind, empfiehlt es sich, die Möglichkeit des sed zu nutzen, die Kommandos in einer Scriptdatei abzulegen.
6 6
sed Editierkommando [Datei/Dateien]
In der einfachsten Variante des Aufrufs wird als erster Parameter ein Editierkommando angegeben. Der sed wendet dieses Kommando auf den Inhalt der Eingabedatei/-dateien an und gibt das Ergebnis auf den Bildschirm aus.
sed [-e Editierkommando | -f Scriptdatei] [Datei/Dateien]
Sollen zwei oder mehr Editierkommandos ausgeführt werden, können diese entweder jeweils mit einem vorangestellten –e als Argument an den sed übergeben oder in eine Scriptdatei geschrieben werden, deren Name dann als Argument nach der Option –f angegeben werden muss. In der Scriptdatei werden die unterschiedlichen Kommandos jeweils in einer separaten Zeile angegeben.
9.2.1
Adressierung
Wenn man den Inhalt einer Datei oder besser einen Datenstrom mit dem sed bearbeiten will, will man die Teile der Daten, auf welche die Editierfunktionen angewendet werden sollen, vielleicht einschränken. Zu diesem Zweck bietet der sed das Konzept der Adressierung. Dieses Konzept findet sich auch bei weiteren Unix-Werkzeugen wie z.B. vi und awk, die zu einem späteren Zeitpunkt in diesem Buch behandelt werden. Was versteht man unter einer Adresse? Eine Adresse bezeichnet immer eine Menge von Zeilen. Dies können einzelne Zeilennummern sein, Zeilenbereiche (z.B. Zeile 5-10) aber auch Zeilen, in denen bestimmte Muster enthalten sind. Die Definition der Muster erfolgt mithilfe regulärer Ausdrücke. Der sed erlaubt es, mit Unterstützung von Mustern auch einen Bereich zu definieren, in der Form »alle Zeilen die zwischen dem Auftauchen von Muster a und dem Auftauchen von Muster b liegen«. Folgende Beispiele zeigen ein paar gültige sed-Adressen.
122
Arbeiten mit dem sed 1
Die erste Zeile im Datenstrom
5,10
Die Zeilen 5-10 im Datenstrom
$
Die letzte Zeile im Datenstrom
30,$
Von Zeile 30 bis zum Ende des Datenstroms
/start/
Alle Zeilen, in denen das Muster start vorkommt.
/start/,/stop/
Alle Zeilen von einer Zeile an, in der das Muster start auftaucht, bis zu der ersten Zeile nach dieser Zeile, in der das Muster stop auftaucht. Gibt es im Eingabedatenstrom mehrere solcher Blöcke, gilt die Adresse für alle Blöcke.
9.2.2
Sed-Kommandos
Alle sed-Editierkommandos sind nach einer bestimmten Syntax aufgebaut:
[Adresse[,Adresse]] Funktion [Argumente]
Die Angabe einer Adresse ist nicht notwendig, aber wenn eine angegeben wird, muss es entweder die Nummer einer Eingabezeile oder das Dollarzeichen $ als Platzhalter für die letzte Eingabezeile oder ein regulärer Ausdruck sein.
6
Für die Verwendung von Adressen gelten folgende Regeln: ✘ Eine Funktion, der keine Adresse vorangestellt ist, wirkt auf alle Eingabezeilen. ✘ Eine Funktion, der genau eine Adresse vorangestellt ist, wirkt ausschließlich auf die Zeile, die durch die Adresse spezifiziert wird. ✘ Werden einer Funktion zwei Adressen vorangestellt, wirkt sie auf alle Zeilen, die zwischen der ersten und der zweiten Adresse liegen. Die Start- und die Endzeile sind dabei in den Bereich mit eingeschlossen. ✘ Wird ein Adressbereich oder eine Adresse gefolgt von einem Ausrufezeichen ! angegeben, sind alle Zeilen betroffen, die nicht durch die Adresse getroffen werden. Die Editierkommandos arbeiten wie auch die Suchbefehle der grep-Familie mit regulären Ausdrücken. Aus diesem Grund ist bei der Verwendung der bereits beim egrep vorgestellten Metazeichen eine gewisse Vorsicht angebracht. Um hier ungewollte Effekte zu vermeiden, sollte jedem potentiellen Metazeichen ein Backslash »\« vorangestellt werden.
123
KAPITEL
9
Der Unix Stream Editor
Die Funktionen des sed unterscheiden sich zum einen durch die Adressierung (nicht bei jeder Funktion dürfen grundsätzlich zwei Adressen vorangestellt werden) und zum anderen durch die erlaubten Argumente (einige Funktionen erwarten einen Dateinamen als Argument, andere einen regulären Ausdruck und einen Ersetzungsstring).
Löschen
6 3 3
[Adr[,Adr]] d
Mit dieser Funktion wird der Text zwischen den beiden Adressen gelöscht. Wird keine Adresse angegeben, wird der gesamte Text im Datenstrom gelöscht – das ist zugegeben nicht gerade sehr sinnvoll.
UNIX-Kurs [~] 56 > sed /^$/d test.txt
In diesem Beispiel werden vom sed all jene Zeilen gelöscht, die einen Treffer für den regulären Ausdruck /^$/ bilden. Dieser Ausdruck besagt, dass das Zeilenende direkt dem Zeilenanfang folgt. Es handelt sich also um alle Leerzeilen, die vom sed gelöscht werden.
UNIX-Kurs [~] 57 > sed /Start/!d test.txt
Dieses sed-Kommando löscht alle Zeilen aus der Datei test.txt, in denen der reguläre Ausdruck »Start« nicht vorkommt, und gibt das Ergebnis auf dem Bildschirm aus.
Suchen und ersetzen
6 124
[Adr[,Adr]] s/regulärer Ausdruck/Ersetzung/Optionen
Diese Funktion ist sicherlich eine der am häufigsten verwendeten des sed. Mit ihr können Sie zwischen den beiden Adressen suchen und ersetzen. Als zu suchende Zeichenkette kann ein regulärer Ausdruck angegeben werden und als Ersetzungsmuster eine einfache Zeichenkette.
Arbeiten mit dem sed Als Optionen können folgende Zeichen angegeben werden: 1..9
Die Ersetzung soll nur für die ersten n Suchmuster durchgeführt werden. Default bedeutet, dass nur das erste Suchmuster ersetzt wird.
g
Alle Suchmuster, die sich nicht überlappen, werden durch das Ersetzungsmuster ersetzt.
UNIX-Kurs [~] 58 > sed s/abc/xxx/g test.txt
Dieses sed-Kommando ersetzt jedes Vorkommen der Zeichenkette abc durch xxx in der Datei test.txt und gibt das Ergebnis auf dem Bildschirm aus.
UNIX-Kurs [~] 59 > sed /^ /s/abc/xxx/g test.txt
Dieses sed-Kommando ersetzt jedes Vorkommen der Zeichenkette abc durch xxx in der Datei test.txt, allerdings nur in jenen Zeilen, die mit mindestens einem Leerzeichen beginnen. Das Ergebnis wird auf dem Bildschirm ausgegeben.
Taucht in dem Ersetzungsstring ein Ampersand »&« auf, wird es durch das Suchmuster ersetzt. Aus diesem Grund muss ein Ampersand im Ersetzungsstring immer mit einem Backslash »\« maskiert werden, wenn es einfach als Zeichen auftauchen soll.
3 3 2
Anhängen, Einfügen und Ändern Die nachfolgenden drei Funktionen wird man nicht mehr über die Kommandozeile eingeben können, weil sie mehrzeilig sind. Aus diesem Grund werden sich die Beispiele immer auf eine sed-Scriptdatei beziehen und nicht auf ein konkretes sed-Kommando, welches von der Kommandozeile aus eingegeben werden kann.
[Adr] a\ text
6 125
KAPITEL
9
Der Unix Stream Editor
(append) Diese Funktion sorgt dafür, dass der als Argument angegebene text nach der durch die Adresse spezifizierten Zeile als eine eigene Zeile eingefügt wird. Wird keine Adresse angegeben, wird der text nach jeder Zeile eingefügt.
6
[Adr] i\ text
(insert) Mit dieser Funktion wird der text vor der durch die Adresse festgelegten Zeile als eigene Zeile eingefügt. Wird keine Adresse angegeben, wird der text vor jeder Zeile eingefügt.
6
[Adr[,Adr]]c\ text
(change) Mit dieser Funktion werden die Zeilen, die durch die Adresse(n) festgelegt werden, durch den angegebenen text ersetzt. Im Gegensatz zu append und insert, bei denen jeweils nur eine Adresse angegeben werden darf (also eine Zeile adressiert werden kann), darf beim change auch ein Zeilenbereich angegeben werden. Wird keine Adresse angegeben, wird der gesamte Datenstrom durch den text ersetzt.
3
1i\
Dieses Beispiel für ein sed-Script fügt vor der ersten Zeile einer Datei eine HTML Document Type Definition ein. Das macht natürlich nur für eine HTML-Datei Sinn.
3
/^$/a\ Vorher war eine Leerzeile.
Dieses sed-Script fügt nach jeder Leerzeile den Text »Vorher war eine Leerzeile« ein.
126
Arbeiten mit dem sed
5,10c\ Hier standen vorher die Zeilen 5 bis 10
3
Mit diesem sed-Script werden die Zeilen 5-10 durch den angegeben Text ersetzt.
Weitere sed-Funktionen
[Adr[,Adr]] l
Unter Umständen kommt es vor, dass in Texten nicht druckbare Zeichen enthalten sind. Derartige nicht druckbare Zeichen können mit dieser Funktion des sed in einer Oktalrepräsentation ausgegeben werden.1
[Adr] r file
Der Inhalt der Datei wird sofort vor dem Lesen einer neuen Zeile auf dem Bildschirm ausgeben. Sollte auf die Datei nicht zugegriffen werden können, erfolgt keine Fehlermeldung.
[Adr[,Adr]] y/Zeichenkette1/Zeichenkette2/
Mit dieser Funktion werden im angegebenen Bereich alle Zeichen der ersten Zeichenkette durch die korrespondierenden Zeichen der zweiten Zeichenkette ersetzt. Das heißt, kommt das erste Zeichen der ersten Zeichenkette im angegebenen Bereich vor, wird es durch das erste Zeichen der zweiten Zeichenkette ersetzt.
6 6 6
Wie jeder andere Editor auch, verfügt der sed über einen Buffer (den so genannten Hold-Buffer), in den kopiert und aus dem eingefügt werden kann.
[Adr[,Adr]] g
6
1. Diese Repräsentation sieht so aus, dass der ASCII-Code des jeweiligen Zeichens als dreistellige Oktalzahl mit einem vorangestellten Backslash \ ausgegeben wird.
127
KAPITEL
9
Der Unix Stream Editor
Der Inhalt des Hold-Buffers wird anstelle des angegebenen Bereichs ausgegeben.
6 6
[Adr[,Adr]] h
Der Inhalt des Hold-Buffer wird durch den angegebenen Bereich ersetzt.
[Adr[,Adr]] H
Der angegebene Bereich wird angeführt von einem Newline Character (also beginnend mit einer neuen Zeile) an den Hold-Buffer angehängt. Nachfolgend werden noch zwei Kommandos vorgestellt, die in erster Linie zum Debugging von sed-Scripts benutzt werden, die aber auch anderen Nutzen haben können.
6 6
[Adr[,Adr]] p
Das print-Kommando p druckt die Zeile aus, die durch die Adressen definiert werden, d.h. es wird eine zusätzliche Ausgabe der entsprechenden Zeilen erzeugt und somit tauchen die betroffenen Zeilen zweimal in der Ausgabe auf.
[Adr] =
Dieses Kommando gibt anstatt der Zeile, die durch die Adresse bestimmt ist, die Zeilennummer dieser Zeile aus.
Fortgeschrittene sed-Scripts Sollen mehrere Funktionen auf den gleichen Bereich der Eingabedatei angewandt werden, können sie zu einer Funktionsliste zusammengefasst werden. Dieser Funktionsliste kann dann der entsprechende Adressbereich vorangestellt werden.
128
Arbeiten mit dem sed
[Adresse[,Adresse]]{ Funktion Funktion . . . Funktion }
6
Dabei müssen die einzelnen Funktionen durch einen Zeilenumbruch voneinander getrennt werden. Jeder Funktion und der abschließenden geschweiften Klammer dürfen White Space Characters vorangehen. Durch diese Form der Zusammenfassung von sed-Kommandos, die alle auf den gleichen Block im Datenstrom angewendet werden sollen, lassen sich nun ganz neue Konstrukte umsetzen, die darauf basieren, dass ein weiterer Adressbereich angegeben werden kann.
/start/,/stop/ { /^$/d }
3
Dieses Script löscht im Bereich zwischen dem Auftreten der beiden Muster start und stop alle Leerzeilen.
/^
*for/ { = p
}
3
Mit diesem sed-Script würde für jedes Vorkommen des Wortes for am Anfang einer Zeile (nur angeführt von Leerzeichen) die Zeilennummer als eigene Zeile und die entsprechende Zeile selbst ausgegeben.
129
KAPITEL
9
Der Unix Stream Editor
Übungen
9.3
Aufgaben
1. Geben Sie ein sed-Kommando an, das alle Leerzeilen aus einer Datei test.txt löscht. 2. Schreiben Sie ein sed-Script, welches die deutschen Umlaute in einer HTML-Datei durch die entsprechenden HTML-Tags ersetzt. Das HTMLTag für ein Ü ist z.B. Ü 3. Schreiben Sie ein sed-Script, welches vor jeder Zeile, die mit einer Kapitelnummer beginnt eine Leerzeile ausgibt.
9.3.1
Lösungen
1. Diese Aufgabe ist ganz einfach durch Nachschlagen im Kapitel zu lösen: sed
/^\$/d test.txt
2. Der schwierigste Teil dieser Aufgabe ist, die entsprechenden HTML-Tags herauszusuchen. Ansonsten ist es ein einfaches Suchen und Ersetzen: s/Ü/\Ü/g s/ü/\ü/g s/Ä/\Ä/g s/ä/\ä/g s/Ö/\Ö/g s/ö/\ö/g
Aufpassen muss man hier noch bei der Bedeutung des Ampersands »&«. Würde man diesem im Ersetzungsstring keinen Backslash »\« voranstellen, würde es der sed durch das Suchmuster ersetzen. 3. Zuerst müssen wir einen regulären Ausdruck konstruieren, der so etwas wie Kapitelnummern abbildet: /[1-9]([0-9]*\.)* /
Diesem regulären Ausdruck stellt man dann nur noch ein Insert-Kommando nach, ohne einen Text einzugeben, und fertig ist das ganze Kommando: /[1-9]([0-9]*\.)* /i\
130
KAPITEL 10
Prozessverwaltung Unix ist ein prozessorientiertes Betriebssystem, in dem einzelne Prozesse – durch Prioritäten gesteuert – um den Prozessor konkurrieren. Jedes abgesetzte Unix-Kommando ist nichts anderes als ein Prozess, der über den Kernel auf die Ressourcen des Betriebssystems zugreift. In der Regel ist die Anzahl der Prozesse beschränkt, die maximal pseudoparallel auf einem Unix-Betriebssystem laufen dürfen. Solange dieses Maximum nicht erreicht ist, steht es dem Benutzer aber frei, neue Prozesse zu starten. Für die Kontrolle, Verwaltung und Kopplung solcher Prozesse bietet Unix verschiedene Mechanismen an, die in diesem Abschnitt beschrieben werden.
10.1
Das Familienleben der Prozesse
Die Fachsprache im Bereich der Prozessverwaltung ist sehr blumig und mit Begriffen aus dem Bereich des zwischenmenschlichen Zusammenlebens gespickt. Bei der Beschreibung von Abhängigkeiten der Prozesse untereinander werden oft Begriffe für »Verwandtschaftsbeziehungen« verwendet. So werden die Prozesse in »Familien« eingeteilt und Substantive wie »Geburt« und »Tod« für Start und Ende eines Prozesses benutzt. Diese Anlehnung an das Familienleben treibt noch so manche Stilblüte, wie im Laufe des Kapitels zu lesen sein wird. Alles in allem wird durch die Verwendung dieser Begriffe der Eindruck erweckt, das System der Prozesse unter Unix verfüge über eine gewisse Eigendynamik. Damit aber genau das nicht passiert, gibt es Kommandos zur Analyse und Regulierung der Prozesse.
131
KAPITEL
10
Prozessverwaltung
Prozesse unter Unix entstehen nicht einfach aus dem »Nichts«, sondern werden von anderen Prozessen erzeugt. Aus diesem Grund sind alle Prozesse eines Unix-Betriebssystems miteinander »verwandt«. Sie stammen nämlich von einem gemeinsamen »Urvater« ab. Dieser »Urvater« ist der so genannte initprocess, der als erster beim Booten des Systems gestartet wird und der die Prozesse der zweiten Generation startet. Im Folgenden soll ein wenig genauer betrachtet werden, was passiert, wenn ein neuer Prozess gestartet wird. Damit ein Programm ablaufen kann, muss es von einem anderen Programm aufgerufen werden. Dieses Programm (in der Regel ist es bei Benutzereingaben eine Shell) wird als Vaterprozess1 bezeichnet. Es sorgt dafür, dass sein Sohnprozess2 in den Speicher eingelagert wird und an der Vergabe der Prozessorzeit teilnimmt. Wie andere gute Väter auch, kümmert sich der Vaterprozess um seinen Sohnprozess, überwacht ihn und stellt ihm Signale zu. Der Sohnprozess steht wiederum in starker Abhängigkeit zu seinem Vaterprozess, die unter Umständen so weit gehen kann, dass ein Sohn ohne seinen Vater nicht weiter existieren kann. Anders als im echten Leben existieren alle Generationen von Prozessen gleichzeitig. Die Verwandtschaftsbeziehungen jedes Prozesses lassen sich bis zum Urvater – dem init-process – zurückverfolgen und ergeben eine Art Stammbaum. Dieser Stammbaum ist die erste wichtige Richtlinie für die Prozessverwaltung. Da Computer mit Zahlen besser umgehen können als mit Namen, wird jedem auf dem System laufenden Prozess bei seiner Entstehung eine eindeutige Nummer, die PID (Process Identification), zugeordnet. Jeder Prozess kann über seine PID angesprochen werden. Neben den »verwandtschaftlichen« Beziehungen zu seinem Vater spielt auch der Eigentümer eines Prozesses beim Ansprechen des Prozesses eine Rolle. Prozesse akzeptieren nur Signale von ihrem Vaterprozess, dem Eigentümer des Prozesses oder vom Systemverwalter.
10.1.1
ps
Die auf dem System laufenden Prozesse mit den dazugehörigen PIDs lassen sich mit dem Kommando ps (process status) auflisten. Ohne weitere Optionen listet ps nur die PIDs der aktuellen Shell und ihrer Sohnprozesse auf.
1. Im englischsprachigen Bereich wird weniger patriarchalisch vom parent process (Elternprozess) gesprochen – was darauf schließen lässt, dass die EDV-Welt in Deutschland von Männern dominiert wird. 2. Auch hier wird in der englischsprachigen Welt eine neutralere Form gewählt. Der Sohnprozess heißt hier child process. Allerdings sprechen mittlerweile auch im deutschsprachigen Raum immer mehr Leute von Kindprozessen oder Tochterprozessen.
132
Signale an Prozesse senden
ps [Optionen]
Folgende Optionen sind für ps üblich: -e
Die Option -e besagt, dass alle in der Prozesstabelle eingetragenen Prozesse aufgelistet werden sollen.
-f
Alle verfügbaren Attribute der Prozesse sollen mit zur Anzeige gebracht werden. Zu diesen Attributen gehört unter anderem auch die so genannte PPID (Parent Process Identifikation). Die PPID ist die PID des Vaterprozesses. Mit dieser Information lässt sich der »Stammbaum« der Prozesse zurückverfolgen.
-u
Mit der Option -u und der nachfolgenden Kennung eines Benutzers werden die Prozesse aufgelistet, die dem Benutzer gehören.
UNIX-Kurs [~] 60 > ps PID 5512 5523
TTY ttyq1 ttyq1
TIME COMMAND 00:05 /bin/tcsh 00:00 ps
6
3
In dem Beispiel gibt das Kommando ps zwei aktive Prozesse aus: die Shell, hier die tcsh, in der die Kommandoeingabe erfolgte, und das Kommando ps selbst.
10.2
Signale an Prozesse senden
Ist ein Prozess gestartet worden, gibt es für den Benutzer nur wenige Möglichkeiten der Einflussnahme, es sei denn, es handelt sich um ein interaktives Programm. Eine der wenigen Möglichkeiten, das Verhalten eines Prozesses zu beeinflussen, ist die Zusendung von Signalen. Signale lösen eine Unterbrechung im normalen Programmablauf des Prozesses aus und können durch einen Signalhandler im Prozess selbst behandelt werden.
10.2.1
kill
Um einem Prozess ein Signal zuzustellen, wird das Kommando kill benutzt. Trotz des drastischen Namens muss die Zustellung eines Signals mit kill nicht automatisch das Ende des Prozesses zur Folge haben. Verfügt der Prozess allerdings nur über den Default-Signalhandler, wird auf nahezu jedes Signal mit der Beendigung des Prozesses reagiert.
133
KAPITEL
10
Prozessverwaltung
So sind dann auch 90% aller Anwendungsfälle des Kommandos kill vorzeitige oder unplanmäßige Abbrüche von Kommandos.
6
kill [-Signalnummer] PID
Wird keine explizite Signalnummer angegeben, übermittelt kill das Signal SIGTERM (Signalnummer 15) an den Prozess, was ihn zur ordnungsgemäßen Terminierung veranlassen soll. Fruchtet diese »freundliche« Aufforderung, sich zu beenden, nicht, bleibt als letzte Alternative die Zustellung des Signals SIGKILL (Signalnummer 9) an den Prozess. Gegen dieses Signal ist kein Prozess gefeit – der Prozess wird sofort beendet und aus der Prozesstabelle gelöscht – abgesehen von zwei Ausnahmen: ✘ Zombieprozesse (siehe unten) lassen sich nicht auf diese Weise aus der Prozesstabelle entfernen. ✘ Prozesse, die eine IO-Ressource belegen, die nicht ohne weiteres freigegeben werden kann (z.B. ein Bandlaufwerk, das gerade ein Band zurückspult, kann erst wieder freigegeben werden, wenn es den Vorgang abgeschlossen hat)
1 3
Versuchen Sie, wenn ein Prozess nicht mehr so will wie Sie, immer zuerst die »freundliche« Tour. Nur so kann ein fehlgeleiteter Prozess noch Zwischenergebnisse o.Ä. sichern und Aufräumarbeiten durchführen, bevor er sich beendet. Bei einem SIGKILL hat er dazu keine Chance.
UNIX-Kurs [~] 61 > ps PID 5512 5542 5556
TTY ttyq1 ttyq1 ttyq1
TIME COMMAND 00:07 /bin/tcsh 00:19 xclock & 00:00 ps
UNIX-Kurs [~] 62 > kill 5542 UNIX-Kurs [~] 63 > ps PID TTY TIME COMMAND 5512 ttyq1 00:08 /bin/tcsh 5564 ttyq1 00:00 ps
134
Vordergrund- und Hintergrundprozesse In diesem Beispiel wird mit dem Kommando ps die PID einer Uhr (xclock) auf der grafischen Bedienoberfläche ermittelt. Die Ausgabe des ps zeigt weiterhin, dass die Uhr von dieser Shell aus gestartet worden sein muss, da dem ps für die Anzeige keine Optionen angegeben werden mussten. Anschließend wird mit dem Kommando kill ein SIGTERM (Default) an den Prozess der xclock (PID = 5542) geschickt. Dieser beendet sich dann auch ordnungsgemäß, wie an der Ausgabe des zweiten ps zu sehen ist.
10.3
Vordergrund- und Hintergrundprozesse
Im Zusammenhang mit Prozessen unter Unix werden immer wieder die Begriffe Vordergrundprozess und Hintergrundprozess verwendet. Was verbirgt sich hinter diesen Bezeichnungen? Für Anwender ist der Vordergrundprozess der Normalfall. Ein solcher Prozess wird in der Regel von einer Shell gestartet und ist mit einem Terminal oder Fenster auf einer grafischen Oberfläche verbunden, in das er seine Ausgaben schreibt. Ein Vordergrundprozess »verdrängt« die Shell, solange er läuft, d.h. der Prompt der Shell, welcher ihre Eingabebereitschaft signalisiert, erscheint erst wieder nach Beendigung des Kommandos. Als echtes Multiprozessing-Betriebssystem ist Unix aber auch in der Lage, Prozesse zu starten, die keine derartige »Verdrängung« zur Folge haben. Ein solcher Prozess ist im Allgemeinen nicht mit einem Fenster oder Terminal verbunden und sollte darum auch keine Ausgaben erzeugen. Wird ein Hintergrundprozess in einer Shell gestartet, so ist die Shell direkt nach dem Absetzen des Kommandos – also noch vor dessen vollständiger Abarbeitung – bereit, neue Eingaben entgegenzunehmen. Hintergrundprozesse werden in der Shell durch Anhängen eines Ampersands »&« an die Befehlszeile gestartet.
UNIX-Kurs [~] 64 > sort -o sort.txt adressen.txt &
Wird die Liste aller Prozesse auf einem System mit dem Kommando ps -e ausgegeben, kann festgestellt werden, dass es eine ganze Reihe von Hintergrundprozessen gibt. Viele dieser Prozesse laufen schon seit dem Start des Systems, was an ihren niedrigen PIDs zu erkennen ist. Unter diesen »alten« Hintergrundprozessen gibt es eine Gruppe von Kommandos, deren Namen auf den Buchstaben »d« enden (syslogd, inetd, ftpd, ...). Diese Prozesse werden Dämonen1 genannt. Sie zeichnen sich dadurch aus, dass sie permanent laufen, dabei aber fast keine Rechenzeit beanspruchen. Sie halten eine Art
3
135
KAPITEL
10
Prozessverwaltung
»Winterschlaf« aus dem sie erst durch an sie gerichtete Anforderungen geweckt werden. So wartet z.B. der ftpd darauf, dass von einem fremden Rechner der Versuch zum Dateitransfer unternommen wird und entfacht dann »dämonenhaft« Aktivität. Zwar ist die Sprache im Bereich der Prozessverwaltung recht ungewöhnlich für die sonst so genaue und vielleicht auch trockene Informatik, aber die Assoziationen, die sich bei einigen Begriffen aufdrängen, sind doch recht treffend, so auch bei den »Untoten«. Zombie-Prozesse – so etwas gibt es tatsächlich – haben meist ihre Verbindung zu dem kontrollierenden Vaterprozess verloren, weil dieser »gestorben« ist. Sie selbst haben das »Desaster« zwar überlebt und sind in der Regel vom init-process (PID 1) »adoptiert« worden, können aber weder ihre Ergebnisse an den neuen Vater weiterreichen noch sich dem Benutzer verständlich machen. Folge: Diese Prozesse versuchen zwar, sich aufgrund dieser Fehlersituation zu beenden, da aber niemand von ihrem Ableben Kenntnis nehmen will, verbleiben sie als »Untote« in der Prozesstabelle. Diese Prozesse werden mit <defunct> gekennzeichnet und nach einer nicht näher definierten Zeit automatisch vom init-Prozess abgeräumt. Zombies entstehen vorwiegend dadurch, dass entweder Fenster einer grafischen Oberfläche nicht mit dem Kommando exit beendet (sondern nur geschlossen) oder Hintergrundprozesse mangelhaft überwacht werden.
10.4
Sequentielle Verkettung von Kommandos
Die einfachste Form, Prozesse zu verwalten, besteht darin, sie nacheinander ablaufen zu lassen. Dies geschieht im Prinzip bei jedem Absetzen eines Kommandos (als Vordergrundprozess) in der Shell. Kommando für Kommando wird in der Reihenfolge der Eingabe abgearbeitet. Dieses Vorgehen lässt sich allerdings auch abkürzen. Alle Shells unter Unix bieten die Möglichkeit, mehrere Kommandos in einer Kommandozeile anzugeben. Die einzelnen Kommandos, die jeweils durch ein Semikolon voneinander zu trennen sind, werden von der Shell sequentiell abgearbeitet, d.h., erst wenn das erste Kommando der Folge beendet wurde, wird das zweite Kommando gestartet und wenn dieses beendet ist, das dritte usw. Die Eingabe solcher Kommandofolgen wird bei der interaktiven Arbeit mit der Shell nur selten benutzt. Sie birgt aber interessante Möglichkeiten in Ver-
1. Dämonen: Geister, hier eher hilfreiche Geister, Heinzelmännchen. Auch diese Assoziation lässt sich eher auf den Spieltrieb der Unix-Programmierer zurückführen: Ursprünglich steht die englische Bezeichnung daemon nämlich für Disk and Execution Monitor.
136
Pipes bindung mit dem Feature der Alias-Namen (s.a. Abschnitt 11.7 Alias-Namen), das die meisten Shells (csh, ksh, tcsh, bash) anbieten.
UNIX-Kurs [~] 65 > cd ; echo Home Directory ; ls -l Home Directory total 15 -rw-r--r--rw-r--r--rw-r--r-drwxr-xr-x drwxr-xr-x -rw-r--r-drwxr-xr-x drwxr-xr-x drwxr-xr-x drwxr-xr-x
1 1 1 2 2 1 2 2 2 2
lutz lutz lutz lutz lutz lutz lutz lutz lutz lutz
3
users 67 Jan 22 14:28 a users 67 Jan 22 14:28 b users 76 Jan 20 13:45 beispiel.txt users 1024 Jan 22 14:24 bin users 1024 Jan 22 14:24 mails users 6118 Jan 22 14:32 man.txt users 1024 Jan 22 14:24 scripte users 1024 Jan 22 14:24 src users 1024 Jan 22 14:24 textdateien users 1024 Jan 22 14:24 tmp
In diesem Beispiel wird durch das cd ohne Parameter in das Home Directory gewechselt, dann mit echo die Überschrift Home Directory ausgegeben und zum Schluss ein ls -l im Home Directory ausgeführt.
10.5
Pipes
Neben der sequentiellen Verkettung von Kommandos bietet Unix auch noch eine Form der parallelen Verknüpfung von Kommandos an. Dabei werden die Kommandos über so genannte Pipes1 miteinander verbunden, die es ihnen erlauben, Daten untereinander auszutauschen. Häufig sind unter Unix mehrere Schritte notwendig, um ein Ergebnis zu erzielen. Das liegt daran, dass Unix über viele kleine Dienstprogramme verfügt, die jeweils nur ganz spezifische Aufgaben zu lösen vermögen. Wenn es erforderlich ist, ein Kommando auf Zwischenergebnissen eines anderen Kommandos aufsetzen zu lassen, so könnte dies dadurch erreicht werden, dass die Kommandos nacheinander ausgeführt und die Zwischenergebnisse in Dateien gespeichert werden. Solche Zwischendateien können unter Umständen recht groß werden, obwohl eventuell nur ein Bruchteil der Informationen, die in ihnen stehen, für den Benutzer interessant sind. An dieser Stelle greift die Idee der Pipes. Eine Pipe ist ein FIFO (First In First Out)-Speicher, in den ein Prozess schreibt und aus dem gleichzeitig ein anderer Prozess liest. Durch den 1. Pipes (engl.): Rohrleitung, Wasserleitung
137
KAPITEL
10
Prozessverwaltung
gleichzeitigen Zugriff von zwei Seiten muss dieser Speicher nicht sehr groß sein – im Gegensatz zur Lösung mit den Zwischendateien beim sequentiellen Ansatz. Werden nun mehrere Unix-Kommandos über solche Pipes verknüpft, entsteht ein gerichteter Datenstrom. Der erste Befehl generiert Daten und gibt sie über die Pipe an den nachfolgenden Befehl weiter. Dieser erzeugt aus den so erhaltenen Daten wieder Ausgaben, die er per Pipe an den nächsten Befehl weiterleitet usw. Dabei kann es durch die Parallelität vorkommen, dass die ersten Ergebnisse am Ende der Prozesskette bereits vorliegen, bevor der erste Befehl alle Daten erzeugt hat. Durch dieses »Zusammenstecken« von Befehlen mittels Pipes lassen sich aus der Verknüpfung vieler kleiner Befehle neue mächtige Befehle konstruieren. Dieses Konzept ist eine der größten Stärken des Unix-Betriebssystems. Die Befehle, die mittels Pipe verknüpft werden können, müssen bestimmte Eigenschaften mitbringen. Soll ein Befehl nach einer Pipe stehen, also Daten aus dieser Pipe empfangen, muss er in der Lage sein, Daten von der Standardeingabe1 zu lesen. Soll ein Befehl vor einer Pipe stehen, also Daten in eine Pipe schreiben, muss er Ausgaben auf die Standardausgabe machen. Befehle, die beide Eigenschaften erfüllen, werden Filter genannt, eine sehr treffende Bezeichnung angesichts der Vorstellung, wie die Daten durch das Programm hindurchlaufen und dieses aus dem Datenstrom bestimmte Informationen »herausfiltert«. Allerdings hinkt der Vergleich doch ein bisschen, denn ein solches Programm muss nicht in jedem Fall die Datenmenge verringern, sondern kann auch neue Daten in den Datenstrom einfügen.
6 3
Kommando | Filter1 | ... | FilterN
Die Pipes zwischen den Kommandos werden durch den senkrechten Strich »|« geschrieben. Das Kommando, welches ganz links in der »Pipekette« steht, erzeugt die ursprünglichen Daten und muss nicht über die Filtereigenschaft verfügen. Der Datenfluss erfolgt von links nach rechts.
UNIX-Kurs [~] 66 > ls | more
1. Die Begriffe Standardeingabe (Tastatur) und Standardausgabe (Bildschirm) werden in den beiden Kapiteln über die Shells ausführlich erläutert.
138
Pipes Dieses Beispiel zeigt eine sehr einfache, aber oft genutzte Pipe. Die Ausgabe des ls, die in Verzeichnissen mit sehr vielen Dateien über einige Bildschirmseiten gehen kann, wird über eine Pipe in den Pager more geschickt, der dafür sorgt, dass jeweils nach einer Bildschirmseite mit der Ausgabe angehalten wird, bis der Benutzer eine Taste drückt.
UNIX-Kurs [~] 67 > file * | fgrep -i "text" | cut -d: -f1
In diesem schon etwas komplexeren Beispiel werden zunächst alle Dateien aus dem Working Directory (bis auf die systemspezifischen)1 durch das Kommando file bewertet. Die Ausgabe, die file für jede Datei ausgibt, sieht wie folgt aus:
3
Dateiname: Bewertung durch file fgrep sucht nun in dieser Ausgabe nach Zeilen, in denen das Muster »text« vorkommt, und übergibt sie durch die Pipe an das Kommando cut, welches
aus jeder Zeile das erste Feld herausschneidet. Als Trennzeichen für die Felder wird, aufgrund der Ausgabe des Kommandos file, der Doppelpunkt »:« vereinbart. Die Kommandofolge gibt also als Endergebnis die Namen aller Dateien im Working Directory aus, die Text enthalten.
10.5.1
Filterprogramme
Die Filtereigenschaft ist unter den Unix-Kommandos weit verbreitet. Fast jedes Kommando, das mit dem Inhalt von Dateien operiert, erfüllt die Filtereigenschaft. In der man-Page eines Kommandos kann die Filtereigenschaft abgelesen werden. Wenn dort erwähnt wird, dass beim Weglassen des Namens der Datei, auf deren Inhalt das Kommando zugreifen soll, von der Standardeingabe gelesen wird, erfüllt das Kommando die Filtereigenschaft. Klassische Filter sind z.B. Kommandos wie sort, head, tail, fgrep, grep, egrep und cut. In diesem Abschnitt sollen nun weitere Filter folgen.
10.5.2
wc
word count – wc zählt, wie der Name schon sagt, die Wörter in Dateien. Darüber hinaus zählt es auch Zeichen und Zeilen. Wird mehr als eine Datei übergeben, werden die Zeichen, Wörter oder Zeilen pro Datei und die Gesamt-
1. Zur Erinnerung: »*« steht als Muster für alle Dateien im Working Directory, abgesehen von denen, die systemspezifische Aufgaben haben und deren Namen deshalb mit einem ».« anfangen.
139
KAPITEL
10
Prozessverwaltung
summen ausgegeben. Wird kein Dateiname angegeben, so wird von der Standardeingabe gelesen.
6 3
wc [Optionen] [Datei/Dateien]
-l
Mit der Option -l werden nur die Zeilen (lines) gezählt.
-c
Mit der Option -c werden nur die Zeichen (characters) gezählt.
-w
Mit der Option -w werden nur die Wörter (words) gezählt.
UNIX-Kurs [~] 68 > wc -l ascii.txt beispiel.txt 4 ascii.txt 3 beispiel.txt 7 total
In diesem Beispiel werden die Zeilen (-l) der beiden Dateien ascii.txt und beispiel.txt von wc gezählt. Die Ergebnisse werden vor den Dateinamen ausgegeben. Die Summe aller gezählten Zeilen erscheint in der letzten Zeile.
10.5.3
fold
Oftmals überschreiten die Ausgaben von Unix-Kommandos die maximale Fenster- oder Terminalbreite. Je nach Terminaltyp werden dabei die überzähligen Zeichen abgeschnitten oder in die nächste Zeile geschrieben. fold bricht die Zeilen bei einer bestimmten Länge um. Dabei zählt fold nicht die Zeichen in der Zeile, sondern die Bildschirmspalten, sodass auch Tabulatorzeichen richtig gehandhabt werden. Default für die Länge sind 80 Zeichen.
6 3 140
fold [Optionen] [Datei/Dateien]
-w
Mit der Option -w wird die Länge festgelegt, bei der umbrochen werden soll,. Die Angabe der Länge folgt der Option durch Leerzeichen getrennt.
UNIX-Kurs [~] 69 > fold -w 60 /var/adm/SYSLOG
Pipes Durch das Kommando im Beispiel werden die Zeilen der Datei /var/adm/SYSLOG bei 60 Zeichen umbrochen und auf dem Bildschirm ausgegeben.
10.5.4
tee
Wenn auch der Vorteil der Pipes im Verzicht auf Zwischendateien liegt, ist es dennoch manchmal wünschenswert, Zwischenergebnisse zu sehen. Für diesen Zweck gibt es das Kommando tee. Es funktioniert wie ein »T-Stück« bei einem Fernsehkabel – die Eingangsdaten werden auf die beiden Ausgabekanäle kopiert. Über einen Kanal wird auf die Standardausgabe geschrieben und damit auch in die nächste Pipe; über den anderen Kanal wird in eine Datei geschrieben. Beim tee ist anhand der man-Page nur schwer festzustellen, dass es sich um einen Filter handelt, weil definitiv eine Datei als Parameter gefordert wird.
tee [Optionen] Dateiname
Wird als Dateiname der Name einer Datei angegeben, die noch nicht existiert, so wird sie angelegt. Sollte eine Datei mit dem Namen Dateiname schon vorhanden sein, wird sie überschrieben. Wird die Option -a benutzt, werden die Daten an die Datei angehängt.
UNIX-Kurs [~] 70 > ls -l | tee verzeichnis.txt | more
Diese Pipe gibt das Ergebnis des ls -l auf dem Bildschirm aus und schreibt es gleichzeitig in eine Datei verzeichnis.txt. Die Ausgabe auf dem Bildschirm erfolgt immer seitenweise (more).
10.5.5
6 3
tr
transform – Mit dem Kommando tr können einzelne Zeichen gegen andere ausgetauscht oder gelöscht werden. tr nimmt unter den Filtern eine Sonderstellung ein, da es ausschließlich als Filter benutzt werden kann. tr liest nur von der Standardeingabe und schreibt nur auf die Standardausgabe. Sollen dem tr Daten zur Transformation zur Verfügung gestellt werden, muss das immer über eine Pipe oder eine Eingabeumlenkung passieren.1
1. Der Mechanismus der Ein-/Ausgabeumlenkung ist in dem Abschnitt über die Arbeitsweise der Shell beschrieben.
141
KAPITEL
6
3
10
Prozessverwaltung
tr [Optionen] Zeichenkette1 [Zeichenkette2]
Wird das Kommando tr ohne Option aufgerufen, so müssen zwei gleich lange Zeichenketten folgen. Für jedes gelesene Zeichen wird dann folgende Transformation vorgenommen: Entspricht das gelesene Zeichen dem ersten Zeichen der Zeichenkette1, wird es durch das erste Zeichen der Zeichenkette2 ersetzt. Entspricht es dem zweiten Zeichen der Zeichenkette1, wird es durch das zweite Zeichen der Zeichenkette2 ersetzt usw. Für die Definition der Zeichenketten dürfen auch die schon aus der Shell bekannten Bereiche (z.B. [A-Z]) verwendet werden. Um eine Interpretation durch die Shell zu verhindern, sind derartige Angaben zu quoten. In den Fällen, bei denen keine Sonderzeichen in den Zeichenketten auftauchen, können die Quotes entfallen. Das wird durch das nachfolgende Beispiel noch einmal verdeutlicht. Beide Befehle formen das kleingeschriebene hallo in Großbuchstaben um, aber nur der zweite Befehl enthält Wildcards, die auch von der Shell interpretiert werden können.
UNIX-Kurs [~] 71 > echo hallo | tr ahloe AHLOE HALLO UNIX-Kurs [~] 72 > echo hallo | tr "[a-z]" "[A-Z]" HALLO
3 142
-d
delete – Bei Verwendung der Option -d ist nur eine Zeichenkette anzugeben. Alle Zeichen, die in der Zeichenkette1 vorkommen, werden aus der Eingabe gelöscht.
-s
squeeze – Bei Verwendung der Option -s ist ebenfalls nur eine Zeichenkette anzugeben. Alle Zeichen aus der Zeichenkette1, die in der Eingabe mehrfach hintereinander vorkommen, werden in der Ausgabe auf ein Zeichen reduziert.
UNIX-Kurs [~] 73 > cat dos.txt | tr -d "\015" | tee unix.txt
Dieses Beispiel zeigt eine Besonderheit des tr. "\015" stellt als Zeichenkette1 genau ein Zeichen dar. Zeichenketten, die mit \ eingeleitet werden und aus drei Ziffern bestehen, werden als oktale Repräsentation von ASCII-Zeichen interpretiert. In diesem Fall steht \015 für dezimal 13 und somit für das nicht druckbare Zeichen Ctrl-M. Dieses Carriage-Return-Zeichen und ein LinefeedZeichen schließen bei einer DOS-Textdatei jede Zeile ab. Unter Unix aber
Aufgaben wird jede Zeile nur mit einem Linefeed abgeschlossen. Durch das oben stehende Beispiel kann das störende Carriage-Return-Zeichen entfernt werden, nachdem eine DOS-Textdatei nach Unix transferiert worden ist. Durch das tee wird das Ergebnis der Umformung sowohl in die Datei unix.txt als auch auf den Bildschirm geschrieben.
UNIX-Kurs [~] 74 > ls -l | tr -s " " | cut -d" " -f5
Das Beispiel schneidet aus der Ausgabe des Kommandos ls -l das fünfte Feld (welches die Dateigröße enthält) heraus. Die Pipe funktioniert nur im Zusammenspiel mit dem tr-Kommando, das mehrfache Leerzeichen aus der Ausgabe des ls-Kommandos entfernt. Andernfalls könnte das Leerzeichen nicht als Trenner für das cut-Kommando genutzt werden, vgl. Abschnitt 8.2.
3
Übungen
10.6
Aufgaben
1. Listen Sie mit ps die von Ihrer aktuellen Shell gestarteten Prozesse und anschließend alle auf dem System laufenden Prozesse auf. 2. Starten Sie mit dem Kommando xclock eine Uhr (hierzu müssen Sie an einer grafischen Bedienoberfläche arbeiten) und versuchen Sie dann, den entsprechenden Prozess von einer zweiten Shell aus zu beenden. 3. Ermitteln Sie die PID Ihrer aktuellen Shell und setzen Sie diese für PID in der folgenden Befehlszeile ein: echo "Noch 15 sek.";sleep 10;echo "Noch 5 sek.";sleep 5; kill -9 PID
Was passiert nach 15 Sekunden? 4. Bilden Sie eine Pipe, die Ihnen die Ausgabe von ls -l in Ihrem Working Directory nach der Größe der Dateien sortiert. 5. Erweitern Sie die Pipe aus 4.) so, dass nur noch Plain Files ausgegeben werden.
143
KAPITEL
10 10.6.1
Prozessverwaltung
Lösungen
1. Geben Sie das Kommando UNIX-KURS [~] 40 > ps -f UID PID PPID C STIME TTY TIME CMD unix 830 812 4 13:25:07 ttyq3 0:00 ps -f unix 812 811 1 12:19:55 ttyq3 0:05 -tcsh
ein, so werden Ihnen alle Prozesse der aktuellen Shell angezeigt.1 Durch die Option -f werden alle verfügbaren Attribute aufgelistet. In diesem Beispiel laufen in der aktuellen Shell zwei Prozesse: zum einen der Prozess ps, der diese Ausgabe erzeugt und zum anderen die Shell selbst (hier eine tcsh, sprich tc-Shell). In der ersten Spalte wird der Eigentümer angegeben. Sie können dort also Ihren Benutzernamen sehen. In der zweiten Spalte wird die PID (Process Identification) ausgegeben, also die eindeutige Nummer des Prozesses. Darauf folgt die PPID (Parent Process Identification). Die PPID gibt an, von wem der Prozess erzeugt wurde. Im Beispiel hat der Prozess ps die PPID 812. ps wurde also von einem Prozess mit der Nummer 812 erzeugt. Dies ist natürlich die PID der Shell selbst. Logisch, denn die Shell ist der Vater des ps-Prozesses. Die Spalte STIME gibt an, wann der Prozess gestartet wurde, und TTY, auf welchem Terminal der Prozess läuft. Interessant ist auch die vorletzte Spalte TIME. Hier sehen Sie, wie viel Rechenzeit ein Prozess verbraucht hat. In der letzten Spalte schließlich wird der Name des Kommandos/Prozesses angezeigt. Sollen alle auf dem System laufenden Prozesse aufgelistet werden, muss die Option -e hinzugefügt werden. UNIX-KURS [~] 41 > ps -ef
Wie Sie an Ihrem Bildschirm sehen können, ist diese Liste sehr lang. Es werden nicht nur Ihre eigenen Prozesse, sondern auch die des Betriebssystems und anderer Benutzer aufgelistet. 2. Öffnen Sie zunächst eine zweite Shell. Starten Sie dann in der ersten Shell das Programm xclock. UNIX-KURS [~] 42 > xclock
Ein neues Fenster erscheint, in dem eine Uhr dargestellt wird. Da wir die xclock jedoch nicht als Hintergrundprozess gestartet haben (vergleiche
1. Die Solaris-Impementierung des Kommandos ps listet das ps selbst nicht mit auf.
144
Aufgaben xclock &), ist in der ersten Shell nun kein Eingabe-Prompt mehr vorhan-
den. Aktivieren Sie die zweite Shell und geben Sie dort Folgendes ein: UNIX-KURS [~] 43 > ps -u unix PID TTY TIME CMD 1374 pts/3 0:00 xclock 1373 pts/3 0:00 ps 1102 pts/3 0:00 tcsh 1097 pts/3 0:02 tcsh
Durch die Option -u unix werden alle Prozesse aufgeführt, die dem Benutzer unix gehören (schauen Sie sich die man-Page dazu an). Natürlich müssen Sie Ihren Benutzernamen statt unix verwenden. In diesem Beispiel hat die xclock die PID 1374. Nun können wir diesen Prozess beenden, indem wir Folgendes eingeben: UNIX-KURS [~] 44 > kill 1374
Der xclock-Prozess mit der PID 1374 wird dadurch beendet und das Fenster, in dem die xclock lief, geschlossen. Daraufhin erscheint im ersten Shell-Fenster wieder der Eingabe-Prompt. 3. Geben Sie in einer der beiden Shells das folgende Kommando ein: UNIX-KURS [~] 45 > ps PID TTY TIME CMD 1373 pts/3 0:00 ps 1102 pts/3 0:00 tcsh
In diesem Beispiel hat meine Shell also die PID 1102 (Sie werden auf Ihrem Rechner natürlich eine andere PID ermitteln ...). Gibt man die in der Aufgabe beschriebene Befehlsfolge ein und ersetzt dort PID durch die eben ermittelte Zahl, so passiert Folgendes: In der Eingabezeile befinden sich mehrere Unix-Kommandos, die jeweils durch ein Semikolon getrennt sind. Dies bedeutet, dass die Befehle einzeln nacheinander abgearbeitet werden und ein neuer Befehl erst dann ausgeführt wird, wenn sein Vorgänger beendet wurde. Zunächst erfolgt eine Ausgabe Noch 15 sek. Danach passiert zehn Sekunden lang nichts, denn der sleep-Befehl verzögert die nächste echo-Ausgabe um zehn Sekunden. Nach diesen zehn Sekunden lesen wir Noch 5 sek. auf dem Bildschirm. Und nach fünf Sekunden wird das Fenster geschlossen, denn nun wird das kill-Kommando mit der PID dieser Shell aufgerufen. Wie dieses Beispiel zeigt, kann man also mit dem kill-Befehl sogar den Vaterprozess des kill-Befehls beenden ...
145
KAPITEL
10
Prozessverwaltung
4. Durch die Eingabe von ls -l werden die Dateien des Working Directorys im »long format« ausgegeben. Dabei steht in der 5. Spalte die Größe der Datei. Die einzelnen Felder einer Zeile sind durch verschieden lange Leerzeichen-Ketten voneinander getrennt. UNIX-KURS [~] 46 > ls -l drwxr-xr-x 2 unix user 46 Nov 30 09:16 uebung_7 -rw-r--r-- 2 unix user 9 Juli 29 17:13 linker -rw-r--r-- 1 unix user 319 Juli 30 12:21 mbox
Diese Ausgabe wird nun an den sort-Befehl »gepiped«. Es soll nach dem 5. Feld sortiert werden. Dies wird durch die Option -k5,5 angegeben. Außerdem empfiehlt sich die Angabe der Option -n (sortiere numerisch), da wir Zahlen sortieren möchten. Die Definition eines Feldtrenners ist in diesem Fall nicht nötig, denn defaultmäßig ist der Leerstring als Feldtrenner definiert. Die Angabe eines Dateinamens muss natürlich entfallen, da durch den Pipe-Mechanismus festgelegt ist, welche Daten an den sort-Befehl übermittelt werden (nämlich die Ergebnisse des ersten Befehls ls -l). UNIX-KURS [~] 47 > ls -l | sort -k5,5 -n -rw-r--r-- 2 unix user 9 Juli 29 17:13 linker drwxr-xr-x 2 unix user 46 Nov 30 09:16 uebung_7 -rw-r--r-- 1 unix user 319 Juli 30 12:21 mbox
5. Wir sollen nun die Pipe so modifizieren, dass nur noch Plain Files ausgegeben werden. Wenn Sie sich das Beispiel in Aufgabe 4 noch einmal anschauen, werden Sie erkennen, dass die Dateien linker und mbox Plain Files sind. Woran haben Sie das mit einem Blick erkannt? Richtig, in der ersten Spalte gibt das erste Zeichen an, um welche Dateiart es sich handelt. »d« steht für Directory, »-« für Plain File. Es sollen also nur noch die Zeilen ausgegeben werden, deren erstes Zeichen ein »-« ist. Dafür hatten wir das grep-Kommando kennen gelernt. UNIX-KURS [~] 48 > ls -l | sort -k5,5 -n | grep "^-"
Sie erinnern sich: Das kleine Dach »^« legt fest, dass der Querstrich am Anfang der Zeile stehen muss. Als Ausgabe erhält man nun: -rw-r--r-- 2 unix user 9 Juli 29 17:13 linker -rw-r--r-- 1 unix user 319 Juli 30 12:21 mbox
Es werden also nur noch Plain Files ausgegeben. An dieser Stelle noch ein kleiner Hinweis: Es ist sinnvoll, sich auch die Reihenfolge der pipe-Befehle zu überlegen: Angenommen, Sie hätten 10.000 Directories (zugegeben etwas unrealistisch) und nur zwei Plain Files in Ihrem Verzeichnis. Die Pipe hätte – so wie
146
Aufgaben sie oben beschrieben ist – erst 10.002 Dateien sortiert (das ist rechen- und somit zeitintensiv) und dann alle bis auf die beiden Plain Files rausgeschmissen. Dreht man sort und grep um UNIX-KURS [~] 49 > ls -l | grep "^-"| sort -k5,5 -n
so wären erst die 10.000 Directory-Zeilen gelöscht und dann die beiden verbliebenen Plain Files sortiert worden. Dies ist selbstverständlich die bessere und schnellere Variante.
147
KAPITEL 11
C-Shell und Tenex-C-Shell Die Tenex-C-Shell1 (tcsh) ist eine Weiterentwicklung der C-Shell (csh), die ursprünglich an der University of California in Berkeley entwickelt wurde. Die csh war Bestandteil des BSD-Unix und hat im Gegensatz zur so genannten Bourne-Shell (sh) eine Scriptsprache, die der Programmiersprache C sehr ähnlich ist. Diese Eigenschaft und einige weitere Erweiterungen der Funktionalität haben sie zur bevorzugten Shell der Entwickler unter Unix gemacht. Die tcsh ist 100% kompatibel zur csh und wurde ebenfalls in Berkeley entwickelt. Sie erweitert die Funktionalität der csh um eine ganze Reihe von Möglichkeiten, die sich jeder Benutzer der csh schon lange gewünscht hat. Das wohl wichtigste neue Feature der tcsh ist das Command Line Editing. Während bei der csh die Cursortasten noch tabu waren und den Benutzer bei ihrer Betätigung mit einer Reihe von Steuerzeichen in der Eingabezeile verärgert haben, kann bei der tcsh mit den Cursortasten der Cursor frei in der Eingabezeile positioniert werden. Neben der Editierung der eingegebenen Zeile selbst kann auch der letzte Befehl mit | in die Eingabezeile zurückgeholt und editiert werden. Neben ihrer Funktion als interaktiver Kommandointerpreter ist die Shell auch ein Interpreter für ihre eigene Programmiersprache. Diese Programmiersprache dient der Formulierung von Kommandoprozeduren, die unter Unix allgemein Shell-Scripts genannt werden. Die Scriptsprache der tcsh ist die gleiche wie die der csh. Während die csh und tcsh bevorzugt für die interaktive
1. Tenex ist der Name eines 1972 für die PDP-10 entwickelten Betriebssystems, von dem Features für die tcsh übernommen wurden.
149
KAPITEL
11
C-Shell und Tenex-C-Shell
Arbeit verwendet werden, werden Shell-Scripts meist für die Bourne-Shell geschrieben.
11.1
Die Arbeitsweise von csh und tcsh
Die Shell als Kommandointerpreter ist für den Unix-Benutzer sicherlich das interessanteste aller Programme. In den vorangegangenen Kapiteln wurde immer nur von »der Shell« gesprochen, so, als gäbe es nur eine. Aber auch hier bietet Unix wieder ein Beispiel für seine Flexibilität. Anders als bei den meisten bekannten Betriebssystemen kann der Benutzer unter Unix zwischen verschiedenen Kommandointerpretern wählen.1 Egal, ob er sich bei seiner Wahl für komfortable Public-Domain-Shells wie die bash oder tcsh entscheidet, die kommerziell bevorzugten ksh oder csh wählt oder als ewig Gestriger an der guten alten sh festhält – jede dieser Alternativen hat eine Reihe von Features auf Lager, die ihm den Umgang mit dem Betriebssystem erleichtern können. Damit aber nicht genau das Gegenteil eintritt, sollte die Arbeitsweise der Shell bekannt sein. Einer der Mechanismen, den die Shell anbietet, sind die im Abschnitt über Dateiverwaltung vorgestellten Wildcards. Entgegen der Meinung vieler Anwender sorgen nämlich nicht die einzelnen Befehle für die richtige Handhabung dieser Sonderzeichen, sondern diese Aufgabe wird von dem Kommandointerpreter erledigt. Allen – auch eigenen – Programmen und Scripts wird der Mechanismus zur Behandlung von Wildcards dadurch auf einfache Art verfügbar gemacht. Dieses Vorgehen bringt aber auch Probleme mit sich. Werden bei der Auflösung von Wildcards zu viele oder zu lange Dateinamen2 von der Shell generiert, streikt diese mit der Fehlermeldung arg list too long oder too many words oder Command too long. Ungewollte Effekte können auch eintreten, wenn Wildcards, die nicht für die Shell bestimmt sind, nicht entsprechend geschützt werden. Dies kann unter Verwendung des Escape Characters »\« geschehen oder über den QuotingMechanismus, über den jede Shell verfügt und der im Abschnitt 11.6 beschrieben ist.
1. Bei einigen Unix-Derivaten, wie z.B. dem IRIX von SGI, kann er sogar seine Default-Shell (die in der /etc/passwd eingetragen ist) umsetzen, wofür es normalerweise des Eingriffs eines Systemverwalters bedarf. 2. In der Regel liegen die Grenzen bei 255 Dateinamen oder bei einer maximalen Befehlslänge von 4096 Zeichen.
150
Die Arbeitsweise von csh und tcsh
UNIX-Kurs [~] 75 > find / -name \*.tmp -print UNIX-Kurs [~] 76 > find / -name *.tmp -print (FALSCH)
3
Das erste Kommando in diesem Beispiel durchsucht den gesamten Dateibaum nach Dateien mit der Endung .tmp. Beim zweiten Kommando wird das Wildcard-Zeichen »*« bereits durch die Shell – und nicht durch das Kommando find – ausgewertet. Existierten z.B. im Working Directory genau zwei Dateien a.tmp und b.tmp mit der Endung .tmp, so setzt die Shell die Eingabe in das Kommando find / -name a.tmp b.tmp -print um. Da nach der Option -name nur genau ein Muster stehen darf, würde dieses Kommando also einen Syntaxfehler erzeugen.
Für die Frage, wann ein Sonderzeichen durch den Escape Character geschützt werden muss, kann folgende Regel dienen: Soll das Sonderzeichen vor der Kommandoausführung interpretiert werden, ist es nicht zu schützen. Soll es erst während der Kommandoausführung interpretiert werden (also durch das Kommando selbst, wie bei dem Beispiel mit find), muss es geschützt werden.
1
Da die Shell als Kommandointerpreter des Unix-Betriebssystems im Gegensatz zu den Interpretern anderer Systeme viel ihrer Funktionalität nicht über eingebaute Befehle umsetzt, muss sie zur Ausführung eines Kommandos zuerst ermitteln, wo das entsprechende auszuführende Programm steht. Damit hier nicht ganze Dateibäume durchsucht werden müssen, verfügen alle Shells über das Konzept des Suchpfads für Kommandos. Über den Suchpfad wird der Shell mitgeteilt, in welchen Verzeichnissen sie nach den entsprechenden Programmen zu suchen hat. Erst das richtige Setzen dieses Pfads (durch Setzen der Environmentvariablen PATH) ermöglicht ein Arbeiten mit den UnixKommandos.
UNIX-Kurs [~] 77 > echo $PATH /bin:/sbin:/usr/bin:/usr/sbin:/usr/bin/X11:/etc:.
3
Die Pfade werden gemäß ihrer Reihenfolge in der Variablen PATH – von links nach rechts – nach einer ausführbaren Datei mit dem Namen des gesuchten Kommandos durchsucht. Die Suche ist beendet, sobald eine solche Datei gefunden wird oder alle Verzeichnisse im Suchpfad durchsucht worden sind.
151
KAPITEL
11
C-Shell und Tenex-C-Shell
Um das Verhalten eines Programms zu beeinflussen, wird neben den Kommandozeilenparametern der Mechanismus der Environmentvariablen eingesetzt. Jedes Programm, das unter Unix gestartet wird, bekommt eine Kopie des Satzes an Environmentvariablen, der zum Startzeitpunkt für das aufrufende Programm definiert war, als »Beigabe«. Die Shell bietet Möglichkeiten, diese Variablen zu setzen und ihre Werte abzurufen. In der Eingabezeile substituiert die Shell den Variablennamen durch den Wert der Variablen, wenn ein Dollarzeichen »$« vor den Variablennamen geschrieben wird. So enthält z.B. die Variable HOME den absoluten Pfad des Home Directoryss des Benutzers. Die Eingabe von cd $HOME bewirkt daher den Wechsel in das Home Directory. Neben der Ausgabe der Ergebnisse von Kommandos auf den Bildschirm bietet jede Shell auch eine Möglichkeit, die Ausgaben in eine Datei umzulenken. Leider hat sich auch hier keine einheitliche Syntax durchgesetzt, was die Nutzung dieses Mechanismus abhängig von der verwendeten Shell macht. Moderne Shells, wie csh und tcsh, bieten dem Benutzer die Möglichkeit, Kürzel für häufig benutzte Befehlsfolgen zu definieren. Diese Kürzel werden Alias genannt. Sie werden ebenfalls von der Shell durch die dahinter verborgenen Befehlsfolgen ersetzt. Eine der beliebtesten Abkürzungen ist ll für den häufig verwendeten Befehl ls -l. Ein Benutzer, der sehr an das DOS-Betriebssystem gewöhnt ist, will vielleicht auch das Kommando ls über den Alias dir ansprechen.
11.2
Command History
Eine wesentliche Neuerung der csh gegenüber der sh war die Einführung der Command History. In dieser merkt sich die Shell die letzten Kommandos, die der Benutzer von dieser Shell abgesetzt hat. Die Befehle werden zu diesem Zweck durchnummeriert. Der Benutzer kann sich zum einen die letzten Befehle, die er ausgeführt hat, anschauen und zum anderen einen Befehl aus der Command History durch ein geeignetes History-Kommando erneut ausführen lassen. Durch die Möglichkeit des Command Line Editings bei der tcsh hat die hier beschriebene History-Funktion nur noch sehr geringe Bedeutung, da sie verhältnismäßig unkomfortabel ist.
11.2.1
history
Mit dem Kommando history werden die letzten abgesetzten Befehle aufgelistet.
152
Command History
history [Anzahl ]
Wird keine Anzahl angegeben, so wird der gesamte Inhalt des History-Speichers ausgegeben. Wie groß dieser Speicher ist, hängt von dem Wert der Shell-Variablen history ab, vgl. Abschnitt 10.4.
6
Nachfolgend sollen einige Kommandos, mit denen auf die Command History zugegriffen werden kann, vorgestellt werden. Dabei ist zu bemerken, dass der so genannte History Character per Default auf das Ausrufezeichen »!« gesetzt ist, aber durch den Benutzer umdefiniert werden kann. In der nachfolgenden Beschreibung wird aber immer das Ausrufezeichen verwendet. Die History-Kommandos sorgen dafür, dass der entsprechende Befehl sofort ausgeführt wird und nicht, wie vielleicht zu vermuten wäre, zunächst auf die Kommandozeile zurückgeholt wird. !!
Wiederholung des letzten Befehls aus der Command History
!4
Wird dem Ausrufezeichen eine Zahl nachgestellt, wird diese von der Shell als History-Nummer interpretiert. Die Shell versucht, den Befehl mit dieser Nummer (in diesem Beispiel den mit der Nummer 4) erneut auszuführen.
!-3
Hat die Zahl, die dem Ausrufezeichen folgt, ein negatives Vorzeichen, bedeutet dies, dass der Befehl ausgeführt werden soll, dessen History-Nummer um die Zahl kleiner ist als die aktuelle HistoryNummer. Das wäre in unserem Beispiel der drittletzte Befehl.
!ab
Der letzte Befehl, der mit der Zeichenkette ab begonnen hat, wird ausgeführt.
^txt^text
Obwohl kein Ausrufezeichen in dieser Befehlsfolge vorkommt, handelt es sich doch um ein History-Kommando. Es bewirkt, dass der letzte Befehl erneut ausgeführt wird, allerdings wird zuvor das erste Auftreten der Zeichenkette txt durch die Zeichenkette text ersetzt. Diese Zeichenketten können natürlich beliebig vom Benutzer definiert werden. Es ist aber zu beachten, dass einzig das erste Auftreten ersetzt wird. Dieser Befehl funktioniert also nicht, wenn das zu ersetzende Muster mehr als einmal im letzten Kommando auftaucht und jedesmal ersetzt werden soll!
153
KAPITEL
11 11.3
C-Shell und Tenex-C-Shell
Environmentvariablen
Ein wichtiger Mechanismus zur Übergabe von Parametern an Programme ist neben den Kommandozeilenparametern die Nutzung der Environmentvariablen. Jeder Prozess, der unter Unix läuft, mit Ausnahme des Schedulers, wird von einem anderen Prozess gestartet. Bei diesem Startvorgang wird dem Prozess eine Kopie des Environments des aufrufenden Prozesses mitgegeben. Zu diesem Environment gehören neben dem Pfad des Working Directoryss auch ein Satz von Variablen: die Environmentvariablen. Diese Variablen haben unterschiedliche Funktionen und Aufgaben. Einige haben rein informativen Charakter (wie z.B. HOME, die den Pfad des Home Directorys beinhaltet), andere wirken steuernd (wie z.B. DISPLAY, die festlegt, welche Maschine die Ausgabe eines X-Programms anzeigt) und wieder andere ermöglichen das Ausführen von Programmen (PATH enthält die Suchpfade für Programme). Der Benutzer kann sich das Environment durch entsprechende Befehle anzeigen lassen und es verändern.
11.3.1
env
Das Kommando env gibt die Namen aller Environmentvariablen, die zur Zeit definiert sind, und deren aktuelle Werte aus.
11.3.2
setenv
Das interne Kommando setenv setzt Environmentvariablen auf einen neuen Wert. War die Variable bereits definiert, wird ihr Wert mit dem neuen Wert überschrieben. War sie noch nicht definiert, wird sie in das Environment eingefügt und mit dem neuen Wert belegt. Das führende Dollarzeichen ist nur bei der Ausgabe des Inhalts einer Variablen anzugeben, nicht aber bei ihrer Definition.
6 3 154
setenv Variablenname Wert
UNIX-Kurs [~] 78 > setenv DISPLAY :0.0 UNIX-Kurs [~] 79 > echo $DISPLAY :0.0
Shell-Variablen In diesem Beispiel wird die Environmentvariable DISPLAY, die angibt, auf welchem Display die Ausgaben von X11-Programmen erscheinen sollen, auf den Bildschirm der lokalen Maschine (:0.0 gelesen als X-Server 0 Screen 0) gesetzt. Anschließend wird mit echo überprüft, ob das Setzen erfolgreich war.
11.3.3
unsetenv
Um definierte Environmentvariablen wieder zu löschen, wird das Kommando unsetenv benutzt.
unsetenv Variablenname
UNIX-Kurs [~] 80 > unsetenv DISPLAY
Durch diesen Befehl wird das Setzen der Environmentvariablen DISPLAY wieder rückgängig gemacht.
11.4
6 3
Shell-Variablen
Neben den Environmentvariablen verfügen die meisten Shells auch noch über so genannte Shell-Variablen. Diese werden für drei Zwecke benutzt: ✘ zur Abbildung von Environmentvariablen in die für die Shell spezifische Darstellung; ✘ zur Steuerung des Verhaltens der Shell; ✘ in Shell-Scripts zum Zwischenspeichern von Ergebnissen. Auch die tcsh verfügt über solche Shell-Variablen. Im Gegensatz zu anderen Shells unterscheidet die tcsh (wie auch schon ihre Vorgängerin, die csh) zwischen numerischen Variablen und Textvariablen. Diese Unterscheidung wird über das Schlüsselwort zur Definition der Variablen getroffen.
11.4.1
Textvariablen
Textvariablen können Zeichenketten aufnehmen. Diese Zeichenketten dürfen auch Leerzeichen enthalten. Allerdings muss dann bei der Definition darauf geachtet werden, dass die Zeichenketten entsprechend gequotet werden.
155
KAPITEL
11 11.4.2
C-Shell und Tenex-C-Shell
set
Das Kommando set dient der Definition von Textvariablen. Mit set können neue Variablen definiert, aber auch die Inhalte bereits gesetzter Variablen überschrieben werden.
6 3
set [Variablenname [ = Wert ]]
Leider sind csh und tcsh recht anfällig, was das Parsing (Einlesen und Zerlegen) von Eingaben betrifft. So muss bei einem set-Kommando peinlich genau darauf geachtet werden, dass entweder auf beiden Seiten des Gleichheitszeichens genau ein oder kein Leerzeichen steht. Der Inhalt einer einzelnen Variablen kann mit dem echo-Kommando abgerufen werden (echo $Variablenname). Das Kommando set ohne Parameter listet den Inhalt aller ShellVariablen auf.
UNIX-Kurs [~] 81 > set autologoff = 20 UNIX-Kurs [~] 82 > echo $autologoff 20
Durch das Setzen der Shell-Variablen autologoff wird, wie im Beispiel gezeigt, die Wartezeit nach der letzten Aktion in Sekunden festgelegt, nach der ein automatisches Abmelden des Benutzers erfolgt. Anschließend wird wieder das Ergebnis mit echo kontrolliert.
11.4.3
Numerische Variablen
Für einfache Integerarithmetik können die numerischen Variablen der beiden Shells genutzt werden. Da dies aber in erster Linie in Shell-Scripts zum Tragen kommt, soll an dieser Stelle nur ihre Definition vorgestellt werden. @ Der »Klammeraffe« ist für die numerischen Variablen das, was set für die Textvariablen ist.
6 156
@ Variablenname = numerischer Ausdruck
Bei der Zuweisung des Ergebnisses an die Variable wird geprüft, ob es sich um einen korrekten numerischen Ausdruck handelt. Das ist im Fall der Shell-Variablen entweder eine Integerzahl oder ein Ausdruck aus ganzen Zahlen, verknüpft durch Multiplikations-, Divisions-, Additions- oder Subtraktionszeichen
Shell-Variablen (jeweils durch ein Leerzeichen voneinander getrennt). Wurde kein korrekter numerischer Ausdruck angegeben, wird eine Fehlermeldung ausgegeben und gegebenenfalls keine Variable erzeugt. Beachten Sie, dass hinter dem at-Symbol (»@«) ein Leerzeichen stehen muss.
11.4.4
Felder aus Textvariablen
Wie viele Programmiersprachen bietet die Scriptsprache der csh und der tcsh neben den einfachen Variablen auch Variablenfelder an. Da die Programmiersprache der tcsh fest im Interpreter integriert ist, können Anweisungen in der Programmiersprache auch direkt auf der Kommandozeile eingegeben werden. Das Setzen von Variablen ist letztlich nichts anderes als ein solches Ausführen von Anweisungen auf der Kommandozeile. Ein Feld aus Textvariablen wird mit dem Kommando set definiert.
set Feldname = ( Element1 Element2 Element3 ... )
In der Variablen #Feldname steht anschließend die Anzahl der Elemente in dem Variablenfeld und in Feldname[1] steht das erste Element.
UNIX-Kurs [~] 83 > set comp = ( PC Workstation Minicomputer ) UNIX-Kurs [~] 84 > echo $#comp 3 UNIX-Kurs [~] 85 > echo $comp[2] Workstation
6 3
Dieses Beispiel zeigt die Definition eines Variablenfeldes comp mit drei Elementen. Diese Anzahl wird auch ausgegeben, wenn der Inhalt der Variablen #comp abgerufen wird. Das zweite Element des Feldes enthält als Wert die Zeichenkette Workstation. Sollen einmal definierte Variablen wieder gelöscht werden, ohne die Shell zu beenden, kann dies durch das Kommando unset erfolgen:
unset Variablenname
UNIX-Kurs [~] 86 > unset autologoff
6 3 157
KAPITEL
11
C-Shell und Tenex-C-Shell
Die Variable autologoff (s.u.) wird gelöscht. Das Löschen hat zur Folge, dass der Mechanismus, mit dem ein Benutzer nach einer gewissen Spanne Untätigkeit automatisch ausgeloggt wird, außer Kraft gesetzt wird.1
11.5
Konfigurationsvariablen der csh und tcsh
Einige Shell-Variablen haben bestimmte Funktionen und können nicht einfach vom Benutzer umdefiniert werden. Eine Auswahl dieser Shell-Variablen mit Sonderbedeutung soll nun vorgestellt werden: Command Listing
Filename Completion
autolist
(tcsh) Ist diese Variable gesetzt (Wert ist egal) und werden die Anfangsbuchstaben eines Kommandos eingegeben und wird dann auf Å gedrückt, werden von der tcsh alle Kommandos aufgelistet, die mit diesen Anfangsbuchstaben beginnen. filec
(csh) Ist diese Variable gesetzt und wird der Beginn eines Datei- oder Pfadnamens eingegeben, vervollständigt die Shell beim Drücken auf È den Dateinamen. Im Gegensatz zur tcsh wird akustisch auf Doppeldeutigkeiten bei der Filename Completion aufmerksam gemacht. (tcsh) In der tcsh muss filec nicht gesetzt sein. Sie vervollständigt beim Drücken auf Å den Dateinamen soweit sie kann und listet bei Doppeldeutigkeiten alle Varianten auf.
History Completion
Auto Correction
autoexpand
(tcsh) Ist diese Variable definiert und wird ein gültiger History-Befehl auf der Kommandozeile eingegeben, dann holt die Shell beim Drücken auf Å den entsprechenden Befehl in die Kommandozeile zurück. autocorrect
(tcsh) Diese Variable sorgt dafür, dass die Shell beim Drücken von ŸE und anschließend Å Tippfehler in Datei- oder Pfadnamen zu beheben versucht.
Auto Logoff autologoff (tcsh) Diese Variable steuert, nach wie viel Sekunden Untätigkeit die Shell automatisch beendet wird. Soll keine automatische Beendigung erfolgen, muss diese Variable mit unset autologoff gelöscht werden.
1. Richtig zum Tragen kommt dieser Mechanismus nur, wenn an einem ASCII-Terminal gearbeitet wird. In diesem Fall läuft nur eine Shell. Wird diese durch den autologoffMechanismus beendet, wird der Benutzer komplett ausgeloggt. Auf Systemen mit grafischer Oberfläche hingegen bedeutet das Beenden einer Shell »nur« das Schließen eines Fensters – der Benutzer bleibt aber weiterhin angemeldet.
158
Quoting
History Space
history
History Character
histchars
Diese Variable steuert, wie viele Befehle in der History-Liste gemerkt werden. In dieser Variablen wird eine Zeichenkette aus zwei Buchstaben abgelegt, die für die History-Kommandos verwendet werden. Default ist »!^«.
Search Path path Unter csh und tcsh gibt es den Inhalt der Environmentvariablen PATH, in dem die einzelnen Verzeichnisse des Suchpfads durch »:« getrennt sind, in Form eines Variablenfeldes path. Wird dieses vom Benutzer überdefiniert, geht nichts mehr!
11.6
Quoting
Für große Verwirrung bei Unix-Einsteigern sorgen immer wieder die unterschiedlichen Anführungszeichen, die bei der Eingabe einiger Unix-Kommandos nötig sind. Dieses Thema ist schon an der einen oder anderen Stelle angeschnitten worden, ohne allerdings den gesamten Umfang der Möglichkeiten und Aufgaben der Quotes offenzulegen. Nachdem nun die wichtigsten Unix-Kommandos ausführlich erläutert worden sind, ist es an der Zeit, die Quotes in einem eigenen Abschnitt genau unter die Lupe zu nehmen. Dass dies im Kapitel über die csh und tcsh erfolgt, ist dabei nicht so wichtig, denn dieser Mechanismus ist in allen Shells im Wesentlichen gleich1. Aufgabe der Quotes ist es generell, Teile der Kommandozeile zusammenzufassen. Unix verwendet für diese Aufgabe drei unterschiedliche Arten von Quotes: ✘ Double Quotes (doppelte Anführungszeichen2) " " ✘ Single Quotes (einfache Anführungszeichen3) ' ' ✘ Back Quotes (rückwärts gerichtete einfache Anführungszeichen4) ’ ’ Double Quotes haben zwei Aufgaben. Mithilfe von Double Quotes können Zeichenketten, die Leerzeichen enthalten, zu einem Kommandozeilenparameter zusammengefasst werden. Dies wird immer dann notwendig, wenn 1. Unterschiede gibt es bei der Behandlung von History-Zeichen (Ausrufezeichen) und von Zeilenenden innerhalb des gequoteten Strings. 2. Es muss das ASCII-Zeichen »Double Quote« verwendet werden, also nicht die in der Textverarbeitung üblichen typografischen englischen oder deutschen Anführungszeichen. 3. Es muss das Apostroph-Zeichen verwendet werden, nicht der Acute-Akzent und auch nicht das typografische Anführungszeichen. 4. Auf europäischen Tastaturen gibt es meist keine eigene Taste, sondern man muss zuerst den Gravis-Akzent und dann die Leertaste drücken, um dieses ASCII-Zeichen zu erhalten.
159
KAPITEL
11
C-Shell und Tenex-C-Shell
eine Zeichenkette, die Leerzeichen enthält, an ein Kommando übergeben werden soll, z.B. als Suchmuster. Das Leerzeichen verliert dann seine Funktion als Trennzeichen von Kommandozeilenparametern. Des Weiteren verlieren innerhalb von Double Quotes Wildcards wie »*«, »~« und »[]« ihre Sonderbedeutung. Allerdings gibt es auch Zeichen, die durch die Double Quotes nicht von ihrer Sonderfunktion befreit werden. So werden Variablen wie $HOME nach wie vor durch ihren Inhalt ersetzt, Kommandos in Back Quotes durch ihre Ausgaben substituiert und auch das History-Zeichen behält seine Funktion. Single Quotes sind eine verschärfte Form der Double Quotes. Sie haben genau die gleichen Aufgaben, aber innerhalb von Single Quotes werden keine Variablen mehr ersetzt und auch die Kommmando-Substitution wird nicht mehr durchgeführt. Nur das History-Zeichen behält auch hier seine Sonderbedeutung. Zwischen den Back Quotes steht immer ein vollständiges Unix-Kommando. Dieses Kommando wird von der Shell ausgeführt, bevor die restliche Kommandozeile interpretiert wird. Die Ausgabe, die das in Back Quotes eingeschlossene Kommando erzeugt, wird an der Stelle in die Kommandozeile eingefügt, an der die Back Quotes stehen. Sinn dieser Quotes ist es, UnixKommandos miteinander zu verknüpfen.
3
UNIX-Kurs [~] 87 > ls -l `fgrep -l Meier *.c`
Bei diesem Beispiel haben wir zwei Unix-Befehle auf der Kommandozeile. ls -l erzeugt ein Listing mit allen Attributen der angegebenen Dateien. fgrep -l Meier *.c listet alle Dateien mit der Endung .c auf, in deren Inhalt die Zeichenkette Meier vorkommt. Da das Kommando fgrep mit seinen Parametern in Back Quotes steht, wird es zuerst ausgeführt. Die Namen der Dateien, die es als Ergebnis liefert, werden in der Kommandozeile hinter das ls -l geschrieben. So werden die beiden Befehle zu dem neuen Befehl kombiniert: »Liste alle Attribute all jener Dateien mit der Endung .c auf, welche die Zeichenkette Meier enthalten.« Diese Variante des Einsatzes von Quotes heißt Kommando-Substitution.
160
Alias-Namen
11.7
Alias-Namen
Schon mit der csh wurde eines der wirkungsvollsten Konzepte zur Arbeitserleichterung im Umgang mit der Shell eingeführt: die Definition von AliasNamen. Ein Alias ist ein Kürzel für eine häufig benutzte Kommandofolge und soll in erster Linie Schreibarbeit sparen. Allerdings kann der Einsatz von Alias-Namen so weit gehen, dass komplette Befehlssätze anderer Betriebsysteme mittels Alias auf die entsprechenden Unix-Kommados umgesetzt werden. Es gibt kaum ein System, auf dem es nicht mindestens den Alias dir für ls -l gibt. Dieser Einsatz von Alias-Namen ist eigentlich genauso wenig Sinn dieses Features wie das Belegen aller Buchstaben der Tastatur mit neuen Funktionen. Durch diese zusätzliche Verkürzung der ohnehin schon kurzen Unix-Befehlsnamen wird jeglicher Zusammenhang zwischen Benennung und Funktion eines Kommandos zerstört. Ein solches Vorgehen muss über kurz oder lang zu folgenschweren Fehlbedienungen führen. Zu guter Letzt erlaubt das Alias-Konzept auch noch die Umdefinition von Unix-Kommandos.1 Wenn auch in manchen Fällen durchaus verständlich, sollte so etwas genau überlegt sein. Hier stellt sich die Frage: was ist denn nun ein sinnvoller Alias? Ein Alias ist dann sinnvoll, wenn er entweder für ein mit den Mitteln von Unix (z.B. Kommandoverkettung über Pipes) neu kreiertes Kommando steht oder wenn er Kommandos mit ihren gängigsten Optionen abkürzt, ohne der Lesbarkeit zu schaden. Hier muss zunächst zwischen den einfachen Alias-Namen und den AliasNamen mit der Umplatzierung der Parameterliste unterschieden werden.
11.7.1
alias
Alias-Namen werden mit dem shellinternen Kommando alias definiert.
alias Alias-Name Kommando
6
1. Die am häufigsten auftretende Form einer solchen Umdefinition ist ein Alias rm für rm -i. Allerdings sollte man diesem Alias einen anderen Namen wie z.B. del oder rmi geben und ihn keinesfalls rm nennen, weil man sonst in verschiedenen Situationen den sehr gefährlichen rm-Befehl mit dem ungefährlichen rm-Alias verwechselt und irrtümlich Dateien unwiderbringlich löscht.
161
KAPITEL
11
C-Shell und Tenex-C-Shell
Wird alias ohne Parameter aufgerufen, listet es alle definierten Alias-Namen auf.
3
UNIX-Kurs [~] 88 > alias ll ls -la UNIX-Kurs [~] 89 > ll a*
Steht als Kommandoname ein Wort, für das ein Alias definiert ist, wird dieses von der Shell bei der Alias-Substitution durch den Wert des Alias ersetzt. In dem oben stehenden Beispiel würde der Alias ll textuell durch seine Definition (ls -la) ersetzt und die so entstandene neue Kommandozeile (ls -la a*) durch die Shell ausgeführt.
11.7.2
Umplatzieren der Parameterliste
Nicht bei allen denkbaren Abkürzungen durch Alias-Namen wäre eine solche reine textuelle Ersetzung erfolgreich. Häufig muss die Parameterliste, die nach einem Alias-Namen beim Aufruf steht, in den Befehl eingefügt werden, um eine sinnvolle Ersetzung zu ergeben. Das ist häufig bei Alias-Namen für find-Kommandos oder bei Kommandoverkettungen über Pipes der Fall. Auch hier soll ein Beispiel für mehr Klarheit sorgen.
3
UNIX-Kurs [~] 90 > alias ff "find / -name \!* -print" UNIX-Kurs [~] 91 > ff "*.txt"
Der Alias ff steht für ein find-Kommando, das Dateien im gesamten UnixDateibaum sucht. Ohne den Alias müsste unser Kommando für den Anwendungsfall in der zweiten Beispielzeile wie folgt lauten: find / -name "*.txt" -print
Dieses Kommando durchsucht den gesamten Dateibaum vom Root-Directory (/) an nach Dateien mit der Endung .txt und gibt alle Treffer mit absolutem Pfad aus. Das Suchkriterium lautet *.txt und muss zwischen dem -name und dem -print stehen, also zwischen zwei Bestandteilen des Kommandos, die eigentlich im Alias verankert sind. An dieser Stelle reicht eine simple Textersetzung wie beim ll nicht mehr aus, weil im Text des Alias die Parameterliste (*.txt) des Kommandos eingefügt werden muss. Für diesen Anwendungsfall gibt es den Platzhalter !*, der bei der Alias-Definition an die Stelle geschrieben wird, an der bei der Umsetzung des Alias in den eigentlichen Befehl die Parameterliste stehen soll. Bei der Definition des Alias fällt auf, dass der gesamte Text des Alias in Double Quotes eingefasst ist
162
Alias-Namen und dass vor dem »!« ein Backslash »\« steht. Warum? Die Quotes dienen dazu, Sonderzeichen wie den Stern »*« vor der Interpretation durch die Shell zu schützen. Das »!« als History Character lässt sich aber nicht quoten und muss deshalb explizit mit einem Backslash geschützt werden.
Folgende Faustregel sollten Sie sich merken: Soll ein Alias definiert werden, bei dem die Parameter nicht einfach hinten angehängt werden dürfen, gehört der gesamte Alias-Text in Double oder Single Quotes und außerdem steht ein \!* an der Stelle, an der die Parameter eingesetzt werden sollen.
11.7.3
1
Permanente Alias-Namen
Wurde ein Alias interaktiv in der Shell definiert, ist er nur auf dieser einen Shell verfügbar und verschwindet, sobald die Shell beendet wird. Dies kann verhindert werden, indem solche Alias-Namen, die in jeder Shell verfügbar sein sollen, in die Startup-Datei .tcshrc (s.u.) der tcsh bzw. .cshrc der csh eingetragen werden. Die Definition erfolgt hier ebenso wie auf der Kommandozeile.
11.7.4
unalias
Soll ein Alias gelöscht werden, so erfolgt das mit dem Kommando unalias.
unalias Alias-Name
UNIX-Kurs [~] 92 > unalias ll UNIX-Kurs [~] 93 > ll ll - Command not found
6 3
Das Löschen eines Alias-Namens hat in der Regel zur Folge, dass das entsprechende Kommando nicht mehr von der Shell gefunden wird.
Aber Vorsicht: Unter Umständen kann an die Stelle des Alias jetzt ein Kommando aus dem Suchpfad treten, das durch den Alias überdefiniert worden war.
2 163
KAPITEL
11 11.8
C-Shell und Tenex-C-Shell
Die Datei .login
Die Datei .login ist eine der beiden Startup-Dateien der csh bzw. tcsh. Bei Shells unter Unix wird zwischen den so genannten Login-Shells und den »normalen« interaktiven Shells, die z.B. aus einer anderen Shell heraus gestartet werden, unterschieden. Der Name der Login-Shell ist in der /etc/passwd eingetragen. Diese Shell wird als erste beim Einloggen gestartet. Wird eine csh oder tcsh als Login-Shell gestartet, sucht sie im Home Directory des Benutzers nach einer Datei .login. Ist diese vorhanden (Ausführungsrechte müssen nicht gesetzt sein), wird der Inhalt der Datei Zeile für Zeile ausgeführt. Die Datei .login wird verwendet, um Terminal-Charakteristika für die gerade gestartete Shell einzustellen (z.B. Definition der Taste, mit der auf der Kommandozeile gelöscht wird). Die Datei .login wird grundsätzlich nur einmal beim Anmelden an das System zusätzlich zur Datei .cshrc oder .tcshrc ausgeführt. Auf einigen Systemen wie z.B. dem IRIX von SGI geschieht das beim Öffnen jedes ShellFensters, auf anderen Systemen wie z.B. dem SCO Unix Ware 7 wird aber beim Öffnen eines Fensters nur das .cshrc bzw. .tcshrc ausgeführt. Aus diesem Grund ist das .login auf vielen Systemen zur Bedeutungslosigkeit verurteilt und alle wichtigen Einstellungen, die in jeder aktuellen Shell gewünscht sind (PATH, umask, alias, ...), werden in der .cshrc bzw. .tcshrc getroffen.
11.9
Die Dateien .tcshrc und .cshrc
Für jede tcsh (es sei denn, sie wird mit der Option -f gestartet) wird im Home Directory des Benutzers nach einer Datei .tcshrc, für jede csh nach einer Datei .cshrc gesucht. Wird diese Datei gefunden (auch hier sind Ausführungsrechte nicht notwendig), wird diese Datei ausgeführt. In dieser Datei werden in der Regel Environmentvariablen und Alias-Namen definiert, der StandardPrompt geändert und Charakteristika für die Shell eingestellt, vgl. auch Abschnitt 10.4. Häufig finden sich in den Dateien .tcshrc und .cshrc auch Veränderungen der User File Creation Mask (umask), welche die Defaultrechte bei neu angelegten Dateien definiert. Diese Einstellungen haben dann auch Gültigkeit innerhalb von Shell-Scripts, sofern deren interpretierende Shell nicht mit der Option -f gestartet wird.
2 164
Keine Aufrufe von xterm in der .cshrc oder .tcshrc!!!
Ein-/Ausgabeumlenkung In der .tcshrc oder der .cshrc dürfen auf keinen Fall Befehle auftauchen, die im Zusammenhang mit der grafischen Bedienoberfläche stehen oder auf Benutzereingaben warten. So hätte z.B. der Aufruf des Kommandos xterm katastrophale Folgen: Beim Starten einer tcsh (die eine Login-Shell ist) wird aus dem .tcshrc ein xterm gestartet. Im xterm läuft aber wiederum eine Login-Shell – also eine neue tcsh. Auch diese durchläuft das .tcshrc und startet ein xterm usw. Resultat ist eine Endlosrekursion, die in der Regel erst dann stoppt, wenn der Rechner einen Seitenwechseleinbruch erleidet, also sämtlicher Speicher plus sämtlicher Swap Space1 aufgebraucht sind. Ein solcher Rechner ist oft nur noch über den Reset-Knopf wieder zum Leben zu erwecken. Auch ein Befehl, der eine Benutzereingabe erwartet, darf darin nicht vorkommen, weil sonst Shell-Scripts und Hintergrundprozesse nicht funktionieren. Neben der Datei .cshrc bzw. .tcshrc gibt es auch noch eine globale StartupDatei für csh und tcsh. Diese Datei wird vom Systemverwalter benutzt, um einheitliche Voreinstellungen für alle Nutzer der csh und tcsh zu schaffen. Diese Datei trägt den Namen /etc/cshrc und kann in der Regel nur vom Systemverwalter verändert werden. Allerdings hat der Benutzer die Möglichkeit, Einstellungen aus der globalen Startup-Datei durch Einstellungen in seiner privaten .cshrc bzw. .tcshrc zu überschreiben. Hierbei sollte eine gewisse Vorsicht an den Tag gelegt werden, denn einige Veränderungen, wie z.B. das Abändern des Suchpfades in der Environmentvariablen PATH, können recht starken Einfluss auf das Arbeiten mit dem Unix-System haben.
11.10 Ein-/Ausgabeumlenkung Obwohl auf jeder Shell verfügbar, ist das Feature der Ein-/Ausgabeumlenkung shellspezifisch. Das liegt daran, dass zwei unterschiedliche Konzepte verfolgt werden: 1. das der csh und der tcsh und 2. das Konzept der sh, der ksh und der bash. Obwohl sonst eine sinnvolle Sache, stört hier die Abwärtskompatibilität der tcsh zur csh, denn das Konzept der csh ist nicht so flexibel wie das der sh und
kann nur einen Überschreibschutz als Plus verbuchen. Doch bevor in die Details eingestiegen werden kann, muss zunächst einmal das Grundkonzept erläutert werden.
1. Swap Space ist ein Festplattenbereich, der zusammen mit dem physischen Speicher den so genannten virtuellen Speicher ausmacht. Virtueller Speicher ist der Speicher, der dem Unix zur Ausführung aller Prozesse zur Verfügung steht.
165
KAPITEL
11
C-Shell und Tenex-C-Shell
Grundidee der Ein-/Ausgabe unter Unix ist die Verwendung spezieller Kanäle. Diese Kanäle sind verbunden mit Geräten, die wiederum durch Dateien – die Device Descriptors – repräsentiert werden. Da die Schnittstelle für den Zugriff auf Geräte identisch zu der für den Zugriff auf Dateien ist (gemäß dem Grundprinzip der Geräteunabhängigkeit), liegt nichts näher, als die vordefinierten Kanäle umzulenken, wenn z.B. Ausgaben nicht auf den Bildschirm, sondern in eine Datei geschrieben werden sollen. Genau das macht die Ein/Ausgabeumlenkung. Drei Standardkanäle sind vordefiniert und können umgelenkt werden. Die Standardeingabe ist per Default mit der Tastatur verbunden. Liest ein Kommando von der Standardeingabe, liest es normalerweise von der Tastatur. Die Standardausgabe ist mit dem Bildschirm verbunden. Alle Ausgaben, die ein Kommando tätigt und welche die Ergebnisse einer fehlerfreien Befehlsausführung sind, werden über die Standardausgabe ausgegeben. Die Standardfehlerausgabe ist wie die Standardausgabe ebenfalls mit dem Bildschirm verbunden. Über diesen Kanal werden alle Fehlermeldungen von Befehlen auf den Bildschirm geschrieben. Die Existenz dieses Fehlerkanals wird in der Regel vom Benutzer zunächst nicht erkannt, da die Fehlermeldungen wie auch die regulären Ausgaben auf dem Bildschirm erscheinen.
11.10.1 Eingabeumlenkung Bei der Eingabeumlenkung werden die Eingaben für einen Befehl in einer Datei vorbereitet. Würde der Befehl von der Tastatur lesen, würde das Ende der Eingaben an der Übermittlung eines ŸD (ASCII-Wert 4) erkannt, das unter Unix mit dem Dateiendezeichen identisch ist. Bei der Eingabeumlenkung sorgt das Ende der Datei somit dafür, dass der Befehl keine weiteren Eingaben erwartet.
6 3 166
Unix-Kommando < Eingabedatei
Bei der Angabe der Eingabedatei dürfen keine Wildcards benutzt werden, da die Umlenkung von der Shell vor der Interpretation der Wildcards aus der Kommandozeile gefiltert wird. Die Eingabe kann nur einmal pro Befehl umgelenkt werden.
UNIX-Kurs [~] 94 > mail
[email protected] < brief
Ein-/Ausgabeumlenkung Ein klassisches Beispiel für die Verwendung der Eingabeumlenkung ist der mail-Befehl, mit dem elektronische Post auf der lokalen Maschine, aber auch in die weite Welt verschickt werden kann. In unserem Beispiel wurde der Text für die E-Mail in der Datei brief vorbereitet (z.B. mit einem Texteditor) und wird nun dem Kommando mail per Eingabeumlenkung zur Verfügung gestellt.
11.10.2 Ausgabeumlenkung Bei der Ausgabeumlenkung werden die Ergebnisse einer fehlerfreien Befehlsausführung in eine Datei geschrieben. Dabei kann entweder eine Datei neu angelegt bzw. überschrieben werden:
Unix-Kommando > Ausgabedatei
oder es können die Ausgaben an eine bereits bestehende Datei angehängt werden (append):
Unix-Kommando >> Ausgabedatei
Beide Varianten bergen ein gewisses Risiko in sich. Die Shell prüft nämlich nicht, was zuvor in der Umlenkungsdatei stand, d.h. es kann mit der Ausgabeumlenkung durchaus Text an eine Binärdatei angehängt bzw. ein Programm oder eine andere wichtige Datei per Ausgabeumlenkung überschrieben werden. Soll an eine noch nicht bestehende Datei angehängt werden, wird diese von der Shell angelegt.
6 6
Alle drei aufgezählten Verhaltensformen sind nicht erwünscht. Allerdings lässt sich nur gegen zwei davon etwas tun: gegen ungewolltes Überschreiben und gegen ungewolltes Anlegen einer Datei beim append. Erreicht wird dieser Schutz durch das Setzen der Schreibschutzvariablen der csh und tcsh. Diese heißt noclobber und verhindert genau die beiden Fälle.
UNIX-Kurs [~] 95 > ls -l > verzeichnis.txt UNIX-Kurs [~] 96 > set noclobber UNIX-Kurs [~] 97 > ls -l > verzeichnis.txt verzeichnis.txt - File exists
3 167
KAPITEL
11
C-Shell und Tenex-C-Shell
Stellt die Shell bei gesetztem noclobber fest, dass eine der beiden Schutzvorschriften verletzt ist, sorgt sie dafür, dass das Kommando nicht ausgeführt wird – also unterbleibt nicht nur die Umlenkung, sondern der ganze Befehl wird nicht ausgeführt!
11.10.3 Ausgabeumlenkung mit Fehlerkanal Bisher wurde nur die Umlenkung der Standardeingabe und -ausgabe beschrieben, was auch die beiden häufigsten Anwendungsfälle sind. Wenn allerdings Gebrauch von der Ausgabeumlenkung gemacht wird, kann festgestellt werden, dass ab und zu dennoch Ausgaben auf dem Bildschirm erscheinen, obwohl die Ausgabe umgelenkt ist. Dabei handelt es sich um solche Meldungen, die über die Standardfehlerausgabe auf den Bildschirm gelangen. Soll dies unterbunden werden, können unter der csh und der tcsh Standardausgabe und Standardfehlerausgabe gemeinsam in eine Datei umgelenkt werden.1 Auch hier gibt es wieder die Varianten des Überschreibens bzw. Anlegens:
6 6 3
Unix-Kommando >& Ausgabedatei
und die des Anhängens:
Unix-Kommando >>& Ausgabedatei
UNIX-Kurs [~] 98 > find / -name .tcshrc -print >& rcs.txt
In diesem Beispiel wird der gesamte Dateibaum des Unix-Betriebssystems nach Dateien mit dem Namen .tcshrc durchsucht. Das Ergebnis dieser Suche wird in die Datei rcs.txt im Working Directory geschrieben. Da find Fehlermeldungen produziert, wenn es auf Verzeichnisse stößt, für die der Benutzer kein Ausführungsrecht oder Leserecht besitzt (mit solchen Verzeichnissen ist bei der Durchsuchung des kompletten Dateibaums zu rechnen), werden Standard- und Standardfehlerausgabekanal umgelenkt.
sh, ksh oder bash können diese beiden Kanäle getrennt umgeleitet werden, was u. U. von Vorteil sein kann.
1. Unter der
168
Subshells
11.11 Subshells Im Zusammenhang mit der Ein-/Ausgabeumlenkung soll noch auf ein weiteres Feature der csh und tcsh hingewiesen werden. Beide sind in der Lage, Kommandos oder Kommandofolgen in einer eigenen so genannten Subshell zu starten. Diese Umhüllung durch eine Shell führt dazu, dass z.B. die Ausgaben der Kommandofolge zusammengefasst werden und dann entweder mit der Ein-/Ausgabeumlenkung gemeinsam behandelt oder per Pipe an ein Filterkommando weitergeleitet werden können. Eine Subshell wird dann für ein Kommando oder eine Kommandofolge gestartet, wenn sie durch runde Klammern eingeschlossen werden.
(Kommando1;Kommando2; ...)
Anhand zweier interessanter Kommandobeispiele lassen sich die Verwendung von Subshells und die daraus resultierenden Vorteile recht gut erläutern. Für Subshells gilt das Gleiche wie für Shell-Scripts – in beiden Fällen wird eine von der Shell, mit der gearbeitet wird, unabhängige Shell gestartet, deren Aufgabe einzig und allein das Ausführen der Kommandos in der Subshell bzw. in dem Script ist. Werden in dieser Subshell Veränderungen an dem Working Directory oder am Environment vorgenommen, so haben die Änderungen nur Einfluss auf die Subshell und die in ihr ausgeführten Kommandos.
UNIX-Kurs [~] 99 > (cd;echo "Inhalt Home Directory";ls)
So hat in diesem Beispiel für die aktuelle Shell, deren Working Directory /etc lautet, das cd keine Auswirkung, da der Wechsel des Working Directoryss nur in der Subshell stattfindet. Sonst wird ganz normal die Kommandofolge abgearbeitet – also mit cd in das Home Directory des Benutzers gewechselt, mit echo die Zeichenfolge ausgegeben und mit ls der Inhalt aufgelistet. Die Subshell wird nach der Ausführung des ls beendet. Das Ergebnis der gesamten Kommandofolge in der Subshell ließe sich mittels einer Ausgabeumlenkung nach der schließenden runden Klammer in eine Datei ausgeben.
6
3
Diesen Effekt macht man sich bei folgender Befehlsfolge zu Nutze:
UNIX-Kurs [~] 100 > (find / -name .tcshrc -print > rcs.txt) >& /dev/null &
3 169
KAPITEL
11
C-Shell und Tenex-C-Shell
Der find-Befehl wurde ja bereits im letzten Abschnitt erläutert. Er dient dazu, im gesamten Dateisystem nach Dateien mit dem Namen .tcshrc zu suchen und das Ergebnis in eine Datei mit dem Namen rcs.txt zu schreiben. Da das Kommando durchaus etwas länger laufen könnte, wird es als Hintergrundprozess gestartet. Wie immer bei einer solchen globalen Suche werden auch ein paar Verzeichnisse ohne ausreichende Zugriffsberechtigungen darunter sein, um in ihnen zu suchen,. Für jedes solche Verzeichnis würde eigentlich eine Fehlermeldung erscheinen. Dies ist aber bei einem Hintergrundkommando äußerst unangenehm und sollte deshalb durch eine geeignete Ausgabeumlenkung unterdrückt werden. Unter der csh und tcsh hat der Benutzer nur die Möglichkeit, Standardausgabe und Standardfehlerausgabe gemeinsam in eine Datei umzulenken, genauso wie dies im letzten Abschnitt gezeigt wurde. Damit landen sowohl die Suchergebnisse alsauch die Fehlermeldungen in der Resultatdatei. Durch die Verwendung einer Subshell, wie im Beispiel gezeigt, kann man jetzt eine Verbesserung dieses Ergebnisses erzielen. Die Standardausgabe – also die Namen der gefundenen Dateien – des find-Kommandos wird in eine Datei rcs.txt umgeleitet. Der Standardfehlerkanal wird innerhalb der Subshell nicht umgeleitet, wodurch die Fehlerausgaben an die Subshell weitergereicht werden. Durch die Kapselung können nun wiederum alle Ausgaben der Subshell mit einer eigenen Ausgabeumlenkung umgeleitet werden. Da hier nur die Fehlermeldungen des find und die Ausgaben der Subshell zu erwarten sind, wird eine Ausgabeumlenkung von Standardausgabe und Standardfehlerausgabe auf das Papierkorb-Device (/dev/null) gemacht. Die Resultatdatei enthält jetzt nur korrekte Ergebnisse und das Hintergrundkommando hat keine störenden Ausgaben erzeugt.
11.12 Von der Eingabe eines Kommandos bis zur Ausführung Nachdem nun die vielen unterschiedlichen Aufgaben der Shell bei der Ausführung eines Kommandos besprochen worden sind, stellt sich nur noch die Frage nach der Reihenfolge, die ja unter Umständen ausschlaggebend für das Ergebnis des Kommandos sein kann. Die csh und die tcsh arbeiten dabei nach den in Abb. 11.1 dargestellten Schritten.
170
Eingabe und Ausführung Abb. 11.1: Arbeitsschritte der csh und tcsh
Nachdem die Kommandozeile eingegeben und mit Æ zur Ausführung freigegeben worden ist, wird von der Shell zuerst die so genannte History-Substitution vollzogen. Bei dieser werden sämtliche History Characters, denen kein Backslash vorangeht, durch korrespondierende Befehle aus der Command History ersetzt. Der History-Substitution folgt die Alias-Substitution. Bei dieser Ersetzung werden vom Benutzer definierte Kürzel (Alias-Namen) durch die eigentliche Schreibweise der Befehle ersetzt. Da hier u.U. wieder History Characters in die Eingabezeile kommen können, kehren wir zur History-Substitution zurück. Der Auswertung der Alias-Substitution folgt die Variablen-Substitution. Bei dieser werden Zeichenketten der Form $xxx, wobei für xxx ein Variablenname aus dem Environment oder der Shell stehen kann, durch den Inhalt der entsprechenden Variablen ersetzt. Anschließend wird die so veränderte Eingabezeile nach Ein-/Ausgabeumlenkungszeichen durchsucht. Mit diesem Feature können die Ausgaben eines Befehls vom Bildschirm in Dateien umgelenkt und die Eingaben eines Befehls statt von der Tastatur aus einer Datei gelesen werden.
171
KAPITEL
11
C-Shell und Tenex-C-Shell
Als vorletzter Schritt werden die Wildcards in der Eingabezeile interpretiert. Die in der Kommandozeile enthaltenen Muster werden dabei – soweit möglich – durch passende Dateinamen ersetzt. Der letzte Schritt vor der Kommandoausführung ist die Zuordnung von Pfaden zu den Kommandos, die in der Kommandozeile stehen. Zu diesem Zweck wird der Suchpfad aus dem Environment benutzt. Kann eine Zuordnung zu einem Pfad vollzogen werden, wird das entsprechende Programm mit der in den vorherigen Schritten ermittelten Kommandozeile von der Shell gestartet. Falls die Befehlszeile mehrere Befehle enthält, die durch Semikola getrennt oder durch Back Quotes verbunden sind, dann gelten diese Regeln für jeden einzelnen Befehl separat.
11.13 Prozessverwaltung der Shell Als letztes Feature der csh und der tcsh soll ihre erweiterte Prozessverwaltung vorgestellt werden. Grundsätzlich lassen sich auch wie unter den anderen Shells Vordergrund- und Hintergrundprozesse erzeugen. Die Kommandos ps und kill sind nach wie vor zur Anzeige und Beendigung von Prozessen verfügbar. Allerdings haben diese beiden Kommandos Schwächen, welche die Entwickler der csh und tcsh dazu bewogen haben, Erweiterungen einzuführen. Werden Kommandos sequentiell (verknüpft mit »;«) oder parallel (verknüpft mit »|«) verkettet, können oft nicht alle Prozesse gleichzeitig mit kill beendet werden. Insbesondere die sequentielle Verkettung bereitet hier Probleme, weil für die noch nicht gestarteten Prozesse keine PIDs bekannt sind. Um diesem Problem beizukommen, werden unter der csh und der tcsh verkettete Kommandos über eine zu diesem Zweck gestartete Shell verwaltet. Diese Shell bildet den Vaterprozess für alle Kommandos. »Stirbt« diese Shell, »sterben« auch alle Kommandos der Verkettung mit ihr. Durch diesen Trick muss nur ein Prozess kontrolliert werden, der mit Sicherheit über eine PID verfügt. Einen Einzelprozess oder eine mehrere Kommandos kontrollierende Shell wird unter der tcsh als Job bezeichnet. Da aber die PIDs auf Systemen mit vielen Prozessen von ps nur recht umständlich zu ermitteln sind, wurden die Job-IDs eingeführt. Jeder Job, der gestartet wird, bekommt, egal ob es sich um ein Einzelkommando oder um eine Verkettung mit kontrollierender Shell handelt, eine eindeutige Job-ID von der Shell zugeteilt.
172
Prozessverwaltung der Shell
jobs
Mit dem internen Kommando jobs der beiden Shells können alle von dieser Shell aus gestarteten Hintergrundprozesse mit ihren Job-IDs aufgelistet werden. Angezeigt werden die Kommandozeile, mit der der Befehl gestartet wurde, und der Zustand, in dem er sich gerade befindet.
6
Soll nun ein Job beendet werden, so kann dies über das kill-Kommando und die zugehörige Job-ID mit einem vorangestellten Prozentzeichen »%« geschehen.
UNIX-Kurs [~] 101 > kill %1
In diesem Beispiel wird dem Job mit der Job-ID 1 durch kill das Signal SIGTERM zugestellt.
3
csh und tcsh bieten aber noch mehr in Sachen Job Control. So lassen sich
z.B. gerade laufende Vordergrundprozesse mit ŸZ stoppen, um sie später fortzusetzen.
11.13.1 bg background – Die Fortsetzung kann mit dem Kommando bg als Hintergrundprozess erfolgen. Diese Variante wird häufig benutzt, wenn Rechenprozesse zu Beginn ihrer Arbeit interaktiv vom Benutzer Angaben abfragen, um dann minuten- und stundenlang vor sich hinzurechnen. Ein solcher Prozess wird als Vordergrundprozess gestartet, dann werden interaktiv die gewünschten Angaben gemacht, der Prozess wird gestoppt und im Hintergrund fortgeführt. Als Ergebnis werden die Job-ID in eckigen Klammern und die PID ausgegeben. bg kann auch als zusätzlichen Parameter eine Job-ID erhalten, wenn mehr als ein Job gestoppt wurde. Diese ist dann mit vorangestelltem Prozentzeichen anzugeben.
UNIX-Kurs [~] 102 > find / -name "*.c" -print >& result.txt UNIX-Kurs [~] 103 > ŸZ UNIX-Kurs [~] 104 > bg [1] 52314
3 173
KAPITEL
11
C-Shell und Tenex-C-Shell
Das Durchsuchen des gesamten Dateibaums nach Dateien mit der Endung .c wie in dem obigen Beispiel kann je nach Größe des Dateibaums recht lange dauern. Aus diesem Grund wurde das als Vordergrundprozess gestartete Kommando in diesem Beispiel mit ŸZ gestoppt und mit dem Kommando bg als Hintergrundprozess fortgesetzt.
11.13.2 fg foreground – Ein gestoppter Prozess kann auch als Vordergrundprozess fortgesetzt werden. Das Stoppen eines Prozesses wird nämlich nicht grundsätzlich »von Hand« durch den Benutzer vorgenommen, sondern kann auch durch die Shell selbst erfolgen, z.B. wenn ein Hintergrundprozess versucht, von der Standardeingabe zu lesen. Dass ein Prozess gestoppt wurde, wird in der Liste der Prozesse, die mit jobs abgefragt werden kann, angezeigt. Da in der Regel nicht immer der zuletzt gestartete Job angehalten wurde, sollte bei der Verwendung von fg immer mit einer Job-ID gearbeitet werden.
3
UNIX-Kurs [~] 105 > fg %2
In diesem Beispiel wird der Job mit der Job-ID 2, der bisher im Hintergrund lief oder gestoppt war, als Vordergrundprozess weitergeführt.
Übungen
11.14 Aufgaben 1. Suchen Sie nach einer Möglichkeit, den folgenden find-Befehl statt mit -exec mit einer Kommando-Substitution (Back Quotes) zu lösen. find ~ -type f -exec file {} \;
2. Welches der beiden Kommandos aus 1.) ist schneller – die Variante mit -exec oder die Kommando-Substitution? Begründen Sie Ihre Antwort. 3. Kann es bei der Kommando-Substitution aus 1.) zu Problemen kommen? 4. Versuchen Sie Beispiele zu finden, welche die Unterschiede zwischen Double und Single Quotes verdeutlichen. 5. Definieren Sie einen Alias dir für das Kommando ls -la. 6. Definieren Sie einen Alias, der in allen Plain Files unterhalb Ihres Working Directorys nach einer Zeichenkette sucht. Der Alias soll mit suche Zei-
174
Aufgaben chenkette aufgerufen werden können. Als Ergebnis sollen die Namen der Dateien ausgegeben werden, welche die Zeichenkette enthalten. 7. Schauen Sie sich den Inhalt der Datei .tcshrc in Ihrem Home Directory an. 8. Versuchen Sie, mithilfe von echo und der Ausgabeumlenkung einen Brief in eine Datei zu schreiben. 9. Starten Sie einen find-Befehl als Hintergrundprozess und lenken Sie die Suchergebnisse in eine Datei um. Werden wirklich alle Ausgaben in die Datei umgelenkt? Was müssen Sie tun, damit auf keinen Fall Ausgaben auf dem Bildschirm erscheinen?
11.14.1 Lösungen Die Aufgaben beziehen sich auf eine Tenex-C-Shell (tcsh). Falls Sie mit einer Korn-Shell oder Bourne-Shell arbeiten, finden Sie die äquivalenten Lösungen am Ende des nächsten Kapitels, soweit sie sich von diesen unterscheiden. 1. Analysieren wir zunächst einmal, was nach Eingabe von find ~ -type f -exec file {} \;
passieren wird. Der find-Befehl sucht in unserem Home Directory (~) und in allen Unterverzeichnissen nach Dateien des Typs Plain File (-type f). Für jede gefundene Datei wird dann durch -exec das Kommando file aufgerufen und der Name der gefundenen Datei wird an der Stelle eingesetzt, wo die geschweiften Klammern {} stehen. Das file-Kommando wiederum gibt an, um welche Art Datei es sich handelt (z.B. ascii text, executable, jpeg-picture, ...). Geben Sie den find-Befehl ein und schauen Sie sich das Ergebnis an. Diese Suchanfrage kann auch mithilfe der Kommando-Substitution (Back Quotes) gestellt werden. Bei der Kommando-Substitution werden zwei Kommandos miteinander verknüpft, wobei der in Back Quotes eingeschlossene Befehl zuerst ausgeführt wird. Das textuelle Ergebnis dieses ersten Befehls wird dann in der Kommandozeile an der Stelle eingefügt, an der das Kommando in Back Quotes stand. Der in der Aufgabe angegebene find-Befehl funktioniert ähnlich: Zuerst werden Dateien gesucht und dann werden sie dem file-Befehl übergeben. Somit wissen wir, welcher der beiden Befehle in Back Quotes gestellt werden wird: der find-Befehl, da er zuerst ausgeführt werden muss. Die Lösung lautet also: UNIX-KURS [~] 42 > file `find ~ -type f -print`
175
KAPITEL
11
C-Shell und Tenex-C-Shell
Zuerst wird der find-Befehl innerhalb der Back Quotes abgearbeitet. Das Ergebnis – also die Liste der Dateinamen – wird dann als Parameterliste dem Kommando file übergeben. 2. Die Kommando-Substitution liefert die Ergebnisse wesentlich schneller. Dies liegt daran, dass sowohl der find- als auch der file-Befehl nur je einmal aufgerufen werden. Die Variante -exec hingegen startet für jeden gefundenen Dateinamen einen eigenen file-Prozess, der die eine Datei dann untersucht. Dieser mehrfache Aufruf ist u.a. deshalb wesentlich langsamer, weil file zur Erfüllung seiner Aufgabe die Datei /etc/magic einlesen muss. 3. Sie ahnen es schon: Wenn man so fragt, lautet die Antwort Ja ... Die Shell ist nur in der Lage, höchstens 255 Parameter oder 4.096 Zeichen an einen Befehl zu übergeben. Findet der find-Befehl in den Back Quotes zu viele oder zu lange Dateinamen, ist die Shell nicht mehr in der Lage, eine Kommandozeile für den Befehl zu erstellen. Die Folge ist eine Fehlermeldung: Arg list too long, Too many words oder Command too long. 4. Um den Umgang mit den diversen Quoting-Mechanismen zu üben, eignet sich das echo-Kommando hervorragend. Probieren Sie, raten Sie, vollziehen Sie nach und vor allem probieren Sie selbst. Nach ein paar Übungsrunden dürfte das Quoting seinen Schrecken verloren haben. Hier ein paar Beispiele für die C-Shell bzw. Tenex-C-Shell: Definieren Sie zwei Shell-Variablen: UNIX-KURS [~] 51 > setenv VORNAME Albert UNIX-KURS [~] 52 > setenv NACHNAME Nagel
Ohne das $-Zeichen werden die Variablennamen selbst ausgegeben: UNIX-KURS [~] 53 > echo VORNAME NACHNAME VORNAME NACHNAME
Double Quotes erhalten Leerzeichen: UNIX-KURS [~] 54 > echo "$VORNAME Albert Nagel UNIX-KURS [~] 55 > echo $VORNAME Albert Nagel
$NACHNAME" $NACHNAME
Single Quotes hingegen verhindern das Auswerten von Variablen: UNIX-KURS [~] 56 > echo '$VORNAME $VORNAME $NACHNAME
176
$NACHNAME'
Aufgaben Back Quotes dienen der Kommando-Substitution, das heißt, es wird ein Unix-Befehl ausgeführt: UNIX-KURS [~] 57 > echo pwd pwd UNIX-KURS [~] 58 > echo `pwd` /home/lutz
Im Gegensatz zu Double Quotes verhindern die Single Quotes die Kommando-Substitution: UNIX-KURS [~] 59 > echo "`pwd`" /home/unix UNIX-KURS [~] 60 > echo '`pwd`' ‘pwd‘
Sind Sie verwirrt? Nicht mehr lange: Üben Sie, machen Sie ein Quiz mit Ihren Kollegen und Freunden. 5. Die Syntax für Alias lautet: alias Alias-Name Kommando. Der Alias-Name soll dir lauten und das Kommando ls -la. Daher lautet die Lösung: UNIX-KURS [~] 61 > alias dir "ls -la"
An dieser Stelle sind die Anführungszeichen zwar nicht unbedingt notwendig, aber gewöhnen Sie sich lieber gleich an, das Kommando zu quoten. Von nun an wird – immer dann, wenn sie dir eintippen – von der Shell statt dir die Zeichenkette ls -la ausgewertet, allerdings nur in dieser einen Shell! Beenden Sie die Shell, so ist auch das Alias verloren, es sei denn, Sie tragen die Definition in der Datei ~/.tcshrc ein. 6. Eine solch komplexe Aufgabe zerlegen wir erst einmal in bekömmliche Häppchen: Suchen Sie alle Plain Files unterhalb Ihres Working Directorys: find . -type f -print
Die gefundenen Dateien sollen nun nach einer Zeichenkette – nehmen wir mal die Zeichenkette unix – durchsucht werden. Statt der Aktion -print müssen wir die Aktion -exec in den find-Befehl einbauen: find . -type f -exec grep -l "unix" {} \;
Sie erinnern sich: -exec und \; bilden ein Art Klammer und der Befehl innerhalb dieser Klammer wird für jede gefundene Datei ausgeführt. Der gefundene Dateiname wird dabei an der Stelle eingesetzt, wo die geschweiften Klammern {} stehen. Der Befehl innerhalb der Klammer lautet grep -l "unix" {}. Die Option -l sorgt dafür, dass der Name der Datei und nicht die Zeile, in der das Wort »unix« vorkommt, ausgegeben wird.
177
KAPITEL
11
C-Shell und Tenex-C-Shell
Definieren wir nun für diesen Befehl einen Alias: UNIX-KURS [~] 62 > alias suche " find . -type f -exec grep -l "unix" {} \;"
Bei Eingabe von suche wird im Working Directory – und in allen Unterverzeichnissen – nach Plain Files gesucht, die die Zeichenkette unix enthalten. Dies können wir noch universeller gestalten, wenn wir unix durch den Platzhalter für die Alias-Aufrufparameter \!* ersetzen. UNIX-KURS [~] 63 > alias suche " find . -type f -exec grep -l \!* {} \;"
Geben wir nun z.B. suche katze in der Shell ein, so wird das Wort katze für das \!* in der Alias-Definition eingesetzt. Die Shell würde also den Befehl find . -type f -exec grep -l katze {} \;
abarbeiten und damit alle Plain Files unterhalb des Working Directory finden, jede gefundene Datei nach der Zeichenkette katze durchsuchen und bei einem Treffer den Namen der Datei ausgeben. 7. Wechseln Sie – falls nötig – in Ihr Home Directory und rufen Sie mit more die Datei auf. UNIX-KURS [uebung_7] 64 > cd; more .tcshrc
Diese Datei wird von der Tenex-C-Shell zur Initialisierung verwendet und immer dann abgearbeitet, wenn Sie eine neue Tenex-C-Shell öffnen. Falls Sie mit einer C-Shell arbeiten, heißt die entsprechende Datei .cshrc. Schauen Sie sich die Datei in Ruhe an. In dieser Datei können Environmentvariablen wie z.B. PATH gesetzt sowie der Eingabe-Prompt definiert werden. Viele Benutzer richten sich in dieser Datei auch ihre persönlichen Alias-Namen ein. 8. Ausgaben, die normalerweise auf dem Bildschirm erscheinen, können durch das Zeichen > in eine Datei umgelenkt werden. Sollte schon eine Datei gleichen Namens existieren, wird diese gnadenlos überschrieben ... UNIX-KURS [uebung_7] 65 > echo "Das war die vorletzte Aufgabe" > res.txt
Schauen Sie sich den Inhalt der Datei res.txt mit dem Befehl cat oder more an. Möchten Sie die Ausgabe an einen Dateiinhalt anhängen und die existierende Datei nicht überschreiben, nutzen Sie zur Ausgabeumlenkung die Zeichen >>. UNIX-KURS [uebung_7] 66 > echo "Gleich Feierabend" >> res.txt
Schauen Sie sich den Inhalt der Datei res.txt erneut an.
178
Aufgaben 9. Wie Bildschirmausgaben in eine Datei umgelenkt werden, haben wir schon in Aufgabe 8 kennen gelernt. Will man wirklich alle Ausgaben auf dem Bildschirm verhindern, so muss man auch die eventuell auftretenden Fehlermeldungen in eine Datei umlenken. Schauen wir uns folgenden Befehl an: UNIX-KURS [~] 67 > find / -name core -print > ergebnis.txt
Dieser Befehl sucht ab dem Root-Verzeichnis (/) in allen existierenden Unterverzeichnissen nach Dateien mit dem Namen core. Die Pfade aller gefundenen Dateien werden dann in einer Datei namens ergebnis.txt abgespeichert. Setzen Sie diesen Befehl ruhig einmal so ab. Sie werden schnell merken, dass Sie trotz der Umlenkung eine Menge Ausgaben auf Ihrem Bildschirm erhalten: Da Sie bei der Suche alle Verzeichnisse absuchen wollen, bekommen Sie Fehlermeldungen für jedes Verzeichnis, für das Sie keine Zugriffsrechte haben. Und das dürften im Normalfall einige sein. Möchten Sie auch diese Fehlermeldungen vom Bildschirm in die Datei umlenken, so müssen Sie >& anstelle von > schreiben. Da diese Suche relativ lange dauern kann, empfiehlt es sich, das Kommando als Hintergrundprozess zu starten. Andernfalls erscheint Ihr Eingabe-Prompt erst dann wieder, wenn der Befehl komplett abgearbeitet ist. Um ein Kommando im Hintergrund ablaufen zu lassen, geben Sie am Ende der Eingabezeile ein Ampersand »&« ein: UNIX-KURS [~] 68 > find / -name core -print >& result.txt &
179
KAPITEL 12
Korn-Shell Die Korn-Shell (ksh) ist eine Weiterentwicklung der Bourne-Shell (sh), der Standard-Shell unter Unix. Die Korn-Shell bietet einiges mehr an Komfort, wenn auch nicht ganz so viel wie moderne Shells aus der GNU-FreewareFamilie, z.B. tcsh oder bash. Die Korn-Shell ist die Default-Shell auf Rechnern der Hersteller IBM und HP. Viele Funktionen der Korn-Shell sind vergleichbar mit denen der C-Shell oder gar der Tenex-C-Shell. Auch die Konzepte, wie diese Funktionen umgesetzt sind, unterscheiden sich oft nur in einigen wenigen, dafür aber oft sehr wichtigen Details von den Konzepten der beiden anderen Shells, die in diesem Buch vorgestellt werden. Aus diesem Grund gibt es in den nachfolgenden Abschnitten sicherlich einige Wiederholungen aus dem vorangegangenen Kapitel, aber auch viele entscheidende Unterschiede. Das wohl wichtigste neue Feature der Korn-Shell ist das Command Line Editing. Während bei der Bourne-Shell bereits abgesetzte Befehle nicht wiederholt werden können und bei der C-Shell nur ein sehr umständlicher HistoryMechanismus zur Verfügung steht, können unter der Korn-Shell vorherige Befehle erneut auf die Kommandozeile geholt, dort verändert und erneut abgesetzt werden. Die Korn-Shell bietet hierfür zwei Editiervarianten an: Die Kommandozeile kann entweder mit emacs oder mit vi-Befehlen1 bearbeitet werden. Neben ihrer Funktion als interaktiver Kommandointerpreter ist die Shell auch ein Interpreter der eigenen Programmiersprache. Diese Programmiersprache 1. emacs und vi sind die beiden am häufigsten benutzten Unix-Texteditoren.
181
KAPITEL
12
Korn-Shell
dient der Formulierung von Kommandoprozeduren, die unter Unix allgemein Shell-Scripts genannt werden. Die Scriptsprache der Korn-Shell ist bis auf einige Erweiterungen die gleiche wie die der Bourne-Shell.
12.1
Die Arbeitsweise der ksh
Ohne die Shell, den Kommandointerpreter, wären Unix-Benutzer ziemlich hilflos, und obwohl ich in den vorangegangenen Kapiteln immer nur von »der Shell« gesprochen habe, als gäbe es nur eine, bietet Unix auch hier wieder ein Beispiel für seine Flexibilität. Anders als bei den meisten bekannten Betriebssystemen kann der Benutzer unter Unix zwischen verschiedenen Kommandointerpretern wählen.1 Egal, ob Sie sich bei seiner Wahl für komfortable Public-Domain-Shells wie die bash oder tcsh entscheiden, die kommerziell bevorzugten ksh oder csh wählen oder als ewig Gestriger an der guten alten sh festhalten – jede dieser Alternativen hat eine Reihe von Features auf Lager, die Ihnen den Umgang mit dem Betriebssystem erleichtern können. Damit Sie nicht genau das Gegenteil erfahren, sollte Ihnen die Arbeitsweise der Shell bekannt sein. Einer der Mechanismen, den die Shell anbietet, sind die im Abschnitt über Dateiverwaltung vorgestellten Wildcards. Entgegen der Meinung vieler Anwender sorgen nämlich nicht die einzelnen Befehle für die richtige Handhabung dieser Sonderzeichen, sondern der Kommandointerpreter. Eigenen Programmen und Scripts wird der Mechanismus zur Behandlung von Wildcards dadurch auf einfache Art verfügbar gemacht. Dieses Vorgehen bringt aber auch Probleme mit sich. Werden bei der Auflösung von Wildcards zu viele (in der Regel sind das mehr als 256) Dateinamen von der Shell generiert, streikt diese mit der Fehlermeldung arg list too long. Ungewollte Effekte können auch eintreten, wenn Wildcards, die nicht für die Shell bestimmt sind, nicht entsprechend unter Verwendung des Escape Characters »\« oder über den Quoting-Mechanismus, über den jede Shell verfügt (Abschnitt 11.4) geschützt werden.
3
UNIX-Kurs [~] 106 > find / -name \*.tmp -print UNIX-Kurs [~] 107 > find / -name *.tmp -print (falsch)
1. Bei einigen Unix-Derivaten, wie z.B. dem IRIX von SGI, darf man sogar seine Default-Shell (die in der /etc/passwd eingetragen ist) umsetzen, wofür es normalerweise des Eingriffs eines Systemverwalters bedarf.
182
Die Arbeitsweise der ksh Das erste Kommando im Beispiel durchsucht den gesamten Dateibaum nach Dateien mit der Endung .tmp. Bei dem zweiten Kommando wird das Wildcard-Zeichen »*« bereits durch die Shell – und nicht durch das Kommando find – ausgewertet. Existierten z.B. im Working Directory genau zwei Dateien a.tmp und b.tmp mit der Endung .tmp, so setzt die Shell die Eingabe in das Kommando find / -name a.tmp b.tmp -print um. Da nach der Option -name nur ein Muster stehen darf, würde dieses Kommando also einen Syntaxfehler erzeugen. Wann muss nun ein Sonderzeichen durch den Escape Character geschützt werden? Merken Sie sich folgende Regel:
Soll das Sonderzeichen vor der Kommandoausführung interpretiert werden, braucht man es nicht zu schützen. Soll es erst während der Kommandoausführung interpretiert werden (also durch das Kommando selbst, wie bei dem Beispiel mit find), muss es geschützt werden.
1
Da die Shell als Kommandointerpreter des Unix-Betriebssystems im Gegensatz zu den Interpretern anderer Systeme den Großteil ihrer Funktionalität nicht über eingebaute Befehle umsetzt, muss sie zur Ausführung eines Kommandos zuerst ermitteln, wo das entsprechende auszuführende Programm steht. Damit hier nicht ganze Dateibäume durchsucht werden müssen, verfügen alle Shells über das Konzept des Suchpfads für Kommandos. Über den Suchpfad erfährt die Shell, in welchen Verzeichnissen sie nach den entsprechenden Programmen suchen soll. Erst das richtige Setzen dieses Pfades (durch Setzen der Environmentvariablen PATH) ermöglicht ein Arbeiten mit den Unix-Kommandos.
UNIX-Kurs [~] 108 > echo $PATH /bin:/sbin:/usr/bin:/usr/sbin:/usr/bin/X11:/etc:.
3
Die Verzeichnisse werden genau in der Reihenfolge, wie sie in der Variablen PATH – von links nach rechts – stehen, nach einer ausführbaren Datei mit dem Namen des gesuchten Kommandos durchsucht. Die Suche ist beendet, sobald eine solche Datei gefunden wird oder alle Verzeichnisse im Suchpfad durchsucht wurden. Um das Verhalten eines Programms zu beeinflussen, gibt es neben den Kommandozeilenparametern noch den Mechanismus der Environmentvariablen. Jedes unter Unix gestartete Programm bekommt eine Kopie des Satzes an Environmentvariablen, der zum Startzeitpunkt für das aufrufende Programm definiert war, als »Beigabe«. Die Shell bietet Möglichkeiten, diese
183
KAPITEL
12
Korn-Shell
Variablen zu setzen und ihre Werte abzurufen. In der Eingabezeile substituiert die Shell den Variablennamen durch den Wert der Variablen, sobald ein Dollarzeichen »$« vor den Variablennamen geschrieben wird. So enthält z.B. die Variable HOME den absoluten Pfad des Home Directorys des Benutzers. Die Eingabe von cd $HOME bewirkt daher den Wechsel in das Home Directory. Neben der Ausgabe der Ergebnisse von Kommandos auf den Bildschirm bietet jede Shell auch eine Möglichkeit, die Ausgaben in eine Datei umzulenken. Leider hat sich auch hier keine einheitliche Syntax durchgesetzt, was die Nutzung dieses Mechanismus abhängig von der verwendeten Shell macht. Moderne Shells wie ksh, csh und tcsh erlauben es dem Benutzer, Kürzel für häufig benutzte Befehlsfolgen zu definieren. Diese Kürzel oder Aliase werden von der Shell durch die dahinter verborgenen Befehlsfolgen ersetzt. Eine der beliebtesten Abkürzungen ist ll für den häufig verwendeten Befehl ls -l. Falls Sie sehr an das DOS-Betriebssystem gewöhnt sind, wollen Sie vielleicht auch das Kommando ls über den Alias dir ansprechen. Während die csh und die tcsh mit dem Alias nur ein Konzept zur Abkürzung häufig benutzter Befehlsfolgen kennen, bietet die Korn-Shell einen weiteren, sehr flexiblen, Mechanismus an – die Functions. Eine Function ist ein Alias, bei dem die Kommandozeilenparameter wie in einem Shell-Script einzeln angesprochen werden können. Solche Functions werden in den Startup-Dateien der Korn-Shell vereinbart.
12.2
Environmentvariablen
Ein wichtiger Mechanismus zur Übergabe von Parametern an Programme ist neben den Kommandozeilenparametern die Nutzung der Environmentvariablen. Jeder Prozess, der unter Unix läuft, wird mit Ausnahme des Schedulers von einem anderen Prozess gestartet. Bei diesem Startvorgang wird dem Prozess eine Kopie des Environments des aufrufenden Prozesses mitgegeben. Zu diesem Environment gehören neben dem Pfad des Working Directorys auch ein Satz von Variablen: die Environmentvariablen. Diese Variablen haben unterschiedliche Funktionen und Aufgaben. Einige haben rein informativen Charakter (wie z.B. PWD, die den Pfad des Working Directorys beinhaltet), andere wirken steuernd (wie z.B. DISPLAY, die festlegt, welche Maschine die Ausgabe eines X-Programms anzeigt) und wieder andere ermöglichen das Ausführen von Programmen (PATH enthält die Suchpfade für Programme). Der Benutzer kann sich das Environment durch entsprechende Befehle anzeigen lassen und es verändern.
184
Environmentvariablen
12.2.1
env
Das Kommando env gibt die Namen aller Environmentvariablen, die zur Zeit definiert sind, und deren aktuelle Werte aus.
12.2.2
export
Das interne Shell-Kommando export setzt eine Variable auf einen neuen Wert und exportiert sie dann in das Environment. War die Variable bereits definiert, wird ihr Wert mit dem neuen Wert überschrieben. War sie noch nicht definiert, wird sie in das Environment eingefügt und mit dem neuen Wert belegt. Das führende Dollarzeichen ist nur bei der Ausgabe des Inhalts einer Variablen anzugeben, nicht aber bei ihrer Definition.
export Variablenname=Wert
UNIX-Kurs [~] 109 > export DISPLAY=:0.0 UNIX-Kurs [~] 110 > echo $DISPLAY :0.0
6 3
In diesem Beispiel wird die Environmentvariable DISPLAY, die angibt, auf welchem Display die Ausgaben von X11-Programmen erscheinen sollen, auf den Bildschirm der lokalen Maschine (:0.0 gelesen als X-Server 0 Screen 0) gesetzt. Anschließend wird mit echo überprüft, ob das Setzen erfolgreich war. Allerdings kann das Belegen einer Variablen mit einem Wert und das Exportieren der Variablen in das Environment auch in zwei Schritten erfolgen.
UNIX-Kurs [~] 111 > DISPLAY=:0.0 UNIX-Kurs [~] 112 > export DISPLAY UNIX-Kurs [~] 113 > echo $DISPLAY :0.0
12.2.3
3
unset
Um definierte Environmentvariablen wieder zu löschen, wird das Kommando unset benutzt.
185
KAPITEL
6 3
12
Korn-Shell
unset Variablenname
UNIX-Kurs [~] 114 > unset DISPLAY
Durch diesen Befehl wird das Setzen der Environmentvariablen DISPLAY wieder rückgängig gemacht.
12.3
Shell-Variablen
Neben den Environmentvariablen verfügen die meisten Shells auch noch über so genannte Shell-Variablen. Diese werden für drei Zwecke benutzt: ✘ zur Abbildung von Environmentvariablen in die für die Shell spezifische Darstellung; ✘ zur Steuerung des Verhaltens der Shell; ✘ in Shell-Scripts zum Zwischenspeichern von Ergebnissen. Auch die ksh verfügt über solche Shell-Variablen. Im Gegensatz zu anderen Shells werden bei der Korn-Shell die Shell-Variablen aber fast ausschließlich in Korn-Shell-Scripts eingesetzt. Um eine Shell-Variable zu definieren, muss folgende Zuweisung angegeben werden:
6
Variablenname=Wert
12.4
Quoting
Für große Verwirrung bei Unix-Einsteigern sorgen immer wieder die unterschiedlichen Anführungszeichen, die bei der Eingabe einiger Unix-Kommandos nötig sind. Dieses Thema ist schon an der einen oder anderen Stelle angeschnitten worden, ohne allerdings den gesamten Umfang der Möglichkeiten und Aufgaben der Quotes offenzulegen. Nachdem nun die wichtigsten Unix-Kommandos ausführlich erläutert worden sind, ist es an der Zeit, die Quotes in einem eigenen Abschnitt genau unter die Lupe zu nehmen. Auch dieser Abschnitt ähnelt stark dem entsprechenden Kapitel über csh und tcsh, da das Quoting in allen Shells gleich funktioniert. Aufgabe der Quotes ist es
186
Quoting generell, Teile der Kommandozeile zusammenzufassen. Unix verwendet für diese Aufgabe drei unterschiedliche Arten von Quotes: ✘ Double Quotes (doppelte Anführungszeichen1) "" ✘ Single Quotes (einfache Anführungszeichen2) '' ✘ Back Quotes (rückwärts gerichtete einfache Anführungszeichen3) `` Double Quotes haben zwei Aufgaben. Mithilfe von Double Quotes können Zeichenketten, die Leerzeichen enthalten, zu einem Kommandozeilenparameter zusammengefasst werden. Dies wird immer dann notwendig, wenn eine Zeichenkette, die Leerzeichen enthält, an ein Kommando übergeben werden soll, z.B. als Suchmuster. Das Leerzeichen verliert dann seine Funktion als Trennzeichen von Kommandozeilenparametern. Des Weiteren verlieren innerhalb von Double Quotes die Wildcards wie »*«, »~« und »[]« ihre Sonderbedeutung. Allerdings gibt es auch Zeichen, die von den Double Quotes nicht von ihrer Sonderfunktion befreit werden. So werden Variablen wie $HOME nach wie vor durch ihren Inhalt ersetzt und Kommandos in Back Quotes durch ihre Ausgaben substituiert. Single Quotes sind eine verschärfte Form der Double Quotes. Sie haben genau die gleichen Aufgaben, aber innerhalb von Single Quotes werden keine Variablen mehr ersetzt und auch die Kommmando-Substitution wird nicht mehr durchgeführt. Zwischen den Back Quotes steht immer ein vollständiges Unix-Kommando. Dieses Kommando wird von der Shell ausgeführt, bevor die restliche Kommandozeile interpretiert wird. Die Ausgabe, die das in Back Quotes eingeschlossene Kommando erzeugt, wird an der Stelle in die Kommandozeile eingefügt, an der die Back Quotes stehen. Sinn dieser Quotes ist es, UnixKommandos miteinander zu verknüpfen.
UNIX-Kurs [~] 115 > ls -l `fgrep -l Meier *.c`
Bei diesem Beispiel haben wir zwei Unix-Befehle auf der Kommandozeile. ls -l erzeugt ein Listing mit allen Attributen der angegebenen Dateien. fgrep -l Meier *.c listet alle Dateien mit der Endung .c auf, in deren Inhalt die Zei-
3
1. Es muss das ASCII-Zeichen »Double Quote« verwendet werden, also nicht die in der Textverarbeitung üblichen typografischen englischen oder deutschen Anführungszeichen. 2. Es muss das Apostroph-Zeichen verwendet werden, nicht der Acute-Akzent und auch nicht das typografische Anführungszeichen. 3. Auf europäischen Tastaturen gibt es meist keine eigene Taste, sondern man muss zuerst den Gravis-Akzent und dann die Leertaste drücken, um dieses ASCII-Zeichen zu erhalten.
187
KAPITEL
12
Korn-Shell
chenkette Meier vorkommt. Da das Kommando fgrep mit seinen Parametern in Back Quotes steht, wird es zuerst ausgeführt. Die Namen der Dateien, die es als Ergebnis liefert, werden in der Kommandozeile hinter das ls -l geschrieben. So werden die beiden Befehle zu dem neuen Befehl kombiniert: »Liste alle Attribute jener Dateien mit der Endung .c auf, welche die Zeichenkette Meier enthalten.« Diese Variante des Einsatzes von Quotes heißt Kommando-Substitution.
12.5
Alias-Namen
Die Korn-Shell bietet durch den Alias-Mechanismus ein einfaches Hilfsmittel an, um häufig eingegebene Befehlsfolgen über einen Kurznamen auszuführen. Der Alias-Mechanismus der Korn-Shell ist eine einfache Textersetzung und soll in erster Linie Tipparbeit sparen helfen. Das Belegen aller Buchstaben der Tastatur mit neuen Funktionen ist allerdings nicht die Intention des Alias-Mechanismus. Durch diese zusätzliche Verkürzung der ohnehin schon kurzen Unix-Befehlsnamen würde jeglicher Zusammenhang zwischen Benennung und Funktion eines Kommandos zerstört. Ein solches Vorgehen muss über kurz oder lang zu folgenschweren Fehlbedienungen führen.
12.5.1
alias
Alias-Namen werden mit dem shellinternen Kommando alias definiert.
6
alias Alias-Name Kommando
Wird alias ohne Parameter aufgerufen, listet es alle definierten Alias-Namen auf. Wird ein Kommando abgesetzt, das als Alias definiert ist, so wird dieses von der Shell bei der Alias-Substitution durch den Wert des Alias ersetzt.
3
UNIX-Kurs [~] 116 > alias ll="ls -la" UNIX-Kurs [~] 117 > ll a*
Im Beispiel wird der Alias ll textuell durch seine Definition (ls -la) ersetzt und die so entstandene neue Kommandozeile (ls -la a*) durch die Shell ausgeführt.
188
Alias-Namen
12.5.2
Umplatzieren der Parameterliste
Nicht bei allen denkbaren Abkürzungen durch Alias-Namen wäre eine solche reine textuelle Ersetzung erfolgreich. Häufig muss die Parameterliste, die nach einem Alias-Namen beim Aufruf steht, in den Befehl eingefügt werden, um eine sinnvolle Ersetzung zu ergeben. Das ist häufig bei Alias-Namen für find-Kommandos oder bei Kommandoverkettungen über Pipes der Fall. Während der Alias-Mechanismus der csh und der tcsh eine Möglichkeit zur Umplatzierung der Parameterliste anbietet, muss der Benutzer der Korn-Shell auf ein anderes Konzept, nämlich das der Functions, zurückgreifen, vgl. Abschnitt 12.6.
12.5.3
Permanente Alias-Namen
Wurde ein Alias interaktiv in der Shell definiert, ist er nur auf dieser einen Shell verfügbar und verschwindet, sobald die Shell beendet wird. Dies kann verhindert werden, indem solche Alias-Namen, die in jeder Shell verfügbar sein sollen, in die Startup-Datei .profile oder – sofern vorhanden – in die Datei .kshrc der ksh eingetragen werden. Die Definition erfolgt hier ebenso wie auf der Kommandozeile.
12.5.4
unalias
Soll ein Alias gelöscht werden, so geschieht dies mit dem Kommando unalias.
unalias Alias-Name
UNIX-Kurs [~] 118 > unalias ll UNIX-Kurs [~] 119 > ll ll - Command not found
6 3
Das Löschen eines Alias-Namens hat in der Regel zur Folge, dass das entsprechende Kommando nicht mehr von der Shell gefunden wird.
Aber Vorsicht: Unter Umständen kann an die Stelle des Alias jetzt ein Kommando aus dem Suchpfad treten, das durch den Alias überdefiniert worden war.
2 189
KAPITEL
12
Korn-Shell
Was man alles mit dem alias-Kommando der Korn-Shell machen kann, soll das folgende Beispiel zeigen, welches von einer Sun Solaris-Maschine stammt.
3
UNIX-Kurs [~] 120 > cat .kshrc ...... export VISUAL=emacs alias __A=‘echo "\020"‘ alias __B=‘echo "\015"‘ alias __C=‘echo "\006"‘ alias __D=‘echo "\002"‘ alias __P=‘echo "\004"‘ alias __H=‘echo "\001"‘ ...... rm -f $HOME/.sh_history
In der Datei .kshrc werden permanente Alias-Namen für die Korn-Shell definiert. Der hier gezeigte Ausschnitt aus einer solchen Datei macht sich zunutze, dass man auch Alias-Namen definieren darf, die nicht druckbare Zeichen enthalten. In unserem Beispiel werden hier Alias-Namen für die Zeichenfolgen, die von den Cursortasten gesendet werden, definiert. So sendet z.B. die |-Taste einen Tastaturcode, der auf den Alias __A zutrifft. Als Wert für den Alias wird die Ausgabe von der Kommando-Substitution ‘echo "\020"‘ definiert. Dieses echo-Kommando gibt ein Control-P (ŸP) aus (\020 ist die oktale Repräsentation für Control-P). Das heißt, jedesmal wenn die |-Taste gedrückt wird, wird durch den Alias ein Control-P an die Shell gesandt. Wozu das Ganze? Das Commandline Editing der Korn-Shell funktioniert entweder mit den Positionierungskommandos für den vi (die Environmentvariable VISUAL hat den Wert vi) oder mit denen für den emacs (die Environmentvariable VISUAL hat den Wert emacs). Diese beiden Editoren der Unix-Welt benutzen zur Positionierung nicht die Cursortasten, sondern bestimmte Tastenfolgen. So muss man z.B. ŸP eingeben, um den Cursor im emacs um eine Zeile nach oben zu positionieren. Da diese Positionierungskommandos nur schwer zu merken sind und man als Benutzer einfach mit den Cursortasten in der Kommandozeile arbeiten will, kann man durch derartige Alias-Definitionen die Cursortasten auf die Positionierungskommandos des verwendeten Kommandozeileneditors abbilden. Damit ist jetzt das Editieren der Eingaben mithilfe der Cursortasten möglich. Wenn wir schon mal bei den netten kleinen Tricks im Umgang mit dem Commandline Editing der Korn-Shell sind, sollte auf jeden Fall der folgende Trick nicht unerwähnt bleiben. Die Command History – also die Liste der bereits
190
Functions abgesetzten Kommandos – wird unter der Korn-Shell in einer Datei abgelegt. Diese Datei trägt den Namen .sh_history und liegt im Home Directory des Benutzers. Leider werden die Kommandos aus allen laufenden Shells des Benutzers in dieser Datei gespeichert, sofern sie existiert. Das Resultat ist, dass in der Command History aus dem Fenster A auch Befehle auftauchen, die im Fenster B abgesetzt worden sind und umgekehrt. Um dieses zu verhindern, kann der Benutzer in seiner Datei .kshrc einfach die beim Start der Shell angelegte Datei .sh_history löschen (rm -f $HOME/ .sh_history). Als Folge hat nun jedes Fenster seine eigene Command History, welche Befehle auch nur aus diesem Fenster enthält.
12.6
Functions
Wer mit einer höheren Programmiersprache vertraut ist, wird mit einer Funktion eine feste Assoziation verbinden, die allerdings auf den ersten Blick nicht so gut in das Konzept eines interaktiven Kommandointerpreters zu passen scheint. Functions haben ihren Ursprung in der Erstellung von Shell-Scripts. Während sich bei der csh und tcsh Shell-Scripts nur durch die Ablaufstrukturen (if, for, while, ...) strukturieren lassen, bietet die Korn-Shell die Möglichkeit, Teile eines Scripts, die sich wiederholen bzw. wiederholt aufgerufen werden, in Form einer Function zusammenzufassen. Eine solche Function kann wie ein Unterprogramm in einer Programmiersprache aufgerufen werden und einen Resultatwert zurückliefern. Im Gegensatz zu einem Unterprogramm in einer Programmiersprache haben Functions keine feste Parameterliste, können also theoretisch mit beliebig vielen Parametern aufgerufen werden. Die Aufrufparameter werden in den Variablen $1 bis $n abgelegt und können einzeln angesprochen werden. Somit ist die Function im Prinzip nichts anderes als ein Script im Script. Ist eine Function einmal definiert, wird sie von der Shell wie ein anderes UnixKommando auch behandelt. Das heißt, bevor die Function aufgerufen wird, wird die Parameterliste nach Metazeichen durchsucht und gegebenenfalls expandiert. Mit einer Function kann also im Prinzip das Gleiche erreicht werden wie mit einem Script. An dieser Stelle kommt nun die Bedeutung von Functions für interaktive Shells zum Tragen. Nicht für jede kleine sich wiederholende Aufgabe, die sich durch drei, vier Unix-Kommandos erledigen lässt, möchte man gleich ein Shell-Script schreiben. Also schreibt man eine Function, die man in einer der Startup-Dateien der Korn-Shell definiert. Wird eine neue Korn-Shell gestartet, werden diese Dateien durchlaufen und die Function in der interaktiven Shell definiert. Nun kann die Function wie ein anderes Unix-Kommando auch auf der Kommandozeile dieser Shell aufgerufen werden.
191
KAPITEL
12
Korn-Shell
Da das Erstellen von Functions sehr viel mit der Programmierung von ShellScripts gemeinsam hat und an dieser Stelle kein Vorgriff auf den entsprechenden Abschnitt erfolgen soll, wird hier nur ein sehr einfaches Beispiel für eine Function gezeigt.
3
UNIX-Kurs [~] 121 > cat .kshrc .... function ff { find / -name "$1" -print } .... UNIX-Kurs [~] 122 > ff "*.txt"
Die Function ff steht für ein find-Kommando, das Dateien im gesamten Unix-Dateibaum sucht. Ohne die Function müsste unser Kommando für den Anwendungsfall in der zweiten Beispielzeile wie folgt lauten: find / -name "*.txt" -print
Dieses Kommando durchsucht den gesamten Dateibaum vom Root-Directory (/) an nach Dateien mit der Endung .txt und gibt alle Treffer mit absolutem Pfad aus. Das Suchkriterium lautet »*.txt« und muss zwischen dem -name und dem -print stehen, also zwischen zwei Bestandteilen des Kommandos, die eigentlich in der Function verankert sind. An dieser Stelle reicht eine simple Textersetzung wie beim Alias-Konzept der Korn-Shell nicht mehr aus, weil Text in die Parameterliste (»*.txt«) des Kommandos eingefügt werden muss. Als Platzhalter für diesen Text, der als Parameter an die Function übergeben wird, wird die Variable $1 benutzt, die den ersten Kommandozeilenparameter vom Aufruf der Function beinhaltet.
12.7
Die Datei .profile
Die Datei .profile ist die Startup-Datei der ksh und auch der sh. Bei Shells unter Unix wird zwischen den so genannten Login-Shells und den »normalen« interaktiven Shells, die z.B. aus einer anderen Shell heraus gestartet werden, unterschieden. Der Name der Login-Shell ist in der /etc/passwd eingetragen. Diese Shell wird als erste beim Einloggen gestartet. Wird eine ksh oder sh als Login-Shell gestartet, sucht sie im Home Directory des Benutzers nach einer Datei .profile. Ist diese vorhanden (Ausführungsrechte müssen nicht gesetzt sein), wird der Inhalt der Datei Zeile für Zeile ausgeführt. Die Datei .profile wird verwendet, um Terminal-Charakteristika für die gerade gestartete Shell einzustellen (z.B. Definition der Taste, mit der auf
192
Ein-/Ausgabeumlenkung der Kommandozeile gelöscht wird). Im Zusammenhang mit der Korn-Shell wird in der Regel über die Environmentvariable ENV in der Datei .profile der Name einer weiteren Datei vereinbart. Diese Datei wird von der Korn-Shell ebenfalls zu Initialisierungszwecken ausgewertet. Im Gegensatz zu der Datei .profile, welche nur von Login-Shells gelesen wird, wird die über die Environmentvariable ENV vereinbarte Datei von jeder Korn-Shell ausgewertet. In dieser Datei sollten deshalb Definitionen von Alias-Namen und Functions vorgenommen werden. In der Regel heißt diese Datei .kshrc, wie auch auf den vorangegangenen Seiten vorausgesetzt wurde, als es um die Definition von Alias-Namen ging.
12.8
Ein-/Ausgabeumlenkung
Obwohl auf jeder Shell verfügbar, ist das Feature der Ein-/Ausgabeumlenkung shellspezifisch. Das liegt daran, dass zwei unterschiedliche Konzepte verfolgt werden: 1. das Konzept der sh, der ksh und der bash 2. und das der csh und der tcsh. Das Konzept der csh ist nicht so flexibel wie das der sh und kann nur einen Überschreibschutz als Plus verbuchen, über den allerdings die Korn-Shell auch verfügt. Doch bevor in die Details eingestiegen werden kann, muss zunächst einmal das Grundkonzept erläutert werden. Die Grundidee der Ein-/Ausgabe unter Unix ist die Verwendung spezieller Kanäle. Diese Kanäle sind verbunden mit Geräten, die wiederum durch Dateien – die Device Descriptors – repräsentiert werden. Da die Schnittstelle für den Zugriff auf Geräte identisch mit der für den Zugriff auf Dateien ist (gemäß dem Grundprinzip der Geräteunabhängigkeit), liegt nichts näher, als die vordefinierten Kanäle umzulenken, wenn z.B. Ausgaben nicht auf den Bildschirm, sondern in eine Datei geschrieben werden sollen. Genau das macht die Ein/Ausgabeumlenkung. Drei Standardkanäle sind vordefiniert und können umgelenkt werden. Die drei Standardkanäle können über ihre »Kanalnummern« – die so genannten Dateideskriptoren – angesprochen werden. Die Standardeingabe ist per Default mit der Tastatur verbunden. Liest ein Kommando von der Standardeingabe, liest es normalerweise von der Tastatur. Der Dateideskriptor für die Standardeingabe ist die 0. Die Standardausgabe ist mit dem Bildschirm verbunden. Alle Ausgaben, die ein Kommando tätigt und welche die Ergebnisse einer fehlerfreien Befehlsausführung sind, werden über die Standardausgabe ausgegeben. Der Dateideskriptor für die Standardausgabe ist die 1.
193
KAPITEL
12
Korn-Shell
Die Standardfehlerausgabe ist wie die Standardausgabe ebenfalls mit dem Bildschirm verbunden. Über diesen Kanal werden in der Regel alle Fehlermeldungen von Befehlen auf den Bildschirm geschrieben. Die Existenz dieses Fehlerkanals wird in der Regel vom Benutzer zunächst nicht erkannt, da die Fehlermeldungen wie auch die regulären Ausgaben auf dem Bildschirm erscheinen. Der Dateideskriptor für die Standardfehlerausgabe ist die 2.
12.8.1
Eingabeumlenkung
Bei der Eingabeumlenkung werden die Eingaben für einen Befehl in einer Datei vorbereitet. Würde der Befehl von der Tastatur lesen, würde das Ende der Eingaben an der Übermittlung eines ŸD (ASCII-Wert 4) erkannt, das unter Unix mit dem Dateiendezeichen identisch ist. Bei der Eingabeumlenkung sorgt das Ende der Datei somit dafür, dass der Befehl keine weiteren Eingaben erwartet.
6 3
Unix-Kommando < Eingabedatei
Bei der Angabe der Eingabedatei dürfen keine Wildcards benutzt werden, da die Umlenkung von der Shell vor der Interpretation der Wildcards aus der Kommandozeile gefiltert wird. Die Eingabe kann nur einmal pro Befehl umgelenkt werden.
UNIX-Kurs [~] 123 > mail
[email protected] < brief
Ein klassisches Beispiel für die Verwendung der Eingabeumlenkung ist der mail-Befehl, mit dem elektronische Post auf der lokalen Maschine, aber auch in die weite Welt verschickt werden kann. In unserem Beispiel wurde der Text für die E-Mail in der Datei brief vorbereitet (z.B. mit einem Texteditor) und wird nun dem Kommando mail per Eingabeumlenkung zur Verfügung gestellt.
12.8.2
Ausgabeumlenkung
Bei der Ausgabeumlenkung werden die Ergebnisse einer fehlerfreien Befehlsausführung in eine Datei geschrieben. Dabei kann eine Datei entweder neu angelegt oder überschrieben werden:
6 194
Unix-Kommando > Ausgabedatei
Ein-/Ausgabeumlenkung oder es können die Ausgaben an eine bereits bestehende Datei angehängt werden (append):
Unix-Kommando >> Ausgabedatei
Beide Varianten bergen ein gewisses Risiko in sich. Die Shell prüft nämlich nicht, was zuvor in der Umlenkungsdatei stand, d.h. es kann mit der Ausgabeumlenkung durchaus Text an eine Binärdatei angehängt bzw. ein Programm oder eine andere wichtige Datei per Ausgabeumlenkung überschrieben werden. Sollen Ausgaben an eine noch nicht bestehende Datei angehängt werden, wird diese von der Shell angelegt.
6
Alle drei aufgezählten Verhaltensformen sind im Allgemeinen nicht erwünscht. Allerdings lässt sich nur gegen zwei davon etwas tun: gegen ungewolltes Überschreiben und gegen ungewolltes Anlegen einer Datei beim append. Erreicht wird dieser Schutz durch das Setzen der Schreibschutzvariable der ksh. Diese heißt noclobber und verhindert genau diese beiden Fälle.
UNIX-Kurs [~] 124 UNIX-Kurs [~] 125 UNIX-Kurs [~] 126 verzeichnis.txt -
> ls -l >verzeichnis.txt > noclobber= > ls -l >verzeichnis.txt File exists
3
Stellt die Shell bei gesetztem noclobber fest, dass eine der beiden Schutzvorschriften verletzt ist, sorgt sie dafür, dass das Kommando nicht ausgeführt wird – also unterbleibt nicht nur die Umlenkung, sondern der ganze Befehl wird nicht ausgeführt!
12.8.3
Ausgabeumlenkung mit Fehlerkanal
Bisher wurde nur die Umlenkung der Standardeingabe und -ausgabe beschrieben, was auch die beiden häufigsten Anwendungsfälle sind. Aus diesem Grund spielen auch die bereits erwähnten Dateideskriptoren noch keine Rolle, da die beiden Varianten auch ohne zusätzliche Kanalkennungen an der Richtung des Umlenkungsymbols zu erkennen sind. Wenn allerdings Gebrauch von der Ausgabeumlenkung gemacht wird, kann festgestellt werden, dass ab und zu dennoch Ausgaben auf dem Bildschirm erscheinen, obwohl die Ausgabe in eine Ausgabedatei umgelenkt ist. Dabei handelt es sich um solche Meldungen, die über die Standardfehlerausgabe auf den Bildschirm gelangen. Soll dies unterbunden werden, kann unter der ksh die Standardfehler-
195
KAPITEL
12
Korn-Shell
ausgabe entweder getrennt in eine Fehlerdatei ausgegeben werden oder Standardausgabe und Standardfehlerausgabe werden gemeinsam in eine Datei umgelenkt. Auch hier gibt es wieder die Varianten des Überschreibens bzw. Anlegens:
6
Unix-Kommando >Ausgabedatei 2>Fehlerdatei Unix-Kommando >Ausgabedatei 2>&1
und die des Anhängens:
6 3
Unix-Kommando >>Ausgabedatei 2>>Fehlerdatei Unix-Kommando >>Ausgabedatei 2>&1
UNIX-Kurs [~] 127 > find / -name .kshrc -print >rcs.txt 2>&1
In diesem Beispiel wird der gesamte Dateibaum des Unix-Betriebssystems nach Dateien mit dem Namen .kshrc durchsucht. Das Ergebnis dieser Suche wird in die Datei rcs.txt im Working Directory geschrieben. Da find Fehlermeldungen produziert, wenn es auf Verzeichnisse stößt, für die der Benutzer kein Ausführungsrecht oder Leserecht besitzt (mit solchen Verzeichnissen ist bei der Durchsuchung des kompletten Dateibaums zu rechnen), werden Standard- und Standardfehlerausgabekanal umgelenkt. Die Korn-Shell bietet im Gegensatz zur csh und tcsh allerdings auch die Möglichkeit, nur die Standardfehlerausgabe (Dateideskriptor 2) umzulenken. Auch hier kann ein Beispiel am besten zeigen, wie das funktioniert.
3
UNIX-Kurs [~] 128 > find / -name .kshrc -print 2>/dev/null
In diesem Beispiel werden die Fehlerausgaben, die der find-Befehl produziert, wenn er in bestimmte Verzeichnisse nicht wechseln darf, einfach auf das NULL-Device umgelenkt. Alles was auf dieses Device umgelenkt wird, wird einfach weggeschmissen. Es erscheinen also nur die gültigen Suchergebnisse des find-Kommandos auf dem Bildschirm.
196
Subshells
12.9
Subshells
Wie auch die csh und die tcsh ist die Korn-Shell in der Lage, Kommandos oder Kommandofolgen in einer eigenen so genannten Subshell zu starten. Diese Umhüllung durch eine Shell führt dazu, dass z.B. die Ausgaben der Kommandofolge zusammengefasst werden und dann entweder mit der Ein-/ Ausgabeumlenkung gemeinsam behandelt oder per Pipe an ein Filterkommando weitergeleitet werden können. Eine Subshell wird dann für ein Kommando oder eine Kommandofolge gestartet, wenn sie durch runde Klammern eingeschlossen wird. Die Syntax ist dabei identisch mit der in der csh und tcsh.
(Kommando1;Kommando2;...)
Im Gegensatz zur csh und tcsh, wo die Subshell oft Verwendung findet, um die in diesen Shells fehlende vollständige Trennung von Standardausgabeund Standardfehlerausgabeumlenkung zu kompensieren, ist dies in der KornShell nicht nötig. Wie im vorangegangenen Abschnitt beschrieben, lassen sich in der Korn-Shell Standardausgabe und Standardfehlerausgabe separat umlenken und bedürfen deshalb keiner Subshell für diese Aufgabe.
6
Dennoch gibt es auch in der Korn-Shell einige sinnvolle Anwendungsbeispiele für die Funktion der Subshell.
UNIX-Kurs [~] 129 > (cd /etc;echo "Inhalt /etc";ls) > dir.txt
Dieses Beispiel zeigt, wie die Ausgaben mehrerer Unix-Kommandos mit nur einer Ausgabeumlenkung in eine Datei geschrieben werden können. Die Verwendung des cd innerhalb der runden Klammern der Subshell führt dazu, dass das Working Directory der Subshell vor der Ausführung der beiden folgenden Befehle auf das Verzeichnis /etc gesetzt wird. Diese Änderung des Working Directorys hat keinen Einfluss auf das Working Directory der Shell, von der die Kommandofolge in den runden Klammern abgesetzt wird. Das Verhalten bei einer Änderung von Environmentvariablen innerhalb der runden Klammern wäre identisch – die Auswirkungen der Änderungen blieben auf die Subshell begrenzt und hätten keinen Einfluss auf die aufrufende Shell.
3
In dieser Hinsicht verhalten sich Subshells also genauso wie jene Shells, die zur Interpretation eines Shell-Scripts gestartet werden.
197
KAPITEL
12
Korn-Shell
12.10 Von der Eingabe eines Kommandos bis zur Ausführung Nachdem nun die vielen unterschiedlichen Aufgaben der Shell bei der Ausführung eines Kommandos besprochen worden sind, stellt sich nur noch die Frage nach der Reihenfolge, die ja unter Umständen ausschlaggebend für das Ergebnis des Kommandos sein kann. Die ksh arbeitet dabei nach den in Abbildung 12.1 dargestellten Schritten. Abb. 12.1: Arbeitsschritte der ksh
Nachdem die Kommandozeile eingegeben und mit Æ zur Ausführung freigegeben worden ist, wird von der Shell zuerst die Alias-Substitution vorgenommen. Bei dieser Ersetzung werden vom Benutzer definierte Kürzel (AliasNamen) durch die eigentliche Schreibweise der Befehle ersetzt. Anschließend wird die so veränderte Eingabezeile nach Ein-/Ausgabeumlenkungszeichen durchsucht. Mit diesem Feature können die Ausgaben eines Befehls vom Bildschirm in Dateien umgelenkt und die Eingaben eines Befehls statt von der Tastatur aus einer Datei gelesen werden. Nach der Interpretation der Ein-/Ausgabeumlenkung erfolgt die VariablenSubstitution. Bei dieser werden Zeichenketten der Form $xxx durch den Inhalt der entsprechenden Variablen ersetzt, wobei für xxx ein Variablenname aus dem Environment oder der Shell stehen kann.
198
Prozessverwaltung der Shell Als vorletzter Schritt werden die Wildcards in der Eingabezeile interpretiert. Die in der Kommandozeile enthaltenen Muster werden dabei – soweit möglich – durch passende Dateinamen ersetzt. Der letzte Schritt vor der Kommandoausführung ist die Zuordnung von Pfaden zu den Kommandos, die in der Kommandozeile stehen. Zu diesem Zweck wird der Suchpfad aus dem Environment benutzt. Kann eine Zuordnung zu einem Pfad vollzogen werden, wird das entsprechende Programm mit der in den vorherigen Schritten ermittelten Kommandozeile von der Shell gestartet.
12.11 Prozessverwaltung der Shell Als letztes Feature der Korn-Shell soll ihre erweiterte Prozessverwaltung vorgestellt werden. Grundsätzlich lassen sich auch wie unter den anderen Shells Vordergrund- und Hintergrundprozesse erzeugen. Die Kommandos ps und kill sind nach wie vor zur Anzeige und Beendigung von Prozessen verfügbar. Allerdings haben diese beiden Kommandos Schwächen, welche die Entwickler der ksh dazu bewogen haben, Erweiterungen einzuführen. Werden Kommandos sequentiell (verknüpft mit »;«) oder parallel (verknüpft mit »|«) verkettet, können oft nicht alle Prozesse gleichzeitig mit kill beendet werden. Insbesondere die sequentielle Verkettung bereitet hier Probleme, weil für die noch nicht gestarteten Prozesse keine PIDs bekannt sind. Um diesem Problem beizukommen, werden unter der ksh verkettete Kommandos über eine extra zu diesem Zweck gestartete Shell verwaltet. Diese Shell bildet den Vaterprozess für alle Kommandos. »Stirbt« diese Shell, »sterben« auch alle Kommandos der Verkettung mit ihr. Durch diesen Trick muss nur ein Prozess kontrolliert werden, der mit Sicherheit über eine PID verfügt. Einen Einzelprozess oder eine mehrere Kommandos kontrollierende Shell wird unter der ksh als Job bezeichnet. Da aber die PIDs auf Systemen mit vielen Prozessen mit ps nur recht umständlich zu ermitteln sind, wurden die Job-IDs eingeführt. Jeder Job, der gestartet wird, bekommt eine eindeutige Job-ID von der Shell zugeteilt, egal ob es sich um ein Einzelkommando oder um eine Verkettung mit kontrollierender Shell handelt.
12.11.1 jobs Mit dem internen Kommando jobs der Korn-Shell können alle von dieser Shell aus gestarteten Hintergrundprozesse mit ihren Job-IDs aufgelistet werden. Angezeigt werden die Kommandozeile, mit der der Befehl gestartet wurde, und der Zustand, in dem er sich gerade befindet.
199
KAPITEL
12
Korn-Shell
Soll nun ein Job beendet werden, so kann dies über das kill-Kommando und die zugehörige Job-ID mit einem vorangestellten Prozentzeichen »%« geschehen.
3
UNIX-Kurs [~] 130 > kill %1
In diesem Beispiel wird dem Job mit der Job-ID 1 durch kill das Signal SIGTERM zugestellt. Die ksh bietet aber noch mehr in Sachen Job Control. So lassen sich z.B. gerade laufende Vordergrundprozesse mit ŸZ stoppen, um sie später fortzusetzen.
12.11.2 bg background – Die Fortsetzung kann mit dem Kommando bg als Hintergrundprozess erfolgen. Diese Variante wird häufig benutzt, wenn Rechenprozesse zu Beginn ihrer Arbeit interaktiv vom Benutzer Angaben abfragen, um dann minuten- oder gar stundenlang vor sich hinzurechnen. Ein solcher Prozess wird als Vordergrundprozess gestartet, dann werden interaktiv die gewünschten Angaben gemacht und der Prozess wird gestoppt und im Hintergrund fortgeführt. Als Ergebnis des Kommandoaufrufs werden die Job-ID in eckigen Klammern und die PID ausgegeben. bg kann auch als zusätzlichen Parameter eine Job-ID erhalten, wenn mehr als ein Job gestoppt wurde. Diese ist dann mit vorangestelltem Prozentzeichen anzugeben.
3
UNIX-Kurs [~] 131 > find / -name "*.c" -print >& result.txt
ŸZ UNIX-Kurs [~] 132 > bg [1] 52314
Das Durchsuchen des gesamten Dateibaums nach Dateien mit der Endung .c wie in dem obigen Beispiel kann je nach Größe des Dateibaums recht lange dauern. Aus diesem Grund wurde das als Vordergrundprozess gestartete Kommando in diesem Beispiel mit ŸZ gestoppt und mit dem Kommando bg als Hintergrundprozess fortgesetzt.
200
Aufgaben
12.11.3 fg foreground – Ein gestoppter Prozess kann aber auch als Vordergrundprozess fortgesetzt werden. Das Stoppen eines Prozesses wird nämlich nicht grundsätzlich »von Hand« durch den Benutzer vorgenommen, sondern kann auch durch die Shell selbst erfolgen, z.B. wenn ein Hintergrundprozess versucht, von der Standardeingabe zu lesen. Dass ein Prozess gestoppt wurde, wird in der Liste der Prozesse, die mit jobs abgefragt werden kann, angezeigt. Da in der Regel nicht immer der zuletzt gestartete Job angehalten wurde, sollte bei der Verwendung von fg immer mit einer Job-ID gearbeitet werden.
UNIX-Kurs [~] 133 > fg %2
In diesem Beispiel wird der Job mit der Job-ID 2, der bisher im Hintergrund lief oder gestoppt war, als Vordergrundprozess weitergeführt.
3
Übungen
12.12 Aufgaben 1. Suchen Sie nach einer Möglichkeit, den folgenden find-Befehl statt mit -exec mit einer Kommando-Substitution (Back Quotes) zu lösen. find ~ -type f -exec file {} \;
2. Welches der beiden Kommandos aus 1.) ist schneller – die Variante mit -exec oder die Kommando-Substitution? Begründen Sie Ihre Antwort. 3. Kann es bei der Kommando-Substitution aus 1.) zu Problemen kommen? 4. Versuchen Sie Beispiele zu finden, welche die Unterschiede zwischen Double und Single Quotes verdeutlichen. 5. Definieren Sie einen Alias dir für das Kommando ls -la. 6. Erstellen Sie eine Function mit dem Namen wer_ist, die Ihnen zu einer Benutzerkennung das zugehörige fünfte Feld aus der Datei /etc/passwd (den Kommentar) ausgibt. 7. Schauen Sie sich den Inhalt der Startup-Dateien Ihrer Shell an. 8. Versuchen Sie mithilfe von echo und der Ausgabeumlenkung einen Brief in eine Datei zu schreiben.
201
KAPITEL
12
Korn-Shell
9. Starten Sie einen find-Befehl als Hintergrundprozess und lenken Sie die Suchergebnisse in eine Datei um. Werden wirklich alle Ausgaben in die Datei umgelenkt? Was müssen Sie tun, damit auf keinen Fall Ausgaben auf dem Bildschirm erscheinen?
12.12.1 Lösungen 1. Zur Lösung schlagen Sie bitte im vorangegangenen Kapitel die entsprechenden Erläuterungen zur C-Shell nach. Es bestehen keine Unterschiede. 2. Die Kommando-Substitution liefert die Ergebnisse wesentlich schneller. Dies liegt daran, dass sowohl der find- als auch der file-Befehl nur je einmal aufgerufen werden. Die Variante -exec hingegen startet für jeden gefundenen Dateinamen einen eigenen file-Prozess, der die eine Datei dann untersucht. Dieser mehrfache Aufruf ist u.a. deshalb wesentlich langsamer, weil file zur Erfüllung seiner Aufgabe die Datei /etc/magic einlesen muss. 3. Gleiches gilt für die Übungsaufgaben 2 und 3. 4. Um den Umgang mit den diversen Quoting-Mechanismen zu üben, eignet sich das echo-Kommando hervorragend. Raten Sie, vollziehen Sie nach und vor allem: probieren Sie selbst. Nach ein paar Übungsrunden dürfte das Quoting seinen Schrecken verloren haben. Hier ein paar Beispiele für die Korn-Shell: Definieren Sie zwei Shell-Variablen: UNIX-KURS [~] 50 > export VORNAME=Albert UNIX-KURS [~] 51 > export NACHNAME=Nagel
Ohne das $-Zeichen werden die Variablennamen selbst ausgegeben: UNIX-KURS [~] 52 > echo VORNAME NACHNAME VORNAME NACHNAME
Double Quotes erhalten Leerzeichen: UNIX-KURS [~] 53 > echo "$VORNAME Albert Nagel UNIX-KURS [~] 54 > echo $VORNAME Albert Nagel
$NACHNAME" $NACHNAME
Single Quotes hingegen verhindern das Auswerten von Variablen: UNIX-KURS [~] 55 > echo '$VORNAME $VORNAME $NACHNAME
202
$NACHNAME'
Aufgaben Back Quotes dienen der Kommando-Substitution, das heißt, der darin stehende Unix-Befehl wird ausgeführt: UNIX-KURS [~] 56 > echo pwd pwd UNIX-KURS [~] 57 > echo ‘pwd‘ /home/lutz
Im Gegensatz zu Double Quotes verhindern Single Quotes die Kommando-Substitution: UNIX-KURS [~] 58 > echo "‘pwd‘" /home/lutz UNIX-KURS [~] 59 > echo '‘pwd‘' ‘pwd‘
5. Die Syntax für Alias lautet: alias Alias-Name="Kommando". Als Alias-Namen benutzen Sie dir und weisen ihm das Kommando ls -la zu. Also lautet die Lösung: UNIX-KURS [~] 60 > alias dir="ls -la"
Die Anführungszeichen sind an dieser Stelle zwingend notwendig (im Gegensatz zum Alias-Kommando der C-Shell). Von nun an wird immer dann, wenn Sie dir eintippen, von der Korn-Shell das Kommando ls -la abgesetzt. Noch eine Anmerkung dazu: Der Alias-Befehl ist kein Unix-Kommando, sondern ein Befehl, der im Kommandointerpreter implementiert ist. Daher ist es auch verständlich, dass die Syntax des Befehls vom Kommandointerpreter abhängig ist. Außerdem kann das Unix-Kommando which die entsprechende ausführbare Datei nicht finden. 6. Bevor wir die Function erstellen, sollten wir uns zunächst einmal überlegen, welcher Unix-Befehl bzw. welche Kombination von Unix-Befehlen die eigentliche Aufgabenstellung – nämlich das Extrahieren des Kommentars für eine Benutzerkennung – lösen kann. Dazu werden wir zunächst den Kommentar für die Benutzerkennung root aus der Datei /etc/passwd filtern. Die gesuchte Zeile liefert uns der Befehl grep root /etc/passwd. Wird der Befehl so abgesetzt, werden allerdings sämtliche Zeilen ausgegeben, die die Buchstabenfolge root enthalten, egal ob im Kommentar oder als Teil der Benutzerkennung oder des Heimatverzeichnisses. Sicherer ist es, den Befehl folgendermaßen zu formulieren: grep ^root: /etc/passwd
Durch das vorangestellte Sonderzeichen ^ wird nach der Zeichenkette nur am Anfang jeder Zeile der Datei gesucht. Der nachgestellte Doppelpunkt integriert das Trennzeichen der Passwortdatei in das Suchermuster, wo-
203
KAPITEL
12
Korn-Shell
durch verhindert wird, dass auch eine Zeile für eine Benutzerkennung der Form rootmail ausgegeben wird. Von der ausgegebenen Zeile, die etwa folgendes Aussehen haben wird root:x:0:0:UNIX-Systemadministrator:/home/root:/bin/sh,
interessiert uns laut Aufgabenstellung nur der Kommentar im fünften Feld. Aus dem Ergebnis des grep-Kommandos ist daher dieses Feld herauszuschneiden. Diese Aufgabe können wir getrost dem Kommando cut überlassen. Es findet Felder in einer Zeile anhand eines über die Option -d vereinbarten Trennzeichens und kann einzelne Felder aus der Standardeingabe oder einer Datei herausfiltern. Das Ergebnis des grep-Befehls ist also über eine Pipe an die Standardeingabe weiterzuleiten. Der zusammengesetzte Befehl lautet: grep ^root: /etc/passwd | cut -d: -f5
Damit sind wir nun fast am Ziel unserer Wünsche. Wir müssen nur noch eine Function definieren, die genau diesen komplexen Befehl ausführt. Allerdings soll nicht immer nach der Benutzerkennung root gesucht werden, sondern die Benutzerkennung soll an die Function wer_ist übergeben werden. Wir wünschen uns also einen Aufruf der Form wer_ist lutz und wer_ist root. Schwierig ist das nicht; es ist nur die Zeichenkette root im Befehl durch das Platzhalterzeichen $1 für den ersten Aufrufparameter zu ersetzen. Die Function wird damit folgendermaßen definiert: function wer_ist { grep ^$1: /etc/passwd | cut -d: -f5 }
Der Befehl kann in der angegebenen Form mit den Zeilenumbrüchen eingegeben werden. Nach dem ersten Betätigen der Æ-Taste erhalten Sie einen anderen Prompt. Der Prompt der Shell erscheint wieder, nachdem die schließende Klammer eingegeben wurde. Die von Ihnen erstellte Function ist nun in der Shell, in der Sie den Befehl abgesetzt haben, verfügbar. Um die Function permanent zu machen, muss die Definition in eine Startup-Datei der Korn-Shell, im Allgemeinen in die Datei .profile oder in die .kshrc in ihrem Heimatverzeichnis eingetragen werden. 7. Die Standard-Startup-Datei der Korn-Shell ist die Datei .profile im Heimatverzeichnis des jeweiligen Benutzers. Diese wird allerdings nur für die Login-Shells ausgeführt. Sobald eine Korn-Shell aufgerufen wird (dies kann entweder explizit durch den Aufruf ksh geschehen oder automatisch beim Öffnen eines Shell-Fensters, wenn die Korn-Shell als Login-Shell für den Benutzer in der Datei /etc/passwd eingetragen ist), wertet die Shell die Environmentvariable ENV aus und führt die Datei aus, deren Name in
204
Aufgaben ENV vermerkt ist. In dieser Startup-Datei werden dann in der Regel Umgebungsvariablen exportiert, insbesondere werden der Suchpfad, AliasNamen und Functions definiert sowie Shell-Variablen gesetzt. Eine Startup-Datei .profile könnte folgenden Inhalt haben: export ENV=$HOME/.kshrc export HISTSIZE=100 export PS1="UNIX-Kurs[`pwd`] >" PATH=$PATH:/sbin:/usr/bin:/usr/local/bin:/etc:/usr/bsd PATH=$PATH:/usr/proc/bin:/usr/sbin:$HOME/bin MANPATH=/usr/catman:/usr/share/catman export PATH MANPATH . /home/db2inst2/sqllib/db2profile
In der ersten Zeile der Datei wird vereinbart, dass die Datei .kshrc im Heimatverzeichnis als zweite Startup-Datei ausgeführt wird. Die zweite Zeile bewirkt, dass die letzten 100 abgesetzten Befehle in der Befehlshistorie zur Verfügung stehen. Die Umgebungsvariable PS1 bestimmt das Aussehen des Prompts. Schließlich werden der Suchpfad (Umgebungsvariable PATH) und der Suchpfad für die Manual-Pages (Umgebungsvariable MANPATH) gesetzt und exportiert. Der Suchpfad wird im Beispiel nicht neu definiert, sondern nur erweitert. Dies verhindert, dass Voreinstellungen, die der Systemadministrator in der globalen Initialisierungsdatei der KornShell (üblicherweise ist dies die Datei /etc/profile) gemacht hat, überschrieben werden. Ohne den export-Befehl werden die Umgebungsvariablen PATH und MANPATH nicht auf die zuvor zugewiesenen Werte gesetzt, und die zuvor definierten Variablen bleiben nur Shell-Variablen. Dieser Effekt ist allerdings nur dann sichtbar, wenn die Shell-Variablen nicht von Umgebungsvariablen überdeckt werden. Die letzte Zeile beginnt mit einem Punkt, dem durch ein Leerzeichen getrennt ein Dateiname folgt. Dieser Befehl bewirkt, dass die angegebene Datei von der aktuellen Shell interpretiert wird. Das heißt, es wird keine Shell zur Ausführung der Datei gestartet; man sagt, die Datei wird »gesourct«. Werden in der Datei Umgebungsvariablen gesetzt, so verändert dies die Umgebung der aktuellen Shell. Dies wäre nicht der Fall, wenn zur Ausführung der Datei eine neue Shell gestartet würde. Für Programmierer gilt: Dieser Mechanismus ist vergleichbar mit einem #include in einem C-Programm. In der Datei .kshrc können sich Einträge der folgenden Form befinden: alias dir="ls -la" function ff { find / -name "$1" -print 2>/dev/null }
205
KAPITEL
12
Korn-Shell
Hier werden der Alias dir für das Kommando ls -la und eine Function ff definiert. Der Function ist beim Aufruf ein Dateiname als Parameter mitzugeben. Der find-Befehl in dieser Function durchsucht dann den gesamten Unix-Dateibaum nach Dateien mit diesem Namen. Beachtenswert ist die Umlenkung eventueller Fehlerausgaben (2>) auf das so genannte NullDevice /dev/null. Dieses Device schluckt alle Ausgaben; sie werden weder auf dem Bildschirm ausgegeben noch irgendwo gespeichert. 8. Zur Lösung siehe die entsprechende Aufgabe im vorangegangenen Kapitel zur C-Shell. 9. Wie Bildschirmausgaben in eine Datei umgelenkt werden, haben wir schon in Aufgabe 8 gesehen. Sollen wirklich keine Ausgaben mehr auf dem Bildschirm erfolgen, so müssen auch die eventuell auftretenden Fehlermeldungen in eine Datei umgelenkt werden. Schauen wir uns folgenden Befehl an: UNIX-KURS [~] 68 > find / -name core -print > ergebnis.txt
Dieser Befehl durchsucht den gesamten Dateibaum nach Dateien mit dem Namen core. Die Pfadnamen aller gefundenen Dateien werden dann in eine Datei namens ergebnis.txt gesichert. Setzen Sie diesen Befehl ruhig einmal so ab. Sie werden schnell merken, dass Sie trotz der Umlenkung eine Menge Ausgaben auf Ihren Bildschirm bekommen: Da Sie bei der Suche sämtliche Verzeichnisse durchforsten wollen, bekommen Sie Fehlermeldungen für jedes Verzeichnis, für das Sie keine Zugriffsrechte haben. Und das dürften im Normalfall, d.h. solange Sie nicht über Superuser-Berechtigung verfügen, einige sein. Sollen diese Fehlermeldungen in eine separate Datei umgelenkt werden, so geben Sie einen Dateinamen für den Dateideskriptor 2 (Standardfehlerausgabe) an: UNIX-KURS [~] 69 > find / -name core -print > ergebnis.txt 2> err.txt
Sollen die Fehlermeldungen in der Datei ergebnis.txt mit protokolliert werden, so muss die Standardfehlerausgabe (2) auf die Standardausgabe (1) verweisen, die ja bereits auf die Datei ergebnis.txt umgelenkt ist: UNIX-KURS [~] 70 > find / -name core -print > ergebnis.txt 2>&1
Beachten Sie, dass vor dem &1 kein Leerzeichen stehen darf. Der Befehl ist sonst syntaktisch nicht korrekt. Unter Umständen interessieren Sie die Fehlermeldungen überhaupt nicht. Dann gibt es eine sehr elegante Lösung, diese Meldungen zu »vernichten«: Alle Daten, die auf das Null-Device /dev/null umgelenkt werden, erscheinen weder auf der Standardausgabe noch werden sie irgendwo gespeichert.
206
Aufgaben UNIX-KURS [~] 71 > find / -name core -print > ergebnis.txt 2> /dev/ null
Da diese Suche relativ lange dauern kann, empfiehlt es sich, das Kommando als Hintergrundprozess zu starten. Andernfalls erscheint Ihr Eingabe-Prompt erst dann wieder, wenn der Befehl komplett abgearbeitet ist. Um ein Kommando im Hintergrund ablaufen zu lassen, geben Sie am Ende der Eingabezeile ein Ampersand (&) ein: UNIX-KURS [~] 72 > find / -name core -print > ergebnis.txt 2> /dev/ null &
207
KAPITEL 13
Die grafische Bedienoberfläche Die Bedienoberflächen verschiedener Unix-Derivate unterscheiden sich im Aussehen oft erheblich. Aus diesem Grund bedeutet das Arbeiten auf einem neuen System immer eine gewisse Umstellung. Allerdings ist die grafische Bedienoberfläche weniger fest mit dem Betriebssystem verflochten als in der MS Windows-Welt. Sie soll lediglich dem Benutzer die Arbeit mit Unix erleichtern und ist nicht zwingend notwendig, um mit dem System zu arbeiten. Dennoch will natürlich niemand, der den Komfort einer grafischen Bedienoberfläche von anderen Betriebssystemen gewöhnt ist, unter Unix darauf verzichten.
13.1
X-Window-Grundlagen
Ich erläutere Ihnen in diesem Abschnitt die wesentlichsten Punkte der Funktionsweise, der Bedienung und der Konfiguration des X-Window-Systems (auch X11 genannt). Denn trotz ihres stark unterschiedlichen Erscheinungsbilds basieren alle wichtigen grafischen Bedienoberflächen der Unix-Welt auf diesem System.
13.1.1
Was ist eigentlich X-Window?
Unix ist ein relativ altes Betriebssystem. Zum Zeitpunkt seiner Entstehung war grafische Datenverarbeitung noch kein Thema – die Schnittstelle aller Programme zum Benutzer war, wie auch heute noch bei der Shell, rein textuell.
209
KAPITEL
13
Die grafische Bedienoberfläche
Doch mit der Leistungssteigerung bei den Rechnern wurde der Ruf nach der Verarbeitung von Grafiken und deren Darstellung laut. So wurden Ende der 70er Jahre die ersten Grafikterminals entwickelt. Diese Displays machten es möglich, mehrere Terminals gleichzeitig in Form von Fenstern anzuzeigen. Was allerdings noch fehlte, war eine Software, welche die Anzeige und Verwaltung dieser Fenster übernahm. Aus einigen anderen Fenstersystemen kristallisierte sich mit der Zeit das von DEC und dem MIT im Projekt Athena entwickelte X-Window-System X11 als populärstes heraus – unter anderem auch, weil die Quellen frei verfügbar waren. Ein weiterer Aspekt für den großen Erfolg von X-Window war seine Fähigkeit, Fenster nicht nur auf dem lokalen Rechner anzeigen zu können, sondern auch auf Rechnern, die über ein Netzwerk mit dem eigenen Rechner verbunden sind.
13.1.2
Wie funktioniert X-Window?
Natürlich würde es den Rahmen dieses Buches sprengen, wenn die Funktionsweise von X-Window bis ins letzte Detail erklärt würde. Deshalb können hier nur die Voraussetzungen für ein grundlegendes Verständnis geschaffen werden. Im X-Window-System versteht man unter einem Display einen Rechner mit einem oder mehreren bitmapfähigen Bildschirmen (Screens), einer Maus (oder einem anderen Zeigegerät) und einer Tastatur. Wie bereits erwähnt, ist X-Window ein netzwerkfähiges Fenstersystem. Das heißt, ein Programm muss nicht auf dem Rechner ablaufen, der den Bildschirm verwaltet, auf dem es angezeigt wird. Auf welchem Display und welchem Screen die Ausgaben seines Programms angezeigt werden sollen, steuert der Benutzer über die Environmentvariable DISPLAY, in welcher der Name des Rechners, die Nummer des X-Servers und die Nummer des Screens gespeichert wird (Rechner:X-Server.Screen).
3
210
UNIX-Kurs [~] 134 > export DISPLAY=PC06:0.0
Das Programm, welches das Display verwaltet und für die Anzeige verantwortlich ist, nennt man den Server oder auch X-Server. Damit von einem beliebigen Rechner Ausgaben auf einem X-Server gemacht werden können, muss dazu erst die Erlaubnis erteilt werden.
X-Window-Grundlagen
xhost Diese Erlaubnis kann derjenige für einen Rechner erteilen, der den X-Server auf diesem Rechner gestartet hat, also in der Regel derjenige, der sich direkt an der Konsole des Systems angemeldet hat. Um Benutzern von einem anderen Rechner die Erlaubnis zu geben, Ausgaben auf dem eigenen X-Server zu machen, wird das Kommando xhost verwendet.
xhost [+|-]Name...]
Mit der Kombination +Name wird einem Benutzer oder einem Rechner Zugriff auf den lokalen X-Server gewährt und mit -Name wird dieses Recht wieder entzogen. Wird nur ein »+« angegeben, wird der Zugriff allgemein freigegeben und bei nur einem »-« allgemein gesperrt.
UNIX-Kurs [~] 135 > xhost +
Jedes Programm, das eine Ausgabe auf einem bestimmten Display machen möchte, nennt man einen (X11)-Client. Der Client verständigt sich mit dem Server über ein bestimmtes Protokoll – das X-Protokoll. Dieses Protokoll unterstützt TCP/IP und DECNet-Netzwerke. Mithilfe dieses Protokolls sendet der Client Anfragen bzw. Anforderungen zur Darstellung an den Server und erhält Informationen über Eingaben in einem seiner Fenster zurück.
6 3
Um die Anordnung der Fenster nicht dem Zufall oder der Willkür einzelner Clients zu überlassen, wird diese Aufgabe von einem speziellen Client übernommen – dem Window-Manager. Dieses Programm ist durch seine Funktion in einer privilegierten Position. Andere Clients dürfen zur Platzierung ihrer Fenster nur so genannte Hints an den Window-Manager geben, die dieser allerdings nicht unbedingt akzeptieren muss. Somit ist das Fensterlayout auf dem Bildschirm ausschließlich Sache des Window-Managers. Dies ist auch der Grund für das unterschiedliche Aussehen der grafischen Bedienoberflächen unter Unix – fast jeder Hersteller verwendet einen anderen WindowManager.
211
KAPITEL
13
Die grafische Bedienoberfläche
Abb. 13.1: Kommunikation der X-WindowKomponenten
13.2
Window-Manager
Da X-Window ein reines Fenstersystem ist, kommt der Anwendung, welche die Fenster verwaltet, eine sehr große Bedeutung zu. Ohne einen WindowManager wäre das Verschieben von Fenstern oder ein Wechsel des Eingabefokus nicht machbar. Aber der Window-Manager hat noch andere ebenso wichtige Aufgaben: ✘ Wird ein Fenster verschoben und werden dadurch Bereiche eines anderen Fensters freigelegt, muss der Window-Manager dafür sorgen, dass der zugehörigen Applikation eine Aufforderung zum Neuzeichnen zukommt (redraw event). ✘ Der Window-Manager stellt die unterschiedlichen Popup-Menüs, die der Benutzer an den verschiedenen Stellen des Systems durch Drücken der rechten Maustaste erhält, zur Verfügung. ✘ Der Window-Manager leitet Eingaben an die zu den Fenstern gehörenden Applikationen weiter.
212
Window-Manager Viele Window-Manager stellen zusätzlich zu ihren Grundfunktionen noch weitere Dienste zur Verfügung. Diese Dienste und die damit verbundenen Möglichkeiten verändern das Aussehen der grafischen Bedienoberfläche erheblich und führen zu den schon eingangs beschriebenen Umgewöhnungseffekten beim Wechsel zwischen den Unix-Systemen unterschiedlicher Hersteller. Um die grundlegenden Unterschiede zwischen den verschiedenen WindowManagern zu erläutern, sollen in den nachfolgenden Abschnitten einige Exemplare vorgestellt werden. Dabei wird kein Anspruch auf Vollständigkeit erhoben, sondern es werden lediglich einige prägnante Window-Manager angeschaut.
13.2.1
Der twm
Der Tab Window-Manager twm ist wohl der älteste und simpelste WindowManager. Er bietet kaum zusätzliche Funktionalität. Besonders auffällig ist, dass er den Fenstern keine Rahmen gibt, sondern sie nur mit einem Titlebar versieht. Auch dreidimensional wirkende Bedienelemente kennt der twm nicht. Kurzum: der twm ist nicht mehr zeitgemäß und eigentlich nur noch etwas für Puristen. Abb. 13.2: Der WindowManager twm
13.2.2
Der mwm
Der Motif Window-Manager mwm ist eng verbunden mit der Entwicklung von OSF Motif, einem von der OSF (Open Software Foundation) entworfenen Standard für grafische Bedienoberflächen von Programmen. Zum Motif-Standard gehört neben einem Style Guide und einer Widget-Library1 auch der Window-Manager mwm.
213
KAPITEL
13
Die grafische Bedienoberfläche
Der Motif Style Guide beschreibt, wie sich eine Applikation bei Eingaben verhalten soll und wie die Bedienoberfläche einer Applikation auszusehen hat. Kurzum: der Style Guide beschreibt das Look and Feel einer grafischen Bedienoberfläche. Aufgabe eines einheitlichen Look and Feel ist es, Benutzern den Einstieg in neue Applikationen dadurch zu erleichtern, dass es immer wiederkehrende Bedienschemata gibt, die der Benutzer nicht neu zu erlernen braucht. Ein sehr gutes Beispiel für eine Umsetzung eines Style Guides ist Apples MacOS. Unter diesem Betriebssystem sehen alle Programme annähernd gleich aus und sind nach dem gleichen Schema zu bedienen. Dadurch wird auch Anfängern ein schneller Zugang ermöglicht. Zur Umsetzung des Look and Feel in eine Bedienoberfläche bedarf es bestimmter Bedienelemente, die ein definiertes Aussehen haben und auf die Bedienung mit der Maus auf eine festgelegte Art und Weise reagieren. Diese Bedienelemente werden unter OSF Motif in Form eines Widget Set in einer Library zur Verfügung gestellt. Mithilfe dieser Library kann der Programmierer bestimmte Widgets im Fenster seiner Applikation erzeugen und er kann mithilfe so genannter Callback-Funktionen auf Events reagieren, die durch die Bedienung der Widgets ausgelöst werden. Der mwm ist der Window-Manager, der als erster Gebrauch von diesem Widget Set gemacht hat, um dreidimensionale Bedienelemente darstellen zu können. Durch diese plastisch wirkende Form der Darstellung lassen sich z.B. eingedrückte Knöpfe oder Eingabefelder besser abheben und somit wird mehr Übersichtlichkeit erzielt. Wie auch der twm stellt der mwm die Popup-Menüs auf dem Desktop zur Verfügung. Der mwm versieht Fenster mit dem bereits vorgestellten Rahmen und den darin integrierten Fensterhandles. Die vom mwm angebotenen Menüs lassen sich durch den Benutzer individuell anpassen. Dazu muss er eine Datei mit dem Namen .mwmrc in seinem Home Directory anlegen, in der in einer festgelegten Syntax das Aussehen der Menüs definiert wird. Doch sollte hier wieder einmal Vorsicht oberstes Gebot sein. Durch eine unvollständige Startup-Datei kann das Arbeiten extrem behindert werden. Deshalb sollte man sich quasi als Template die Default Startup-Datei kopieren und nach eigenen Vorstellungen erweitern. Diese Datei heißt in der Regel system.mwmrc und befindet sich in dem Verzeichnis /usr/ lib/X11.
1. Widget ist ein Kunstwort und ist zusammengesetzt aus Window (Fenster) und Gadget (heißt so viel wie kleines Zubehör). Ein klassisches »kleines Fensterzubehör« ist zum Beispiel ein Push Button, der beim Anklicken eine Aktion auslöst. Eine Library ist eine Sammlung von Funktionen, die bereits in Maschinensprache vorliegen, und auf die der Programmierer zur Erstellung seiner Programme zurückgreifen kann.
214
Window-Manager Abb. 13.3: Der mwm-Window-Manager
13.2.3
Der fvwm2
Der fvwm2 ist eine Weiterentwicklung des fvwm, der seinerseits eine Weiterentwicklung des twm ist. Der fvwm stammt aus dem XFree86-Projekt, welches durch seine X-Window-Portierung auf Intel-Plattformen und im speziellen für Linux allen Linux-Benutzern ein Begriff sein dürfte. Das v in fvwm steht für virtuell und beschreibt eines der wichtigsten Features dieses Window-Managers: Der fvwm2 ist in der Lage, eine virtuelle Bildschirmgröße und eine Anzahl virtueller Desktops zu verarbeiten. Die virtuelle Bildschirmgröße (Virtual Screen Size) ist limitiert durch den Speicher auf der Videokarte und nicht durch die Größe, die der Bildschirm darstellen kann. So kann man mit diesem Window-Manager bei einer Bildschirmauflösung von 800x600 auf einem 14"-Bildschirm und einer virtuellen Bildschirmgröße von 1.024x768 arbeiten. Kommt man mit der Maus an den Rand des Bildschirms, wird solange gescrolled, bis der Rand des virtuellen Bildschirms erreicht ist. Vorteil einer solchen Einstellung ist, dass auch Programme, die sich auf Auflösungen von 800x600 nicht darstellen lassen, ausgeführt und bedient werden können. Auf die Dauer hilft hier aber sicherlich nur ein größerer Bildschirm.
215
KAPITEL
13
Die grafische Bedienoberfläche
Virtual Desktop Im Abschnitt »Wie funktioniert X-Window?« wurde erwähnt, dass der Window-Manager die Fenster auf einem Main Window oder auch Desktop genannten Bildschirmhintergrund anordnet. Im Normalfall gibt es nur einen solchen Desktop, auf dem Fenster angeordnet werden können, und der entspricht auch in der Regel der Größe des sichtbaren Bereichs auf dem Bildschirm. Der fvwm2 erlaubt es aber dem Benutzer, zwei oder mehrere solcher Desktops zu verwalten. Das heißt, der Benutzer kann z.B. die Fenster einer sehr umfangreichen Applikation auf einem eigenen Desktop anordnen und mit seinen Shell-Fenstern auf einem anderen Desktop arbeiten. Dieses Prinzip der virtuellen Desktops finden wir auch bei den Standard-Desktops wie CDE und KDE wieder, wo es noch um einige Funktionen erweitert wurde. Abb. 13.4: Der WindowManager fvwm2
Um zwischen den virtuellen Desktops umzuschalten, verfügt der fvwm2 über einen Chooser1, der in eine Buttonleiste integriert ist. Jeder Button dieser Buttonleiste löst ein Pull-Down-Menü aus, über das weitere Applikationen erreicht werden können. Diese Buttonleiste ist ein Feature des Window-Managers und typisch für den fvwm2. Andere Window-Manager wie der 4Dwm des Silicon Graphics-Betriebssystems IRIX verfügen über etwas Ähnliches – hier heißt die Buttonleiste »ToolChest« und ist nicht mit Icons versehen.
1. In Abbildung 12.4. ist der Chooser das Feld links außen in der Buttonleiste. Er ist in diesem Beispiel in sechs rechteckige Bereiche unterteilt, die jeweils für einen virtuellen Desktop stehen.
216
Die Konfiguration von X-Window Die Aufgabe ist in beiden Fällen die gleiche: Dem Benutzer soll ein einfacher und schneller Zugang zu Applikationen gewährt werden, ohne dass er sich mit dem Pfad oder dem Kommando zum Starten auseinander setzen muss. Wie der mwm verfügt auch der fvwm2 über eine eigene Ressourcendatei. Diese trägt den Namen .fvwm2rc und kann ebenfalls vom Benutzer in seinem Home Directory angelegt werden. Neben den Popup-Menüs lässt sich über diese Datei auch das Aussehen der Buttonleiste beeinflussen. Auch hier gibt es eine systemweite Default-Datei (üblicherweise /usr/lib/x11/fvwm/.fvwm2rc), die sich der geneigte Benutzer in sein Home Directory kopieren kann, um sie seinen Bedürfnissen anzupassen.
13.3
Die Konfiguration von X-Window
Die meiste Arbeit bei der Konfiguration eines X-Window-Systems hat der Systemverwalter, denn er muss die globalen Einstellungen des Fenstersystems an die Bedürfnisse der Benutzer anpassen. Dazu gehören Vorgaben für die Menüs des verwendeten Window-Managers genauso wie Vorgaben für das Aussehen einiger Applikationen1. Wie bei den Shells gibt es bei allen diesen Voreinstellungen auch Veränderungsmöglichkeiten für den einzelnen Benutzer. So kann er sich z.B. den verwendeten Window-Manager selbst aussuchen (sofern nicht CDE benutzt wird), die Menüs dieses Window-Managers selbst verändern, Zeichensätze und Farben für einzelne Applikationen verändern, die Vergabe des Eingabefokus auf Fenster festlegen und entscheiden, welche Applikationen für ihn nach dem Einloggen automatisch gestartet werden. Obwohl X-Window selbst ein grafisches System ist, erfolgen all diese Konfigurationen über Textdateien. Jede dieser Dateien hat eine bestimmte Funktion und in der Regel auch eine eigene Syntax. Häufig ist dem Benutzer unklar, welche Datei er editieren muss, um eine bestimmte Konfiguration zu ändern. Da Aufbau und Syntax einiger dieser Dateien recht komplex sind, sollen an dieser Stelle nur die wichtigsten Dateien mit ihrer Funktion vorgestellt werden, ohne dabei die Syntax zu erläutern.
1. Nicht jede Applikation ist für eine Veränderung ihres Aussehens vorbereitet. Das Aussehen wird durch so genannte Ressourcen bestimmt, und die sind nicht in jedem Fall in einer Ressourcendatei abgelegt, die verändert werden kann.
217
KAPITEL
13 13.3.1
Die grafische Bedienoberfläche
Die Datei .xinitrc
Auf den meisten Systemen findet der Benutzer heute einen grafischen Login vor. Das heißt, das X-Window-System ist bereits gestartet und die Anmeldung erfolgt durch ein spezielles Anmeldefenster. Dieses Fenster läuft nicht unter der Kontrolle eines Window-Managers und ist demzufolge nicht verschiebbar. Sobald der Benutzer sich ordnungsgemäß angemeldet hat, wird für ihn eine Session gestartet und er kann mit dem X-Window-System arbeiten. Das war nicht immer so und ist auch heute noch nicht überall so. Wenn man z.B. Red Hat Linux installiert oder unter Solaris das CDE nicht installiert, starten beide System zunächst ohne eine grafische Bedienoberfläche. Der Benutzer erhält einen nicht grafischen Login, der an eine Anmeldung über telnet (siehe nächstes Kapitel) erinnert. Nach der Anmeldung kann er, sofern sein X-Window-System richtig konfiguriert ist, die grafische Bedienoberfläche »von Hand« starten.
xinit Zu diesem Zweck existiert ein Programm mit dem Namen xinit, mit dessen Hilfe das X-Window-System gestartet werden kann. Bei diesem Start wird zunächst der X-Server auf der lokalen Maschine gestartet und anschließend per Default nach einer Datei .xinitrc im Home Directory des Benutzers gesucht. Diese Datei beinhaltet ein Shell-Script, welches die initialen Clients und den Window-Manager für den Benutzer startet. Dabei werden alle Clients als Hintergrundprozesse und der Window-Manager als Vordergrundprozess gestartet. Solange der Window-Manager läuft, läuft das Script .xinitrc und somit auch das X-Window-System. Beendet der Benutzer den Window-Manager, wird auch das Fenstersystem beendet. Hat der Benutzer kein .xinitrc, wird stattdessen ein xterm gestartet. xterm ist die grafische Variante eines Terminals. Dieses xterm läuft wie der WindowManager im Vordergrund. Wird dieses xterm geschlossen, wird wieder das Fenstersystem beendet. Das Interessante ist nun, dass das xterm ohne Window-Manager läuft. Will der Benutzer einen Window-Manager aktivieren, so wird dieser als Hintergrundprozess (ein Window-Manager ist ja im Prinzip auch nur ein Client) aus dem xterm gestartet.
startx Auf vielen Systemen, die über kein grafisches Login verfügen, versucht der Systemverwalter die Situation zu vermeiden, dass ein xterm ohne WindowManager gestartet wird, indem er den Start des X-Window-Systems über ein gesondertes Script mit dem Namen startx erlaubt. Dieses Script sorgt dafür, dass ein Default-Script aufgerufen wird, das zumindest ein xterm und einen Window-Manager startet, wenn der Benutzer kein .xinitrc in seinem Home
218
Die Konfiguration von X-Window Directory hat. Diese Vorgehensweise erleichtert insbesondere unerfahrenen Benutzern das Starten der grafischen Bedienoberfläche.
13.3.2
Die Datei .xsession
Im letzten Abschnitt wurde über die Schwierigkeiten, die beim Start des X-Window-Systems auftreten können, berichtet. Eine logische Schlussfolgerung daraus ist, den Einlogvorgang selbst in einem Fenstersystem durchzuführen. Das Problem bei dieser Variante ist, dass sich der »normale« Unix-Einlogvorgang ändert. Wie erfolgt ein solcher »normaler« Login-Vorgang? Da wäre zunächst einmal ein Prozess, der auf Eingaben von der Tastatur wartet und bei seinem Start einen Begrüßungstext ausgibt sofern niemand eingeloggt ist,. Dieser Prozess gibt die erste Eingabe, die mit einem Return abgeschlossen wird – das sollte die Benutzerkennung sein – an einen zweiten Prozess weiter. Dieser Prozess fragt nun vom Benutzer das Passwort ab und prüft es.1 Passen Benutzerkennung und Passwort zusammen, wird die Shell für den Benutzer gestartet, die in der /etc/passwd für ihn als Login-Shell eingetragen ist. Beendet er diese Shell, wird er ausgeloggt und der Zyklus beginnt wieder mit dem ersten Prozess. Diese Abfolge von Prozessen stellt eine Bildschirmsitzung oder neudeutsch eine Session dar. Bei einer grafischen Bedienoberfläche ist dieses Zusammenspiel von Prozessen um einiges komplizierter, zumal nicht nur ein einzelnes initiales Startprogramm wie die Shell für den Benutzer gestartet werden muss. Aus diesem Grund werden alle Programme, die zum Betrieb des X-WindowSystems für den Benutzer wichtig sind, mittels eines Scripts mit dem Namen Xsession gestartet. Ähnlich zum xinit stellt das Terminieren dieses Scripts die Beendigung des Fenstersystems und das Ende der Benutzersession dar. Wie auch beim xinit gibt es beim Xsession die Möglichkeit, ein eigenes Script anstelle der Systemdefaults zur Ausführung zu bringen. Dieses Script trägt den Namen .xsession und liegt ebenfalls im Home Directory des Benutzers. In dieser Datei werden die initialen Clients und der Window-Manager für den Benutzer gestartet. Was noch fehlt, ist ein Programm, das ein grafisches Login-Fenster zur Verfügung stellt und bei Beenden einer Benutzersession für den Restart des Fenstersystems sorgt. Dieses Programm nennt sich xdm (X Display Manager) und wird auf den meisten Systemen eingesetzt, die über ein grafisches Login verfügen und keinen der Standard-Desktops KDE oder CDE einsetzen2. 1. Diese Prüfung erfolgt durch Verschlüsseln des Passworts und Vergleich mit dem verschlüsselten Passwort, welches in der Datei /etc/passwd bzw. in /etc/shadow steht. 2. Selbstverständlich kann KDE auch gestartet werden, wenn der xdm benutzt wird – in der Regel wird man sich als KDE-Benutzer aber eher für den hübschen kdm-Display-Manager des KDE-Projekts entscheiden.
219
KAPITEL
13 13.3.3
Die grafische Bedienoberfläche
Die Datei .Xdefaults
Wenn ein Anwender mit dem X-Window-System arbeitet, arbeitet er eigentlich mit den Clients, die auf dem System laufen bzw. ihre Ausgaben auf dem X-Server machen. Da diese Clients die Arbeitsumgebung bestimmen und der Mensch ja stets nach Individualität strebt, ist der Wunsch, das Aussehen dieser Clients an seine eigenen Sehgewohnheiten anzugleichen, nicht allzu ungewöhnlich. Anders als bei MS Windows, wo die Farbgebung und die verwendeten Zeichensätze für alle Programme gleichzeitig vorgegeben werden, lassen sich unter X-Window gezielt Veränderungen an einzelnen Programmen vornehmen. Voraussetzung für eine solche Veränderung ist, dass das Programm über eine Anzahl veränderbarer Ressourcen verfügt. Diese Ressourcen werden im Allgemeinen in einer Datei abgelegt, die den gleichen Namen wie die Applikation trägt, nur dass sie meist mit einem Großbuchstaben anfängt. Diese Dateien werden unterhalb des Verzeichnisses /usr/lib/X11/appdefaults abgelegt. Wird nun eine Applikation gestartet, werden diese Einstellungen gelesen und an das Programm weitergegeben. Will der Benutzer einige dieser Einstellungen ändern, z.B. einen anderen Zeichensatz oder eine andere Farbgebung wählen, trägt er die entsprechenden Zeilen aus der globalen Startup-Datei in die Datei .Xdefaults in seinem Home Directory ein und verändert dort die Einstellungen. Wird jetzt das X-WindowSystem gestartet, sorgt ein Programm namens xrdb dafür, dass die veränderten Werte in die X Resource Data Base eingetragen werden. Wird nun die Applikation durch den Benutzer gestartet, werden die Einstellungen aus der Ressourcedatei unter /usr/lib/X11/app-defaults durch die Benutzereinstellungen überschrieben und die so geänderten Werte werden an die Applikation weitergeleitet.
13.4
Der Standard-Desktop CDE
Im letzten Kapitel wurde gezeigt, dass die Window-Manager das Aussehen der grafischen Bedienoberfläche maßgeblich prägen. Insbesondere der fvwm2 mit seinen zusätzlichen Features wie virtuellen Screengrößen, virtuellen Desktops und der Buttonleiste bietet weit mehr als ein reiner Window-Manager. Noch weiter gehen die Standard-Desktops wie CDE und KDE. Ihnen liegt die Überlegung zu Grunde, dass man den Benutzern ein einheitliches frontend anbietet, unabhängig von der Unix-Version, mit der sie arbeiten. Diese Standard-Desktops verfügen ähnlich wie der fvwm2 über eine Verwaltung virtueller Desktops und eine Art Buttonleiste, über die Applikationen gestartet werden können. Das CDE entstand aus einem Projekt namens COSE (Common Open Systems Environment), welches von den vier Firmen Hewlett Packard (HP),
220
Der Standard-Desktop CDE International Business Maschines (IBM), Sun Soft und Novell durchgeführt wurde. Das CDE nutzt die grafischen Elemente des OSF/Motif1 für die Umsetzung seiner Bedienoberfläche. Die Umsetzung der Standard-Desktops erfolgt über eigene spezielle WindowManager. Im Gegensatz zum fvwm2 gehören aber zu den Standard-Desktops nicht nur die Window-Manager, sondern auch ein grafisches Login und eine ganze Reihe von Tools wie z.B. ein grafischer Editor, ein grafischer Terminkalender und eigene spezielle Shell-Fenster.
13.4.1
Das CDE-Bedienpanel
Das Common Desktop Environment (CDE) wurde von der COSE-Gruppe, in der auch die führenden Mitglieder der OSF aktiv sind, standardisiert. Es zeichnet sich durch einen speziellen Window-Manager aus, den dtwm. Dieser Window-Manager bietet zusätzlich zu den normalen Funktionalitäten ein spezielles Bedienpanel, über welches vier virtuelle Screens zur Verfügung gestellt werden und eine Reihe von Utilities erreichbar sind, vgl.13.5.
Abb. 13.5: Das CDEBedienpanel
Wird in diesem Panel auf einen der Menü-Buttons geklickt, erscheint jeweils ein Menü, über das unterschiedliche Utilities gestartet werden können. Diesen Menüs können eigene Einträge hinzugefügt werden, sodass der Benutzer sich seinen individuellen Desktop zusammenstellen kann. Abb. 13.6: Ein CDE-Menü
1. Die OSF (Open Software Foundation) ist ein Zusammenschluß einiger großer Unix-Anbieter, zu denen u.a. auch IBM und DEC gehören. OSF/Motif ist ein von der OSF definierter Standard für die Gestaltung von grafischen Bedienoberflächen.
221
KAPITEL
13 13.4.2
Die grafische Bedienoberfläche
Das CDE-Shell-Fenster dtterm
Während bei Systemen, auf denen kein CDE eingesetzt wird, in der Regel xterm als Shell-Fenster zum Einsatz kommen, wird bei der Verwendung von CDE der so genannte dtterm benutzt. Ein dtterm emuliert ein VT102- bzw. ein VT220-Terminal und ist per Default mit einem Scrollbar ausgerüstet. Das dtterm verfügt weiterhin über ein eigenes Pull-Down-Menü mit den Menüpunkten WINDOW, EDIT, OPTIONS und HELP. Unter dem Menüpunkt Window kann der Benutzer ein neues Fenster öffnen (NEW) oder das aktuelle dtterm schließen (CLOSE). Über den Menüpunkt EDIT erreicht man die Funktionen COPY und PASTE und unter den OPTIONS lassen sich Menüleiste und Scrollbar ausblenden sowie das Verhalten des Cursors, die Farbgestaltung und die Errorbell (visuell oder akustisch) festlegen. Abb. 13.7: Das CDEShell-Fenster dtterm
13.4.3
Der CDE-Standardeditor dtpad
Später in diesem Buch wird der Unix-Standardeditor vi vorgestellt. Er ist ein »Dinosaurier« unter den Editoren und nicht gerade mit einem selbsterklärenden Benutzerinterface versehen – für den ungeübten Benutzer ist er deshalb kaum geeignet. Zu seiner Ehrenrettung sei allerdings gesagt, dass er über so manche versteckte Qualität verfügt. Mit der Einführung grafischer Bedienoberflächen, die den einfachen Zugang zur Unix-Welt ermöglichen sollen, wurde auch ein grafischer Editor notwendig, der ohne Spezialkenntnisse zu bedienen ist. Der dtpad ist zwar nicht mit den Fähigkeiten des vi oder emacs gesegnet, hat aber eine einfache Formatierungshilfe und ermöglicht das Suchen und Ersetzen von Worten. Diese Funktionen sind über das Pull-Down-Menü des dtpad
222
Der Standard-Desktop CDE zu erreichen. Über den Menüpunkt FILE kann der Benutzer neue Dateien anlegen (NEW), bestehende öffnen (OPEN) oder einfügen (INCLUDE), die aktuelle Datei speichern (SAVE oder SAVE AS), den Inhalt des Editors drucken (PRINT) oder den Editor beenden (CLOSE). Die Bearbeitungsfunktionen aus dem Menü EDIT umfassen das UNDO der letzten Änderung, das Ausschneiden (CUT), Kopieren (COPY) und Einfügen (PASTE), das Löschen von selektiertem Text (DELETE), das Selektieren des gesamten Editorinhalts (SELECT ALL), das Suchen und Ersetzen (FIND/CHANGE) und das Prüfen der Schreibweise (CHECK SPELLING). Abb. 13.8: Der CDEStandardeditor dtpad
Unter dem Menüpunkt FORMAT findet der Benutzer die Unterpunkte SETTINGS zum Einstellen der Seitenränder und des Alignment, PARAGRAPH für die Formatierung eines Abschnitts und ALL für die Formatierung des gesamten Editorinhalts. Als OPTIONS lässt sich einstellen, ob überschrieben werden soll (OVERSTRIKE), ob automatisch umgebrochen werden soll (WRAP TO FIT) und ob eine Statuszeile angezeigt werden soll (STATUS LINE).
13.4.4
Der CDE-File-Manager dtfile
Für den Unix-Unkundigen ist es kaum möglich, ohne die Unterstützung von Werkzeugen eine Dateiverwaltung zu betreiben. In den ersten Kapiteln dieses Buchs haben wir gesehen, welche Gefahren beim unvorsichtigen Umgang mit Unix-Kommandos auf den Benutzer warten. Nicht umsonst hat es den Ruf, kein »Try and Error«-System zu sein.
223
KAPITEL
13
Die grafische Bedienoberfläche
Abb. 13.9: Der CDE-FileManager dtfile
Eine Reihe dieser Gefahren lassen sich durch den Einsatz des CDE-File-Managers zur Dateiverwaltung umschiffen. Zwar verliert man die Shell als mächtigen Verbündeten mit ihren Pipes und Filtern und all den anderen nützlichen Dingen, gewinnt dafür aber ein ganzes Stück an Sicherheit. Kein ungewolltes Löschen von Dateien ohne Rückfrage oder Überschreiben durch Kopieren mehr. So wird vor jedem Löschen einer Datei – auch beim Kopieren oder Verschieben – der Benutzer gefragt.
Icons Der File-Manager stellt den Inhalt eines Dateiverzeichnisses grafisch dar. Dazu zeigt er unterschiedliche Icons für die unterschiedlichen Dateitypen an. So ist z.B. das Icon für ein Verzeichnis einem Hängeordner nachgebildet. Der Pfad des aktuellen Verzeichnisses – gemäß der Sprechweise bei der Shell sollten wir Working Directory sagen – wird unterhalb des Pull-Down-Menüs zum einen als Abfolge von Verzeichnissen und zum anderen als absoluter Pfad textuell dargestellt.
Working Directory wechseln Um das Working Directory neu zu setzen, existieren eine Reihe von Möglichkeiten. Zum einen kann der Benutzer an der Stelle, an der der Pfad textuell ausgegeben wird, einen neuen Pfad eingeben. Zum anderen kann er entweder in der Verzeichnisabfolge unterhalb des Pull-Down-Menüs oder im Fenster des File-Managers auf das Icon eines Verzeichnisses doppelklicken. In jedem Verzeichnis außer dem Root-Directory / wird außerdem vom File-Manager ein Icon, unter dem go up steht, ausgegeben, über das der Benutzer das
224
Der Standard-Desktop CDE Parent Directory erreichen kann. Nach Auswahl eines anderen Verzeichnisses wird der Inhalt dieses Verzeichnisses im Fenster des File-Managers angezeigt. Unter dem Menü VIEW findet sich der Punkt SET FILTER OPTIONS, mit dem die Auswahl der angezeigten Dateien und die Icons für die unterschiedlichen Dateitypen beeinflusst werden können. Je nach Icon/Dateityp passiert etwas anderes, wenn der Benutzer auf ein Icon doppelklickt. Wie von MS Windows gewohnt, gibt es auch im CDE-File-Manager Verknüpfungen zwischen Dateitypen und Anwendungen. Wird eine Datei, für die eine solche Verknüpfung besteht, doppelt geklickt, so wird die zugehörige Applikation mit der Datei gestartet. Ist die Datei selbst ein Executable, wird sie ausgeführt.
Selektieren Um eine oder mehrere Dateien zu kopieren oder zu verschieben, hat der Benutzer wieder unterschiedliche Möglichkeiten. Zuerst muss er die Dateien markieren, indem er sie mit der Maus anklickt. Um mehr als eine Datei zu selektieren, muss er die Ÿ-Taste zusätzlich drücken oder mit gedrückter linker Maustaste einen Rahmen über die zu selektierenden Dateien aufziehen. Die selektierten Dateien und Verzeichnisse werden durch inverse Darstellung des Dateinamens von den unselektierten Dateien abgehoben.
Kopieren Wurde nur eine Datei selektiert, kann der Benutzer den Menüpunkt COPY TO aus dem Menü SELECTED auswählen, um die Datei in ein neues Zielverzeichnis zu kopieren. Hat er eine oder mehrere Dateien selektiert, muss er die ÁTaste drücken und eine der Dateien erneut mit der linken Maustaste anklicken und die Maustaste gedrückt halten. Wird die Maus jetzt bei noch immer gedrückter Á- und Maustaste bewegt, erscheint ein Icon am Mauszeiger, welches an diesem »klebt«. Dieses Icon soll die selektierten Dateien symbolisieren. Lässt er dann diese Icons auf ein Icon für ein Dateiverzeichnis fallen (durch Lösen der Á- und Maustaste), werden die Dateien in das Verzeichnis kopiert.1 Das Ganze funktioniert auch mit einem zweiten geöffneten File-Manager, in dem ein anderes Verzeichnis angezeigt wird. Bewegt man den Mauszeiger über diesen zweiten File-Manager und lässt dann die Á- und die linke Maustaste los, werden die Dateien ebenfalls in das entsprechende Verzeichnis kopiert.
1. Dieses Bewegen von selektierten Icons und Fallenlassen über einem anderen Icon oder auf einer bestimmten Fläche nennt man »Drag&Drop« (also ziehen und fallen lassen). Beim »Drag&Drop« wird die eigentliche Aktion aus dem Kontext der Icons, die »gezogen« werden, und dem Icon oder der Fläche, über dem/der sie »fallengelassen« werden, gebildet. So kann man mit einer gleichartigen Bedienung ganz unterschiedliche Aktionen auslösen.
225
KAPITEL
13
Die grafische Bedienoberfläche
Verschieben Das Verschieben von Dateien funktioniert nach dem gleichen Prinzip wie das Kopieren. Zuerst muss der Benutzer die Dateien, die er verschieben will, markieren. Anschließend kann er entweder bei Einzeldateien mit dem Menüpunkt MOVE TO aus dem Menü SELECTED arbeiten oder die Icons per Drag&Drop über einem Verzeichnis-Icon fallen lassen. Allerdings darf er im Gegensatz zum Kopieren nicht die Á-Taste drücken, während er den Mauszeiger bewegt.
Löschen Wir erinnern uns: Das Löschen mit rm auf der Shell war der »gefährlichste« Befehl, den wir bisher kennen gelernt haben, weil durch einen unbedachten Einsatz von Metazeichen (also Wildcards) oder überflüssiger Leerzeichen ungewollt Dateien unwiederbringlich gelöscht werden können. Die Gefahr wird durch den Einsatz des File-Managers auf zweifache Weise gebannt. Erstens unterliegt man nicht den Tücken der Expandierung durch die Shell (Metazeichen und Leerzeichen haben im grafischen File-Manager kaum Bedeutung) und zum anderen löscht der File-Manager in zwei Schritten. Im ersten Schritt verschiebt er nur die zu löschenden Dateien in ein besonderes Verzeichnis (das Verzeichnis heißt Trash – was so viel wie Müll bedeutet – und liegt im Ordner .dt) und erst im zweiten Schritt löscht er den Inhalt dieses Mülleimer-Verzeichnisses. Erreichen kann der Benutzer dieses Verschieben in den »Mülleimer«, indem er die zu löschenden Dateien selektiert und entweder den Menüpunkt PUT IN TRASH anwählt oder die Dateien per Drag&Drop auf das Papierkorb-Icon im CDE-Bedienpanel fallen lässt. Ein Leeren des Papierkorbs kann er erreichen, indem er durch einen Doppelklick auf das MülleimerIcon eine besondere Variante des File-Managers startet. In diesem speziellen File-Manager müssen nun noch die Dateien, die endgültig zu löschen sind, selektiert werden, ehe der Menüpunkt SHRED aus dem File-Menü ausgewählt wird. Danach sind die Dateien endgültig gelöscht. Zwar ist das Stöbern im Müll nicht gerade die feine englische Art, aber wer hat nicht im realen Leben schon mal etwas aus Versehen weggeworfen und war hinterher froh, dass er es unbeschadet wieder aus dem Mülleimer ziehen konnte. Den gleichen Effekt hat das zweistufige Löschen des File-Managers – solange die Dateien sich noch im Mülleimer-Verzeichnis befinden, kann man sie jederzeit wieder herausholen – sogar ohne sich schmutzige Finger zu machen. Doch Vorsicht: Bei allen Vorteilen, die dieses zweistufige Verfahren gegenüber dem Benutzen von rm hat, bleibt doch die Gefahr, dass der Papierkorb von alten Dateien überquillt und die Entlastung der Platte – das eigentliche Ziel des Löschens – unterbleibt.
226
Der Standard-Desktop CDE
Umbenennen Mit dem Kopieren, Verschieben und Löschen haben wir bereits drei grundlegende Aufgaben aus dem Bereich der Dateiverwaltung mit dem File-Manager zu lösen gelernt. Was noch fehlt, ist das Umbenennen von Dateien. Für diese Aufgabe bietet sich nicht eine Umsetzung über Drag&Drop an. Um eine Datei im File-Manager umzubenennen, klickt man auf den Dateinamen unter dem Icon der Datei. Es wird ein Cursor eingeblendet und der Bediener kann den Namen editieren, wie er dies von einem Texteditor gewöhnt ist. Hat er die Änderung abgeschlossen, bestätigt er sie durch Drücken von Æ. Auch die verbleibenden Aufgaben der Dateiverwaltung wie das Anlegen eines Verzeichnisses oder das Ändern von Zugriffsrechten lassen sich über den FileManager abwickeln.
Neues Verzeichnis anlegen Um ein neues Verzeichnis anzulegen, muss der Benutzer zuerst in das zukünftige Parent Directory des neu anzulegenden Verzeichnisses wechseln. Anschließend wählt er den Menüpunkt NEW FOLDER aus dem Menü FILE und der File-Manager fügt ein neues Verzeichnis-Icon in die aktuelle Verzeichnisansicht ein. Das Verzeichnis erhält zunächst einen Standardnamen, den der Benutzer auf dem schon beschriebenen Weg ändern kann.
Zugriffsrechte Die Zugriffsrechte für eine Datei können geändert werden, indem der Benutzer zuerst die Datei selektiert und dann den Punkt CHANGE PERMISSIONS aus dem Menü SELECTED wählt. Es erscheint ein Fenster auf dem Bildschirm, in dem für jedes zu vergebende Recht an der Datei ein Toggle-Button enthalten ist. Wird der Toggle-Button eingedrückt, wird das Recht gesetzt, bleibt er erhaben, wird das Recht nicht vergeben.
13.4.5
Der CDE-Application-Manager
Der Application-Manager ist eine spezielle Form des File-Managers. Über ihn werden dem Benutzer eine Reihe nützlicher Werkzeuge zugänglich gemacht. Einige dieser Werkzeuge gehören zum Repertoire des CDE – andere sind entweder »ganz normale« Unix-Tools, die lediglich mit den Mitteln des CDE eine grafische Bedienoberfläche erhalten haben, oder Tools, die bereits über eine X11/Motif-Oberfläche verfügen.
227
KAPITEL
13
Die grafische Bedienoberfläche
Abb. 13.10: Der CDEApplicationManager
Die Tools werden der besseren Übersicht halber in Kategorien unterteilt, die der Application-Manager analog zu den Directories des File-Managers verwaltet. So kann sich der Benutzer wie aus dem File-Manager gewohnt durch eine Directory-Struktur navigieren. Die einzelnen Werkzeuge können per Doppelklick mit der linken Maustaste gestartet werden – wie ebenfalls bereits aus dem File-Manager für Programme mit grafischer Bedienoberfläche gewohnt.
13.4.6
Den CDE-Desktop konfigurieren
Die meisten Einstellungen des CDE-Desktops lassen sich vom Benutzer nach seinen eigenen Vorstellungen verändern. In der Regel muss der Benutzer sich dazu nicht auf die Unix-Ebene hinabbegeben, sondern er kann aus dem reichen Vorrat an CDE-Werkzeugen schöpfen. Falls der eine oder andere der Leser auch sein Bedienpanel erweitern will, so muss an dieser Stelle allerdings auf weiterführende Werke verwiesen werden. Dazu ist eine nicht ganz einfache Umgestaltung der Startup-Dateien des CDE erforderlich. Fehler dabei können u.U. dazu führen, dass der Benutzer sich nicht mehr einloggen kann. Wir wollen uns nur mit den Einstellungen beschäftigen, die über das CDE selbst veränderbar sind. Derartige Einstellungen lassen sich über den StyleManager des CDE bewerkstelligen, der über das CDE-Bedienpanel aufrufbar ist. Der Style-Manager ist in die Menüpunkte COLOR, FONT, BACKDROP, KEYBOARD, MOUSE, BEEP, SCREEN, WINDOW und STARTUP unterteilt – je nachdem, was der Benutzer konfigurieren will. Abb. 13.11: Der CDE-StyleManager
228
Der Standard-Desktop CDE
Color Über diesen Menüpunkt des Style-Managers lassen sich im Wesentlichen zwei Dinge konfigurieren: zum einen das Farbschema des CDE und zum anderen die Menge an Farben, die durch das CDE belegt werden sollen. Das Farbschema sorgt für die Farbgebung der Fensterrahmen, des Hintergrundbildes des Desktops sowie der Bedienelemente. CDE bietet eine Reihe aufeinander abgestimmter Farbschemata an, aber der geneigte Benutzer kann auch die vier Grundfarben eines Farbschemas selbst frei wählen.1 Wichtiger als das Aussehen des Desktops ist es aber, die richtige Anzahl von nicht durch CDE belegten Farben zu wählen. So manche Applikation benutzt Farbe zur Hervorhebung von Sachverhalten und ist ohne die vollständige Anzahl Farben quasi unbedienbar. Diese Einstellung der durch den Desktop belegten Farben ist auch im Zeitalter der 24 Bit True Color-Displays noch immer ein Thema, da die meisten Applikationen zur Darstellung auf ein 8-Bit-Visual (256 Farben) zurückgreifen.
Font Über diesen Menüpunkt erreicht der Benutzer ein Fenster, in dem er die Zeichensätze für seinen Desktop umdefinieren kann. Da lange Bildschirmarbeit bekanntlich die Augen ermüdet, kann so die Belastung durch größere oder besser lesbare Zeichensätze vermindert werden.
Backdrop Das Hintergrundbild des Desktops kann ebenfalls durch den Benutzer verändert werden. Bei vielen Firmen ist es zur Stärkung der Corporate Identity üblich, ein Firmenlogo als voreingestelltes Hintergrundbild zu definieren. Neben den eigenen Erweiterungen bietet CDE eine ganze Reihe mehr oder minder tauglicher Hintergrundbilder an. Trotz aller Vielfalt auf diesem Gebiet – ein schnöder einfarbiger Hintergrund bietet in der Regel den besten Kontrast zu den Fenstern und den auf dem Desktop abgelegten Icons.
Keyboard Da Unix durch die Einführung des Native Language Supports (NLS) auch andere Sprachen als Englisch unterstützt, würde man erwarten, dass sich eine Unterstützung von Tastaturen mit nationalen Layouts hinter diesem Punkt verbirgt. Doch leider befinden sich unter diesem Menüpunkt nur eine Einstellung für die Autorepeat-Geschwindigkeit (d.h., wie schnell Zeichen geschrieben werden, wenn eine Taste gedrückt gehalten wird) und die Lautstärke für das Geräusch, das bei einem Tastendruck ausgegeben wird. 1. Auf PC-X-Servern wird häufig der Wechsel des Farbschemas erst beim nächsten Einloggen durchgeführt, so dass so manche freie Wahl der vier Grundfarben in einer unansehnlichen Farbüberraschung endet.
229
KAPITEL
13
Die grafische Bedienoberfläche
Mouse Da Mäuse international sind, erlaubt dieser Menüpunkt nur eine Anpassung, ob die Maus links- oder rechtshändig bedient wird, wie schnell ein Doppelklick zu erfolgen hat, damit er als solcher erkannt wird, und ob bei der Verwendung einer Zwei-Tasten-Maus eine dritte Taste durch das gleichzeitige Drücken beider Maustasten emuliert werden soll.
Beep Wer kennt es nicht, dieses Geräusch, wenn er mit der Maus an eine Stelle klickt, die dafür nicht gedacht ist, oder wenn er beim Drag&Drop das Icon an der falschen Stelle fallen lässt. Dieser Signalton, der auf eine Fehlbedienung hinweisen soll, kann durch das Fenster, welches über das Menü BEEP zu erreichen ist, in Lautstärke, Tonhöhe und Dauer verändert werden.
Screen Unter dem Konfigurationspunkt SCREEN befinden sich die Einstellungen zum Bildschirmschoner. Zwar ist im Zeitalter der Monitore mit einem eigenen Power-Management die Verwendung eines Bildschirmschoners nur noch bedingt notwendig, aber unter dem CDE fungiert der Bildschirmschoner auch als Bildschirm-Lock, der ebenfalls über dieses Fenster eingestellt werden kann. Links neben den Buttons für die vier virtuellen Desktops im CDE-Bedienpanel befindet sich ein Icon in Form eines Vorhängeschlosses. Klickt man mit der Maus auf dieses Icon, wird der Screen Lock aktiviert. Es erscheint der eingestellte Bildschirmschoner und bei Betätigung einer Taste wird erneut das Passwort des Benutzers abgefragt. Wird das Passwort richtig angegeben, kann der Benutzer seine angefangene Session fortsetzen. Sinn und Zweck eines solchen Screen Locks ist es, den Arbeitsplatz bei kurzer Abwesenheit vor unbefugter Benutzung zu schützen, ohne sich komplett abzumelden. Machen Sie von dieser Möglichkeit Gebrauch, wenn Sie z.B. kurz das Zimmer verlassen.
Window Über das Window-Menü lässt sich einstellen, wie ein Fenster den Eingabefokus erhält (durch Anklicken oder durch einfaches Bewegen des Mauszeigers in das Fenster), ob das Fenster mit dem Fokus automatisch zuoberst auf den Fensterstack gelegt werden soll und ob beim Bewegen des Fensters nur ein Umriss oder das ganze Fenster angezeigt werden soll. Ebenfalls einge-stellt werden kann, ob die Icons auf dem Hintergrundbild des Desktops oder in einem eigenen Fenster – der so genannten Icon Box – abgelegt werden sollen.
230
Der Standard-Desktop CDE Abb. 13.12: Das WindowFenster des Style-Managers
Startup Über das Startup-Fenster lässt sich konfigurieren, ob CDE nach Betätigen des Exit-Buttons (auf dem Bedienpanel) eine Sicherheitsabfrage in Form eines Dialogs ausgeben soll. Ferner kann der Benutzer bestimmen, ob er beim nächsten Einloggen mit den gleichen Fenstern auf dem Desktop wie beim Ende seiner vorangegangenen Session fortfahren will oder ob er nach dem Einloggen mit einer Basiskonfiguration starten will. Um eine solche Basiskonfiguration festzulegen, startet er all jene Applikationen und Fenster, die er immer beim Einloggen vorfinden möchte, und klickt dann mit der linken Maustaste auf den Button SET HOME SESSION. Abb. 13.13: Das StartupFenster des Style-Managers
231
KAPITEL
13 13.4.7
Die grafische Bedienoberfläche
Die Erweiterung der CDE-Menüs um eigene Einträge
Um ein Programm in die Menüs des CDE zu integrieren, muss der Benutzer zuerst eine so genannte Action erzeugen. Dies geschieht mit einem speziellen Utility namens Create Action, welches sich unter dem Application-Manager des Benutzers befindet. Den Application-Manager erreicht man, indem man auf das Werkzeugkasten-Icon im CDE-Panel klickt. Abb. 13.14: Die DesktopApps des ApplicationManagers
Nach der Eingabe des Namens, unter dem die Action gespeichert werden soll, und des Pfads der Applikation, die über die Action ausgeführt werden soll, erzeugt Create Action, sobald man aus dem Menü FILE den Punkt SAVE auswählt, eine Datei im Home Directory des Benutzers, die stellvertretend für die Action steht. Abb. 13.15: Das Create Action Utility
232
Der Linux-Standard-Desktop KDE Es empfiehlt sich, ein eigenes Unterverzeichnis in seinem Home Directory anzulegen, in dem solche Action-Dateien abgelegt werden. Die Action wiederum steht für den Aufruf der Applikation, die in das Menü integriert werden sollte. Die Action-Datei wird wie jede andere Datei auch als Icon im File-Manager angezeigt. Wird das Icon dieser Datei aus dem File-Manager per Drag&Drop auf die Schaltfläche INSTALL ICON aus einem CDE-Menü fallengelassen, wird die Action in das Menü integriert und kann von nun an über das Menü gestartet werden. Abb. 13.16: Die Schaltfläche Install Icon
13.5
Der Linux-Standard-Desktop KDE
Auch hier geht Linux seinen eigenen Weg. Die Gründe hierfür sind zum einen in der Kreativität seiner Schöpfer zu suchen und zum anderen in dem steten Bemühen, Linux weiterhin als kostengünstiges – weil freies – Betriebssystem zur Verfügung zu stellen. Ein derartiges Bestreben steht natürlich im krassen Gegensatz zu den Lizenzgebühren, die die OSF für ihr Motif und die COSEGruppe1 für ihr CDE nimmt. Also wurde von einigen findigen Linux-Entwicklern das KDE-Projekt ins Leben gerufen. Das K Desktop Environment – kurz KDE genannt – stellt die Freeware-Alternative zum kommerziellen CDE dar. Dabei setzt es eine Mischform des »Look and Feel« von MS Windows 95 und seines kommerziellen Gegenstücks ein. Der Umstieg von der Windows-Welt hin zu Linux wird so erheblich vereinfacht. Genau wie das CDE verfügt KDE über eine Reihe von Tools, die über das KDE-Bedienpanel gestartet werden. Aus MS Windows 95 wurde der File-Manager adaptiert und die Idee der Task-Leiste aufgegriffen. Obwohl KDE in der Linux-Welt die größte Verbreitung hat, ist es auch für Solaris und einige andere kommerzielle Unix-Derivate verfügbar. Vor allem aber ist es mittlerweile so mächtig und vielfältig, dass ich ihm an dieser Stelle kaum gerecht werden kann.
1. Die COSE(Common Open Systems Environment)-Gruppe ist ein Zusammenschluß von IBM, HP, Sun und Novell, die sich neben dem CDE auch mit Netzwerktechnologien, Multimedia und Objekttechnologie auseinandersetzen.
233
KAPITEL 14
Networking Wir leben im Informations- und Kommunikationszeitalter. Der Austausch von Daten ist mittlerweile genauso selbstverständlich geworden wie das Telefonieren. Home Banking, Elektronische Post und nicht zuletzt das »sagenumwobene« Internet sind in aller Munde. Bei all diesen Dingen geht es um das gleiche Thema: Networking. Kaum ein Rechner ist mehr ohne Verbindung zu einem Netz und Prognosen zufolge wird der Trend zur Vernetzung anhalten. Was aber hat das alles mit Unix zu tun? Bei der Konzeption von Unix wurde der Vernetzungsansatz mit in das Betriebssystem integriert. Im Gegensatz zu anderen Systemen, bei denen Netzwerkkomponenten erst umständlich aufgepfropft werden müssen, gehört die Netzwerksoftware bei Unix zum Lieferumfang. Jede Unix-Workstation wird mit einem Netzwerkadapter ausgeliefert und die Integration in das lokale Netzwerk ist oft nur eine Sache von Minuten. Neben all diesen Vorteilen hat sich das Protokoll, das am häufigsten von Unix verwendet wird, zu einem der populärsten auf der Welt entwickelt.
14.1
Grundlagen
Immer wenn von Netzwerken gesprochen wird, kommen neben der Art der Leitungen (wie Ethernet, Token Ring oder FDDI) auch die Protokolle zur Sprache (wie TCP/IP, SPX/IPX, DECnet, AppleTalk oder SNA). Für das Arbeiten mit dem Netzwerk ist es hilfreich, zumindest gewisse Grundzüge dieser Komponenten zu verstehen.
235
KAPITEL
14
Networking
Die Vernetzung von Computern ist ein komplexes Thema und ähnlich wie bei der Kommunikation zwischen Menschen müssen bestimmte Regeln zum Verbindungsaufbau und zu der »Sprache«, in der die Übermittlung der Daten erfolgen soll, zu Beginn festgelegt werden. Diese Regeln werden in Protokollen beschrieben. Im Netzwerkbereich wird in der Regel nicht nur ein Protokoll eingesetzt, sondern eine Kombination aus mehreren, die aufeinander aufbauen. In diesem Zusammenhang wird auch von einem »Protokollstack« gesprochen, weil die Protokolle in Schichten »gestapelt« werden. Die Abfolge dieser Protokollschichten wird durch Modelle beschrieben, von denen das OSI (Open System Interconnection) 7-Schichten-Modell den größten Bekanntheitsgrad erlangt hat. Es teilt den Protokollstack in folgende Schichten, die zwischen dem physikalischen Kabel und dem Benutzer stehen: 1. Physikalische Schicht 2. Leitungsschicht 3. Netzwerkschicht 4. Transportschicht 5. Sitzungsschicht 6. Darstellungsschicht 7. Anwendungsschicht
236
Schicht 1
Das physikalische Protokoll beschreibt die physikalischen Eigenschaften des Übertragungsmediums. Dazu gehören Spannungen, Ströme und Widerstände, die für den Informationstransport genutzt werden.
Schicht 2
Das Leitungsprotokoll gewährleistet den fehlerfreien Transport von Bits und Bytes zwischen zwei Knoten. Im Leitungsprotokoll sind Vorschriften verankert, die sicherstellen sollen, dass festgestellt werden kann, ob die empfangenen Daten mit den gesendeten übereinstimmen. Mit diesen Vorschriften lassen sich also fehlerhafte Daten »aussortieren«, aber nicht korrigieren. Somit gewährleistet das Leitungsprotokoll nicht die Vollständigkeit der übertragenen Daten.
Schicht 3
Während das Leitungsprotokoll nur die Übermittlung zwischen zwei Knoten abdeckt, sorgt das Netzwerkprotokoll für den Transport der Daten durch das ganze Netz. Zu seinen Aufgaben gehören die Verwaltung der erreichbaren Knoten und der Wege zu diesen Knoten. Die Verwaltung der Wege wird auch Routing genannt. Des Weiteren sorgt das Netzwerkprotokoll auch für die Kontrolle der Datenpakete zwischen Sender und Empfänger.
TCP, UDP und IP
Schicht 4
Das Transportprotokoll ist für den fehlerfreien und vollständigen Transport ganzer Nachrichten zuständig. Es zerlegt die Daten in einzelne Datenpakete gemäß den Anforderungen der Schicht 3 und setzt sie wieder aus diesen Paketen zusammen.
Schicht 5
Das Sitzungsprotokoll legt die Aktionen für den Auf- und Abbau von Verbindungen fest. Es definiert Operationen, die mit dem Open und Close auf der Dateisystemebene vergleichbar sind.
Schicht 6
Das Darstellungsprotokoll ist häufig nur sehr schwach ausgeprägt oder gar nicht vorhanden. Seine Aufgabe ist die Umsetzung unterschiedlicher Darstellungen, wie z.B. die Umsetzung zwischen den Zeichensätzen ASCII und EBCDIC.
Schicht 7
Die letzte Schicht, das Anwendungsprotokoll, beschreibt die Schnittstelle zu den Applikationen, die einen Datenaustausch über das Netz vornehmen. Diese Protokolle sind anwendungsspezifisch und nur in einigen Fällen, wie z.B. bei der E-Mail, genormt.
14.2
TCP, UDP und IP
In den Schichten 1 und 2 werden von Unix unterschiedlichste Transportmedien unterstützt, die in der Regel transparent über die Hardware-Schnittstellen angesprochen werden können. Als verbreitetes Transportmedium gilt im Unix-Bereich das relativ preiswerte Ethernet (IEEE 802.3).1 In der Schicht 3 wird bei Unix-Betriebssystemen in der Regel das Internet Protokoll (IP) verwendet. Hauptaufgabe des IP ist das Routing zwischen den verschiedenen Rechnern und Netzen. Zu diesem Zweck werden die so genannten IP-Adressen benutzt. Jeder Rechner hat eine eindeutige IP-Adresse im Netzwerk. Befindet sich der Rechner in einem Netz mit Zugang zum Internet, so ist die Adresse international eindeutig. Eine Internetadresse (oder auch IP-Adresse) ist vier Byte2 lang und wird im Allgemeinen in der so genannten Dot-Notation – die Werte der vier Bytes durch einen Punkt getrennt (z.B. 192.168.20.10) – angegeben. Ein Byte kann Werte zwischen 0 und 255 annehmen. Eine IP-Adresse setzt sich aus einer Netzkennung (einer Art Vorwahl) und einer Rechnerkennung (einer Art Anschlussnummer) zusammen. Je nach ihrer Größe werden Rechnernetze in Klassen eingeteilt (Class A bis C). In 1. Meist wird der Begriff Ethernet mit dem ThinWire-Ethernet, welches Coaxial-Kabel verwendet, gleichgesetzt. Der Vollständigkeit halber sei hier erwähnt, dass es noch weitere Ethernetvarianten wie das ThickWire oder TwistetPair gibt. Darüber hinaus gibt es noch Unterschiede bzgl. der Übertragungskapazität (10 Mbit/s = 10BASE oder 100 Mbit/s = 100BASE). 2. Angesichts der stark zunehmenden Vernetzung werden zukünftig 4 Bytes für eine InternetAdresse nicht mehr ausreichen. Es wird deshalb über eine Erweiterung auf 16 Byte nachgedacht.
237
KAPITEL
14
Networking
einem Class-C-Netz können 254 verschiedene Rechner angeschlossen sein, in einem Class-B-Netz 65.534 und in einem Class-A-Netz sogar 16.777.214 Rechner. Das erste Byte der IP-Adresse zeigt die Netzklasse an. Class-A-Netzwerke haben hier Werte von 1 bis 126, Class-B-Netze Werte von 128 bis 191 und Class-C-Netze Werte von 192 bis 223. Die Klasse eines Netzes bestimmt, welcher Teil der IP-Adresse »Vorwahl« – also Netzwerkkennung – und welcher Teil »Durchwahl« – also Rechnerkennung – ist. Abb. 14.1: IP-Adressen
In der Schicht 4 wird bei Unix-Betriebssystemen in erster Linie das Transmission Control Protocol (TCP) verwendet. Es stellt sicher, dass alle Pakete, die verschickt wurden, beim Empfänger ankommen. TCP sorgt ebenfalls dafür, dass die Reihenfolge, in der die Daten verschickt wurden, erhalten bleibt. Zum Zweck der gesicherten Übertragung wird beim Einsatz von TCP eine Verbindung zwischen Sender und Empfänger aufgebaut. Der Begriff der Verbindung ist hier nicht im Sinn der Kabelverbindung zu verstehen, sondern wieder als eine Art Protokoll, bei der der Empfänger dem Sender den Empfang der Daten quittiert. Durch diese Quittierung kann das Bestehen der Verbindung überprüft werden. Ein anderes gebräuchliches Schicht-4-Protokoll ist das User Datagram Protocol (UDP). Im Gegensatz zum TCP ist das UDP ein »verbindungsloses« Protokoll. UDP sorgt nur dafür, dass die Daten korrekt vom Sender zum Empfänger transportiert werden, stellt aber nicht sicher, dass die Reihenfolge erhalten bleibt und dass alle versandten Päckchen auch beim Empfänger ankommen. UDP-Pakete werden zwar im Allgemeinen an einen bestimmten Empfänger gesandt, aber eine Quittierung der Daten erfolgt, wenn überhaupt, nicht innerhalb des UDP. UDP wird z.B. für das Network File System (NFS) eingesetzt.
238
Netzdienste
14.3
Netzdienste
Die Leistungen, die ein Netzwerk für die tägliche Arbeit zur Verfügung stellt, lassen sich in drei Klassen unterteilen. Die wohl häufigste Form, das Netzwerk in Anspruch zu nehmen, ist das Durchführen von Bildschirmsitzungen1 an fernen Rechnern. Es wird auch von einem Remote-Zugriff auf den Rechner gesprochen. Nicht wesentlich weniger häufig ist der Austausch von Dateien mit einem anderen Rechner. Gemeint ist hier nicht der Zugriff mehrerer Rechner auf eine einzelne Kopie einer Datei auf einem anderen Rechner, sondern das Kopieren einer Datei von Rechner A nach Rechner B. Die dritte und letzte Gruppe umfasst eine Reihe unterschiedlichster Dienste zur Gewinnung von Informationen über das Netz und andere Rechner sowie zur Kommunikation mit Benutzern an fernen Rechnern.
14.3.1
Bildschirmsitzungen an Remote-Rechnern
Grundsätzliche Voraussetzung, um sich an einem Remote-Rechner zur Durchführung einer Bildschirmsitzung anzumelden, ist die Kenntnis seiner IP-Adresse und der Besitz eines Accounts auf diesem Rechner. Ferner muss eine Route – also ein Weg – existieren, um vom eigenen Rechner auf den fernen Rechner zu gelangen. Sind diese Bedingungen erfüllt, lässt sich mit den beiden folgenden Kommandos eine Bildschirmsitzung auf dem Remote-Rechner durchführen.
telnet telnet ist eine Terminalsimulation und stammt ursprünglich aus dem ARPANET.2 Mit telnet können Verbindungen zu den unterschiedlichsten Rechnertypen mit den verschiedensten Betriebssystemen aufgebaut werden. telnet simuliert u.a. Terminals der Typen vt100 und vt102. Der Benutzer muss in edem Fall seinen Benutzernamen und das zugehörige Passwort angeben, bevor er Zugang zum Remote-System erhält.
1. Unter einer Bildschirmsitzung ist ein Arbeiten auf einem fernen Rechner zu verstehen, so, als ob man an einem direkt an diesen Rechner angeschlossenen Terminal arbeitet. In Wirklichkeit wird aber auf dem eigenen Rechner ein Terminal durch eine Software nachgebildet, und die Kommandos und Daten werden über das Netz an den fernen Rechner weitergeleitet. Also werden die abgesetzten Kommandos auf dem entfernten Rechner ausgeführt und die Ergebnisse in einer Terminalemulation auf dem lokalen Rechner angezeigt. 2. Das ARPANET, aus dem sich das Internet entwickelte, ist heute ein Teil des militärischen Datennetzes des Departement of Defense (DoD) in den USA.
239
KAPITEL
6
14
Networking
telnet Hostname
Als Hostname kann der Aufrufer entweder direkt eine IP-Adresse in Dot-Notation oder einen Alias für diese Adresse aus der Datei /etc/hosts oder über einen Nameserver angeben. Die telnet-Sitzung wird mit dem Verlassen der Shell auf dem Remote-Rechner beendet.
3
UNIX-Kurs [~] 136 > telnet box01
rlogin rlogin (remote login) gehört zu der Gruppe der so genannten r-Tools aus der
BSD-Welt. Es ist in erster Linie für die Durchführung von Bildschirmsitzungen auf anderen Unix-Betriebssystemen gedacht.
6
rlogin Hostname [-l Username]
Wird die Option -l mit dem nachgestellten Username weggelassen, wird versucht, eine Anmeldung unter der gleichen Benutzerkennung wie auf dem lokalen Rechner vorzunehmen. Im Gegensatz zum telnet kennt das Kommando rlogin Möglichkeiten, die Authentifizierung des Benutzers in einigen Fällen zu unterdrücken. Zu diesem Zweck kann jeder Benutzer in seinem Home Directory eine Datei mit dem Namen .rhosts anlegen. Diese Datei muss als Zugriffsrechte den Mode 644 eingestellt haben. Sie enthält Zeilen der Form: Hostname [Username]
Diese Einträge besagen Folgendes: Will sich der Benutzer Username vom Rechner Hostname auf dem Account, zu dem die Datei .rhosts gehört, remote anmelden, muss er kein Passwort eingeben. Steht in der Zeile kein Username, sondern nur ein Hostname, bedeutet dies, dass sich ein Benutzer von dem Rechner Hostname unter demselben Namen wie dem des Accounts, zu dem die Datei .rhosts gehört, anmelden kann, ohne das Passwort angeben zu müssen. Zwar ist dieser Mechanismus sehr praktisch, wenn ein Benutzer auf mehreren Rechnern einen gleichnamigen Account besitzt und sich bei der Remote-Anmeldung auf einem dieser Rechner die erneute Eingabe des Passworts schen-
240
Netzdienste ken kann. Aber dieser Mechanismus wird zu einer Gefahr, sobald ein unberechtigter Benutzer in den Besitz des Passworts auf einem dieser Rechner kommt. Er kann dann auf alle anderen Rechner ohne Angabe von Passworten »weiterreisen«.
UNIX-Kurs [~] 137 > rlogin box01 -l lutz
14.3.2
Dateitransfer
3
Die Zeiten, in denen Daten auf Bändern und Disketten von Rechner zu Rechner getragen wurden, beginnen langsam der Vergangenheit anzugehören. Angesichts oft unüberwindbarer Hardware-Inkompatibilitäten (die oftmals vom Hersteller künstlich hervorgerufen worden sind, nur um seine eigene Peripherie zu verkaufen) sind die unterschiedlichen Rechnersysteme durch die Vernetzung ein ganzes Stück näher zusammengerückt.
Um Dateien von einem anderen Rechner auf seine lokale Maschine zu kopieren oder umgekehrt Dateien von der lokalen Maschine auf den Remote-Rechner zu transferieren, muss der Benutzer auch über eine Benutzerkennung auf dem anderen Rechner verfügen.
1
ftp file transfer protocol – Wie das telnet für den Remote-Zugriff stammt auch der erste Vertreter dieser Kategorie aus dem militärischen ARPANET. Das File Transfer Protocol wurde dort als komfortable Methode entwickelt, um Dateien zwischen Rechnern unterschiedlichen Typs auszutauschen. Mit ftp kann nur zu solchen Accounts eine Verbindung aufgebaut werden, die über ein Passwort verfügen1 (was hoffentlich auf jedem Account der Fall ist). Mit ftp können nur Dateien, aber keine Verzeichnisse kopiert werden.
ftp [Hostname]
Wird beim Aufruf von ftp ein Hostname angegeben, so werden zunächst die Benutzerkennung und das zugehörige Passwort abgefragt. Nach einer erfolgreichen Anmeldung am Remote-Rechner gelangt der Benutzer in den ftp-
6
1. Ausgenommen sind so genannte anonyme FTP-Server, bei denen der Lesezugriff auf bestimmte Verzeichnisse für jeden erlaubt ist, ähnlich wie bei Web-Servern.
241
KAPITEL
14
Networking
Kommandomodus. Wurde keine gültige Kombination aus Benutzerkennung und Passwort angegeben oder wurde beim Aufruf der Hostname weggelassen, gelangt der Benutzer zwar auch in den Kommandomodus, muss dort aber erst mit dem Kommando open eine Verbindung zu einem Rechner aufbauen. Der ftp-Kommandomodus entspricht einem Kommandointerpreter, der durch ein spezielles Prompt (ftp>) seine Bereitschaft, Kommandos entgegenzunehmen, anzeigt. Soll ftp nicht interaktiv betrieben werden, kann eine Datei .netrc im Home Directory angelegt werden. In dieser Datei können Makros definiert werden, die Teile einer ftp-Sitzung oder die ganze Sitzung automatisieren. Nähere Informationen zu .netrc können der entsprechenden man-Page entnommen werden. Folgende wichtige Kommandos sind im Kommandomodus des ftp verfügbar: open
6 6 242
Mit diesem Kommando wird eine Verbindung zu einem Remote-Rechner geöffnet. Nach Eingabe des Kommandos wird der Benutzer zur Angabe einer Benutzerkennung und des zugehörigen Passwortes aufgefordert.
open Hostname
close
close schließt eine Verbindung zu einem Remote-Rechner. Der Benutzer verbleibt danach aber im ftp-Kommandointerpreter.
help
Über diesen Befehl kann die Online-Hilfe des ftp abgerufen werden. Im Normalfall liefert help eine Liste der verfügbaren Kommandos. Dem Befehl kann noch der Name eines anderen Kommandos folgen. help gibt in dem Fall detaillierte Hilfe zu diesem Befehl aus.
help [Kommando]
Netzdienste
bina
FTP kennt zwei Übertragungsmodi für Dateien: binär und ASCII. Im Binärmodus werden die Bytes einer Datei Bit für Bit ohne Umwandlung übertragen. bina1 schaltet den binären Übertragungsmodus ein. Bei Übertragungen zwischen Rechnern gleichen Typs sollte stets der binäre Modus verwendet werden, da er schneller ist. Bei unterschiedlichen Rechnertypen dürfen Textdateien nicht im Binärmodus, sondern nur im ASCIIModus übertragen werden.
asc
Der Befehl asc2 schaltet in den ASCII-Übertragungsmodus um, der für die richtige Übertragung von Textdateien sorgt. Der Zeichencode (z.B. ASCII, EBCDIC, Iso-Latin-1, ...) und die interne Darstellung an den Zeilenenden (Unix verwendet nur ein Line Feed, während DOS ein Carriage Return und ein Line Feed benötigt) werden dabei automatisch so umgewandelt, dass die Datei auf dem Zielrechner eine gültige Textdatei mit lesbaren Zeichen und Zeilen ist. Im Gegensatz zum binären Modus werden alle Bytes einer Datei daraufhin überprüft, ob sie gültige (druckbare) ASCII-Zeichen enthalten. Ist das nicht der Fall, gibt ftp am Ende der Übertragung eine entsprechende Meldung aus. Dateien, die unverändert auf das Zielsystem transportiert werden sollen, wie z.B. Bilddateien, ZIP-Archive o.Ä., dürfen demzufolge nicht im ASCII-Modus übertragen werden. Im ASCII-Übertragungsmodus werden aber auch Umsetzungen von ASCII-Zeichen vorgenommen, wenn das Zielsystem z.B. den EBCDIC-Zeichensatz verwendet.
cd
Soll auf dem Remote-Rechner in ein anderes Verzeichnis gewechselt werden (Default nach dem Anmelden ist das Home Directory des Accounts, unter dem der Benutzer sich angemeldet hat), geschieht dies durch das Kommando cd.
cd Pfadname12
lcd
lcd ist das Äquivalent zu cd, um das Working Directory auf dem lokalen
6
Rechner zu wechseln. Die Syntax ist identisch. pwd
Mit pwd kann der Pfad des Working Directorys auf dem Remote-Rechner angezeigt werden.
get
Das Kommando get kopiert eine Datei vom entfernten Rechner auf den lokalen Rechner. Bei diesem Kopiervorgang kann die Datei umbenannt werden, muss aber nicht.
get DateinameRemote [DateinameLokal]
6
1. Statt bina können Sie wahlweise auch binar, bin oder bi schreiben. 2. Statt asc können Sie auch wahlweise ascii, asci oder as schreiben.
243
KAPITEL
14
Networking
Werden beide Dateinamen angegeben, muss jeder in der am jeweiligen System gültigen Syntax geschrieben werden (z.B. lange Filenamen mit richtiger Groß-/Kleinschreibung am Unix-, kurze Filenamen am Windows-3-PC). Wird nur ein Name angegeben, erfolgt eine automatische Umwandlung des Dateinamens, wenn nötig. put
put ist das Gegenstück zu get und kopiert eine Datei vom lokalen Rechner
auf den Remote-Rechner.
6
put DateinameLokal [DateinameRemote]
Für die Syntax der Dateinamen gilt das Gleiche wie bei get. mget
6 6
244
Der Kommandoname mget steht für multiple get. mget kopiert mehrere Dateien vom Remote-Rechner auf den lokalen Rechner. Eine Umbenennung der Dateien ist im Rahmen des Kommandos nicht möglich. Die Namen der zu kopierenden Dateien können über Wildcards angegeben werden.
mget Datei/Dateien
mput
Beim multiple put werden mehrere Dateien vom lokalen Rechner auf den Remote-Rechner kopiert. Auch hier ist keine Umbenennung im Rahmen des Kommandos möglich.
mput Datei/Dateien
prompt
Das Kommando prompt ist ein Toggle (engl. für Ein-/Ausschalter) und schaltet zwischen interaktivem und nicht interaktivem Modus beim mget bzw. mput um. Im interaktiven Modus wird vor der Übertragung jeder Datei beim Benutzer rückgefragt.
quit
Mit quit wird der ftp-Kommandointerpreter beendet.
bye
Anstelle von quit kann auch bye benutzt werden.
Netzdienste
UNIX-Kurs [~] 138 > ftp box01
rcp
3
remote copy – Das Kommando rcp ist, wie das rlogin, ein Vertreter der r-Tools aus dem BSD-Unix. Es ist für das Kopieren von Dateien zwischen unterschiedlichen Unix-Rechnern gedacht und verwendet eine ähnliche Syntax wie das cp-Kommando. rcp kann nur dann für den Datentransfer zwischen zwei Unix-Rechnern benutzt werden, wenn es auf dem Remote-Rechner einen Account mit dem gleichen Benutzernamen gibt, unter dem der Benutzer sich auf dem lokalen Rechner angemeldet hat. Des Weiteren muss auf beiden Rechnern in den .rhosts-Dateien unter dieser Benutzerkennung der jeweils andere Rechner eingetragen sein. rcp verwendet wie auch das cp zwei unterschiedliche Syntaxvarianten.
rcp [Optionen] Rechner1 :Datei1 Rechner2 :Datei2
In dieser Variante wird eine Datei Datei1 vom Rechner Rechner1 unter dem Namen Datei2 auf den Rechner Rechner2 kopiert. Ist einer der Rechner der lokale Rechner, so kann hier der Rechnername mit dem nachfolgenden »:« entfallen.
rcp [Optionen] Rechner1:Datei/-en Rechner2:Verzeichnis
In der zweiten Variante werden die Dateien vom Rechner1 unter Beibehaltung ihrer Namen in das Verzeichnis Verzeichnis auf dem Rechner2 kopiert. Dabei muss vor jedem Dateinamen der Rechnername angegeben werden.
Besondere Vorsicht muss für das Kommando rcp bei der Verwendung von Wildcards gelten. Dabei gilt folgende Regel: Wildcards, die zu Mustern für Dateinamen gehören, die auf Remote-Rechnern liegen, sind stets zu quoten!
6 6 2 245
KAPITEL
14
Networking
Folgende Optionen sind für rcp verfügbar:
3
-p
Mit dieser Option bleiben die Einträge für die Änderungs- und Entstehungszeit sowie die Zugriffsrechte und der Eigentümereintrag im i-node beim Kopiervorgang unverändert.
-r
Wie auch beim cp können mit dieser Option ganze Verzeichnisstrukturen kopiert werden. Diese Option macht die wesentliche Stärke des rcp gegenüber dem ftp aus.
UNIX-Kurs [~] 139 > rcp box01:/usr/home/lutz/.tcshrc .
14.3.3
Informations- und Kommunikationsdienste
Vor dem Absetzen eines Netzkommandos möchte sich der Benutzer oft zunächst über den Zustand des Netzes oder eines bestimmten Rechners erkundigen. Warum remote auf einem Rechner arbeiten, wenn dieser ohnehin schon mit anderen Benutzern überlastet ist? Was für den seriösen Computerbenutzer oft eine sinnvolle Hilfe sein kann, wird unter Umständen vom Systemverwalter nicht gerne gesehen, weil sich hier auch Möglichkeiten zum Ausspähen von Benutzerkennungen und evtl. sogar von Passworten bieten. Seien Sie deshalb nicht verwundert, wenn Sie den einen oder anderen Dienst auf Ihrem Rechner nicht finden oder nicht ausführen dürfen (solange Ihr Systemverwalter solche tollen Sachen wie die Netzspiele battlezone (bz) und den Flug- und Luftkampfsimulator dogfight unangetastet lässt, ist er zumindest kein Spielverderber).
finger Das Kommando finger dient dazu, Informationen über Benutzer auf fernen Rechnern zu erlangen. Weil dies nicht ganz unproblematisch ist (wenn z.B. ein Hacker weiß, welche Benutzer auf einem System arbeiten, hat er damit auch schon Benutzerkennungen für etwaige Einbruchsversuche), mögen es viele Systemadministratoren nicht, wenn an ihren Systemen »herumgefingert« wird und unterbinden diesen Dienst.
6 3 246
finger [User ]@Rechner
UNIX-Kurs [~] 140 > finger @box01
Netzdienste Ein so abgesetztes finger-Kommando liefert eine Liste aller zur Zeit eingeloggten Benutzer mit Informationen über ihre Klarnamen (Fullname-Eintrag aus der /etc/passwd) und die Shell, mit der sie arbeiten, und diversen weiteren Angaben. Eine bessere Information kann sich ein Hacker kaum wünschen.
ping Dieses Werkzeug mit dem vom Ping-Pong-Spiel abgeleiteten Namen ist eine primitive, aber wertvolle Hilfe, wenn es darum geht, gestörte Netzverbindungen zu anderen Rechnern und Netzen zu finden.
ping Rechner
Mit ping kann bei einem anderen Rechner »angeklingelt« werden. Dies geht entweder direkt über seine IP-Adresse oder über einen Hostnamen aus der / etc/hosts oder von einem Nameserver.1 ping schickt so genannte pingPakete an den Zielrechner und schaut dann, wie viele dieser Pakete quittiert werden. Für jedes quittierte Paket erzeugt ping eine Ausgabezeile mit der Umlaufzeit für das Paket. Wurde ping mit ŸC abgebrochen, liefert es eine Statistik mit der durchschnittlichen Umlaufzeit und einem prozentualen Anteil verlorener Pakete.
6
Auf folgende Werte ist bei einer Fehlersuche zu achten: ✘ In einem lokalen mit 10Base2-Ethernet (ThinWire) verkabelten Netzwerk sollten die Umlaufzeiten bei wenigen Millisekunden (bis zu 10) liegen. ✘ Bleibt ping ganz stehen oder läuft es gar nicht erst los, hilft manchmal schon das Ruckeln am eigenen oder fremden Netzwerkkabel/-anschluss.2 ✘ Bei einer langsamen Modemleitung (2.400, 4.800 oder 9.600 Baud) kann die packetloss rate schon mal bei 30% liegen, weil eine größere Anzahl Pakete gebuffert wurden und zum Zeitpunkt des Abbruchs noch nicht verschickt waren. Bei einem lokalen ThinWire-Netzwerk ist aber alles andere als 0% nicht tolerierbar.
1. Ein Nameserver ist ein Rechner, der über eine »Adressdatenbank« für IP-Adressen verfügt. Über bestimmte Services wie DNS oder YP können Rechner bei einem Nameserver die IPAdresse eines anderen Rechners über dessen Hostnamen »erfragen«. Alternativ können auch Hostnamen und IP-Adressen in die /etc/hosts-Datei eingetragen werden, was allerdings den Nachteil hat, das dies nur lokal für einen Rechner geschieht. 2. Natürlich kann ein solcher Fehler auch mit einem Netzanalysator gefunden werden, aber mal ganz ehrlich: Wer wird denn gleich mit Haubitzen auf Spatzen schießen, solange er noch das eine oder andere Hausmittel auf Lager hat?
247
KAPITEL
14
Networking
Leider meldet die ping-Version des »alten« SunOS 4.x und von Solaris ohne weitere Optionen, wenn das Quittieren von Paketen geklappt hat, nur Host XXX is alive. Wenn Sie bei einer dieser Versionen von ping die Option -s direkt nach dem ping angeben, verhält sich aber auch dieses ping wie gewünscht.
3
UNIX-Kurs [~] 141 > ping 192.168.2.16
talk talk ist ein Kommando, mit dem eine Online-Kommunikation mit einem an-
deren Benutzer aufgebaut werden kann. Dabei ist es egal, ob sich dieser Benutzer auf der gleichen oder einer anderen Maschine befindet. Zum Aufbau der Kommunikation wird der gewünschte Gesprächspartner »angeklingelt«. Nur wenn dieser »abnimmt« und damit seine Gesprächsbereitschaft bekundet, wird die Verbindung aufgebaut. Das Terminal/Fenster, in dem der so genannte talk request abgesetzt wurde, wird halbiert. In der oberen Hälfte kann der Benutzer seine Eingaben machen, während er in der unteren Hälfte lesen kann, was sein Gesprächspartner tippt. Das Gespräch wird durch das Drücken von ŸC beendet.
6 3 248
talk User [@Rechner]
Sollten Sie einen talk request bekommen, äußert sich das durch ein Piepen und eine Ausgabe auf Ihrem Console-Fenster (oder wenn Sie an einem Terminal sitzen, auf diesem Terminal). Im talk request steht eine Zeile, die mit respond with beginnt und die im Anschluss das Kommando enthält, mit dem Sie antworten müssen, um die Verbindung aufzubauen. Am besten machen Sie ein Cut & Paste mit der Maus, um diesen Befehl auf Ihre Kommandozeile zu transferieren.
UNIX-Kurs [~] 142 > talk lutz@box01
Netzdienste
14.3.4
Electronic Mail
Mit der internationalen Vernetzung ist ein Thema immer mehr in den Vordergrund gerückt: die elektronische Post. Kaum ein Unternehmen ist heute nicht über E-Mail erreichbar und wenn Informationen mit dem anderen Ende der Welt ausgetauscht werden müssen, ist E-Mail oft die preisgünstigste und schnellste Methode.
mail Wenn das Mail-System entsprechend eingerichtet ist, kann elektronische Post für Empfänger auf dem gleichen Rechner und für Empfänger auf RemoteRechnern über das Kommando mail verschickt werden. Im Normalfall kann eine Mail interaktiv eingegeben werden, aber auch eine Vorbereitung der Mail in einer Datei und die Benutzung einer Eingabeumlenkung sind möglich.
mail User @[Rechner.]Domain
Der Aufbau von E-Mail-Adressen ist recht flexibel, da zum einen die Eingaben für User durch Alias-Namen verändert werden können und zum anderen, weil es in vielen Firmen Rechner gibt, die für die Versendung von Mail im LAN (Lokal Area Network) der Firma sorgen. Dadurch muss in der Regel nur die Domain, nicht aber der genaue Rechner angegeben werden.
UNIX-Kurs [~] 143 > mail
[email protected] Hallo Lutz, dies ist eine Test-Mail! Ich hoffe, sie erreicht dich.
6 3
Viele Gruesse :-) Ein Kursteilnehmer
ŸD
Auf vielen Systemen gibt es heute komfortable Mail-Reader wie z.B. elm, mutt oder pine. Diese Programme bieten im Allgemeinen ein Adressbuch für Ihre Mail-Adressen und machen den Zugriff auf empfangene Post extrem einfach. Fragen Sie Ihren Systemadministrator nach solchen Hilfen, bevor Sie direkt mit dem Kommando mail arbeiten.
1 249
KAPITEL
14
Networking
Übungen
14.4
Aufgaben
1. Melden Sie sich mit rlogin auf einem anderen Rechner an. Schauen Sie sich dort die Datei .rhosts an. Fehlt in der Datei der Eintrag für Ihren lokalen Rechner, so ergänzen Sie die Datei, indem Sie Ihren lokalen Rechnernamen hinzufügen (echo und Ausgabeumlenkung mit append benutzen). Melden Sie sich anschließend vom entfernten Rechner ab und wiederholen Sie dann den Anmeldevorgang. 2. Melden Sie sich mit telnet an demselben Rechner an. 3. Erstellen Sie auf dem anderen Rechner mithilfe der Ausgabeumlenkung eine Datei, die eine Liste der Dateien im Working Directory auf dem Remote-Rechner enthält. 4. Transferieren Sie die Datei aus 3.) einmal mit ftp und einmal mit rcp auf Ihren lokalen Rechner. 5. »Pingen« Sie ein paar Rechner aus Ihrem Netz an und vergleichen Sie die Statistiken. Namen für mögliche Rechner finden Sie in der Datei /etc/ hosts. 6. Versuchen Sie, ein finger auf alle Rechner aus 5.) zu machen, die auf das ping geantwortet haben.
14.4.1
Lösungen
Die Aufgaben zu diesem Kapitel lassen sich logischerweise nur dann bearbeiten, wenn Ihr Rechner in ein Netzwerk (lokal oder auch Internet) integriert ist. In den folgenden Beispielen sitzen wir an einem Rechner mit dem Namen hp01 und möchten Kontakt mit dem Rechner sgi15 aufnehmen. 1. Um sich auf einem entfernten Unix(!)-Rechner mit rlogin anzumelden, geben Sie das Kommando rlogin, gefolgt von der IP-Adresse oder dem Namen des Rechners, den Sie besuchen wollen, ein. UNIX-KURS [~] 70 > rlogin sgi15
Falls auf dem entfernten Rechner die Datei ~/.rhosts nicht existiert oder dort der Name Ihres lokalen Rechners nicht eingetragen ist, werden Sie nach Ihrem Passwort gefragt.
250
Aufgaben passwort: xxxxx Irix Release 6.3 IP32 sgi15 ...
Bei diesem Beispiel mussten wir unser Passwort angeben. Schauen wir uns nun die Datei .rhosts an: sgi-Lutz [~] 71 > more .rhosts hp02 sun01 pc06
Der Rechner, an dem wir gerade sitzen (in diesem Beispiel hp01), ist nicht dabei. Ergänzen wir nun diese Datei um den Namen unseres Rechners. sgi-Lutz [~] 72 > echo hp01 >> .rhosts
Achten Sie bei der Eingabe auf die doppelten Größer-als-Zeichen (>>), sie bewirken, dass der Eintrag hp01 an die existierende Datei angefügt wird. Bei nur einem Größer-als-Zeichen wäre die Datei durch die Zeile hp01 ersetzt worden! Überprüfen wir unsere Aktion: sgi-Lutz [~] 73 > more .rhosts hp02 sun01 pc06 hp01
Die Datei wurde um eine Zeile ergänzt. Wir melden uns nun bei dem fremden Rechner durch Eingabe von exit ab und sind jetzt wieder auf unserer Maschine (hp01). Sie erkennen dies leicht an den verschiedenen EingabePrompts: sgi_Lutz [~] 74 > exit UNIX-KURS [~] 75 >
Da auf dem entfernten Rechner in der Datei ~/.rhosts ein Eintrag für unseren lokalen Rechner existiert, werden wir beim nächsten rlogin nicht mehr nach unserem Passwort gefragt werden: UNIX-KURS [~] 76 > rlogin sgi15 IRIX (sgi15) sgi-Lutz [~] 1 >
2. Weil wir durch die erste Aufgabe noch immer auf dem entfernten Rechner zu Gast sind, muss die rlogin-Verbindung erst einmal beendet werden: sgi_Lutz [~] 77 > exit
251
KAPITEL
14
Networking
Nun nehmen wir – diesmal mit telnet – wieder Kontakt zu dem entfernten Rechner sgi15 auf: UNIX-KURS [~] 78 > telnet sgi15 IRIX (sgi15) login:lutz passwort: xxxxx ... sgi_Lutz [~] 79 >
Da telnet den .rhosts-Mechanismus nicht kennt, müssen grundsätzlich die Benutzerkennung und das Passwort eingegeben werden. 3. In Aufgabe 2 hatten wir uns gerade per telnet auf dem entfernten Rechner sgi15 angemeldet. Wir sollen nun eine Liste aller Dateien im Working Directory des entfernten Rechners erstellen. Dazu lenken wir die Ausgabe des Befehls ls -l oder auch ls -la in eine Datei um: sgi_Lutz [~] 80 >ls -l > verzeichnis.text
4. Diese Datei soll nun einmal via ftp und einmal via rcp auf unseren lokalen Rechner kopiert werden. Verlassen wir dazu den entfernten Rechner und verbinden uns erneut, diesmal mittels ftp: sgi_Lutz [~] 81 >ls -l > exit UNIX-KURS [~] 73 > ftp sgi15 Connected to sgi15. 220 sgi15 FTP server ready. User (sgi15:(none)): lutz 331 Password required for lutz. Password: xxxxx 230 User lutz logged in. ftp>
Die Eingabe der Benutzerkennung und des Passwortes ist bei ftp immer zwingend vorgeschrieben (es sei denn, es existiert auf dem entfernten Rechner die Datei ~/.netrc mit einem entsprechenden Eintrag) und kann nicht durch einen Eintrag in der Datei ~/.rhosts umgangen werden. Der FTP-Service benutzt eigene Kommandos, wobei die wichtigsten im vorangegangenen Kapitel vorgestellt wurden. Vielleicht wundern Sie sich, was die Zahlen (220, 331, 230) im Beispiel bedeuten: Der FTP-Server quittiert jedes Kommando mit einer Antwortzeile. Diese Antwort beinhaltet auch immer eine Art Fehlercode. Zahlen, die mit einer 2 beginnen, bedeuten: »bestätigt«, die mit einer 3 beginnen: »mehr Eingaben erforderlich« und 5: »Fehler bzw. abgelehnt«. Da wir nun eine ASCII-Datei (unser abgespeichertes Inhaltsverzeichnis aus Aufgabe 3) auf unseren lokalen Rechner übertragen wollen, müssen wir
252
Aufgaben als Übertragungsformat ASCII auswählen. Dies ist aber nur dann explizit nötig, wenn zwei Rechner mit unterschiedlichen Betriebssystemen miteinander kommunizieren. Der Befehl hierfür lautet asc oder auch ascii. Anschließend wird mit dem get ftp-Befehl die Datei transferiert. ftp> asc 200 Type set to A. ftp> get verzeichnis.text 200 PORT command successful. 150 Opening ASCII mode data connection for 'verzeichnis.text' (450 bytes). 226 Transfer complete. 462 bytes received in 0.01 seconds (47000 Kbytes/sec) ftp>
Der ftp-Server bestätigt den erfolgreichen Versand und wir können durch Eingabe von quit bzw. bye wieder auf unseren lokalen Rechner zurückkehren. ftp>bye 221 goodbye. UNIX-KURS [~] 82 >
Mit dem Befehl more oder cat können wir uns die Datei ~/verzeichnis.text anschauen. Die gleiche Aufgabe wollen wir nun mithilfe des rcp-Befehls erledigen. Voraussetzung hierfür ist, dass auf dem entfernten Rechner die Datei .rhosts existiert und dort auch Ihr lokaler Rechner aufgeführt ist. Da in unserem Home Directory die Datei verzeichnis.text bereits existiert, werden wir beim folgenden Kopiervorgang auch gleich den Namen ändern: UNIX-KURS [~] 83 > rcp sgi15:~/verzeichnis.text ./dir.text
Es hätte auch gereicht, nach der Bezeichnung des Rechners (sgi15:) nur den Dateinamen anzugeben, denn ohne Pfadangabe wird automatisch im Home Directory gesucht. Als Ziel haben wir das aktuelle Verzeichnis unseres lokalen Rechners (der Punkt) ausgewählt und der Datei auch gleich einen neuen Namen (dir.text) zugewiesen. 5. ping stellt ein zwar primitives, aber wirkungsvolles Werkzeug zum Testen einer Netzwerkverbindung zur Verfügung. Mit Angabe einer IP-Adresse oder eines Rechnernamens (aus der /etc/hosts-Datei oder durch Nutzung eines Nameservers) baut ping eine Verbindung zu dem entfernten Rechner auf und schickt fortlaufend Datenpakete. Der entfernte Rechner schickt dann diese Pakete wieder zurück. Informationen darüber, wie lan-
253
KAPITEL
14
Networking
ge ein Paket unterwegs war und ob es vollständig beim Empfänger angekommen ist, werden auf dem Bildschirm ausgegeben. Der Befehl muss mit den Tasten ŸC beendet werden. UNIX-KURS [~] 84 > ping sgi15 PING sgi01 (192.168.1.103): 56 data bytes 64 bytes from 192.168.1.103: icmp_seq=0 ttl=255 time=1.1 ms 64 bytes from 192.168.1.103: icmp_seq=1 ttl=255 time=1.0 ms 64 bytes from 192.168.1.103: icmp_seq=2 ttl=255 time=1.1 ms 64 bytes from 192.168.1.103: icmp_seq=3 ttl=255 time=1.0 ms 64 bytes from 192.168.1.103: icmp_seq=4 ttl=255 time=1.0 ms 64 bytes from 192.168.1.103: icmp_seq=5 ttl=255 time=1.0 ms 64 bytes from 192.168.1.103: icmp_seq=6 ttl=255 time=1.0 ms --- sgi01 ping statistics --7 packets transmitted, 7 packets received, 0% packet loss round-trip min/avg/max = 1.0/1.0/1.1 ms
6. Wie schon erwähnt, ist der finger-Befehl nicht ganz unumstritten und sei es auch nur aus Gründen des Datenschutzes. Daher wird der finger-Service von vielen Administratoren unterbunden. Versuchen Sie aber Ihr Glück, vielleicht finden Sie einen Rechner, der auf das Kommando reagiert. Geben Sie wieder den Rechnernamen oder dessen IP-Adresse ein. Vergessen Sie bei der Eingabe nicht das @-Zeichen: UNIX-KURS [~] 85 > finger @192.168.1.109 Welcome to Linux version 2.0.36 at server ! 14:29pm up 1 day, 20:27, 2 users, load average: 0.00, 0.00, 0.00 Login franz nagel
Name Tty Idle Login Time Office Lars Franzkowiak p1 1 Jan 20 12:27 (sgi01) Albert Nagel p0 1:09 Jan 20 6:19 (pc02)
Der hier abgefragte Rechner mit der IP 192.168.1.109 gab bereitwillig Informationen über seine Benutzer preis: Wir wissen nun, dass dort zwei Benutzer eingeloggt sind, einer mit dem Benutzernamen franz und einer mit dem Benutzernamen nagel. Herr Nagel ist ein ausgesprochener Frühaufsteher, da er sich schon heute früh um 6:19 in den Rechner einloggte. Dafür scheint er eine ausgiebige Mittagspause zu machen, denn seit einer Stunde und neun Minuten hat er den Rechner nicht mehr benutzt (Idle). Herr Franzkowiak hingegen kam heute sehr spät und loggte sich erst um 12:27 ein. Sie sehen, man kann mit dem finger-Befehl eine Menge über die Benutzer eines Rechners erfahren ...
254
KAPITEL 15
Datensicherung Unix ist ein Betriebssystem, das nicht gerade durch Sicherheitsabfragen zur Vermeidung von Fehlbedienungen glänzt. Selbst große Datenmengen lassen sich schnell und effizient löschen – so verschwinden ganze Dateibäume ohne Rückfrage mit einem kurzen rm-Kommando. Oft stellen die Dateien, die Benutzer im Laufe ihres Arbeitstages erstellen, erhebliche finanzielle Werte dar. Zwar besagt ein Sprichwort aus EDV-Kreisen, dass beim zweiten Mal alles schneller geht, aber das muss nicht sein. Datensicherung ist unabhängig vom Betriebssystem eine wichtige Sache – egal, ob im kommerziellen oder im privaten Bereich. Leider wird dies von vielen Anwendern nicht so gesehen. Rechner, von denen nie oder höchstens einmal im Jahr ein Backup1 gemacht wird, sind leider nicht die Ausnahme. Dabei sind heute kostengünstige Datensicherungsmedien verfügbar und auch der Aufwand für ein tägliches Backup ist nicht gravierend.
15.1
Sicherungsmedien
In den letzten Jahren sind die Preise für Festplatten geradezu inflationär gesunken, was zu ebenso inflationär steigenden Festplattenkapazitäten an den Rechnern geführt hat. Während vor zehn Jahren der durchschnittliche PC ca. 40 MByte Plattenkapazität besaß, sind wir heute bei Größen um die 20 GByte und mehr angelangt – Tendenz steigend.
1. Unter einem Backup ist eine Sicherheitskopie zu verstehen. Eine solche Kopie kann auf unterschiedliche Arten angefertigt werden.
255
KAPITEL
15
Datensicherung
Doch egal, wie viel Festplattenkapazität ein Rechner hat, die Benutzer geben nicht auf, ehe nicht ein Füllungsgrad um die 90% erreicht ist. Bei etwa 2 GByte scheiden damit bestimmte Sicherungsmedien, wie z.B. Disketten, von vornherein aus. Welche bleiben? Ein immer noch sehr verbreitetes (wenn auch bzgl. der Speicherkapazität nicht mehr ganz zeitgemäßes) Format sind die QIC-Tapes (Quarter Inch Cartridges). Die Angabe ¼ Inch bezieht sich auf die Breite des Magnetbandes. QIC-Tapes gibt es in den unterschiedlichsten Kapazitäten. Meist handelt es sich um Kassetten, wie z.B. die QIC 150, auf denen bis zu 150 MByte Daten gespeichert werden können. Mit zunehmender Verbreitung von Videogeräten hat sich der Video-8-mmStandard, der vor allen Dingen in Sony-Videokameras eingesetzt wird, auch für die Datensicherung eingebürgert. Unter dem Namen EXABYTE werden diese Bandlaufwerke, auf deren Kassetten sich unkomprimiert bis zu zwei GByte (90 m) speichern lassen, vertrieben. Durch den Einsatz von HardwareKompression kann dieser Wert bis auf das Doppelte gesteigert werden. Das zweite Datensicherungsformat der neuen Generation ist das 4-mm-DAT (Digital Audio Tape). Für die Datensicherung eingesetzt, lassen sich auf einem 90-m-DAT-Band ebenfalls unkomprimiert zwei GByte Daten speichern (DAT DDS-1). Auch bei diesen Geräten lässt sich die Speicherkapazität durch Hardware-Kompression auf das Doppelte steigern. Moderne Varianten bieten heutzutage bereits Kapazitäten von zwölf und mehr GBytes (DAT DDS-3 bzw. DAT DDS-4). Sowohl EXABYTE als auch DAT können neben günstigen Speichermedien mit guten Transferraten aufwarten, sodass die Speicherung eines 2 GByte großen Datenbestandes in weniger als zwei Stunden erfolgt ist. Diese Technik, gepaart mit einem vernünftigen Backup-Konzept, ist ein Garant für die Vermeidung von Datenverlust.
15.2
Grundlagen
Unix ist nicht beschränkt auf irgendein spezielles Backup-Medium. Bedingt ist dies durch die Geräteunabhängigkeit des Systems. Alle Kommandos, die Unix zur Archivierung von Dateien anbietet, greifen über den Kernel und die Hardware-Schnittstellen auf die Peripheriegeräte zu. Sie verwenden also die Standardschnittstelle für Geräte, die Device Descriptors. Der Zugriff auf diese Device Descriptors unterscheidet sich nicht von dem Zugriff auf ein Plain File. Aus diesem Grund kann das Vorgehen bei der Datensicherung unabhängig vom Sicherungsmedium betrachtet werden.
256
Grundlagen Prinzipiell werden zwei Arten von Backup-Strategien unterschieden: 1. Image Backups 2. Backups auf File-Ebene Image Backups werden vornehmlich im Bereich der Systemverwaltung eingesetzt, um ganze Partitionen in ihrem augenblicklichen Zustand zu konservieren. Bei diesen Verfahren werden die Bytes der gesamten Partition unabhängig von ihrer Zuordnung zu Dateien gesichert. Werden solche Bakkups wieder eingespielt, geschieht dies in der Regel in ihrer Gesamtheit. Die Partition wird dadurch bis auf das letzte Bit des gesicherten Zustandes wiederhergestellt. Backups auf File-Ebene beschränken sich auf die logische Ebene; sie sichern Dateien. Dabei spielen weder die genaue Struktur der i-nodes (welcher Datenblock steht wo) noch die Zuordnung zu Partitionen und Filesystemen eine Rolle. Lediglich die Daten einer Datei und separat davon die Informationen aus dem i-node bzgl. Eigentümer, Zugriffsrechten, Typ und Zeiten werden gesichert. Es ist egal, nach welchem Verfahren gesichert wird, in beiden Fällen wird auf dem Sicherungsmedium eine einzelne Datei, abgeschlossen durch eine End Of File-Marke, abgelegt, die sämtliche Daten enthält. Bei Backups der zweiten Kategorie werden diese Dateien auch Dateiarchive genannt, weil in ihnen mehrere Dateien mit all ihren Daten und Attributen archiviert sind. Für den normalen Anwender macht der Einsatz von Image Backups keinen Sinn, da er weder den Inhalt einer ganzen Partition lesen, geschweige denn wieder einspielen darf. Aus diesem Grund werden in diesem Abschnitt nur Kommandos zum Anlegen von File Backups behandelt. Die Dateiarchive, die von diesen Werkzeugen angelegt werden, verfügen im Prinzip über einen identischen Aufbau, der in Abb. 15.1 dargestellt ist. Natürlich unterscheiden sich die genauen Formate der Header für die Archive und die Formen, in denen die Angaben aus dem i-node vor den Daten jeder Datei gespeichert werden. Aus diesem Grund kann ein Archiv auch nur mit dem Befehl wieder gelesen werden, mit dem es geschrieben wurde. Leider gibt es unter Unix kein Kommando, das die unterschiedlichen Header unterscheiden kann, sodass es bei einer fehlenden Beschriftung nur hilft, alle Befehle durchzuprobieren.
257
KAPITEL
15
Datensicherung
Abb. 15.1: Aufbau eines Dateiarchivs
Um sich dieser Gefahr nicht auszusetzen, sollten auf jedem Sicherungsmedium folgende Daten vermerkt werden: ✘ Sicherungskommando einschließlich Optionen ✘ Datum der Sicherung ✘ Gesicherte Datenmenge (Rechner, Verzeichnisse/Projekte) Die Archivierungsbefehle unter Unix speichern grundsätzlich1 die Pfadangaben zu den Dateien mit ab. Wenn also der Name einer Datei oder eines Verzeichnisses mit einem absoluten Pfad angegeben wird, wird dieser in dem Archiv mitgespeichert. Beim Lesen aus dem Archiv wird versucht, die Datei unter genau dem Pfad wieder auf die Platte zu speichern, der im Archiv steht. Bei relativen Pfaden ist das kein Problem, da notfalls die Verzeichnisstruktur unterhalb des Working Directory neu aufgebaut werden kann. Sind aber absolute Pfade in einem Archiv enthalten, kann es zu Problemen kommen. Stehen nämlich im Archiv Verzeichnisse, die auf der lokalen Maschine nicht exis-
1. Nur bei der expliziten Angabe von einzelnen Dateien aus dem Working Directory speichert z.B. tar keine Pfadangaben.
258
Archivierungsbefehle tieren und die an Stellen im Dateibaum stehen, an denen der Benutzer kein Schreibrecht hat, können diese Daten nicht zurückgelesen werden. Deshalb gilt als erste Regel:
Wechseln Sie stets in das Oberverzeichnis der Daten, die Sie sichern wollen, und benutzen Sie dann relative Pfade bei der Sicherung!
1
Die zweite wichtige Regel leitet sich aus dem Mangel an Sicherheitsabfragen des Unix-Betriebssystems ab. Da Dateien auf der Platte auch durch das Einlesen gleichnamiger Dateien aus einem Archiv überschrieben werden können, lautet diese zweite Regel:
Lesen Sie immer erst das Inhaltsverzeichnis eines Archivs, bevor Sie es auspacken!
1
Die dritte Regel steht in sehr engem Zusammenhang mit der zweiten Regel und lautet:
Legen Sie für die Daten aus einem Archiv ein neues Verzeichnis an und wechseln Sie zum Lesen in dieses Verzeichnis!
1
So wird gewährleistet, dass sich feststellen lässt, welche Daten aus dem Archiv stammen. Wer diese drei einfachen Regeln beherzigt, erspart sich viele Unannehmlichkeiten und hoffentlich auch Datenverlust.
15.3
Archivierungsbefehle
Zum Umfang eines jeden Unix-Betriebssystems gehören mindestens die beiden Standardarchivierungskommandos tar und cpio. Darüber hinaus bietet fast jeder Hersteller noch ein eigenes Werkzeug an, das entweder speziell auf die Bedürfnisse seiner Hardware (z.B. bootable backups) zugeschnitten ist oder versucht, die Schwachstellen der beiden Standardprogramme zu kompensieren. Haben Sie eine uniforme Hardware-Landschaft im Unix-Bereich, empfiehlt es sich eigentlich immer, das Zusatzangebot des Herstellers zu nutzen. In der Regel ist diese Software einfach und unproblematisch in der Bedienung und
259
KAPITEL
15
Datensicherung
bietet zusätzliche Features, wie z.B. die Umwandlung absoluter in relative Pfadnamen beim Lesen eines Bandes. Bei einer heterogenen Hardware-Landschaft empfiehlt sich bei einem Datentransfer zu Zulieferern oder Kunden meist eines der beiden Standardprogramme. Welches der beiden Sie wählen, entscheiden Sie am besten anhand der nachfolgenden Beschreibungen.
15.3.1
tar
tar (tape archiver) ist eines der beiden Standardprogramme zur Archivierung. Es ist einfach zu bedienen und per Default mit dem Device Descriptor für das Bandlaufwerk (oder wenn dies nicht vorhanden ist, eventuell auch mit der Floppy) verbunden. Ältere Versionen des tar hatten außerdem oftmals Schwierigkeiten mit der Sicherung über mehrere Medien. tar berechnet für jede Datei, die es speichert, eine Prüfsumme, die beim Zurücklesen geprüft wird. Stimmt diese Prüfsumme nicht, meldet tar einen checksum error und weigert sich im Allgemeinen, weitere Informationen aus dem Archiv zu lesen.
Beim Lesen aus einem Archiv überschreibt tar grundsätzlich Dateien gleichen Namens unabhängig von deren Datum, sofern die Zugriffsrechte der Dateien dies erlauben. tar interpretiert den ersten Kommandozeilenparameter immer als Optionsblock, auch wenn man kein führendes Minuszeichen, wie bei Optionen sonst üblich, angibt. Grund für dieses Verhalten ist, dass mindestens eine der Optionen -c, -t oder -x angegeben werden muss, um das tar überhaupt benutzen zu können. Zu Optionen gehörige Argumente müssen nach dem Optionsblock in der Reihenfolge, in der die Optionen im Optionsblock auftauchen, angegeben werden. Über die drei Basisoptionen -c, -x und -t wird gesteuert, ob das Kommando ein Archiv erzeugt, ausliest oder das Inhaltsverzeichnis anzeigt.
6 3 260
tar -c [Optionen] [Argumente] Datei(-en)/Verzeichnis(-se)
Die Option -c steht für create und zeigt an, dass ein neues Archiv angelegt werden soll.
UNIX-Kurs [~] 144 > tar -cv .
Archivierungsbefehle Häufig wird der Befehl in der oben angegebenen Form gebraucht, um das Working Directory mit allen darunter liegenden Dateien und Verzeichnissen zu sichern. Der Punkt steht dabei als relativer Pfad für das Working Directory und darf auf keinen Fall weggelassen werden. Die Sicherung erfolgt auf das Default-Medium.
tar -t [Optionen] [Argumente]
Die Option -t steht für table of contents und sorgt dafür, dass das Inhaltsverzeichnis eines tar-Archivs gelesen wird. Bei dieser Operation werden keine Daten auf die Platte zurückgeschrieben. Sofern nichts anderes angegeben, wird vom Default-Medium gelesen.
UNIX-Kurs [~] 145 > tar -tv
tar -x [Optionen] [Argumente] [Datei/Dateien]
Das -x steht für extract und liest entweder einzelne Dateien (sofern angegeben) oder das ganze Archiv auf die Platte zurück. Sofern nicht anders definiert, wird vom Default-Medium gelesen.
UNIX-Kurs [~] 146 > tar -xv
Folgende Optionen lassen sich mit den drei Grundoptionen koppeln: -v
verbose – Mit der Option -v werden die Namen der Dateien, die in das Archiv geschrieben oder ausgelesen werden, auf dem Bildschirm ausgegeben. Diese Option sollte immer angegeben werden, um zu sehen, was tar sichert oder liest.
-b
blocking – Dieser Option folgt als Argument der so genannte BlockingFaktor. Der Blocking-Faktor ist eine ganze Zahl, die angibt, wie viele Einheiten pro 512 Byte zu einem tar-Block zusammengefasst werden sollen. Ein solcher Block stellt die kleinste auf dem Band adressierbare Einheit dar und wird »in einem Stück« an das Bandlaufwerk transferiert. Ist der Blocking-Faktor zu klein, kann die Performance bei der Datensicherung sinken.
6 3 6 3
261
KAPITEL
3
3
15
Datensicherung
UNIX-Kurs [~] 147 > tar -cvb 30 .
-f Argument
file – Soll nicht das Default-Medium verwendet werden, kann mit dem Argument der Option -f das Medium (durch Angabe des Device Descriptors) oder die Festplattendatei angegeben werden, auf das bzw. in die das Archiv geschrieben werden soll. Für das Lesen oder die Anzeige des Inhaltsverzeichnisses von einem anderen Medium oder einer Festplattendatei kann ebenfalls die Option -f verwendet werden.
UNIX-Kurs [~] 148 > tar -cvf /tmp/archiv.tar .
Bei der Option -f ist im Besonderen darauf zu achten, dass nicht die Reihenfolge vertauscht wird. Direkt nach der Option -f ist der Name der Archivdatei anzugeben und – wie immer zuletzt – welche Dateien oder Verzeichnisse in der Archivdatei gesichert oder aus dem Archiv gelesen werden sollen. Wird die Reihenfolge vertauscht, wird unter Umständen die zu sichernde Datei überschrieben. Ein Minuszeichen als Argument für die Option -f veranlasst tar, auf die Standardausgabe zu schreiben (-c) oder von dieser zu lesen (-t, -x). Dieses Vorgehen wird im Zusammenhang mit Pipes eingesetzt.
15.3.2
cpio
copy input/output – Das Archivierungsprogramm cpio geht auf den Vorschlag der X/OPEN-Gruppe zurück, ein einheitliches Werkzeug zur Datensicherung auf allen Unix-Plattformen zu schaffen. Auch wenn das tar heute nahezu einheitlich ist, so gab es doch in der Vergangenheit eine Reihe von Problemen mit unterschiedlichen Formaten. cpio stellt einen Konsens des X/OPEN-Konsortiums dar und zeichnet sich vielleicht gerade deshalb nicht durch eine einfache Bedienung aus. cpio nutzt
konsequent Unix-Features wie Pipes und Ein-/Ausgabeumlenkung, was den »unbedarften Benutzer« in einige Verwirrung stürzt, von Unix-Freaks aber »geliebt« wird. cpio hat kein Default-Medium, was stets die Angabe eines Ziels für die Daten-
sicherung bzw. einer Quelle für das Lesen erzwingt.
262
Archivierungsbefehle cpio erwartet die Namen aller Dateien, die es sichern soll. Im Gegensatz zum tar werden Verzeichnisse nicht automatisch mit ihrem Inhalt gesichert. Die Namen der zu sichernden Dateien erwartet cpio nicht als Kommandozeilen-
parameter, sondern als Daten über den Standardeingabekanal. Aus diesem Grund wird cpio fast immer von einem anderen Kommando mit den Namen der Dateien »gefüttert«, was das Sichern von Einzeldateien sehr umständlich macht. Was auf den ersten Blick unpraktisch erscheint, eröffnet in der Praxis die Chance, die vielfältigen Möglichkeiten des Kommandos find zur Selektion der zu sichernden Dateien zu nutzen. Besonders bei inkrementellen Tagessicherungen1 ist dieses Feature nicht von der einfachen Bedienbarkeit des tar aufzuwiegen. cpio überschreibt per Default nur dann beim Zurückspielen eine Datei, wenn
diese ein älteres Modifikationsdatum aufweist als die im Archiv befindliche Datei gleichen Namens. Ein anderes Verhalten muss durch eine Option »erzwungen« werden. cpio kennt keine Checksummen und kann somit auch aus nicht ganz intakten
Archiven Daten restaurieren (weil es nicht merkt, dass etwas nicht stimmt, und es sich an dem Header einer neuen Datei synchronisieren kann). Mit einer speziellen Option speichert cpio die Header für das Archiv und die Dateien im ASCII-Format, was Byte-Order-Probleme2 ausschließt. Über die drei Basisoptionen -o, -i und -it wird gesteuert, ob cpio ein Archiv erzeugt, ausliest oder das Inhaltsverzeichnis anzeigt.
Namensquelle | cpio -o [Optionen] > Device-/Dateiname
Beim Schreiben eines cpio-Archivs wird das Sicherungsmedium immer über eine Ausgabeumlenkung (>) auf den zugehörigen Device Descriptor oder einen Dateinamen angegeben. Als Namensquelle hat sich das find-Kommando eingebürgert. Es ist aber auch denkbar, die Namensliste direkt über die Tastatur einzugeben (dann steht keine Pipe vor dem cpio; die interaktiv eingegebene Namensliste wird mit ŸD abgeschlossen) oder einzelne Namen über das echo-Kommando in das cpio zu »pipen«.
6
1. Dabei handelt es sich um tägliche Sicherungen, bei denen die jeweils jüngsten bisher noch nicht gesicherten Dateien gespeichert werden. Bei diesem Konzept müssen oft mehrere Sicherungen eingespielt werden, bevor der gesamte Datenbestand wieder restauriert ist. Aus diesem Grund werden diese Sicherungen häufig zusammen mit wöchentlichen Vollsicherungen verwendet, um die Anzahl inkrementeller Sicherungen klein zu halten. 2. Die Byteorder beschreibt die Wertigkeit der einzelnen Bytes in einer Folge von Bytes. Zahlen werden durch diese unterschiedliche Sortierung der Bytes auf verschiedenen Rechnern unterschiedlich dargestellt.
263
KAPITEL
3 6 3 6
3 264
15
Datensicherung
UNIX-Kurs [~] 149 > find . -print | cpio -ocvB > /dev/tape
Im Beispiel wird der Inhalt des Working Directorys mit allen darunter liegenden Verzeichnissen auf Band gesichert.
cpio -it [Optionen] < Device-/Dateiname
Für das Lesen des Inhaltsverzeichnisses ist es unbedingt notwendig, dass ein i und ein t als Optionen angegeben werden. Fehlt das t, handelt es sich um einen Befehl zum Lesen von Daten, also zum Schreiben von Daten auf die Platte. Die Daten werden per Eingabeumlenkung (<) an das cpio übergeben.
UNIX-Kurs [~] 150 > cpio -itcvB < /dev/tape
cpio -i [Optionen] [Datei/Dateien] < Device-/Dateiname
Beim Lesen von Dateien aus dem Archiv auf die Platte muss beachtet werden, dass das cpio ohne entsprechende Option keine Verzeichnisse anlegt, die im Archiv gespeichert sind, (und dann natürlich auch die Dateien aus diesen Verzeichnissen nicht ausliest) und dass es auch keine auf der Platte befindlichen Dateien mit jüngerem Modifikationsdatum überschreibt. Die Daten werden per Eingabeumlenkung (<) an das Kommando übergeben. Sollen nur einzelne Dateien aus dem Archiv gelesen werden, werden deren Namen in der Kommandozeile angegeben.
UNIX-Kurs [~] 151 > cpio -icvBd < /dev/tape
Archivierungsbefehle Neben den Richtungsindikatoren -o für das Sichern (output) von Daten und -i für das Lesen (input) gibt es noch folgende Optionen: -v
verbose – Mit der Option -v gibt cpio auf der Standardfehlerausgabe (Vorsicht bei der Ausgabeumlenkung beim Schreiben!) die Namen der Dateien aus, die gesichert/gelesen werden.
-c
ASCII – Diese Option sollte eigentlich immer angegeben werden. Sie bewirkt, dass die Header des Archivs in ASCII-Notation geschrieben werden. Dieses Format ist beim Datenaustausch zwischen unterschiedlichen Hardware-Plattformen ein Muss.
-B
blocking – Diese Option setzt die Blockgröße des cpio (Default 512 Byte) um den Faktor 10 auf 5.120 Byte hoch.
-d
directory – Sollen Daten auf die Platte zurückgelesen werden, ist diese Option eigentlich immer anzugeben, es sei denn, es sind keine Verzeichnisstrukturen im Archiv gespeichert (in diesem Fall würde sie aber auch keinen Schaden anrichten). Sie sorgt dafür, dass Verzeichnisse aus einem Archiv ausgelesen werden.
-u
unconditional – Mit dieser Option kann das Überschreiben von auf der Platte befindlichen Dateien, die ein jüngeres Modifikationsdatum tragen, erzwungen werden. Abgesehen davon, dass Daten von einem Archiv nicht in ein bestehendes Verzeichnis eingelesen werden sollten, ist diese Option aus gutem Grund nicht die Default-Einstellung und sollte deshalb auch nur gezielt verwendet werden.
-O Rechner:Device Falls auf ein Bandlaufwerk an einem Remote-Rechner
zugegriffen werden soll, kann dessen Device Descriptor in der Form -O Rechner:Device angegeben werden. Dieses Feature ist aber mit Vorsicht zu genießen und funktioniert nur in den seltensten Fällen zwischen Rechnern unterschiedlicher Hersteller. Daneben kann die Option -O auch genutzt werden, um die Ausgabe des cpio in eine Datei oder auf ein Device zu schreiben, ohne den Mechanismus der Ausgabeumlenkung zu benutzen.1 -I Rechner:Device Die Option -I ist das Äquivalent für lesenden Zugriff auf
den anzugebenden Descriptor/Dateinamen zur Option -O.
1. Unter csh oder tcsh lassen sich nur Standardausgabe und -fehlerausgabe gemeinsam in eine Datei umlenken. Sollen in einer dieser beiden Shells die mit cpio gespeicherten Dateien in
einer Datei mitprotokolliert werden (bei verbose werden deren Namen über die Standardfehlerausgabe ausgegeben), darf die Ausgabeumlenkung nicht benutzt werden.
265
KAPITEL
15
Datensicherung
cpio wird mit seinen vielen Möglichkeiten und Optionen eigentlich allen Ansprüchen für ein Backup-Tool gerecht. Allerdings fehlen dem cpio leider Mög-
lichkeiten zur Verifizierung der gespeicherten Daten, sodass jedes andere Werkzeug, das ein Hersteller zusätzlich zu cpio und tar anbietet und das ähnliche Charakteristika aufweist, aber zusätzliche Verifikationen anbietet, cpio für reine Backup-Zwecke vorzuziehen ist.1
15.4
Datenkompression
Im Abschnitt über die Datensicherungsmedien wurde bereits der Aspekt der Datenkompression angeschnitten. Dort war die Rede von Hardware-Kompression. Darunter ist eine Form der Kompression zu verstehen, die nicht durch die CPU des Rechners selbst, sondern durch die entsprechenden Peripheriegeräte durchgeführt wird. Vorteil dieser Art der Kompression ist, dass der Rechner nicht belastet wird. Nachteil ist, dass bei diesem Verfahren nicht unbedingt ein Austausch von Bändern zwischen Geräten unterschiedlicher Hersteller möglich ist.
15.4.1
Software-Kompression
Die Hardware-Kompression ist nicht immer ein gangbarer Weg. Die Archivierungsbefehle unter Unix werden oft auch eingesetzt, um Dateiarchive auf der Festplatte zu erzeugen. Hintergrund dafür ist z.B., dass Befehle wie ftp nicht in der Lage sind, Baumstrukturen über das Netz zu übertragen. Also wird ein Dateiarchiv mit der Baumstruktur erzeugt und dann als einzelne Datei über das Netz verschickt. Bei dieser Art des Vorgehens ist es wünschenswert, die Daten des Dateiarchivs vor der Übertragung zu komprimieren, um die Zeit für den Netztransfer möglichst gering zu halten. Genau für diesen und ähnlich gelagerte Fälle bietet Unix das Kommando compress an. Es arbeitet nach einem Lempel-Ziv-Kompressionsverfahren (LZW). compress ersetzt die Originaldatei durch eine komprimierte Version der Datei, die die zusätzliche Endung .Z erhält. Diese Ersetzung findet allerdings nur statt, wenn die komprimierte Version wirklich kleiner ist als das Original. Insbesondere bei ASCII-Texten wie z.B. CAD-Schnittstellendateien können sehr hohe Kompressionsraten von bis zu 70% erzielt werden. Sollte eine Datei, die den gleichen Namen trägt wie die komprimierte Version, bereits existieren, wird sie nicht überschrieben. compress verändert den Zeitstempel der Datei nicht.
1. Die Hersteller wissen natürlich auch um die Schwächen der Standardwerkzeuge zur Datensicherung, und egal, ob es sich um SGIs bru oder Intergraphs scpio handelt, haben sie dieses Mehr an Sicherheit und Leistungsumfang.
266
Datenkompression Wird keine zu komprimierende Datei angegeben, arbeitet compress als Filter, liest also von der Standardeingabe und schreibt auf die Standardausgabe.
compress [Optionen] [Datei/Dateien]
Folgende Optionen sind verfügbar: -c
cat – Das Ergebnis der Kompression wird statt in eine Datei auf die Standardausgabe geschrieben. Die Originaldatei wird nicht ersetzt.
-v
verbose – Mit dieser Option wird nach der Komprimierung das Größenverhältnis zwischen der Originaldatei und der komprimierten Datei ausgegeben.
-b
bits – Dieser Option folgt eine ganze Zahl, die die Kompressionstiefe angibt. Die Zahl muss kleiner als 16 (Default) sein. Je größer die Zahl ist, desto stärker wird komprimiert – aber um so länger dauert auch der Vorgang der Kompression.
UNIX-Kurs [~] 152 > ls beispiel.txt UNIX-Kurs [~] 153 > compress beispiel.txt UNIX-Kurs [~] 154 > ls beispiel.txt.Z
6
3
Mit compress komprimierte Daten werden mit dem Kommando uncompress wieder dekomprimiert. Es wandelt die komprimierte Version mit der Endung .Z wieder in die unkomprimierte Originalversion um. uncompress kann auch als Filter eingesetzt werden, wenn keine Datei angege-
ben wird.
uncompress [Optionen] [Datei/Dateien]
Folgende Option ist verfügbar: -c
6
cat – Das Ergebnis der Dekompression wird statt in eine Datei auf die Standardausgabe geschrieben. Die komprimierte Version der Datei bleibt erhalten. Für die Kombination von uncompress mit der Option -c findet sich auf vielen Systemen auch das Synonym zcat.
267
KAPITEL
3
15
Datensicherung
UNIX-Kurs [~] 155 > uncompress beispiel.txt.Z UNIX-Kurs [~] 156 > ls beispiel.txt
Neben dem Standard-Kommando zur Kompression compress, welches zum Umfang jedes Unix-Systems gehört, finden vielfach auch Utilities aus der GNU-Familie Verwendung für diesen Zweck. Die GNU-Software unterliegt der so genannten GNU-Public-License. Das heißt, diese Software darf frei kopiert und weitergegeben werden, sofern der Quellcode ebenfalls mit weitergegeben wird. Dieses Verfahren soll dafür sorgen, dass niemand einen Vorteil aus der Verwendung dieser Software zieht, der einem etwaigen Kunden in Rechnung gestellt wird. Durch die Weitergabe des Quellcodes ist der Kunde jederzeit in der Lage, sich die Software selbst zu kompilieren und anschließend zu benutzen. Wie in vielen anderen Bereichen auch, hat die Free Software Foundation, die das GNU-Projekt ins Leben gerufen hat, im Bereich der Kompression leistungsfähigere Werkzeuge anzubieten als das Standard-Unix. Durch die große Verbreitung des Linux-Systems und die wachsende Anzahl von Internetzugängen ist diese Software heute für jeden Unix-Anwender verfügbar. So findet man heute auf fast jedem Unix-System auch das Werkzeug gzip zur Datenkompression. Vielfach wird heute auch das Werkzeug bzip2 eingesetzt, welches gegenüber dem gzip noch bessere Kompressionseigenschaften besitzt. Auch bzip2 unterliegt der GNU-Public-License.
15.4.2
gzip
gzip verringert das Datenvolumen von Dateien nach dem Lempel-Ziv-Verfah-
ren. Wenn möglich, wird jede Datei nach dem Komprimieren durch eine komprimierte Version der Datei mit der Endung .gz ersetzt. Die Zugriffsrechte und der Eigentümer der Datei bleiben dabei unverändert. Symbolic Links werden von gzip nicht bearbeitet. Die besten Komprimierungsergebnisse werden wie beim compress von ASCII-Dateien erzielt.
6 268
gzip [Optionen] [Datei/Dateien]
Datenkompression Folgende Optionen sind verfügbar: -c
cat – Das Ergebnis der Kompression wird statt in eine Datei auf die Standardausgabe geschrieben. Die unkomprimierte Version der Datei bleibt erhalten.
-d
decompress – Mit dieser Option wird eine bereits komprimierte Datei dekomprimiert.1
-f
force – Die Datei wird bearbeitet, obwohl sie einen Linkcount verschieden von eins hat oder die korrespondierende Datei bereits existiert. Diese Option ist mit Vorsicht zu genießen, da durch unsachgemäße Benutzung Dateien überschrieben werden können.
-l
list – Mit dieser Option können Informationen über eine komprimierte Datei ermittelt werden. Als Informationen sind die Originalgröße, die Größe der komprimierten Datei, die Kompressionsrate und der Name der Originaldatei verfügbar.
-r
recursive – Mit dieser Option kann mit gzip ein Dateiarchiv erstellt werden. Statt einzelner Dateien werden ganze Verzeichnisse mit ihrem Inhalt in ein Dateiarchiv gespeichert und gleichzeitig komprimiert.
-v
verbose – Wird diese Option beim Komprimieren oder Dekomprimieren von Dateien angegeben, wird die Kompressionsrate jeder einzelnen Datei ausgegeben.
-V
version – Diese Option führt dazu, dass die Versionsnummer des gzip ausgegeben wird. Nach der Ausgabe wird das gzip beendet.
UNIX-Kurs [~] 157 > gzip beispiel.txt UNIX-Kurs [~] 158 > ls beispiel.txt.gz
3
Obwohl man auch mit gzip selbst schon Dateien dekomprimieren kann, gibt es genau wie beim compress auch ein eigenes Kommando zum Dekomprimieren.
15.4.3
gunzip
gunzip ist in der Lage, Dateien, die mit compress, pack, zip und gzip kompri-
miert wurden, zu dekomprimieren.
1. siehe gunzip
269
KAPITEL
15
Datensicherung
Jede Datei, die als Parameter angegeben wird und deren Name auf .z, -z, _z, .gz, -gz, _gz oder .Z endet, wird von gunzip durch die dekomprimierte Datei ersetzt. gunzip erkennt auch die spezielle Endung .tgz, welche für komprimierte tar-Archivdateien steht.
6
gunzip [Optionen] [Datei/Dateien]
Folgende Option ist verfügbar: -c
cat – Das Ergebnis der Dekompression wird statt in eine Datei auf die Standardausgabe geschrieben. Die komprimierte Version der Datei bleibt erhalten.
Für diese Funktionalität existiert eine veränderte Version von zcat, die in der Lage ist, auch Dateien, die mit gzip komprimiert sind, zu verarbeiten.
3
UNIX-Kurs [~] 159 > gunzip beispiel.txt.gz UNIX-Kurs [~] 160 > ls beispiel.txt
Übungen
15.5
Aufgaben
1. Sichern Sie den Inhalt Ihres Home Directorys mit tar in eine Datei. 2. Worauf müssen Sie bei der Sicherung in eine Datei achten? 3. Lesen Sie das Inhaltsverzeichnis Ihrer Sicherung. 4. Legen Sie ein Unterverzeichnis in Ihrem Home Directory an und spielen Sie Ihre Sicherung in dieses Verzeichnis wieder ein. 5. Wiederholen Sie die Übungen 1 bis 4 mit cpio. 6. Kopieren Sie das in Aufgabe 1 erzeugte Dateiarchiv in Ihr Home Directory und komprimieren Sie es. 7. Speichern Sie alle Dateien, die in der letzen Woche verändert worden sind, in ein Dateiarchiv. Welchen der beiden Sicherungsbefehle müssen Sie verwenden?
270
Aufgaben
15.5.1
Lösungen
1. Wechseln Sie – falls noch nicht geschehen – in Ihr Home Directory. Der Befehl zum Erstellen eines tar-Archivs in eine Datei lautet: UNIX-KURS [~] 80 > tar -cvf /tmp/home.tar .
Beachten Sie, dass die Optionen des tar-Befehls entgegen der Unix-Vereinbarung nicht mit einem Minus-Zeichen eingeleitet werden müssen. Die drei Optionen -cvf bedeuten: c
create – Erzeuge ein Archiv
v
verbose – Zeige an, welche Dateien bearbeitet werden
f
file – Sichere nicht auf das Bandlaufwerk, sondern in eine Datei
Der Option f muss als Argument ein Dateiname folgen. Warum wir in diesem Fall die Datei in das Verzeichnis /tmp schreiben, wird in Aufgabe 2 erklärt. Am Ende der Eingabezeile steht dann noch in relativer Pfadangabe, was gesichert werden soll. In diesem Fall – wir stehen im Heimatverzeichnis – soll also das Working Directory gesichert werden. (Dafür steht der Punkt – schauen Sie noch einmal genau in die Zeile mit dem tar-Befehl.) Sie wissen, dass das Heimatverzeichnis auch über die Tilde (~) angesprochen werden kann. Dies ist aber ein absoluter Pfad (die Tilde wird von der Shell expandiert zum Heimatverzeichnis, also z.B. /home/unix). Warum es so wichtig ist, beim Anlegen eines Archivs relative Pfade zu benutzen, finden Sie in der Lösung zu Aufgabe 4 erläutert. 2. Angenommen, Sie hätten in Aufgabe 1 folgenden Befehl eingegeben: UNIX-KURS [~] 81 > tar -cvf home.tar .
Der tar-Befehl hätte eine Sicherungsdatei in unserem Home Directory (wir stehen im Home Directory und der Punkt am Ende der Eingabezeile bedeutet ja »das aktuelle Verzeichnis«) angelegt und dort alles hineingepackt, was in und unterhalb unseres Home Directory liegt. ... Ahnen Sie es? Da der tar-Befehl das Dateiarchiv zunächst nicht im Hauptspeicher erzeugt und dann auf einen Schlag auf die Platte schreibt, sondern das Archiv von der ersten gesicherten Datei an auf Festplatte anlegt, würde die Sicherungsdatei home.tar in sich selbst eingepackt. In dem Moment, wo der tar-Befehl anfängt zu arbeiten, wird die Datei home.tar vom Befehl erzeugt und nacheinander jede Datei (in alphanumerischer Reihenfolge) in und unterhalb des Home Directorys in home.tar geschrieben. Irgendwann wird der tar-Befehl auch auf die Datei home.tar treffen und diese Datei in sich selbst einpacken.
271
KAPITEL
15
Datensicherung
Daher ist es wichtig, die Sicherungsdatei in ein Verzeichnis zu schreiben, das nicht selbst gesichert wird. Dies ist nicht ganz einfach, wenn wir unser Heimatverzeichnis sichern wollen, da wir für andere Verzeichnisse meist kein Schreibrecht besitzen. Im Unix-Dateibaum ist jedoch ein Verzeichnis, nämlich /tmp, so eingerichtet, dass alle Benutzer Schreibrecht in diesem Verzeichnis haben. (Dennoch können andere Benutzer Dateien, die Sie dort anlegen, nicht löschen. Aber das ist ein anderes Thema. Wir nennen nur als Stichwort das Sticky Bit.)
1
Abschließend noch ein Tipp: Sie sollten das zu sichernde Verzeichnis immer mit relativem Pfad angeben! Ein absoluter Pfad kann dazu führen, dass die gesamte Sicherung nicht zurückgespielt werden kann.
Dazu ein Beispiel: Angenommen, Sie haben von Ihrem Home Directory /home/lutz eine Sicherung angelegt und möchten dieses nun auf einem anderen Rechner wieder einspielen. Das neue Home Directory liegt dort aber unter /usr/ people/lutz. Bei einer Sicherung in absoluten Pfaden würde beim Einlesen versucht werden, im Verzeichnis / – in dem Sie höchstwahrscheinlich kein Schreibrecht haben – ein Verzeichnis home anzulegen. 3. Das Inhaltsverzeichnis wird durch die Option t angezeigt. Da unsere Sicherungsdatei in dem Verzeichnis /tmp liegt, lautet der Befehl: UNIX-KURS [~] 82 > tar -tvf /tmp/home.tar
4. Unsere Sicherung soll nun in einem neuen Verzeichnis ausgepackt werden. Dazu legen wir zunächst ein neues Directory an und wechseln anschließend dort hinein. UNIX-KURS [~] 83 > mkdir so_wars UNIX-KURS [~] 84 > cd so_wars UNIX-KURS [so_wars] 85 >
Bevor wir das Archiv auspacken, folgt hier noch einmal der Hinweis, dass dies nur dann in den aktuellen Ordner ausgepackt wird, wenn wir es in Aufgabe 1 mit relativer Pfadangabe (der Punkt) erzeugt haben. Hätten wir einen absoluten Pfad angegeben, so würde jetzt das Archiv nicht in das neue Verzeichnis so_wars geschrieben, sondern es würden die absoluten Pfade der gesicherten Dateien benutzt! UNIX-KURS [so_wars] 86 > tar -xvf /tmp/home.tar
Es wird lediglich der Name der Sicherungsdatei angegeben. Ausgepackt wird in das aktuelle Verzeichnis so_wars. Schauen Sie sich nun mit dem Befehl ls -la die Dateien und Verzeichnisse in so_wars an.
272
Aufgaben 5. Die Syntax des Befehls cpio ist etwas komplexer. Dies liegt daran, dass der Befehl beim Schreiben (Option -o) die Namen der zu sichernden Dateien auf der Standardeingabe erwartet und das Archiv auf die Standardausgabe schreibt. cpio muss daher über eine Pipe, normalerweise von einem findKommando, gefüttert werden. Die Ausgabe wird üblicherweise umgelenkt, entweder an einen Device Descriptor (z.B. /dev/tape) oder in eine Datei. Für das Schreiben des Heimatverzeichnisses würde der Befehl lauten: UNIX-KURS [~] 87 > find . -print | cpio -ocvB > /tmp/home.cpio
Das Inhaltsverzeichnis eines Dateiarchivs kann mit der Option -it angezeigt werden. Das Kommando cpio erwartet das Archiv auf der Standardeingabe. In unserer Aufgabe ist die Standardeingabe entsprechend auf die zuvor erstellte Datei umzuleiten: UNIX-KURS [so_wars] 88 > cpio -itcvB < /tmp/home.cpio
Soll das Archiv ausgelesen werden, ist das t im Optionsblock durch ein d zu ersetzen. Die Option d bewirkt, dass Verzeichnisse (Directories), deren Inhalt im Archiv gespeichert ist, angelegt werden, wenn sie nicht bereits auf der Platte vorhanden sind: UNIX-KURS [so_wars] 89 > cpio -idcvB < /tmp/home.cpio
6. Wechseln wir zunächst wieder in unser Home Directory und kopieren anschließend die Sicherungsdatei home.tar dorthin. UNIX-KURS [so_wars] 90 > cd; cp /tmp/home.tar .
Nun komprimieren wir diese Datei: UNIX-KURS [~] 91 > compress -v home.tar
Durch die Option -v (verbose) wird das Größenverhältnis zwischen der Originaldatei und der komprimierten Datei ausgeben. Der compress-Befehl erzeugt eine komprimierte Datei, die unter dem Namen der Originaldatei, erweitert um die Endung .Z, abgelegt wird. Nach Abschluss der Komprimierung wird die Originaldatei gelöscht. In unserem Beispiel existiert das tar-Archiv des Heimatverzeichnisses also nun nur noch in komprimierter Form unter dem Namen home.tar.Z. Das Ganze lässt sich durch den Befehl uncompress wieder zurückverwandeln. 7. Alle Dateien, die in der letzten Woche geändert wurden, listet der folgende find-Befehl auf: find . -mtime -8 -print
273
KAPITEL
15
Datensicherung
Er findet alle Dateien unterhalb des Working Directorys, das hier mit dem Punkt als Startverzeichnis vereinbart wird. Beim Nutzen eines find-Befehls zur Dateiarchivierung sollte beachtet werden, dass der Befehl Dateinamen als relative oder als absolute Pfade zurückgibt, je nachdem ob das Startverzeichnis als relativer oder als absoluter Pfad angegeben wird. (Nochmals der Hinweis: Beim Schreiben eines Archivs sollten Sie relative Pfadnamen verwenden.) In Aufgabe 5 wird cpio bereits von einem find-Befehl mit den Namen der zu sichernden Dateien »gefüttert«. Wird dieser durch den hier vorgestellten find-Befehl ersetzt, so ist die Aufgabe gelöst: find . -mtime -8 -print | cpio -ocvB > /tmp/last_week.cpio
Für den Fall, dass Sie auf die Idee kommen, die Aufgabe mit einem tarBefehl unter Zuhilfenahme der Kommando-Substitution zu lösen, denken Sie bitte daran, dass der Kommandoaufruf scheitert, falls der find-Befehl mehr als 255 Dateinamen als Ergebnis liefert.
274
KAPITEL 16
Der Texteditor vi Wie auch die meisten anderen Betriebssysteme verfügt Unix über einen eigenen Texteditor – den vi. Er gehörte ursprünglich zur BSD-Variante des UnixSystems und ist von Bill Joy entwickelt worden. Später wurde der vi auch der System V-Linie hinzugefügt, sodass er heute auf jedem Unix-System zu finden ist. Als der vi entstand, waren Fernschreibkonsolen noch gängige Eingabegeräte für Computer und an grafische Bedienoberflächen, wie wir sie heute kennen, dachte man noch nicht einmal. Diese Umstände sind nicht spurlos am vi vorübergegangen. So verfügt er z.B. nicht über eine Menüsteuerung oder über Möglichkeiten, Text durch reverse Darstellung als markiert zu kennzeichnen. Weiterhin werden die Kommandos ohne Echo auf dem Bildschirm ausgeführt – man sieht also nur an der Reaktion, welches Kommando man eingegeben hat. Diese nicht gerade gelungene Bedienerführung ist einer der Hauptkritikpunkte an diesem Editor und führt bei Erstbenutzern oft zu Ablehnung. Für solche Anwender eignen sich oft grafische Editoren wie der einfache dtpad des CDE besser. Ungeachtet dieser Schwächen ist der vi dennoch ein wichtiges Hilfsmittel und in Ermangelung einer Alternative oft auch der einzige auf einem Unix-System verfügbare Editor. Darüber hinaus bietet der vi eine ansehnliche Palette von Features, die so manchen moderneren Editor vor Neid erblassen lassen. Aus diesen Gründen sollen auf den folgenden Seiten die wichtigsten Kommandos und die grundlegende Bedienung des vi beschrieben werden.
275
KAPITEL
16 16.1
Der Texteditor vi
Grundlagen
Der vi verfügt über vier verschiedene Modi: ✘ Direkt nach dem Aufruf befindet sich der vi stets im Kommandomodus. In diesem Modus darf der Cursor mithilfe der Cursortasten oder durch entsprechende Kommandos positioniert werden. Ferner können in diesem Modus Kommandos abgesetzt werden. ✘ Zur Eingabe von Text ist der vi erst nach Übergang in den Eingabemodus bereit. In diesen Modus, in dem die Cursortasten nicht benutzt werden dürfen, wird durch Eingabe eines Editierkommandos gewechselt. Nach der Eingabe von È kehrt der Editor wieder in den Kommandomodus zurück. ✘ Wird im Kommandomodus ein Suchkommando abgesetzt, schaltet der Editor in den so genannten Statuszeilenmodus. Nach Beendigung des Suchvorgangs wird automatisch wieder in den Kommandomodus zurückgekehrt. ✘ Der vi wird oft als Frontend für den zeilenorientierten Editor ex bezeichnet, da viele der Möglichkeiten des vi durch Aufrufe von ex-Kommandos realisiert werden. Um ein ex-Kommando auszuführen, muss zunächst durch die Eingabe eines Doppelpunkts in den ex-Modus gewechselt werden. Dieser wird nach Ausführung des ex-Kommandos automatisch wieder verlassen. Die nachfolgende Abbildung soll das Zusammenspiel dieser vier Modi veranschaulichen. vi Dateiname
Abb. 16.1: Modi des vi
Kommandomodus
:
i, I, a, A, o, O Enter
Ex-Modus
276
/, ?, n, N Esc
Eingabemodus
Statuszeilenmodus
Der Kommandomodus Leider zeigt der vi nicht per Default an,1 in welchem Modus er sich gerade befindet, was insbesondere im Eingabemodus zu Problemen führt. Während der ex-Modus und der Statuszeilenmodus an der Cursorposition in der letzten Bildschirmzeile zu erkennen sind, unterscheiden sich Kommandomodus und Eingabemodus rein äußerlich nicht. Deshalb sollte bei Unklarheit, in welchem der beiden Modi man sich befindet, die È-Taste betätigt werden, um gezielt in den Kommandomodus zu wechseln.
16.2
Der Kommandomodus
Der Kommandomodus des vi ist der Ausgangspunkt für die Bearbeitung von Texten. Vom Kommandomodus aus wird in die drei anderen Modi verzweigt. Daneben dient der Kommandomodus auch zur Cursorpositionierung, zur Definition von Textmarken, zum Löschen von Zeichen, Zeilen und Zeilenbereichen sowie zum Absetzen von Änderungskommandos.
16.2.1
Cursorpositionierung
Neben den Cursortasten stehen im Kommandomodus des vi noch die folgenden Tasten bzw. Tastenkombinationen zur Positionierung des Cursors zur Verfügung: 0
Durch die Eingabe einer Null wird der Cursor auf den Anfang der aktuellen Zeile positioniert.
^
Durch die Eingabe eines ^ wird der Cursor auf das erste nicht leere Zeichen der aktuellen Zeile positioniert.
$
Die Eingabe eines Dollarzeichens setzt den Cursor auf das letzte Zeichen in der aktuellen Zeile.
G
Bei Eingabe des Großbuchstabens G wird der Cursor auf die letzte Zeile der Datei gesetzt.
1G
Bei Eingabe von 1G wird der Cursor auf die erste Zeile der Datei gesetzt.
nG
Für das n kann eine beliebige Ziffernfolge eingegeben werden, die vom vi als Zeilennummer interpretiert wird. Existiert die Zeilennummer, wird der Cursor auf die entsprechende Zeile positioniert.
ŸF
Mit dieser Tastenkombination wird um eine Bildschirmseite vorwärtsgeblättert.
ŸB
Mit dieser Tastenkombination wird um eine Bildschirmseite zurückgeblättert.
1. Man kann den vi dazu bewegen, anzuzeigen, wenn er sich im Eingabemodus befindet, siehe Abschnitt 15.6.
277
KAPITEL
16
Der Texteditor vi
h
Mit dieser Taste kann der Cursor um ein Zeichen nach links bewegt werden. Auf den meisten Systemen kann natürlich auch die entsprechende Cursortaste verwendet werden.
j
Mit dieser Taste kann der Cursor um eine Zeile nach unten bewegt werden. Auf den meisten Systemen kann natürlich auch die entsprechende Cursortaste verwendet werden.
k
Mit dieser Taste kann der Cursor um eine Zeile nach oben bewegt werden. Auf den meisten Systemen kann natürlich auch die entsprechende Cursortaste verwendet werden.
l
Mit dieser Taste kann der Cursor um ein Zeichen nach rechts bewegt werden. Auf den meisten Systemen kann natürlich auch die entsprechende Cursortaste verwendet werden.
16.2.2
Zeichen und Zeilen löschen
Aus dem Kommandomodus des vi kann man sowohl einzelne Zeichen als auch ganze Zeilen und Zeilenbereiche löschen. x
Mit der Eingabe eines x wird das Zeichen, auf dem der Cursor steht, gelöscht.
dd
Mit dieser Eingabe wird die Zeile, in welcher der Cursor steht, gelöscht.
Beide Befehle können durch einen vorangestellten Wiederholungsfaktor auf mehrere Zeichen bzw. Zeilen angewandt werden. So löscht die Eingabe von 4x vier Zeichen und die Eingabe von 12dd zwölf Zeilen jeweils ab der Cursorposition. Die Möglichkeit, vorangestellte Wiederholungsfaktoren anzugeben, bietet der vi auch bei anderen Editierkommandos.
2
278
Bedenken Sie immer, dass Sie kein Echo für die eingegebenen Kommandos sehen, bevor diese ausgeführt werden. Gerade beim Löschen mit einem Wiederholungsfaktor kann also eine prellende Taste oder ein Zahlendreher fatale Folgen haben. Sollte Ihnen ein solches Ungeschick widerfahren, haben Sie die Möglichkeit, den letzten Befehl rückgängig zu machen.
Der Kommandomodus
16.2.3
Kommandos zurücknehmen und wiederholen
Wie im letzten Abschnitt schon erwähnt, verfügt der vi auch über eine undoFunktion. u
Die undo-Funktion des vi dient dazu, den letzten Änderungsbefehl rückgängig zu machen. Unter einem Änderungsbefehl versteht man z.B. den letzten Löschbefehl oder die letzte Eingabe im Eingabemodus, aber auch das undo selbst. Mit dem undo kann allerdings nur genau der letzte Änderungsbefehl rückgängig gemacht werden. Die Eingabe eines zweiten undo-Kommandos nimmt das vorangegangene undo-Kommando zurück, führt also zu einer Wiederholung des zuvor zurückgenommenen Änderungsbefehls. Eine Fehleingabe kann daher nur solange zurückgenommen werden, wie noch kein weiteres Kommando im vi abgesetzt wurde. Sollten Sie bei der Arbeit im vi z.B. an einer Stelle 100 statt zehn Zeilen gelöscht haben, dies aber erst nach Eingabe eines weiteren Kommandos bemerken, so bleiben die 100 Zeilen unwiederbringlich verschwunden.
Das folgende Kommando ist ein wenig ungewöhnlich für Editoren, wird aber von vi-Freunden sehr geschätzt. .
Die Eingabe eines Punktes im Kommandomodus wiederholt das letzte Änderungskommando an der aktuellen Cursorposition.
16.2.4
Markieren und Kopieren
ma Mit dem Kommando m wird eine Marke definiert. Als Bezeichner für eine Marke muss ein Kleinbuchstabe folgen. Marken dienen der Definitionen von Bereichen und als Sprungmarken zu bestimmten Textstellen. Eine Marke wird mit 'a (a ist dabei der Bezeichner der Marke) angesprungen bzw. bei einer Bereichsangabe referenziert, vgl. Abschnitt 16.5.2. Die Befehle zum Kopieren im vi sind etwas gewöhnungsbedürftig, aber genau genommen funktionieren sie nach dem gleichen Prinzip wie in anderen Editoren auch: Eine gewisse Anzahl von Zeilen wird in einen Puffer kopiert, von dem aus sie wieder in die Datei eingefügt werden können. Der vi verfügt über 27 Puffer. 26 der Puffer sind jeweils durch einen Kleinbuchstaben ansprechbar. Der 27. Puffer, der auch für die undo-Funktion benutzt wird, ist unbenannt.
279
KAPITEL
16
Der Texteditor vi
nyy
Für n kann in diesem Kommando eine beliebige Ziffernfolge angegeben werden. Der vi kopiert, beginnend mit der Zeile, in welcher der Cursor steht, n Zeilen in den unbenannten Puffer. Um nur eine Zeile zu kopieren, kann auf die Eingabe der Ziffer 1 verzichtet werden.
"ay'e
Mit diesem Kommando kopiert der vi, beginnend bei der Zeile, in welcher der Cursor steht, alle Zeilen bis zur Marke e in den benannten Puffer a.
P
Die Zeilen aus dem unbenannten Puffer werden nach der aktuellen Zeile eingefügt.
"ap
Die Zeilen aus dem benannten Puffer a werden nach der aktuellen Zeile eingefügt.
16.2.5
vi-Kommandos für Fortgeschrittene
Wie bereits angesprochen, sind die Befehlsfolgen und Kommandos des vi nicht einfach zu merken und an vielen Stellen recht kryptisch. Allerdings liegt die wahre Stärke des vi in der Kombination verschiedener Befehle. Wer also bis in die Tiefen des vi hinabsteigen will, sollte den folgenden Abschitt unbedingt lesen – den anderen sei gesagt, es geht auch ohne die folgenden Befehle. Xp
Mit dieser Befehlskombination kann man zwei Zeichen vertauschen.
Ddp
Diese Kombination vertauscht zwei Zeilen.
1GyGGp
Durch die Kombination dieser Befehle wird der Inhalt der aktuellen Datei verdoppelt.
Besonders interessant sind die vi-Kommandos, die sich auf Textobjekte anwenden lassen. Der vi kennt eine Reihe solcher Textobjekte. Die nächste Liste zeigt die wichtigsten Textobjekte des vi.
280
w,W
Wort
Unter einem Wort versteht der vi eine Folge von Zeichen, die durch ein Leerzeichen von anderen Zeichen getrennt sind. Ein w steht dabei für ein Wort, das nur aus Buchstaben und Ziffern besteht, und W für ein Wort, das auch Sonder- und Satzzeichen enthalten darf.
)(
Satz
Ein Satz ist eine Folge von Worten, die durch ., ! oder ? abgeschlossen wird. ) steht dabei für das Ende eines Satzes und ( für den Anfang eines Satzes.
}{
Paragraph
Ein Paragraph ist eine Folge von Sätzen, die durch eine Leerzeile eingeleitet und ebenfalls durch eine Leerzeile abgeschlossen wird. } steht dabei für das Ende eines Paragraphen und { für den Anfang eines Paragraphen.
Der Eingabemodus Diese Textobjekte lassen sich mithilfe der beiden Editorkommandos c (change) und d (delete) für gezielte Editieraktionen benutzen. Die folgende Liste zeigt einen Ausschnitt der Kommandos, die sich mit diesen beiden Kommandos in Verbindung mit den Textobjekten bilden lassen. dw
Löschen eines einzelnen Wortes
ndw
Für n kann in diesem Kommando eine beliebige Ziffernfolge angegeben werden. Der vi löscht dann n Worte.
d)
Löschen bis zum Ende des Satzes
d}
Löschen bis zum Ende des Paragraphen
cw
Durch dieses Kommando kann ein Wort geändert werden. Das nächste Wort wird ersetzt durch die Eingaben bis zum È.
ncw
Das n kann wieder für eine beliebige Ziffernfolge stehen. Es werden die nächsten n Worte durch die Eingabe bis zum È ersetzt.
c)
Es wird bis zum Ende des Satzes geändert.
c}
Es wird bis zum Ende des Paragraphen geändert.
Die beiden Kommandos c und d lassen sich aber nicht nur mit den Textobjekten des vi koppeln, sondern auch mit einigen der Positionierungskommandos. d$
Löschen von der aktuellen Cursorposition bis zum Ende der Zeile
dG
Löschen von der aktuellen Cursorposition bis zum Ende der Datei
d1G
Löschen von der aktuellen Cursorposition bis zum Anfang der Datei
d'a
Löschen von der aktuellen Cursorposition bis zur Marke a.
c$
Ändern von der aktuellen Cursorposition bis zum Ende der Zeile. Der Text wird ersetzt durch die Eingaben bis zum È.
16.3
Der Eingabemodus
Um aus dem Kommandomodus in den Eingabemodus zu gelangen, kann eine ganze Reihe unterschiedlicher Kommandos benutzt werden. Die Unterschiede zwischen den Kommandos liegen im Wesentlichen darin, wo der Cursor positioniert wird, bevor in den Eingabemodus umgeschaltet wird. Innerhalb des Eingabemodus kann man mit der Ã-Taste Tippfehler korrigieren und mit der Æ-Taste in die folgende Zeile springen. Ist die Eingabe abgeschlossen, kehrt man mit der È-Taste in den Kommandomodus zurück.
281
KAPITEL
16
Der Texteditor vi
Mit folgenden Kommandos wird in den Eingabemodus gewechselt: a
Mit dem kleinen a (append) wird der Cursor hinter das Zeichen, auf dem der Cursor steht, positioniert. Anschließend kann Text eingefügt werden.
A
Mit dem großen A wird der Cursor hinter das letzte Zeichen in der aktuellen Zeile positioniert. Anschließend kann Text eingefügt werden.
i
Mit dem Kommando i (insert) wird der Cursor vor das Zeichen, auf dem der Cursor steht, positioniert. Anschließend kann Text eingefügt werden.
I
Mit diesem Kommando wird der Cursor vor das erste nicht white space – also Leerzeichen oder TAB-Zeichen – positioniert. Anschließend kann Text eingefügt werden.
o
Dieses Kommando fügt nach der aktuellen Zeile eine Leerzeile ein und positioniert den Cursor am Anfang dieser Leerzeile (open), bevor in den Eingabemodus gewechselt wird.
O
Mit diesem Kommando wird vor der aktuellen Zeile eine Leerzeile eingefügt. Anschließend kann Text eingefügt werden.
r
Dieses Kommando unterscheidet sich ein wenig von den anderen Kommandos, da es nur für die Eingabe genau eines Zeichens in den Eingabemodus umschaltet. Mit r (replace) wird das Zeichen, auf dem der Cursor steht, durch das anschließend eingegebene Zeichen ersetzt.
R
Dieses Kommando unterscheidet sich von den vorangegangenen dadurch, dass beginnend mit dem Zeichen, auf dem der Cursor steht, alle Zeichen der aktuellen Zeile durch die Eingabe überschrieben werden können.
s
Mit diesem Befehl wird das Zeichen, auf dem der Cursor steht, durch die eingegebenen Zeichen ersetzt (substitute).
S
Mit diesem Befehl wird die gesamte aktuelle Zeile durch die Eingabe ersetzt.
16.4
Der Statuszeilenmodus
Der Statuszeilenmodus dient der Suche nach Textmustern im vi. Dabei kann sowohl nach einfachen Zeichenketten als auch nach regulären Ausdrücken1 gesucht werden. Das Ergebnis einer Suchaktion wird dem Benutzer mitgeteilt, indem der Cursor vor dem ersten Suchergebnis platziert wird. Wurde kein passender Ausdruck gefunden, so wird auf der Statuszeile eine entsprechende Meldung ausgegeben. Der vi sucht immer den gesamten Inhalt des Editors ab. Ein zu suchendes Muster wird also auch dann gefunden, wenn es vor der aktuellen Cursorposition steht und in Richtung Dateiende gesucht wird. Allerdings beginnt eine Suche immer an der Cursorposition. Bei Erreichen des Anfangs bzw. des Endes der Datei (je nach Suchrichtung) wird eine
1. Die Suchfunktion des vi gleicht also der eines grep und nicht der Dateinamenvervollständigung mit Wildcards durch die Shell.
282
Der ex-Modus entsprechende Meldung in der Statuszeile ausgegeben und die Suche entsprechend fortgeführt. Folgende Kommandos überführen den vi in den Statuszeilenmodus: /
Wird im Kommandomodus ein Slash »/« eingegeben, wird der Cursor in die Statuszeile gesetzt und der Bediener kann ein Suchmuster eingeben. Sonderzeichen wie »*« oder ».« werden dabei als Bestandteile eines regulären Ausdrucks aufgefasst. Es wird von der aktuellen Position in Richtung Dateiende gesucht.
?
Bei der Eingabe eines Fragezeichens im Kommandomodus wird der Cursor ebenfalls auf die Statuszeile gesetzt und der Benutzer kann ebenfalls ein Suchmuster eingeben. Es wird von der aktuellen Position in Richtung Dateianfang gesucht.
n
Wiederholung des letzten Suchkommandos mit »/« oder »?« in der gleichen Suchrichtung
N
Wiederholung des letzten Suchvorgangs mit »/« oder »?« in entgegengesetzter Suchrichtung
16.5
Der ex-Modus
Der ex-Modus bietet neben der Eingabe von Text und der Suche mithilfe des Statuszeilenmodus fast alle verbleibenden Möglichkeiten des vi. So gesehen kann der vi als Frontend des ex eingestuft werden. Alle folgenden Kommandos werden durch einen Doppelpunkt eingeleitet, der den vi für die Ausführung eines Kommandos in den ex-Modus überführt. Obwohl der Doppelpunkt eigentlich nicht zur Befehlssyntax gehört, sondern nur für die Umschaltung in den anderen Modus zuständig ist, wird er bei den folgenden Kommandos immer mit angegeben.
16.5.1
Dateikommandos
Dateioperationen werden im vi grundsätzlich im ex-Modus durchgeführt. Folgende Kommandos stehen für Dateioperationen zur Verfügung: Änderungen übernehmen
:x
Mit diesem Kommando wird der vi verlassen. Wurden am Text Änderungen vorgenommen, werden diese gespeichert.
Datei speichern
:w
Die Eingaben und Veränderungen werden gespeichert und der Benutzer verbleibt im Editor.
Editor verlassen
:q
Wurden seit dem Laden der Datei oder dem letzten Abspeichern keine Änderungen mehr vorgenommen, wird mit diesem Befehl der Editor verlassen.
283
KAPITEL
16
Der Texteditor vi
Speichern und Verlassen
:wq
Mit diesem Kommando werden zuerst die Änderungen und Eingaben gespeichert. Dann wird der Editor verlassen.
Änderungen verwerfen
:q!
Sollen alle Änderungen seit der letzten Speicherung verworfen und der Editor verlassen werden, so verwendet man dieses Kommando.
:w Name Mit diesem Kommando kann der Inhalt des Editors Unter neuem unter einem neuen Namen gespeichert werden. Um Namen speichern eine bereits existierende Datei mit diesem Kommando überschreiben zu können, muss statt des einfachen w ein w! angegeben werden.
Datei einfügen
:r Name Mit diesem Kommando wird die angegebene Datei hin-
ter der aktuellen Zeile eingefügt.
16.5.2
Suchen und Ersetzen
Neben der Eingabe von Text spielt das Überarbeiten oftmals eine große Rolle – gerade bei der Programmentwicklung. In diesem Zusammenhang ist wohl das Suchen und Ersetzen eines der am häufigsten gebrauchten Kommandos. An dieser Stelle spielt der vi, gepaart mit dem ex, seine wahren Stärken aus. Denn der vi lässt für das Suchmuster reguläre Ausdrücke zu und erlaubt im Ersetzungsstring Zugriffe auf die gefundene Zeichenkette oder auch auf Teile davon. Bevor wir uns ein paar praktische Beispiele für diese Fähigkeiten anschauen, soll zunächst die Syntax für einen solchen Befehl erläutert werden.
6
[Anfang,Ende] s/Suchmuster/Ersetzungsmuster/[Optionen]
Der Anfang des Bereichs kann alternativ durch eine Zeilennummer oder eine Referenz auf eine Marke (z.B. 'a) festgelegt werden. Das Ende des Bereichs kann durch eine Zeilennummer, eine Referenz auf eine Marke oder das Dollarzeichen »$« festgelegt werden. Das Dollarzeichen steht hierbei für das Ende der Datei und nicht wie bei der Cursorpositionierung für das Zeilenende. Der Bereich 1,$ steht also für die gesamte Datei. Fehlt der Bereich, wird der Befehl auf die aktuelle Zeile angewandt. Als Suchmuster können einfache Zeichenketten, aber auch reguläre Ausdrücke definiert werden. Der vi interpretiert dabei die Zeichen ».«, »*«, »$«, »^«, »[«, »]« und »\« gemäß ihrer Sonderfunktion (siehe hierzu Kommandos grep und egrep, Abschnitt 8.1). Teile des Suchmusters lassen sich durch »\(« und »\)« gruppieren. Die Entsprechungen für die ersten neun dieser Gruppen, die im Suchmuster auftauchen, werden in so genannte Hold-Buffer kopiert und können dann im Ersetzungsstring referenziert werden.
284
Der ex-Modus Der Ersetzungsstring kann bis auf folgende Einschränkungen eine beliebige Zeichenkette sein: ✘ Das Ampersand »&« wird, sofern es nicht einem einzelnen Backslash »\« folgt (dann steht das Ampersand für sich selbst), durch den Treffer für das Suchmuster ersetzt, d.h. das zu ersetzende Textstück kann in den Ersetzungsstring eingebaut werden. Da dieses Textstück durch die Verwendung regulärer Ausdrücke für die Definition des Suchmusters sehr variabel werden kann, stecken in diesem Feature eine Menge Möglichkeiten. ✘ Ausdrücke der Form \1 werden durch die Inhalte der Hold-Buffer ersetzt. Dabei steht \1 für Hold-Buffer 1, \2 für Hold-Buffer 2 usw. ✘ Um einen Backslash »\« in einem Ersetzungsstring anzugeben, muss ihm ein zweiter Backslash vorangehen. Als Optionen sind die folgenden beiden Buchstaben möglich. Sie können jeder für sich oder gemeinsam angegeben werden, dürfen im letzteren Fall aber nicht durch ein Leerzeichen o.Ä. getrennt werden. g
Normalerweise wird nur der erste Treffer pro Zeile für ein Suchmuster durch das Ersetzungsmuster ausgetauscht. Mit der Option g wie global wird jeder Treffer in einer Zeile ersetzt.
c
Wie unter Unix üblich, arbeitet auch der vi per Default ohne Rückfragen. Soll dennoch vor jeder Ersetzung vom Benutzer eine Bestätigung eingeholt werden, ist die Option c (confirm) anzugeben.
Um die verwirrende Vielfalt beim Einsatz von Suchen und Ersetzen ein wenig zu entwirren, sollen nun ein paar Beispiele zur Illustration der Möglichkeiten dieses Befehls folgen.
:1,$ s/^/Hallo:/
Bei diesem Beispiel wird vor jede Zeile der aktuell bearbeiteten Datei die Zeichenkette Hallo: geschrieben.
:1,$ s/$/;/
In diesem Beispiel wird hinter jede Zeile der aktuellen Datei ein Semikolon geschrieben.
3 3 285
KAPITEL
3
3
16
Der Texteditor vi
:1,$ s/.*/mv & &.old/
Gedacht ist dieses Kommando zur Erzeugung eines einfachen Scripts für die Umbenennung vieler Dateien. Dabei wurde zuerst eine Datei erzeugt, bei der in jeder Zeile der Name einer umzubenennenden Datei steht (eine solche Datei könnte z.B. durch ein ls > datei.txt erzeugt werden), die nun editiert wird. Das oben stehende Kommando erzeugt nun pro Zeile einen Unix-mv-Befehl, in dem die Ampersands aus dem Kommando durch den in der Zeile stehenden Dateinamen ersetzt werden. Stünde also beispiel.txt als Dateiname in einer Zeile, würde diese Zeile nach dem Kommando aus dem Beispiel mv beispiel.txt beispiel.txt.old lauten. Die so veränderte Datei müsste nur noch mit Ausführungsrechten versehen werden und könnte dann ausgeführt werden.
:1,$ s/\([Tt]reat\) or \([Tt]rick\)/\2 or \1/g
Das letzte Beispiel zeigt eine Anwendung der Hold-Buffer. Es werden die Hold-Buffer 1 und 2 belegt. In Hold-Buffer 1 landet bei einem Treffer das Wort treat in einer durch den regulären Ausdruck vorgegebenen Schreibweise, und in Hold-Buffer 2 wird das Wort trick genauso gespeichert. Durch das Kommando aus dem Beispiel werden die beiden Worte unter Beibehaltung ihrer Schreibweisen vertauscht.
16.5.3
Unix-Kommandos
Wie mächtig Unix-Kommandos sind, wurde schon in den vorangegangenen Kapiteln unter Beweis gestellt. Viele der Filter wie z.B. sort, tr oder cut erfüllen Aufgaben, die auch innerhalb eines Editors interessant sein können. Und auch hier bietet der vi wieder eine Möglichkeit an, um derartige Kommandos auf den Inhalt einer Datei oder auf Teilbereiche davon anzuwenden.
6
[Anfang,Ende] ! Filter
Ein Bereich kann genauso definiert werden wie ein Kommando zum Suchen und Ersetzen, vgl. Abschnitt 16.5.2. Auch hier gilt wieder: Wenn die Bereichsangabe fehlt, wird nur auf der aktuellen Zeile gearbeitet. Ein Filter kann ein beliebiges Unix-Kommando, aber auch ein selbst geschriebenes Programm oder Script sein, das die Filtereigenschaft erfüllt, d.h.,
286
Setup es muss in der Lage sein, von der Standardeingabe zu lesen und seine Ausgaben auf die Standardausgabe zu schreiben.
:1,$ ! sort -u
In diesem Beispiel werden alle Zeilen der Datei über ihre gesamte Länge dem ASCII-Code entsprechend sortiert und doppelte Zeilen eliminiert. Das Ergebnis dieses Vorgangs wird dann wieder an der Stelle des betroffenen Bereichs in die Datei geschrieben. In dem Beispiel bedeutet dies, dass der gesamte Dateiinhalt ersetzt wird.
16.6
3
Setup
Ähnlich wie bei vielen anderen Programmen lässt sich das Verhalten des vi durch setup-Optionen auf die persönlichen Bedürfnisse anpassen. Die setupOptionen lassen sich sowohl interaktiv während einer vi-Sitzung über den exModus verändern als auch über eine Ressource-Datei voreinstellen. set
Sollen die Optionen interaktiv in einer vi-Sitzung verändert werden, geschieht dies im ex-Modus durch das Kommando set.
.exrc
Sollen die setup-Optionen in einer Ressource-Datei voreingestellt werden, muss eine Datei mit dem Namen .exrc im Home Directory des Benutzers angelegt werden, in die dann die einzelnen setKommandos eingetragen werden können.
Die Fülle der möglichen setup-Optionen würde den Rahmen eines Grundlagenbuches sprengen. Aus diesem Grund werden hier nur exemplarisch einige wenige, allgemein interessante setup-Optionen vorgestellt. showmode noshowmode
Ist showmode gesetzt, zeigt der vi an, in welchem Modus er sich gerade befindet. Dazu wird rechts unten in der Statuszeile ein entsprechender Text eingeblendet.
number nonumber
Ist number gesetzt, wird vor jeder Zeile im Editor die Zeilennummer angezeigt. Diese Nummerierung wird nicht als Text in der Datei gespeichert!
autoindent noautoindent
Mit dieser Option schaltet man die automatische Einrückung ein. Ist autoindent gesetzt, wird eine neue Zeile jeweils genauso weit eingerückt wie die vorherige.
shiftwidth=
Dieser Option folgt ohne Zwischenraum ein Zahlenwert, der angibt, wie viele Leerzeichen bei einem Back-Tab im autoindent-Modus zurückgegangen wird.
287
KAPITEL
3
16
Der Texteditor vi
ignorecase noignorecase
Mit ignorecase wird bei Suchkommandos im Statuszeilenmodus
report=
Dieser Option folgt ohne Zwischenraum eine Zahl, die angibt, ab wie vielen betroffenen Zeilen eine Meldung ausgegeben wird. Bei set report=5 würde z.B. beim Kommando 6yy im Kommandomodus auf der Statuszeile 6 lines yanked ausgegeben.
errorbells noerrorbells
Mit dieser Option steuert man, ob der vi bei einer Fehleingabe ein akustisches Warnsignal ausgeben soll (errorbells) oder nicht (noerrorbells).
nicht zwischen Groß- und Kleinbuchstaben unterschieden.
UNIX-Kurs [~] 161 > cat .exrc set showmode set number
Welche Optionen sich noch im vi setzen lassen und wie deren derzeitige Einstellung lautet, kann mit dem Kommando :set all angezeigt werden. Diese Anzeige kann durch ein Æ wieder verlassen werden.
Übungen
16.7
Aufgaben
1. Wechseln Sie in Ihr Heimatverzeichnis und geben Sie dort den Befehl ls -la > inhalt ein. Rufen Sie nun den vi mit der dadurch angelegten Datei inhalt auf. 2. Bewegen Sie den Cursor mit den Cursortasten oder den Befehlen zur Cursorpositionierung über den Text. Schalten Sie durch die Eingabe eines i in den Eingabemodus um und verlassen Sie den Eingabemodus wieder. Achten Sie dabei auf Veränderungen der Statusanzeige unten im Shell-Fenster. Beenden Sie den Editor vi. 3. Gibt es in Ihrem Heimatverzeichnis eine Datei mit dem Namen .exrc? Falls ja, öffnen Sie diese Datei mit dem vi. Ansonsten erzeugen Sie diese Datei neu. Schreiben Sie in die Datei – sofern nicht bereits vorhanden – die beiden Zeilen: set showmode set number
Speichern Sie die Änderungen und verlassen Sie den Editor.
288
Aufgaben 4. Öffnen Sie ein zweites Mal die Datei inhalt. Gibt es Änderungen in der Darstellung? 5. Suchen Sie in der Datei nach Ihrer Benutzerkennung. Wie suchen Sie vorwärts? Wie suchen Sie rückwärts? 6. Löschen Sie die erste Zeile der Datei. 7. Positionieren Sie den Cursor auf die dritte Zeile der Datei und setzen Sie eine Marke. Bewegen Sie den Cursor dann auf die vorletzte Zeile der Datei und setzen Sie dort ebenfalls eine Marke. Kopieren Sie den Text zwischen den beiden Marken in den Kopierpuffer a. Gehen Sie mit dem Cursor an das Dateiende und fügen Sie dort den Inhalt dieses Kopierpuffers ein. 8. Gehen Sie an den Anfang der Datei. Ersetzen Sie in der gesamten Datei in Ihrer Benutzerkennung Kleinbuchstaben durch Großbuchstaben und umgekehrt. 9. Ermitteln Sie die Anzahl der Zeilen in der Datei und machen Sie für die zweite Hälfte der Datei die Ersetzung aus Übung 8 rückgängig. 10. Sortieren Sie den Inhalt der Datei numerisch nach dem fünften Feld (der Dateigröße). Speichern Sie das Ergebnis unter einem anderen Namen, ohne den vi zu verlassen. 11. Verlassen Sie den vi und schauen Sie sich mit dem Pager more den Inhalt der beiden bearbeiteten Dateien an.
16.7.1
Lösungen
1. Nachdem Sie die Datei inhalt erzeugt haben, können Sie sie mit dem Kommando vi inhalt in den Editor vi laden. 2. Nachdem Sie die Datei geöffnet haben, können Sie den Cursor mit den auf dem Keyboard nebeneinander liegenden Tasten h (nach links), j (nach unten), k (nach oben) und l (nach rechts) über den Text bewegen. Im Allgemeinen können Sie dazu auch die Pfeiltasten benutzen. In den Eingabemodus wechseln Sie durch Drücken der Taste i (wie insert). Den Eingabemodus verlassen Sie über die È-Taste. Ob der Eingabemodus in der Statuszeile des vi angezeigt wird oder nicht, hängt von den Einstellungen in der Datei .exrc ab, die wir in der nächsten Aufgabe etwas näher betrachten.
289
KAPITEL
16
Der Texteditor vi
3. Gibt es die Datei .exrc in Ihrem Heimatverzeichnis, so lädt der Befehl UNIX-KURS [~] 80 > vi .exrc
diese Datei in den Editor. Gibt es die Datei nicht, so öffnet der Befehl eine leere Datei, die unter dem Namen .exrc abgelegt wird, sobald Sie speichern. Gehen wir davon aus, dass die Datei nicht existiert und Sie nun eine leere Datei vor sich haben. Die beiden Zeilen fügen Sie ein, indem Sie mit der Taste i in den Eingabemodus wechseln, die beiden Zeilen tippen und anschließend mit der È-Taste den Eingabemodus wieder verlassen. Existiert die Datei bereits, schauen Sie zunächst, ob die beiden Zeilen bereits existieren. Ist dies nicht der Fall, gehen Sie analog vor. Beachten Sie nur, dass Sie am Zeilenanfang stehen, bevor Sie in den Eingabemodus wechseln. Die Datei .exrc wird vom Editor vi beim Start eingelesen. Die Zeile set showmode bewirkt, dass in der Statuszeile des vi, immer wenn Sie sich im Eingabemodus befinden, der jeweilige Eingabemodus (also insert, append usw.) unten rechts angezeigt wird. Da das Drücken einer Taste je nach viModus sehr unterschiedliche Wirkungen haben kann, ist es sicherlich hilfreich, zu wissen, in welchem Modus man sich befindet. Der Befehl set number stellt bei der Anzeige jeder Dateizeile eine Zeilennummer voran. Den Editor verlassen Sie mit dem Befehl :wq oder :x. Die Änderungen in der Datei werden dadurch gespeichert. 4. Öffnen Sie nun eine Datei, so werden Sie sehen, dass die Dateizeilen durchnummeriert sind. Sobald Sie in den Eingabemodus wechseln, wird dies in der Statuszeile angezeigt. 5. Angenommen, Ihre Benutzerkennung ist unix, dann suchen Sie vorwärts mit dem Befehl /unix und rückwärts mit ?unix. Die Eingabe muss jeweils im Kommandomodus des vi erfolgen. Die Suche können Sie durch ein kleines n in der gleichen Suchrichtung und durch ein großes N in der umgekehrten Richtung wiederholen. 6. Gehen Sie zur ersten Zeile der Datei, am einfachsten durch Eingabe von 1G im Kommandomodus. Sobald Sie auf einer Zeile stehen, löschen Sie diese durch Eingabe von dd. 7. Zur dritten Zeile gehen Sie mit den Cursor-Tasten oder durch Eingabe von 3G. Hier setzen Sie mit dem Befehl mb eine Marke mit dem Namen b. In der vorletzten Zeile setzen Sie dann mit mc eine Marke mit dem Namen c. Um nun den Text zwischen den beiden Marken in einen Kopierpuffer zu schreiben, müssen Sie am Anfang dieses Textes stehen. Da dort die Marke b gesetzt ist, können Sie diese Zeile mit dem Kommando 'b anspringen. In den Kopierpuffer bekommen Sie den Text nun mit dem (zugegebenermaßen recht kryptischen Befehl) "ay'c.
290
Aufgaben "a spricht den benannten Puffer a an. y steht für yank (anfügen) und 'c
spricht die Marke c an. Nachdem Sie an das Dateiende gegangen sind, z.B. mit der Tastenkombination ÁG, können Sie den Pufferinhalt dort mit dem Befehl "ap einfügen. 8. Ist Ihre Benutzerkennung unix, so bedeutet die Aufgabenstellung, dass Sie die Zeichenkette unix durch UNIX ersetzen sollen. Dies ist durch eine Operation im ex-Modus des vi möglich. Die entsprechende Eingabe im Kommandomodus lautet: :1,$ s/unix/UNIX/g
Durch Eingabe des Doppelpunkts wechseln Sie in den ex-Modus. Sie merken dies daran, dass der Cursor in die Statuszeile des vi springt. Alle Eingaben, die Sie nun machen, werden in der Statuszeile angezeigt, bis Sie das Kommando durch Drücken der Æ-Taste absetzen. Dann wird es ausgeführt und verschwindet aus der Statuszeile. Betrachten wir aber zuvor das Kommando genauer. Es beginnt mit einer Bereichsangabe in Dateizeilen, wobei das Dollarzeichen für das Dateiende steht. Der Bereichsangabe folgt das eigentliche Kommando, welches die Zeichenkette unix durch UNIX ersetzt. Das abschließende g (global) bewirkt, dass nicht nur das erste Auftreten der Zeichenkette in einer Zeile ersetzt wird, sondern jedes. 9. Um diese Ersetzung rückgängig zu machen, sind nur die Zeichenketten im Befehl zu vertauschen. Nehmen wir an, dass die Datei dreißig Zeilen besitzt, so lautet der Befehl, der die Aufgabe löst: :15,$ s/UNIX/unix/g
10. Die Sortierung des Dateiinhalts kann mithilfe des Unix-Befehls sort erfolgen. Auf Unix-Befehle kann aus dem ex-Modus über den Befehl ! zugegriffen werden. Der Unix-Befehl, der abzusetzen ist, lautet: sort -k 5 -n (numerische Sortierung nach dem fünften Feld)
Soll der gesamte Dateiinhalt sortiert werden, so lautet der vi-Befehl dafür: :1,$ !sort -k 5 -n
Nach Drücken der Æ-Taste ist der Dateiinhalt in der gewünschten Form sortiert. Das Ergebnis wird über das Kommando :w inhalt.sort
unter dem Dateinamen inhalt.sort im Heimatverzeichnis abgelegt.
291
KAPITEL
16
Der Texteditor vi
11. Den vi können Sie nun mit :q! verlassen. Die Datei inhalt wird dann nicht verändert. Die alte Datei inhalt und die neue Datei inhalt.sort können Sie anschließend mit dem Kommando UNIX-KURS [~] 81 > more inhalt inhalt.sort
ausgeben lassen.
292
KAPITEL 17
Shell-Programmierung Trotz der Fülle an Kommandos gibt es immer wieder Aufgaben, die sich erst durch eine Aneinanderreihung von Unix-Kommandos lösen lassen. Zwar lassen sich solche Aufgaben bereits durch Verwendung von Alias-Namen erheblich verkürzen, aber nicht für alle Zwecke bieten die Alias-Namen genügend Möglichkeiten, so z.B. wenn Kommandozeilenparameter gezielt einzeln angesprochen oder in Abhängigkeit von Bedingungen bestimmte Kommandos ausgespart werden sollen. Für diese weitergehenden Bedürfnisse hält Unix die so genannten ShellScripts parat.1 Ein Shell-Script ist eine Datei, in der Unix-Kommandos vermischt mit Ablaufstrukturen und Variablen stehen. Die Ablaufstrukturen haben die Aufgabe, die Abfolge der Unix-Kommandos zu steuern, d.h., sie sorgen dafür, dass bestimmte Kommandos nur in Abhängigkeit von Bedingungen ausgeführt werden, oder dass einige Kommandos mehrfach abgearbeitet werden. Innerhalb von Shell-Scripts werden Shell-Variablen dazu eingesetzt, Zwischenergebnisse zu speichern. Die Ablaufstrukturen und die Variablen ergeben zusammen eine Programmiersprache, in der Unix-Kommandos quasi als Funktionen aufgerufen werden können. Die Syntax der Programmiersprache ist abhängig von der jeweiligen Shell. Während C-Shell (csh) und Tenex-C-Shell (tcsh) auf eine C-ähnliche Syntax 1. Genauer gesagt, wird der Mechanismus von den verschiedenen Shells zur Verfügung gestellt. Die Syntax der Shell-Scripts hängt daher von der jeweiligen Shell ab, siehe weiter unten.
293
KAPITEL
17
Shell-Programmierung
setzen, verwenden die Bourne- (sh), Korn- (ksh) und Bourne-Again-Shell (bash) eine eigene Syntax, die an manchen Stellen Anleihen bei Algol68 genommen hat. Die meisten Scripts werden in der Programmiersprache der Bourne-Shell formuliert. Für die Verwendung der Bourne-Shell spricht neben der Tatsache, dass eine solche zu jedem System-V-Release-4-Unix gehört, auch, dass die Scripts, die zum Umfang des Unix-Betriebssystems gehören, in der Scriptsprache der Bourne-Shell verfasst sind. Aus diesem Grund soll hier ebenfalls die Programmierung von Bourne-ShellScripts besprochen werden, obwohl für die interaktive Arbeit eine tcsh vorzuziehen ist.
17.1
Allgemeine Hinweise zur Programmierung
Programmierung ist etwas, gegen das sich viele Anwender von Rechnern sträuben. Aus diesem Grund sind auf vielen Systemen die Möglichkeiten von Batch- oder Script-Dateien stark eingeschränkt. Unter Unix ist das anders – als ein System von Entwicklern für Entwickler bietet es seinen Anwendern mit den Programmiersprachen der Shells ein leistungsfähiges Werkzeug zur Abwicklung systemnaher Aufgaben. Trotz aller Leistungsfähigkeit sind die Konzepte auch für den Programmierlaien einfach und durchschaubar gehalten. Fehlende Programmierkenntnisse sollten also kein Hinderungsgrund sein, die folgenden Seiten zu lesen. In den vorangegangenen Kapiteln wurden bereits die wichtigsten Programmelemente für ein Shell-Script vorgestellt: die Unix-Kommandos. Sie bilden auch gleichzeitig den niedrigsten Level, auf den man sich als Programmierer von Shell-Scripts hinabbegeben muss. Der Programmfluss, d.h. die Abfolge der Kommandos beim Ausführen eines Shell-Scripts, wird durch die Ablaufstrukturen in Abhängigkeit von Bedingungen, die der Programmierer formuliert, gesteuert. An dieser Stelle kommt die boolesche Algebra ins Spiel. Dieser Zweig der Mathematik beschäftigt sich, allgemein ausgedrückt, mit der Formulierung von Bedingungen. Grundlage für die boolesche Algebra ist die so genannte zweiwertige oder binäre Logik, die nur zwei Ergebnisse – wahr (true) oder falsch (false) – kennt. Die boolesche Algebra definiert Regeln, welchen Wahrheitswert (true oder false) das Ergebnis einer Verknüpfung anderer Wahrheitswerte durch logische Operatoren (ODER, UND oder NICHT) bildet. Die logischen Verknüpfungen und ihre Ergebnisse werden in Abschnitt 17.4 erläutert.
294
Grundlagen
17.2
Grundlagen
Bevor wir uns näher mit der eigentlichen Programmierung auseinandersetzen wollen, müssen noch ein paar Grundlagen vermittelt werden. Dazu zählt Folgendes: ✘ Wie wird ein Script aufgerufen? ✘ Woran erkennt die Shell ein Script? ✘ Wie wird erkannt, für welche Shell ein Script geschrieben ist?
17.2.1
Wie wird ein Script aufgerufen?
Ein Script ist eine Textdatei, die ein oder mehrere Kommandos enthält. Damit das Script ausgeführt werden kann, müssen die Ausführungsrechte gesetzt werden. Dadurch wird der Shell signalisiert, dass die Datei einen ausführbaren Inhalt hat. Sind die Ausführungsrechte gesetzt, kann das Script einfach über den Dateinamen aufgerufen und ausgeführt werden.
17.2.2
Woran erkennt die Shell ein Script?
Neben den Ausführungsrechten, die man mit dem Kommando chmod jeder beliebigen Datei zuweisen kann, gibt es für die Shell kein verlässliches Indiz, ob es sich bei einer Datei um ein Script handelt. Die Shell stellt fest, dass es sich um eine Textdatei handelt, und versucht, die erste Zeile dieser Textdatei, die nicht mit einem Kommentarzeichen (»#«) beginnt, auszuführen. Sollte dieser Versuch fehlschlagen, gibt die Shell eine Fehlermeldung aus.
17.2.3
Wie wird erkannt, für welche Shell ein Script geschrieben ist?
Durch die unterschiedlichen Shells gibt es allerdings noch ein weiteres Problem: Auch wenn es sich bei einer Datei um ein Shell-Script handelt, muss sie dennoch nicht von der aktuellen Shell ausführbar sein. Da die Shell den Inhalt eines Shell-Scripts interpretiert, kann sie nur solche Scripts abarbeiten, deren Inhalt sich an die Syntax ihrer Programmiersprache hält, d.h. ein C-ShellScript könnte z.B. nicht durch eine Bourne-Shell interpretiert werden. Aus diesem Grund lässt sich in der ersten Zeile eines Scripts vereinbaren, durch welche Shell es auszuführen ist. Findet eine andere Shell beim Versuch, eine Datei auszuführen, eine solche Zeile, startet sie die dort genannte Shell und übergibt ihr den Inhalt der Datei zur Interpretation.
295
KAPITEL
6 3 1
17
Shell-Programmierung
#!shell
Für shell muss stets der komplette absolute Pfad der Shell eingegeben werden. Alle anderen Zeilen der Datei, die mit einem Doppelkreuz »#« beginnen, sind Kommentarzeilen. Ein einfaches Bourne-Shell-Script, das nur die Worte hello world ausgibt, sieht wie folgt aus:
#!/bin/sh # Testausgabe echo "hello world"
Vereinbaren Sie immer in der ersten Zeile, durch welche Shell Ihr Script zu interpretieren ist. Das macht Ihre Scripts unabhängig von der Shell, mit der Sie interaktiv arbeiten.
Nach Eingabe des Beispiels in eine Datei mit dem Namen first_-Script muss die Datei noch mit Ausführungsrechten versehen werden, bevor sie ausgeführt werden kann.
3
UNIX-Kurs [~] 162 > chmod a+x first_-Script UNIX-Kurs [~] 163 > first_-Script hello world
17.3
Variablen
Wie die C-Shell und die Tenex-C-Shell verfügt auch die Bourne-Shell über Shell-Variablen. Diese werden aber nicht zu Steuerungszwecken eingesetzt, sondern dienen nur zur Speicherung von Werten. Im Gegensatz zu den beiden anderen genannten Shells unterscheidet die Bourne-Shell nicht zwischen numerischen Variablen und Textvariablen. Sie kennt nur Textvariablen, die ohne ein Schlüsselwort (wie set unter der C-Shell) mit einem neuen Wert versehen werden können.
6 296
Variable=Wert
Variablen Für den Wert kann eine beliebige Zeichenkette angegeben werden. Enthält die Zeichenkette Leerzeichen oder shellspezifische Sonderzeichen, sind diese mit Single oder Double Quotes zu quoten. Wird als Wert ein in Back Quotes eingeschlossenes Unix-Kommando angegeben (Kommando-Substitution), wird das Ergebnis1 des Kommandos in der Variablen Variable abgelegt.
lines=`wc -l < /etc/passwd`
Bei diesem Beispiel wird in der Variablen lines die Anzahl der Zeilen der Datei /etc/passwd gespeichert.
17.3.1
3
Standardvariablen
Neben den Variablen, die der Benutzer selbst definieren kann, stellt die Shell beim Aufruf eines Scripts eine Anzahl vorbelegter Variablen zur Verfügung. Diese Variablen dienen in erster Linie dem Zugriff auf die Kommandozeilenparameter und können im Script abgefragt werden. Folgende Variablen werden durch die Shell vorbelegt:2 $0
In dieser Variablen befindet sich der Pfadname des aufgerufenen Scripts.
$1,...,$n
Diese Variablen enthalten die Kommandozeilenparameter (die Parameter, die beim Aufruf des Scripts dem Script-Namen folgen). Sollte n größer sein als die Anzahl der vorhandenen Parameter, hat die entsprechende Variable keinen Inhalt.
$#
In dieser Variablen wird von der Shell die Anzahl der aktuellen Kommandozeilenparameter abgelegt.
$*
Diese Variable enthält die gesamten Kommandozeilenparameter als eine Zeichenkette. Die einzelnen Parameter sind durch Leerzeichen getrennt.
$?
Wird in einem Shell-Script oder auf der Shell ein Kommando abgesetzt, wird in dieser Variablen nach Beendigung des Kommandos der ExitStatus (siehe 16.5) abgelegt.
1. Ergebnis einer Kommando-Substitution ist die Ausgabe, die das Kommando auf der Standardausgabe erzeugen würde. 2. Die Dollarzeichen vor den Variablennamen sind nur beim Zugriff auf den Inhalt der Variablen, nicht aber bei der Wertzuweisung anzugeben. Die in dieser Tabelle aufgeführten speziellen Variablen können nicht überschrieben werden.
297
KAPITEL
17
Shell-Programmierung
Natürlich kann in einem Shell-Script auch auf Variablen aus dem Environment zugegriffen werden.
17.3.2
Verknüpfung von Zeichenketten und Shell-Variablen
Sollen die Inhalte von Variablen mit konstanten Zeichenketten zu einer neuen Zeichenkette verknüpft werden, ist in den meisten Fällen für die Shell nicht festzustellen, wo der Name einer Variablen endet und wo ein konstanter Teil der neuen Zeichenkette beginnt.
3
name="Shell-" echo $nameVariablen
In diesem Beispiel würde die Shell versuchen, den Inhalt einer Variablen mit dem Namen nameVariablen auszugeben, statt den Inhalt der Variablen name mit der Zeichenkette Variablen zu konkatenieren. Dies tritt auf, weil ShellVariablen vor ihrer ersten Benutzung nicht deklariert werden müssen und weil jede erstmalig verwendete Variable per Default mit der leeren Zeichenkette initialisiert ist. Um hier das gewünschte Ergebnis zu erzielen, müsste das Beispiel wie folgt geschrieben werden:
3
name="Shell-" echo ${name}Variablen
Durch die Verwendung der geschweiften Klammern wird der Shell eindeutig angezeigt, welcher Teil der Zeichenkette zum Dollarzeichen gehört – also der Name der zu referenzierenden Variablen – und welcher Teil konstant ist. Bei der Ausführung würde nun also der String Shell-Variablen ausgegeben werden.
298
Spezielle Kommandos
17.4
Spezielle Kommandos
In diesem Abschnitt werden einige Unix-Kommandos beschrieben, die sehr oft in Shell-Scripts eingesetzt werden.
17.4.1
basename
Das Kommando basename entfernt von einem Dateinamen den Pfadanteil und wenn gewünscht, auch eine Extension.
basename Dateiname [ Extension ]
Es wird der Pfadanteil des Dateinamens entfernt, d.h. alle Zeichen bis einschließlich des letzten Slashs »/«. Der verbleibende Teil wird auf die Standardausgabe ausgegeben. Ist kein Slash enthalten, wird der komplette Dateiname ausgegeben. Wird zusätzlich eine Extension angegeben, werden diese Zeichen, sofern vorhanden, vor der Ausgabe vom Ende des Dateinamens entfernt.
17.4.2
6
dirname
Das Kommando dirname liefert für einen Dateinamen den Verzeichnisanteil. Enthält der Dateiname keinen Pfadanteil, weil er sich auf eine Datei im Working Directory bezieht, liefert dirname den ».« als relativen Pfadnamen für das Working Directory als Ergebnis.
dirname Dateiname
Es wird der Pfadanteil des Dateinamens ausgegeben, d.h. alle Zeichen bis zum letzten Slash »/«.
17.4.3
6
expr
Das Kommando expr dient der Auswertung von Ausdrücken. Dabei kann es sich sowohl um ganzzahlige numerische Ausdrücke als auch um relationale Ausdrücke handeln. expr wird häufig in Bourne-Shell-Scripts eingesetzt, um einfache arithmetische Operationen mit Variablen durchzuführen.
299
KAPITEL
6
17
Shell-Programmierung
expr Arg1 Operator Arg2 [Operator Arg3 ...]
expr gibt das Ergebnis des Ausdrucks auf die Standardausgabe aus. Bei rela-
tionalen Ausdrücken wird eine 1 ausgegeben, wenn der Ausdruck erfüllt ist. Ist er nicht erfüllt, ist das Ergebnis 0.
17.4.4
Arithmetische Operatoren
Bei der Verknüpfung mit arithmetischen Operatoren lassen sich zur Formulierung komplexerer Ausdrücke auch runde Klammern zur Klärung der Vorrangverhältnisse einsetzen. Da die runden Klammern aber unter der BourneShell eine Sonderbedeutung haben, muss ihnen ein Backslash »\« vorangestellt werden. Folgende Operatoren werden u. a. von expr angeboten: +
Addition der beiden durch den Operator verbundenen Argumente
-
Subtraktion der beiden durch den Operator verbundenen Argumente
'*'
Multiplikation der beiden durch den Operator verbundenen Argumente. Da der Stern »*« eine Sonderbedeutung unter der Shell hat, ist er zu quoten.
/
Ganzzahlige Division der beiden durch den Operator verbundenen Argumente. Das Ergebnis ist also wieder eine ganze Zahl.
%
Modulo-Operation mit den beiden Argumenten, die über den Operator verknüpft werden (ganzzahliger Divisionsrest)
17.4.5
Relationale Operatoren
Die relationalen Operatoren gelten sowohl für numerische als auch für textuelle Argumente. Beim Vergleich von Zeichenketten gilt a < z.
300
=
Sind die beiden durch diesen Operator verknüpften Argumente gleich, liefert expr als Ergebnis eine 1.
!=
Sind die beiden durch diesen Operator verknüpften Argumente verschieden, liefert expr als Ergebnis eine 1.
>
Ist das erste Argument größer als das zweite, liefert expr als Ergebnis eine 1.
>=
Ist das erste Argument größer oder gleich dem zweiten, liefert expr als Ergebnis eine 1.
<
Ist das erste Argument kleiner als das zweite, liefert expr als Ergebnis eine 1.
<=
Ist das erste Argument kleiner oder gleich dem zweiten, liefert expr als Ergebnis eine 1.
Spezielle Kommandos
i=`expr $i + 1`
Dies ist ein typisches Beispiel für den Einsatz von expr in einem Bourne-ShellScript. Mithilfe von expr und der Kommando-Substitution wird die Variable i um 1 erhöht. Voraussetzung für das Funktionieren dieser Lösung ist, dass i einen ganzzahligen Wert enthält.1
17.4.6
3
read
Mit dem Kommando read können Werte vom Standardeingabekanal gelesen werden.
read Variablen
Nach dem Kommando read können ein oder mehrere Namen von Variablen angegeben werden. read liest immer eine ganze Zeile. Enthält die Zeile mehr durch Leerzeichen getrennte Worte als Namen für Variablen angegeben wurden, werden alle überzähligen Worte in der letzten Variablen gespeichert. Wird nur ein Variablename angegeben, wird die ganze Zeile in diese Variable eingelesen.
read answer
Diese Anweisung liest eine Eingabezeile und speichert sie in der Variablen answer.
17.4.7
6 3
test
Das Kommando test ist in dem oben beschriebenen Zusammenhang die wichtigste Hilfe in Bourne-Shell-Scripts bei der Formulierung von Bedingungen. test prüft die Bedingungen und liefert einen entsprechenden Exit-Status zurück.
1. Dies widerspricht scheinbar der Aussage, dass es unter der Bourne-Shell nur Textvariablen gibt, vgl. Abschnitt 16.3. Mit $i wird zwar auf eine Textvariable zugegriffen, diese wird aber von dem Kommando expr, wenn sie nur Ziffern enthält, als Zahl interpretiert. Das Ergebnis wird dann wiederum als String an die Variable i zugewiesen.
301
KAPITEL
6 6
17
Shell-Programmierung
test Argumente
[ Argumente ]
test ist in den beiden vorangehenden Syntaxvarianten in Shell-Scripts anzu-
treffen. Die zweite Variante mit den eckigen Klammern ist auf den ersten Blick nur schwer als Aufruf des test-Kommandos zu erkennen und dient in erster Linie dazu, die Syntax von Bedingungen in Bourne-Shell-Scripts denen einer Programmiersprache wie C oder Pascal anzugleichen. test verfügt über folgende Argumente zur Formulierung von Bedingungen:
302
17.4.8
Bedingungen für Dateien
-d Datei
Wenn Datei existiert und ein Verzeichnis ist, liefert test als ExitStatus eine Null.
-f Datei
Wenn Datei existiert und ein Plain File ist, liefert test als Exit-Status eine Null.
-r Datei
Wenn Datei existiert und für den Aufrufer von test lesbar ist, liefert test eine Null als Exit-Status.
-s Datei
Wenn Datei existiert und größer als 0 Byte ist, liefert test einen Exit-Status von Null.
-w Datei
Wenn Datei existiert und für den Aufrufer von test schreibbar ist, liefert test einen Exit-Status von Null.
-x Datei
Wenn Datei existiert und für den Aufrufer von test ausführbar ist, liefert test einen Exit-Status von Null.
17.4.9
Bedingungen für Strings
-n str
Ist die Zeichenkette str länger als Null Zeichen, liefert test einen Exit-Status von Null.
-z str
Ist die Zeichenkette str Null Zeichen lang, liefert test einen ExitStaus von Null.
str1 = str2
Ist die Zeichenkette str1 gleich der Zeichenkette str2, liefert test einen Exit-Status von Null.
str1 != str2
Ist die Zeichenkette str1 verschieden von der Zeichenkette str2, liefert test als Exit-Status eine Null.
Spezielle Kommandos
17.4.10 Bedingungen für ganze Zahlen z1 –eq z2
Sind die beiden Zahlen z1 und z2 gleich, liefert test als Exit-Status eine Null.
z1 –ge z2
Ist z1 größer oder gleich z2, liefert test als Exit-Status eine Null.
z1 –gt z2
Ist z1 größer als z2, liefert test als Exit-Status eine Null.
z1 –le z2
Ist z1 kleiner oder gleich z2, liefert test als Exit-Status eine Null.
z1 –lt z2
Ist z1 kleiner als z2, liefert test als Exit-Status eine Null.
z1 –ne z2
Sind z1 und z2 verschieden voneinander, liefert test als Exit-Status eine Null.
17.4.11 Logische Verknüpfungen ! bed
Ist die Bedingung bed erfüllt, liefert test einen Exit-Status verschieden von Null. Das Ausrufezeichen entspricht also einem logischen NICHT. bed kann eine mit den vorangehenden Operatoren erzeugte Bedingung oder eine Verknüpfung von Bedingungen dieses Typs sein. Für die bessere Übersichtlichkeit empfiehlt sich die Klammerung mit runden Klammern »()«, die allerdings einzeln mit einem Backslash von ihrer shellspezifischen Bedeutung befreit werden müssen.
bed1 -a bed2
Logische UND-Verknüpfung der beiden Bedingungen. Ist bed1 erfüllt und ebenso bed2, liefert test als Exit-Status eine Null.
bed1 -o bed2
Logische ODER-Verknüpfung der beiden Bedingungen. Ist bed1 oder bed2, oder sind bed1 und bed2 erfüllt, liefert test eine Null als Exit-Status.
test -d /home/lutz
In diesem Beispiel wird getestet, ob /home/lutz ein Verzeichnis ist.
test \( -d /home/ralph \) -a \( -x /home/ralph \)
In diesem Beispiel wird die Verwendung runder Klammern und die Verknüpfung zweier Bedingungen gezeigt. Es wird getestet, ob es sich bei /home/ralph um ein Verzeichnis handelt und ob für den Aufrufer von test Ausführungsrechte an diesem Verzeichnis gesetzt sind.
3 3 303
KAPITEL
6
17
Shell-Programmierung
test "$USER" = "lutz"
In diesem Beispiel wird getestet, ob der Inhalt der Environmentvariablen $USER mit der Zeichenkette lutz übereinstimmt.
17.5
Ablaufstrukturen
Ohne die Ablaufstrukturen wären die Scripts reine Batch-Dateien, in denen nur eine Abfolge von Unix-Kommandos stehen könnte. Durch die Ablaufstrukturen ergeben sich Möglichkeiten, auf bestimmte Umstände zum Zeitpunkt der Ausführung zu reagieren, Eingaben vom Benutzer abzufragen oder die Ausführung bestimmter Kommandos zu wiederholen, ohne das Script erneut zu starten. Die Ablaufstrukturen der Bourne-Shell weisen eine Besonderheit auf – sie arbeiten mit dem Exit-Status von Kommandos stellvertretend für die Wahrheitswerte true und false. Jedes Kommando unter Unix liefert als Ergebnis seiner Ausführung an den aufrufenden Prozess einen numerischen Wert zurück. Ist dieser Wert von Null verschieden, signalisiert dies in der Regel eine unplanmäßige Beendigung des Kommandos. Der Exit-Status Null dagegen besagt, dass das Unix-Kommando ordnungsgemäß abgearbeitet wurde und wird deshalb von den Ablaufstrukturen der Bourne-Shell mit dem Wahrheitswert true assoziiert, während alle anderen Werte für den Exit-Status als false interpretiert werden. Alle nun folgenden Ablaufstrukturen müssen mit genau den hier aufgeführten Zeilenumbrüchen verwandt werden, da die Shell sonst Syntaxfehler meldet.
17.5.1
if
Die am häufigsten benutzte Ablaufstruktur ist die bedingte Verzweigung mit if.
6 304
if Kommando1 then Anweisungen1 [elif Kommando2 then Anweisungen2] [else Anweisungen3] fi
Ablaufstrukturen Liefert das Kommando Kommando1 nach dem if einen Exit-Status von Null zurück, wird der Anweisungsblock Anweisungen1 nach dem then ausgeführt. Ist der Exit-Status verschieden von Null und ein elif-Zweig vorhanden, wird das Kommando2 ausgeführt und wenn dessen exit-Status 0 ist, die Anweisungen2 nach dem zweiten then. Ist kein elif-Zweig vorhanden oder der Exit-Status von Kommando2 verschieden von Null, werden die Anweisungen3 aus dem else-Zweig, sofern vorhanden, ausgeführt.
if [ -f $datei ] then echo "$datei ist ein Plain File" else echo "$datei existiert nicht oder ist kein Plain File" fi
3
In diesem Beispiel wird durch einen Aufruf des Kommandos test in der Syntaxvariante mit den eckigen Klammern getestet, ob der Wert der Variablen datei ein Name für ein existierendes Plain File ist. Je nach dem Exit-Status von test wird dann eine entsprechende Meldung ausgegeben.
17.5.2
for
In vielen Shell-Scripts müssen die Kommandozeilenparameter abgearbeitet werden. Hierbei leistet die for-Schleife sehr gute Dienste.
for Variable [in Werteliste] do Anweisungen done
6
Die Anweisungen zwischen dem do und dem done werden für jeden Wert aus der Werteliste einmal ausgeführt. Der aktuelle Wert wird dabei immer in der Schleifenvariablen Variable gespeichert und kann in den Anweisungen mit $Variable abgefragt werden. Wird keine Werteliste angegeben, werden stattdessen die Parameter aus der Kommandozeile genommen. In diesem Fall wird die for-Schleife so häufig durchlaufen, wie es die Anzahl der Kommandozeilenparameter vorgibt, und bei jedem Durchlauf steht in Variable der Wert eines Parameters.
305
KAPITEL
3
17
Shell-Programmierung
count=0 for arg do count=`expr $count + 1` echo Parameter Nummer $count lautet $arg done
Dieses Beispiel zeigt neben einer for-Schleife, die alle Kommandozeilenparameter abarbeitet, einen weiteren wichtigen Mechanismus – die Verwendung der Kommando-Substitution, um die Ergebnisse einer Kommandoausführung in einer Variablen zu speichern. Als zweites Beispiel soll eine for-Schleife mit einer Werteliste dienen. Dabei kann man sich die Expansion von Wildcards durch die Shell bei der Erstellung der Werteliste zu Nutze machen.
3
for datei in *.txt do cp $datei ${datei}.old done
Mit dieser Schleife werden alle Dateien mit der Endung .txt (*.txt) im Working Directory mit der zusätzlichen Endung .old versehen. Dies ist insbesondere dann eine bequeme Methode für diese Arbeit, wenn man eine ganze Reihe solcher Dateien gleichartig umbenennen muss.
17.5.3
while
Als weitere Schleife verfügt die Programmiersprache der Bourne-Shell über die while-Schleife.
6
while Kommando do Anweisungen done
Solange das Kommando bei seiner Ausführung als Exit-Status den Wert Null liefert, werden die Anweisungen ausgeführt.
306
Ablaufstrukturen
while read input do echo "Die Eingabe lautet $input" done
3
Bei diesem Beispiel werden solange vom Benutzer Zeilen eingelesen, in der Variablen input abgelegt und mit echo ausgegeben, bis dieser ein ŸD eingibt.
17.5.4
until
Die until- und die while-Schleife sind sich sehr ähnlich. Einziger Unterschied ist die Bedeutung der Bedingung, die durch das Kommando zwischen dem until und dem do formuliert wird. Während bei der while-Schleife die Bedingung erfüllt sein muss, damit die Anweisungen ausgeführt werden, werden bei der until-Schleife die Anweisungen solange ausgeführt, bis die Bedingung das erste Mal erfüllt ist.
until Kommando do Anweisungen done
6
Solange das Kommando bei seiner Ausführung einen Exit-Status verschieden von Null liefert, werden die Anweisungen ausgeführt.
17.5.5
case
Mit der case-Anweisung ist eine Mehrfachauswahl möglich.
case Wert in Muster1) Anweisungen1;; Muster2) Anweisungen2;; Muster3|Muster4) Anweisungen3;; . . . [ *) Default-Anweisungen;; ] esac
6
307
KAPITEL
17
Shell-Programmierung
Der Wert wird mit den Mustern Muster1, Muster2 usw. verglichen. Stimmt Wert z.B. mit Muster1 überein, werden die Anweisungen1 ausgeführt. Stimmt Wert mit keinem der Muster überein und ist ein *)-Zweig vorhanden, werden die Default-Anweisungen ausgeführt. Sollen bei zwei oder mehr Mustern die gleichen Anweisungen ausgeführt werden, so sind die Muster vor der schließenden runden Klammer durch »|« zu trennen. In der Syntaxbeschreibung sieht man einen solchen Fall für Muster3 und Muster4 – egal ob der Wert gleich Muster3 oder Muster4 ist, es werden in beiden Fällen die Anweisungen3 ausgeführt. Der Wert kann direkt, als Ergebnis einer Kommando-Substitution oder als Inhalt einer Variablen angegeben werden.
3
read answer case $answer in yes) result=0;; no) result=1;; *) echo "Falsche Eingabe" result=-1;; esac
In diesem Beispiel wird zuerst eine Eingabe vom Benutzer in die Variable answer eingelesen und mit den beiden Zeichenketten yes und no verglichen. Ist die Variable answer gleich yes, wird die Variable result auf 0 gesetzt. Bei einem Wert von no für die Variable answer erhält result den Wert 1. In allen anderen Fällen wird result der Wert -1 zugewiesen.
17.5.6
break
Mit dem Kommando break verlässt man die innerste for-, while- oder untilSchleife.
6
break
17.5.7
continue
Während beim Kommando break die gesamte Schleife beendet wird, sorgt continue nur für die Beendigung des aktuellen Schleifendurchlaufs, d.h., es wird mit einem neuen Schleifenwert (im Fall einer for-Schleife) bzw. mit der Prüfung der Bedingung fortgefahren.
308
Ein Muster-Script
continue
17.5.8
exit
6
Mit dem Kommando exit wird die Shell beendet, die das Script interpretiert. Das ist gleichbedeutend mit dem Beenden des Scripts.
exit [ Status ]
Dem Kommandonamen exit kann eine ganze Zahl folgen. Dieser Exit-Status kann in der aufrufenden Shell bzw. in einem aufrufenden Script abgefragt werden. Wird kein Exit-Status angegeben, so wird als Default-Wert der ExitStatus des zuletzt im Script ausgeführten Kommandos zurückgegeben. Werte verschieden von Null bedeuten dabei eine nicht erfolgreiche Abarbeitung, ein Wert von Null zeigt eine erfolgreiche Ausführung an. Für eine Beendigung des Scripts im Fehlerfall sollten Sie daher immer explizit einen Exit-Status setzen, am besten für jeden unterschiedlichen Fehlerfall einen anderen Exit-Status.
17.6
6
Ein Muster-Script
Nach all den theoretischen Betrachtungen soll nun das angekündigte Beispiel für ein Shell-Script folgen. Das Beispiel ist in drei Abschnitte unterteilt: 1. Aufgabenstellung 2. Entwicklung eines Ablaufplans 3. Kodierung in der Programmiersprache der Bourne-Shell
17.6.1
Aufgabenstellung
Das Beispiel-Script soll folgende Aufgabe leisten: Es soll als Parameter den Namen eines Benutzers entgegennehmen, überprüfen, ob es diesen Benutzer gibt, und dann folgende Informationen über den Benutzer zusammenstellen: ✘ Klarname ✘ Login-Shell des Benutzers ✘ Home Directory des Benutzers ✘ Speicherverbrauch des Benutzers
309
KAPITEL
17 17.6.2
Shell-Programmierung
Ablaufplan
Der Ablauf für ein solches Script lässt sich durch folgendes Flussdiagramm veranschaulichen: Abb. 17.1: Ablaufdiagramm
310
Ein Muster-Script Wie in diesem Flussdiagramm zu sehen ist, wird in Shell-Scripts häufig eine bestimmte Taktik angewandt. Diese lautet, zuerst alle Fehlerfälle zu testen, bevor die eigentliche Funktionalität implementiert wird. Sollte einer der Fehlerfälle eintreten, wird das Script mit einer entsprechenden Fehlermeldung verlassen. Diese Vorgehensweise entspricht zwar nicht ganz der klassischen TopDown-Methode, bei der alle möglichen Fälle in einem gemeinsamen Ausgang aus dem Programm enden, sorgt aber dafür, dass Scripts aufgrund geringer Schachtelungstiefe übersichtlich bleiben.
17.6.3
Kodierung
Nachdem der Ablaufplan in Form eines Flussdiagramms entwickelt worden ist, verbleibt als letzter Schritt die Kodierung in der Programmiersprache der Bourne-Shell. Diese soll Schritt für Schritt entwickelt werden, um die einzelnen Bestandteile besser erläutern zu können.
Anzahl der Parameter überprüfen Will man ein Script erstellen, das nicht nur von einem selbst, sondern auch von anderen benutzt werden kann, empfiehlt es sich stets, als erstes zu testen, ob der Aufruf korrekt erfolgt ist. Die häufigsten Fehler werden bei der Anzahl der Parameter gemacht. Das Muster-Script erwartet genau einen Parameter.
if [ $# -ne 1 ] then echo "Usage: `basename $0` username" exit 1 fi
3
Dieses if-Statement testet, ob die Anzahl der übergebenen Parameter ($#) verschieden (-ne) von 1 ist. Die Überprüfung wird durch das Kommando test in der Syntax mit den eckigen Klammern vollzogen. Tritt der Fehlerfall ein, dass die Anzahl der Parameter verschieden von 1 ist, wird eine so genannte Usage-Zeile ausgegeben. Unter Unix ist es üblich, dem Benutzer bei einem unkorrekten Aufruf eines Kommandos statt einer Fehlermeldung mit einer solchen Zeile die korrekte Syntax mitzuteilen. Für die Ausgabe wird das Kommando echo benutzt, welches Zeichenketten auf die Standardausgabe ausgibt. In der Zeichenkette befindet sich die Kommando-Substitution `basename $0`. Die Variable $0 wird von der Shell mit dem Pfadnamen des aufgerufenen Kommandos – also in diesem Fall mit dem Namen des Scripts – vorbelegt. basename $0 sorgt dafür, dass der Pfad vom Namen des Scripts entfernt wird. Die Kommando-Substitution sorgt dafür, dass dieses vor der Ausgabe der Usage-Zeile geschieht.
311
KAPITEL
17
Shell-Programmierung
Man setzt basename $0 statt eines festen Namens ein, um auch bei der Ausführung über einen Link oder nach einer Umbenennung des Scripts eine korrekte Usage-Zeile zu erhalten. Nach Ausgabe der Usage-Zeile wird das Script mit exit 1 verlassen. Wenn also dieser Fehlerfall eintritt, liefert das Script eine 1 als Exit-Status.
Existiert der Benutzer? Wurde nur ein Parameter übergeben, sollte es sich um einen Benutzernamen handeln. Ob diese Bedingung erfüllt ist, wird nun geprüft.
3
line="`grep \^${1}: /etc/passwd`" if [ -z "$line" ] then echo "Der User $1 hat keinen Eintrag in der /etc/passwd" exit 2 fi
Für jeden Benutzer steht in der Datei /etc/passwd eine Zeile,1 die mit seinem Benutzernamen beginnt und die Angaben über das verschlüsselte Passwort, die User-ID, die Gruppen-ID, den Klarnamen, das Home Directory und die Login-Shell des Benutzers enthält. Die einzelnen Felder sind durch Doppelpunkte getrennt. Das Suchmuster des grep-Kommandos (^${1}:) spiegelt genau diesen Sachverhalt wieder. Im ersten Parameter ($1 – die geschweiften Klammern dienen zur Abgrenzung vom nachfolgenden Text) sollte der Name des gesuchten Benutzers stehen. Dieser steht in der /etc/passwd am Anfang der Zeile »^«, direkt gefolgt von einem Doppelpunkt »:«. Existiert eine solche Zeile, muss sie für den Benutzer stehen, weil Benutzernamen unter Unix eindeutig sein müssen. Das Ergebnis der Suche wird mithilfe der Kommando-Substitution in die Variable line geschrieben. Da das Ergebnis eventuell Leerzeichen enthalten kann, die ebenfalls in die Variable geschrieben werden sollen, ist die Kommando-Substitution in den Back Quotes zusätzlich in Double Quotes eingeschlossen. Das nachfolgende if-Statement verwendet wieder einen Aufruf von test in der Syntax mit den eckigen Klammern, um festzustellen, ob die Zeichenkette in der Variablen line die Länge Null hat. Ist das der Fall, wird eine entspre-
1. Es sei denn, es wird mit Yellow Pages (yp) oder Network Information Services (NIS) gearbeitet. In diesem Fall müssen sich nicht für jeden Benutzer Einträge in der /etc/passwd befinden.
312
Ein Muster-Script chende Fehlermeldung ausgegeben und das Script mit dem Exit-Status 2 beendet. Für den Fall, dass eine Zeile in der /etc/passwd gefunden wurde, müssen nun die gewünschten Informationen extrahiert werden. Für diese Aufgabe eignet sich das Kommando cut.
klarname="`echo $line | cut -d: -f5`" homedir="`echo $line | cut -d: -f6`" loginshell="`echo $line | cut -d: -f7`"
3
Auch für diese Aufgabe wird wieder die Kommando-Substitution eingesetzt. Der Inhalt der Variablen line wird über eine Pipe in den Filter cut gegeben. Diesem wird über die Option -d mitgeteilt, dass als Trennzeichen zwischen den Feldern ein Doppelpunkt steht. In den drei Zeilen wird jeweils ein Feld (mittels -fx) aus der Zeile »herausgeschnitten« und in einer Variablen abgelegt. Um den Speicherverbrauch des Benutzers zu ermitteln, muss sein Home Directory existieren und betretbar sein. Das bedeutet, für den Aufrufer müssen die Execute-Rechte an dem Verzeichnis gesetzt sein. Dieses lässt sich ebenfalls wieder mit einem Aufruf von test ermitteln. Dabei testet der Ausdruck -d $homedir, ob das Verzeichnis, dessen Name in der Variablen homedir gespeichert ist, existiert und ein Verzeichnis ist, und der Ausdruck -x $homedir testet, ob für das Verzeichnis die Execute-Rechte gesetzt sind. Durch die Angabe von -a zwischen den beiden Ausdrücken wird erreicht, dass der thenZweig nur dann ausgeführt wird, wenn beide Bedingungen erfüllt sind.
if [ -d $homedir -a -x $homedir ] then diskspace="`du -s $homedir | cut -f1` Blocks" else diskspace="konnte nicht ermittelt werden" fi
3
Existiert das Home Directory und ist es betretbar, so erfolgt die Bestimmung des Speicherverbrauchs über das Kommando du. Die Ausgabe des du wird noch durch das cut -f1 »beschnitten«, da du zusätzlich zu der Größe auch immer noch den Namen des Verzeichnisses bzw. der Datei mit ausgibt. Die Vereinbarung eines Trenners mittels der Option -d kann hier entfallen, da du zwischen Größe und Namen den Default-Trenner des cut – das Å-Zeichen – ausgibt.
313
KAPITEL
17
Shell-Programmierung
Konnte keine Bestimmung des Speicherverbrauchs vorgenommen werden, weil eine der Bedingungen nicht erfüllt war, wird die Variable diskspace mit einer erklärenden Zeichenkette belegt. Das fertige Script sieht dann wie folgt aus:
3
#!/bin/sh # Anzahl Parameter testen if [ $# -ne 1 ] then echo "Usage: `basename $0` username" exit 1 fi # Usernamen testen line="`grep \^${1}: /etc/passwd`" if [ -z "$line" ] then echo "Der User $1 hat keinen Eintrag in der /etc/passwd" exit 2 fi # Informationen extrahieren klarname="`echo $line | cut -d: -f5`" homedir="`echo $line | cut -d: -f6`" loginshell="`echo $line | cut -d: -f7`" # Speicherplatz bestimmen if [ -d $homedir -a -x $homedir ] then diskspace="`du -s $homedir | cut -f1` Blocks" else diskspace="konnte nicht ermittelt werden" fi # Ergebnisse ausgeben echo "Benutzer : " $1 echo "Klarname : " $klarname echo "Home Directory : " $homedir echo "Login-Shell : " $loginshell echo "Speicherverbrauch : " $diskspace # Script ordnungsgemaess beenden exit 0
314
Aufgaben
Übungen
17.7
Aufgaben
1. Auf den folgenden Seiten finden Sie ein paar einfache Beispiele für Scripts mit den unterschiedlichen Ablaufstrukturen. Schauen Sie sich die Beispiele an, versuchen Sie, deren Funktionsweise zu ergründen und erstellen Sie anschließend diese Scripts auf Ihrem Unix-System, um Ihre Überlegungen zu überprüfen. 2. Unter MS DOS werden die Zeilen einer Textdatei zusätzlich zum newline (\012) mit einem carriage return (\015) abgeschlossen. Beim Austausch von Textdateien zwischen Unix und MS DOS wird man eventuell mit dem Problem konfrontiert, die carriage return-Zeichen am Zeilenende entweder ergänzen oder beseitigen zu müssen. Zu diesem Zweck sollen zwei Scripts fromdos und todos geschrieben werden, die genau diese Aufgabe erledigen. Die Aufgabe soll in drei Teilschritten gelöst werden. a) In der ersten Version sollen die beiden Scripts genau für eine Datei arbeiten, deren Name als Parameter an das Script übergeben wird. b) In der zweiten Version sollen die beiden Scripts für eine beliebige Anzahl von Dateien arbeiten. Die Namen der Dateien werden ebenfalls wieder als Parameter an das Script übergeben. c) In der letzten Version sollen noch ein paar Sicherheitschecks eingebaut werden. Und zwar: ✘ Beide Scripts arbeiten nur mit Textdateien. ✘ fromdos gibt eine Warnung aus, wenn die Datei keine carriage returns enthält. ✘ todos hängt keine carriage returns an die Zeilen an, wenn die Datei schon carriage returns enthält.
17.7.1
Beispiel-Scripts
simple.sh #!/bin/sh # # Beispiel Script simple.sh # # cd echo Der Inhalt von `pwd` lautet:
315
KAPITEL
17
Shell-Programmierung
ls -l exit
Dieses Script ist wirklich kaum an Einfachheit zu übertreffen – außer vielleicht durch das obligatorische hello_world-Script aus dem vorangegangenen Kapitel. In der ersten Zeile wird durch das Kommando cd ohne Parameter in das Home Directory des Benutzers gewechselt. Anschließend wird per echo ein Text, der den Namen des Home Directorys enthält (dafür sorgt das pwd in den Back Quotes per Kommando-Substitution), ausgegeben. Der Inhalt des Home Directorys wird dann mit ls -l im ausführlichen ls-Format ausgegeben, bevor das Script mit dem Exit-Status des ls -l beendet wird. Interessant an diesem Script ist vielleicht für den Einsteiger, dass der Pfadwechsel im Script für die Shell, von der das Script aufgerufen wird, ohne Auswirkungen bleibt. Noch einmal zur Erinnerung: Für jedes Script wird durch die erste Zeile #!/bin/sh eine eigene Shell gestartet, welche die Abarbeitung des Scripts übernimmt. In dieser neuen Shell wird durch das cd das Working Directory verändert. Ist das Script abgearbeitet, wird diese Shell terminiert und die Veränderung des Working Directorys genauso wie die in ihr deklarierten Variablen verlieren ihre Gültigkeit.
if.sh #!/bin/sh # # Beispiel Script fuer die Ablaufstruktur if # # if [ $# -ne 1 ] then echo 'Diese Ausgabe erfolgt, wenn das Kommando ' echo '[ $# -ne 1 ] einen exit Status von 0' echo '(was TRUE bedeutet) liefert.' else echo 'Diese Ausgabe erfolgt, wenn das Kommando' echo '[ $# -ne 1 ] einen exit Status verschieden von 0' echo '(was FALSE bedeutet) liefert.' fi exit 0
Das zweite Beispiel-Script ist schon ein wenig anspruchsvoller, da es eine Ablaufstruktur enthält und somit der Programmfluss im Script nicht mehr geradlinig von oben nach unten verläuft. Die Ablaufstruktur if steht für die bedingte Verzweigung – in einem Flussdiagramm würde sich das als eine Gabelung bzw. Raute darstellen. Welche der beiden möglichen Fortsetzungen des Programmflusses eingeschlagen wird, entscheidet eine Bedingung, die entweder wahr (true) oder falsch (false) sein kann. Unter der Bourne-Shell werden diese beiden Wahrheitswerte durch den Exit-Status eines Kommandos repräsen-
316
Aufgaben tiert, wobei ein Status von 0 wahr und ein Status verschieden von 0 falsch bedeutet. In unserem Beispiel-Script ist es ein Aufruf des Kommandos test, welches durch seinen Exit-Status über die Verzweigung im Programmfluss entscheiden soll. test ist in der Lage, logische oder mathematische Vergleiche durchzuführen. Im Beispiel-Script ist zu überprüfen, ob die Anzahl der Kommandozeilenparameter (dieser Wert ist in der Variablen $#, die von der Shell eigenständig befüllt wird, gespeichert) ungleich (-ne) der Anzahl 1 ist. Ist das der Fall, gibt test einen Exit-Status von 0 zurück, was dazu führt, dass die echoKommandos zwischen dem then und dem else ausgeführt werden. Ist das Ergebnis des Vergleichs falsch, ist also die Anzahl der Kommandozeilenparameter gleich 1, so gibt test einen Exit-Status verschieden von Null – der genaue Wert spielt keine Rolle – zurück, was dazu führt, dass die echoKommandos zwischen dem else und dem fi ausgeführt werden.
for.sh #!/bin/sh # # Beispiel Script fuer die Ablaufstruktur for # # counter=1 if [ $# -eq 0 ] then # Wir haben keinen Aufrufparameter ausser dem # Scriptnamen for value in 1 zwei drei 4 fuenf do echo ${counter}. Durchlauf mit '$value' = $value counter=`expr $counter + 1` done else # Wir haben mind. einen Aufrufparameter ausser dem # Scriptnamen for value do echo ${counter}. Durchlauf mit '$value' = $value counter=`expr $counter + 1` done fi exit 0
Und wieder wird der Schwierigkeitsgrad ein wenig nach oben geschraubt. Wir haben diesmal eine Kopplung von zwei Ablaufstrukturen. Zum einen haben wir eine Ablaufverzweigung mit if und dann jeweils in beiden Zweigen eine
317
KAPITEL
17
Shell-Programmierung
Schleife mit for. Das Kriterium für die Ablaufverzweigung ist ähnlich geartet wie bei unserem letzten Beispiel – es wird getestet ([ $# -eq 0 ]), ob die Anzahl der Kommandozeilenparameter gleich 0 ist. Ist die Anzahl 0, so wird die for-Schleife zwischen dem then und dem else ausgeführt; ist sie nicht 0, wird die for-Schleife zwischen dem else und dem if ausgeführt. Nachdem das if mehr schmückendes Beiwerk ist, um die beiden unterschiedlichen Varianten der for-Schleife zu erläutern, wollen wir uns nun die beiden Schleifen mal genauer ansehen. Die Schleife zwischen dem then und dem else ist eine for-Schleife, die eine feste Zahl von Werten verarbeiten kann. Die Werte werden nach dem Schlüsselwort in in der ersten Zeile der for-Ablaufstruktur angegeben. Die einzelnen Werte (1 zwei drei 4 fuenf) werden durch Leerzeichen getrennt. Die Anzahl der Werte – in unserem Beispiel also fünf – legt fest, wie oft die Schleife durchlaufen wird. Ein Durchlauf ist dabei die Ausführung aller Kommandos, die zwischen dem do und dem done stehen. Damit nun nicht fünfmal exakt die gleichen Kommandos ausgeführt werden, verfügt die for-Schleife über eine so genannte Schleifenvariable, die in unserem Beispiel den Namen value trägt. Der Benutzer kann diesen Namen frei wählen, indem er den gewünschten Namen zwischen das for und das in schreibt. Diese Schleifenvariable hat nun die Eigenschaft, in jedem Schleifendurchlauf einen anderen der fünf Werte, die nach dem in angegeben sind, zu speichern. Im ersten Durchlauf steht in der Variablen der erste Wert (also 1), im zweiten Durchlauf der zweite Wert (also zwei) usw. ... Der Programmierer kann in den Kommandos zwischen dem do und dem done auf den Inhalt der Variablen zugreifen, indem er ein $ vor den Namen der Variablen schreibt ($value). Somit kann man unterschiedliche Werte durch die gleiche Kommandofolge bearbeiten lassen. Die zweite Variante der for-Schleife arbeitet exakt nach dem gleichen Prinzip – es werden die gleichen Kommandos zwischen dem do und dem done mit unterschiedlichen Werten für die Schleifenvariable value abgearbeitet. Aber woher kommen diese Werte? Schließlich fehlt ja das Schlüsselwort in und die ihm folgende Liste von Werten. Ganz einfach: An die Stelle einer konkreten und immer gleich bleibenden Liste von Werten tritt in dieser Variante der for-Schleife die variable Liste der Kommandozeilenparameter. So lässt sich auf elegante Art und Weise ein Shell-Script erstellen, welches in der Lage ist, unterschiedlich viele Parameter zu verarbeiten. Unter diesem Gesichtspunkt wird auch klar, warum wir zuvor durch das if abgefragt haben, ob überhaupt Kommandozeilenparameter vorhanden sind. Diese Variante der for-Schleife wird also nur dann zur Ausführung gebracht, wenn mindestens ein Parameter beim Aufruf angegeben wurde.
318
Aufgaben
while.sh #!/bin/sh # # Beispiel Script fuer die Ablaufstruktur while # # echo "Sie koennen die Eingabe durch ein CONTROL-D " echo "beenden.\n\n" counter=1 echo "Eingabe ($counter) > \c" while read input do echo "Es wurde eingegeben: $input" counter=‘expr $counter + 1‘ echo "Eingabe ($counter) > \c" done echo "\n\n-Ende-\n" exit 0
Zur Abwechslung folgt wieder etwas Einfacheres – das Beispiel für die whileSchleife. Wie auch die for-Schleife dient die while-Schleife zur wiederholten Abarbeitung der gleichen Kommandos. Allerdings verfügt sie nicht zwangsläufig wie die for-Schleife über eine Schleifenvariable, die ihren Inhalt bei jedem Durchlauf automatisch ändert, sondern sie wird über eine so genannte Laufbedingung gesteuert. Eine Laufbedingung ist dabei ein Unix-Kommando, welches vor jedem Schleifendurchlauf ausgeführt wird und durch seinen ExitStatus steuert, ob die Schleife ein weiteres Mal durchlaufen wird (das Kommando liefert einen Exit-Status von 0) oder nicht (das Kommando liefert einen Exit-Status verschieden von 0). Durch dieses Verfahren kann die Laufbedingung sehr variabel ausfallen. Allerdings sind wohl unterschiedliche Varianten des test-Kommandos die gebräuchlichsten Laufbedingungen für whileSchleifen. Um zu zeigen, dass hier auch andere Kommandos durchaus Sinn machen, habe ich in diesem Beispiel das Kommando read benutzt. read liest eine Eingabe des Benutzers in eine Variable – in diesem Beispiel heißt sie input – ein. Nach Eingabe von ŸD liefert read einen Exit-Status von 1. Jede andere Eingabe gibt einen Exit-Status von 0 zurück. Die while-Schleife liest also solange Benutzereingaben, bis dieser die Tastenkombination ŸD drückt. Die restlichen Zeilen des Scripts sind zwar nicht ganz so ausschlaggebend für seine Funktion, zeigen aber dennoch das eine oder andere nette Anschauungsbeispiel. Da wäre z.B. das Kommando echo "Eingabe ($counter) > \c" – der Ausdruck $counter wird durch den Inhalt der Variablen counter ersetzt, die als Zähler für die getätigten Eingaben fungiert, und das \c sorgt dafür, dass nach der Ausgabe des Textes kein Zeilenumbruch erfolgt. Das Inkrementieren der Zählervariablen counter wird durch das Statement
319
KAPITEL
17
Shell-Programmierung
counter=‘expr $counter + 1‘ erreicht. Hierbei bekommt die Variable counter die textuelle Ausgabe des Kommandos expr $counter + 1 als neuen Inhalt zugewiesen. Das Kommando wird ausgeführt, nachdem für $counter der bisherige Inhalt von counter eingesetzt wurde. Handelt es sich hierbei um eine Zahl, liefert das Kommando als Ergebnis die Summe dieser Zahl mit 1. Da counter mit dem Wert 1 initialisiert und danach nur noch über dieses State-
ment mit neuen Werten versorgt wird, ist gewährleistet, dass die Variable als Zähler dient.
case.sh #!/bin/sh # # Beispiel Script fuer die Ablaufstruktur case # # result=-1 while [ $result -eq -1 ] do echo "Ihre Eingabe bitte > \c" read answer case $answer in yes) result=0;; no) result=1;; *) echo Bitte entweder yes oder no eingeben. result=-1;; esac done echo "der Wert von '$result' lautet $result" exit 0
Das letzte Beispiel für eine Ablaufstruktur ist eigentlich wieder eine Kombination zweier Ablaufstrukturen, zum einen einer while-Schleife, die in diesem Fall eine unterstützende Funktion hat, und zum anderen einer case-Anweisung, die das Herzstück des Scripts ausmacht. Die while-Schleife hat als Abbruchbedingung einen test-Ausdruck. In diesem Ausdruck wird überprüft, ob der Inhalt der Variablen result gleich (-eq) -1 ist. Solange diese Bedingung erfüllt ist, liefert test (hier in der Syntaxvariante mit den eckigen Klammern) den Exit-Code 0 und die while-Schleife wird erneut durchlaufen. Da result mit -1 initialisiert wird, ist mindestens ein Durchlauf der Schleife garantiert. Zwischen dem do und dem done der while-Schleife passieren im Wesentlichen zwei Dinge: Zum einen wird vom Benutzer eine Eingabe mittels read eingelesen und in der Variablen answer gespeichert, und zum anderen wird der Inhalt dieser Variablen mithilfe einer case-Struktur bewertet.
320
Aufgaben Dass der Inhalt der Variablen answer durch den case bewertet wird, erkennt man daran, dass zwischen dem case und dem in ein $answer steht. Dieser Ausdruck wird von der Shell durch den Inhalt der Variablen answer ersetzt und mit den Mustern in den nächsten Zeilen verglichen. Diese Muster stehen in eigenen Zeilen und werden durch eine schließende runde Klammer abgeschlossen. Wir haben also die drei Muster yes, no und »*«. Der schließenden runden Klammer folgt nun jeweils ein oder mehrere Kommandos, die durch die Zeichenkombination »;;« beendet werden. Entspricht der Inhalt von answer dem Muster vor der runden Klammer, werden diese Kommandos ausgeführt. Das Muster »*« nimmt dabei eine Sonderstellung ein, es steht nämlich für ein beliebiges Muster. Da die Vergleiche in der Reihenfolge durchgeführt werden, in der sie stehen und auch nur dann, wenn nicht bereits das vorangehende Muster eine Übereinstimmung mit dem Inhalt der Variablen answer ergeben hat, bedeutet das, dass der »*« den Default-Fall der Mehrfachauswahl case darstellt. Das bedeutet: Stimmt keines der anderen Muster mit dem Inhalt von answer überein, werden die Kommandos nach der runden Klammer hinter dem »*« ausgeführt. Das Script erzwingt also als Eingabe ein yes oder no vom Benutzer.
17.7.2
Lösungen
An dieser Stelle erneut auf alle Mechanismen der fromdos- und todos-Scripts detailliert einzugehen, wäre nur eine Wiederholung der Erläuterungen zu den in Aufgabe 1 besprochenen Muster-Scripts. Daher wird an dieser Stelle nur die prinzipielle Funktionsweise der Scripts beschrieben. Außerdem sei bereits an dieser Stelle gesagt, dass die Umsetzung eines Scripts immer einige Freiheitsgrade in sich birgt, sodass es nicht die eine einzig wahre Lösung geben kann, es sich vielmehr immer um eine mögliche Lösung handelt. Seien Sie also auf keinen Fall traurig oder enttäuscht, wenn Ihr Script ein wenig anders aussieht. Wichtig ist, dass es die gestellte Aufgabe erfüllt.
fromdos #!/bin/sh # # Musterloesung fromdos # # # Anzahl der Parameter testen if [ $# -lt 1 ] then echo "Usage: `basename $0` file [file ...]" exit 1 fi
321
KAPITEL
17
Shell-Programmierung
# Schleife ueber alle Dateien for arg do # Testen ob es sich um ein Plain File handelt if [ ! -f $arg ] then echo "Die Datei $arg existiert nicht oder ist kein" echo "Plain File!" continue fi # Testen ob es sich um eine Textdatei handelt type="`file $arg | cut -d: -f2 | fgrep -ci text`" if [ $type -eq 0 ] then echo "Die Datei $arg ist keine Textdatei - " echo "tue nichts" continue fi # Testen ob man Schreibrecht auf die Datei hat if [ ! -w $arg ] then echo "Kein Schreibrecht auf die Datei $arg - " echo "tue nichts" continue fi # Testen ob die Datei bereits carriage returns enthaelt count1=`cat $arg | tr -d "\015" | wc -c` count2=`cat $arg | wc -c` if [ $count1 -eq $count2 ] then echo "Die Datei $arg beinhaltet keine carriage " echo "returns - tue nichts" continue fi # Und nun kommt die eigentliche Aufgabe tmpfile=`date '+.%H%M%S'` cat $arg | tr -d "\015" > $tmpfile mv $tmpfile $arg done
322
Aufgaben Also schauen wir uns die einzelnen Schritte, in die sich das Script unterteilt, an: Zuerst wird getestet, ob der Aufruf der Syntax entspricht. In unserem Fall soll fromdos in seiner letzten Ausbaustufe eine oder mehrere MS DOS-Dateien von den überflüssigen Carriage Return-Zeichen (^M) befreien. Dazu ist es notwendig, dass mindestens ein Dateiname als Parameter angegeben wird. Genau das testet unser erstes if-Statement. Ist die Anzahl der Kommandozeilenparameter gleich 0, liegt ein Syntaxfehler vor, was von dem Script mit der Ausgabe einer Usage-Zeile und seinem Abbruch quittiert wird. Der gesamte Rest des Scripts ist in eine for-Schleife eingeschlossen, die alle beim Aufruf von fromdos angegebenen Kommandozeilenparameter abarbeitet. Wir kennen diese Variante der for-Schleife bereits aus den BeispielScripts. Bei jedem Durchlauf durch diese Schleife erhält die Schleifenvariable arg einen anderen Kommandozeilenparameter als Wert. Innerhalb der Schleife erfolgen für jeden Kommandozeilenparameter ein paar Tests und wenn alle Tests bestanden wurden, wird die Datei, deren Name als Kommandozeilenparameter übergeben wurde, von ihren für Unix überflüssigen Carriage Return-Zeichen befreit. Schauen wir uns dies nun genauer an: Der erste Test in der Schleife überprüft, ob es sich bei der Datei nicht um ein Plain File (! -f $arg) handelt. Dieser Test ist absichtlich durch die Verwendung eines ! negiert worden, da nur im Negativfall etwas passieren soll. Dateien, die keine Plain Files – also keine »normalen« Datendateien – sind, sollen übersprungen werden. Dafür sorgt das continue zwischen dem then und fi. Es wird ein neuer Durchlauf für die Schleife mit dem nächsten Parameter angestoßen. Der nächste Test stellt sicher, dass die Datei nur reinen Text enthält. Unterbliebe dieser Test, würden eventuell aus einer Binärdatei oder einem Executable Daten entfernt, was fatale Folgen haben könnte. Ob die Datei Text enthält, wird durch die Pipe file $arg | cut -d: -f2 | fgrep -ci text geprüft. Diese Pipe lässt zunächst den Inhalt der Datei (der Name steht in der Variablen arg) durch das Kommando file analysieren. Das Ergebnis dieser Analyse wird durch den cut-Befehl vom Dateinamen der untersuchten Datei befreit. In dem verbleibenden Text, also dem eigentlichen Analyseergebnis des Kommados file, sucht das fgrep nach der Zeichenkette text (ohne Beachtung von Groß- und Kleinschreibung) und zählt das Vorkommen. Das Ergebnis dieser Zählung ist letztlich die textuelle Ausgabe der gesamten Pipe, die per Kommando-Substitution der Variablen type zugewiesen wird. Ist das Ergebnis der Zahlenwert 0, kam in der Bewertung durch file das Wort text nicht vor. Die Datei soll also auch übersprungen werden. Der nächste Test überprüft, ob ein Schreibrecht für die Datei existiert. Das ist dann notwendig, wenn der Inhalt der Datei durch das Script verändert werden
323
KAPITEL
17
Shell-Programmierung
soll. Da diese Lösung eine solche Veränderung vorsieht, ist das Schreibrecht notwendig für die weitere Bearbeitung. Dateien, für die kein Schreibrecht existiert, werden ebenfalls per continue übersprungen. Der letzte Test, der in diesem Script vor der eigentlichen Umwandlung erfolgen soll, ist ein Test, ob die Datei überhaupt Carriage Returns enthält. Sind keine solchen Zeichen enthalten, muss man sie auch nicht löschen. Um diesen Test durchführen zu können, werden zunächst einmal zwei Pipes ausgeführt und die Ergebnisse in den Variablen count1 und count2 gespeichert. In count1 wird die Anzahl der Zeichen in der Datei gespeichert, nachdem die eventuell enthaltenen Carriage Return-Zeichen durch ein tr-Kommando (tr -d "\015") gelöscht wurden. In count2 wird die Gesamtanzahl der Zeichen in der Datei gespeichert. Sind die beiden Werte in count1 und count2 identisch, enthält die Datei keine Carriage Returns und wird demzufolge mit einem continue übersprungen. Hat die Datei, deren Name in der Variablen arg gespeichert ist, all diese Tests erfolgreich überstanden, ohne dass einmal ein continue ausgeführt wurde, kann die Entfernung der Carriage Return-Zeichen erfolgen. Dies geschieht in zwei Schritten. Im ersten Schritt wird der Inhalt der Datei mittels einer Pipe durch den schon bekannten tr-Befehl zum Löschen von Carriage Returns geleitet und das Ergebnis per Ausgabeumlenkung in eine temporäre Hilfsdatei geschrieben, deren Name mit einem date-Kommando konstruiert wird. Anschließend wird dann diese Datei per mv-Kommando über die ursprüngliche Datei »gemoved«. Damit kann die nächste Datei bearbeitet werden. Das Script bricht ab, sobald alle Kommandozeilenparameter bearbeitet worden sind.
todos #!/bin/sh # # Musterloesung fuer todos # # # Anzahl der Parameter testen if [ $# -lt 1 ] then echo "Usage: `basename $0` file [file ...]" exit 1 fi # Schleife ueber alle Dateien for arg do
324
Aufgaben # Testen ob es sich um ein Plain File handelt if [ ! -f $arg ] then echo "Die Datei $arg existiert nicht oder ist kein" echo "Plain File!" continue fi # Testen ob es sich um eine Textdatei handelt type="`file $arg | cut -d: -f2 | fgrep -ci text`" if [ $type -eq 0 ] then echo "Die Datei $arg ist keine Textdatei - " echo "tue nichts" continue fi # Testen ob man Schreibrecht auf die Datei hat if [ ! -w $arg ] then echo "Kein Schreibrecht auf die Datei $arg - " echo "tue nichts" continue fi # Testen ob die Datei bereits carriage returns enthaelt count1=`cat $arg | tr -d "\015" | wc -c‘ count2=`cat $arg | wc -c` if [ $count1 -ne $count2 ] then echo "Die Datei $arg beinhaltet bereits carriage " echo "returns - tue nichts" continue fi # Und nun kommt die eigentliche Aufgabe tmpfile=`date '+.%H%M%S'` cat $arg | sed "s/$/\r/" > $tmpfile mv $tmpfile $arg done
Das Script todos ist von der Logik her in weiten Teilen mit dem Script fromdos identisch. Aus diesem Grund will ich mich diesmal nur um die kleinen, aber feinen Unterschiede dieser beiden Scripts kümmern. Zum einen werden bei todos die Inhalte von count1 und count2 auf Ungleichheit getestet. Denn nur wenn die Datei noch keine Carriage Returns enthält – also die Werte von count1 und count2 gleich sind –, darf an die einzelnen Zeilen der Datei jeweils ein Carriage Return angehängt werden.
325
KAPITEL
17
Shell-Programmierung
Zum anderen gestaltet sich die Pipe ein wenig anders. Der Inhalt der Datei wird in ein sed gepiped, das für jede Zeile das Zeilenende ($) durch ein Carriage Return (\r) ersetzt. Es wird also an jede Zeile ein Carriage Return angehängt. Das Ergebnis dieser Umformung wird, wie gehabt, in eine temporäre Hilfsdatei geschrieben, die dann anschließend wieder auf das Original »gemoved« wird.
326
KAPITEL 18
Der Reportgenerator awk Wer Software unter Unix entwickeln will oder der Programmierung von eigenen kleinen Werkzeugen zur Erleichterung der täglichen Arbeit positiv gegenüber steht, wird unter Unix ein erstaunliches Spektrum an Interpretern, programmierbaren Filtern und ähnlichen Dingen finden. Allerdings verschwinden immer mehr dieser Werkzeuge in Zusatzpaketen, die nicht mehr im Minimalumfang der kommerziell vertriebenen Unix-Systeme enthalten sind. So sind eigentlich auf allen Plattformen die Compiler, von denen es im Ur-Unix noch einige gab, zu teuren Add-Ons geworden, die nützliche Werkzeuge wie den yacc oder den lex »mit sich gerissen« haben. So ist von den Programmier-Werkzeugen neben den Shells mit ihren Programmiersprachen im Prinzip nur der awk in der Minimal-Distribution übrig geblieben. Wie auch bei einigen anderen Unix-Kommandos kommt der Name des awk durch eine nicht ganz leicht ergründbare Abkürzung zustande. Die drei Buchstaben des awk stehen für die Anfangsbuchstaben der Nachnamen der drei Entwickler: Aho, Weinberger und Kernigham. Demjenigen, der sich schon ein wenig länger mit der Programmierung in der Sprache C beschäftigt, ist bestimmt der Name Kernigham ein Begriff. Brian Kernigham entwickelte zusammen mit Dennis Richie die Sprache C und hat ihre Syntax in einem Buch beschrieben. So lassen sich in der Programmiersprache des awk dann auch reichlich Anleihen bei dieser Programmiersprache finden. Sollten Sie Grundkenntnisse in C besitzen, werden Sie Ihnen auf den folgenden Seiten sicher zu Gute kommen. Allerdings können sich auch diejenigen freuen, die bisher C gescheut haben
327
KAPITEL
18
Der Reportgenerator awk
– beherrschen Sie erst einmal den awk, ist der Schritt zum Programmieren in C nur noch ein Klacks. Im Prinzip ist der awk ein frei programmierbarer Filter, mit dem sich hervorragend Textdateien auswerten, umformatieren oder aufbereiten lassen. Aus diesem Grund wird der awk auch oft als Reportgenerator bezeichnet. Zusammen mit dem Konzept der Pipes wird der awk in vielen Shell-Scripts eingesetzt.
18.1
Grundlagen
Der awk ist sowohl in der Lage, den Inhalt von Dateien zu bearbeiten, als auch von der Standardeingabe zu lesen. In beiden Varianten sollte es sich bei den Eingangsdaten um ASCII-Text handeln. Für den awk besteht jeder ASCII-Text primär aus Records. Zwischen zwei Records steht ein Recordseperator in Form eines ASCII-Zeichens. Jeder Record besteht seinerseits aus einer Reihe von Words. Die Words eines Records werden untereinander durch Wordseperators getrennt. Ein Word ist eine Reihe von ASCII-Zeichen, in denen kein Wordseperator oder Recordseperator vorkommt. Eine andere Bezeichnung für Word ist Field. Per Default sind Recordseperator und Wordseperator so vorbelegt, dass die Zeilen einer Textdatei einzelnen Records entsprechen und die Words eines Records durch White Space-Zeichen voneinander getrennt sind. Der awk arbeitet rekordorientiert, d.h. er liest zunächst immer einen kompletten Record von der Eingabe, den er dann in die einzelnen Words zerlegt, bevor er auf diesen Record sein awk-Programm anwendet. Den gesamten Ablauf einer Bearbeitung durch den awk beschreibt das Flussdiagramm in Abb. 18.1. Der Aufruf des awk kann auf zwei unterschiedliche Arten erfolgen. Entweder werden die Statements des awk-Programms direkt auf der Kommandozeile angegeben oder aus einer Datei gelesen.
6 328
awk [-Fx] Script [ Datendatei ] awk [-Fx] -f Scriptdatei [ Datendatei ]
Das awk-Programm
Abb. 18.1: awk – Ablauf einer Bearbeitung
Wird das awk-Programm als Script direkt auf der Kommandozeile angegeben, muss es in der Regel in Single Quotes eingeschlossen werden. Wird keine Datendatei angegeben, liest der awk von der Standardeingabe, arbeitet also als Filter. -Fx
Mit der Option -F wird das Zeichen x als Fieldseparator-Zeichen (s.u.) gewählt. Default sind Leerzeichen und Tabulatorzeichen.
18.2
Das awk-Programm
Das Programm des awk besteht aus zwei grundlegenden Bestandteilen, die paarweise zusammengehören: ✘ Kriterien ✘ Aktionen Unter einem Kriterium ist eine Art Bedingung zu verstehen. Der awk prüft für den aktuellen Record alle im Programm definierten Kriterien in der Reihen-
329
KAPITEL
18
Der Reportgenerator awk
folge ihres Erscheinens. Ist ein Kriterium für einen Record erfüllt, wird die zugehörige Aktion vom awk ausgeführt. Die Aktionen werden in einer C-ähnlichen Sprache definiert und beschreiben, was mit den Words des aktuellen Records zu tun ist. Allerdings ist es nicht zwingend notwendig, dass eine Aktion den Inhalt des Records in irgendeiner Form bearbeitet. Eine Aktion ist immer dem vorangehenden Kriterium zugeordnet. Gibt es kein solches Kriterium, d.h. folgen zwei Aktionen direkt aufeinander, so ist die zweite Aktion für das leere Kriterium definiert. Diese Aktion wird dann für jeden Record ausgeführt. Analog zum leeren Kriterium gibt es auch eine leere Aktion. Folgen zwei Kriterien direkt aufeinander, ist für das erste Kriterium die leere Aktion definiert. Das heißt, ist dieses Kriterium erfüllt, gibt der awk den aktuellen Record auf die Standardausgabe aus.
18.3
Die Definition von Kriterien
Wie bereits bei den Kommandos grep und egrep sowie dem vi und dem sed spielen bei der Definition von Kriterien reguläre Ausdrücke wieder eine große Rolle. Die Kriterien werden in erster Linie über solche Ausdrücke definiert. Taucht im aktuellen Record eine Zeichenkette auf, die den regulären Ausdruck erfüllt, gilt das Kriterium als erfüllt und die zugehörige Aktion wird ausgeführt. Dies ist aber nur eine Form, um ein Kriterium zu definieren. Im Prinzip gibt es fünf unterschiedliche Formen von Kriterien, die sich teilweise miteinander kombinieren lassen.
18.3.1
BEGIN
Das Kriterium BEGIN sollte – wenn es vorhanden ist – das erste Kriterium im awk-Programm sein. Diesem Kriterium muss eine Aktion folgen. Die zu BEGIN gehörende Aktion wird genau einmal ausgeführt und zwar bevor die erste Eingabe gelesen wird. Dieses Kriterium dient dazu, eine Aktion mit Initialisierungsanweisungen auszuführen.
18.3.2
END
Das Kriterium END sollte, sofern vorhanden, stets als letztes in einem awk-Programm auftauchen. Auch das Kriterium END muss eine zugehörige Aktion haben. Diese Aktion wird genau einmal, nachdem alle Eingaben gelesen worden sind, ausgeführt und für Abschlussarbeiten, z.B. zur Ausgabe von Ergebnissen, benutzt.
330
Die Definition von Kriterien
18.3.3
/muster/
Für muster kann ein beliebiger regulärer Ausdruck gemäß der beim egrepKommando erklärten Syntax stehen, vgl. Abschnitt 7.1. Ist im aktuellen Record eine Zeichenkette enthalten, die auf den regulären Ausdruck muster passt, wird die Aktion zu diesem Kriterium ausgeführt. Als Aktion darf auch die leere Aktion stehen.
18.3.4
/m1/,/m2/
Ein solches Kriterium wird als Bereich bezeichnet. m1 und m2 sind jeweils reguläre Ausdrücke. Das Kriterium eines Bereichs ist genau dann erfüllt, wenn der aktuelle oder ein vorangegangener Record eine Zeichenkette enthält, die auf m1 passt, und seitdem kein Record gelesen wurde, der eine auf m2 passende Zeichenkette enthält. Das heißt also, das Bereichskriterium ist für alle Records zwischen dem Auftauchen von m1 und dem Auftauchen von m2 erfüllt, inklusive der Zeilen, die m1 und m2 enthalten.
18.3.5
ausdruck
Ein ausdruck hat immer einen so genannten Wahrheitswert zum Ergebnis. Es gibt zwei Wahrheitswerte: true und false. true bedeutet, dass der Ausdruck und damit das Kriterium erfüllt ist, false entsprechend das Gegenteil. Im awk unterscheidet man zwischen zwei unterschiedlichen Arten von Ausdrücken: ✘ relationale Ausdrücke ✘ Mustervergleichs-Ausdrücke Bei einem relationalen Ausdruck werden zwei Werte – das können sowohl Zahlen als auch Zeichenketten sein – miteinander verglichen. Für den Vergleich werden folgende binäre Vergleichsoperatoren1 eingesetzt: <
Kleiner als: Der Wert auf der linken Seite ist numerisch bzw. gemäß des ASCII-Wertes kleiner als der auf der rechten Seite.
>
Größer als: Der Wert auf der linken Seite ist numerisch bzw. gemäß des ASCII-Wertes größer als der auf der rechten Seite.
<=
Kleiner gleich: Der Wert auf der linken Seite ist kleiner oder gleich dem Wert auf der rechten Seite.
>=
Größer gleich: Der Wert auf der linken Seite ist größer oder gleich dem Wert auf der rechten Seite.
1. Unter einem binären Operator versteht man einen Operator, bei dem auf beiden Seiten ein Wert steht, also in der Form Wert1 Operator Wert2.
331
KAPITEL
18
Der Reportgenerator awk
==
Gleich: Der Wert auf der linken Seite ist gleich dem Wert auf der rechten Seite.
!=
Ungleich: Der Wert auf der linken Seite ist verschieden von dem auf der rechten Seite.
Während sich relationale Ausdrücke sowohl mit numerischen als auch mit textuellen Werten bilden lassen, geht es beim Mustervergleich ausschließlich um den Vergleich zwischen Zeichenketten und regulären Ausdrücken. Es wird also getestet, ob eine Zeichenkette auf einen regulären Ausdruck passt oder nicht. Auch hier gibt es zwei binäre Operatoren: ~
Der zugehörige Ausdruck ist true, wenn die Zeichenkette auf der linken Seite zum regulären Ausdruck auf der rechten Seite passt.
!~
Der mit diesem Operator gebildete Ausdruck ist dann true, wenn die Zeichenkette auf der linken Seite nicht zum regulären Ausdruck auf der rechten Seite passt.
18.3.6
Kombinierte Kriterien
Die drei zuletzt vorgestellten Formen von Kriterien lassen sich miteinander kombinieren. Die Kombination erfolgt über die Verknüpfung der Kriterien mit den beiden folgenden Operatoren. ||
Logisches ODER: Ein Ausdruck der Form a || b ist genau dann true, wenn entweder a oder b true ist oder a und b true sind.
&&
Logisches UND: Ein Ausdruck der Form a && b ist genau dann true, wenn a und b true sind.
Werden mehr als zwei Kriterien kombiniert, gilt als Vorrangregel, dass && stärker bindet als ||.
3 3 332
/[Aa]uto/
Dieses Kriterium ist für alle Records erfüllt, in denen die Zeichenkette Auto auftaucht. Dabei wird durch die eckigen Klammern im regulären Ausdruck dafür gesorgt, dass auch solche Zeichenketten als Treffer erkannt werden, bei denen das a klein geschrieben ist.
/
Die Definition von Kriterien Dieses Bereichskriterium trifft auf alle Records zu, die zwischen dem Auftauchen der Zeichenkette stehen. beendet ihn wieder.
Das heißt also, dieses Kriterium ist für alle Records erfüllt, die zu einem HTML-Kommentar gehören.
length() > 30
Bei diesem Kriterium handelt es sich um einen relationalen Ausdruck. Der Wert auf der linken Seite des Operators ist eine eingebaute Funktion1 des awk und liefert in der hier verwendeten Form als Ergebnis die Länge des Records in Buchstaben als Ergebnis. Das Kriterium ist also für alle Records erfüllt, die länger als dreißig Zeichen sind.
$1 ~ /[Aa]uto/
Um die Aussage dieses Kriteriums zu verstehen, muss ein wenig vorgegriffen werden. Wie oben erwähnt, zerlegt der awk, nachdem er einen Record gelesen hat, diesen in seine einzelnen Words. Auf diese kann man in der Programmiersprache des awk und in den Kriterien über bestimmte Variablen zugreifen. So befindet sich das erste Word des aktuellen Records in einer Variablen mit dem Namen $12. Also ist das Kriterium aus dem Beispiel genau dann true, wenn das erste Word des Records auto oder Auto lautet – denn genau diese beiden Zeichenketten erfüllen den regulären Ausdruck /[Aa]uto/.
length() > 30 && $1 ~ /[Ll]utz/
Dieses Beispiel zeigt eine UND-Verknüpfung der Kriterien aus den beiden vorangegangenen Beispielen. Dieses Kriterium ist also genau dann true, wenn die Länge des Records dreißig Zeichen überschreitet und das erste Word lutz oder Lutz lautet.
3 3
3
1. Eine Zeichenkette müsste in doppelte Hochkommas eingeschlossen werden. 2. Im Gegensatz zur Shell gehört beim awk das Dollarzeichen mit zum Namen der Variablen.
333
KAPITEL
18 18.4
Der Reportgenerator awk
Die Sprache der Aktionen
Die Programmiersprache des awk für die Aktionen ist stark an die Programmiersprache C angelehnt. Eine Aktion muss folgender Syntax genügen:
6
{ Statement [Statement [Statement ...]]}
Eine Aktion setzt sich aus einer Abfolge von Statements zusammen. Die Reihenfolge, in der die Statements bearbeitet werden, kann durch spezielle Statements, die Ablaufstrukturen, gesteuert werden. Eine Aktion muss immer in geschweifte Klammern »{}« eingeschlossen werden. Stehen zwei Statements in einer Zeile, sind sie durch ein Semikolon »;« zu trennen.
18.4.1
Zuweisungen
Die einfachste Form eines Statements ist die Zuweisung. In einem Statement dieser Art wird einer awk-Variablen ein Wert zugewiesen. Im Gegensatz zu den Variablen der Programmiersprache C sind die Variablen des awk typenlos. Sie können einzelne Zeichen, Zeichenketten und numerische Werte aufnehmen. Enthält eine Variable einen numerischen Wert, lassen sich mit ihr arithmetische Ausdrücke bilden, deren Ergebnis entweder einer anderen Variablen zugewiesen, auf der Ausgabe ausgegeben oder in einem Vergleich abgefragt werden kann.
6 3 334
Variablenname = Wert
Der Name einer Variablen ist innerhalb eines awk-Programms eindeutig, d.h., nach seinem erstmaligen Gebrauch – gleichbedeutend mit der Deklaration der Variablen – verweist der Variablenname immer auf die gleiche Variable. Dabei kann der Wert entweder eine Konstante, eine Variable oder das Ergebnis eines Ausdrucks sein.
version = "test"
In diesem Beispiel wird einer Variablen mit dem Namen version als Wert die Zeichenkette test zugewiesen.
Die Sprache der Aktionen Neben dieser klassischen Art der Zuweisung kennt der awk auch eine Reihe von Abkürzungen für bestimmte Zuweisungen. Diese sollen in der nun folgenden Tabelle vorgestellt werden: Zuweisung
Bedeutung
I++
i = i + 1
i--
i = i – 1
i += j
i = i + j
i -= j
i = i – j
i *= j
i = i * j
i /= j
i = i / j
i %= j
i = i % j
18.4.2
Konstanten
Eine Konstante kann entweder numerisch oder textuell sein. Numerische Konstanten müssen eine der folgenden Formen haben: 1234
Ganzzahlige Konstante
1234.79
Rationale Konstante
1234.0e7
Rationale Konstante in Exponentialschreibweise
"Text"
Textuelle Konstante. Textuelle Konstanten müssen immer in doppelte Anführungszeichen eingeschlossen werden.
18.4.3
Variablen
Neben den Variablen, die der Benutzer selbst definieren kann, gibt es auch eine Reihe von Variablen, die vom awk zur Verfügung gestellt und mit den entsprechenden Werten vorbelegt werden. FILENAME
Name der aktuellen Datei, aus der die Eingaben gelesen werden
FS
Fieldseparator: In dieser Variablen steht das Zeichen, welches die einzelnen Words eines Records trennt. Der Default ist »White Space« – also ein oder mehrere Leerzeichen oder das Tabulatorzeichen. Wird der Wert des FS in der Initialisierungsaktion des awk-Programms verändert, verändert sich entsprechend die Zerlegung in Words.
NF
Number of Fields: Für jeden gelesenen Record wird in dieser Variablen die Anzahl der enthaltenen Words gespeichert.
NR
Number of Record: Für jeden gelesenen Record wird diese Variable um 1 erhöht. Sie enthält also immer die Nummer des aktuell eingelesenen Records.
335
KAPITEL
18
Der Reportgenerator awk
OFS
Output Fieldseparator: In dieser Variablen steht das Zeichen, welches bei der Ausgabe des kompletten Records zwischen den einzelnen Words steht. Default ist das Leerzeichen.
ORS
Output Recordseparator: Werden mehrere Records auf die Ausgabe ausgegeben, werden sie durch das Zeichen aus dieser Variablen getrennt. Default ist das newline-Zeichen.
RS
Recordseparator: Durch dieses Zeichen werden die einzelnen Records in der Eingabe getrennt. Der Default ist das newline-Zeichen. Wird das Zeichen in der Initialisierungsaktion des awk-Programms verändert, verändert sich auch die Aufteilung der Eingabe in Records. Bleibt es bei dem Default-Zeichen, arbeitet der awk zeilenweise.
$0
In dieser Variablen steht der komplette Record. Das Dollarzeichen gehört mit zum Namen der Variablen.
$n
Die Variablen der Form $n enthalten die Words eines Records. Dabei können für n die Werte 1 <= n <= NF stehen.
$NF
In dieser Variablen steht das letzte Word des aktuellen Records.
18.4.4
Ablaufstrukturen
Wie alle prozeduralen Programmiersprachen verfügt auch die des awk über Ablaufstrukturen.
if Die wohl am häufigsten benutzte Ablaufstruktur ist das if. Durch den Einsatz des if kann in Abhängigkeit von einer Bedingung eine Verzweigung im Programmfluss erzielt werden. Die Bedingung liefert als Ergebnis eines der beiden Wahrheitswerte true oder false.
6
if (Bedingung) Anweisungsblock [else Anweisungsblock]
Als Bedingung kann ein relationaler Ausdruck, der nach den gleichen Regeln wie für ein Kriterium gebildet wird, angegeben werden. Mehrere Bedingungen können durch logisches UND oder ODER verknüpft werden. Enthält ein Anweisungsblock mehr als ein Statement, ist er in geschweifte Klammern »{}« einzuschließen. Stehen mehrere Statements in einer Zeile, sind sie durch Semikola zu trennen.
336
Die Sprache der Aktionen
if (version == "test") { print "Testversion" a = 2 } else print "normale Version"
3
In diesem Beispiel wird getestet, ob die Variable version die Zeichenkette test enthält. Ist dies der Fall, wird die Zeichenkette Testversion ausgegeben und die Variable a mit dem Wert 2 belegt. Enthält die Variable version eine andere Zeichenkette, wird normale Version ausgegeben.
for Die am zweithäufigsten verwendete Ablaufstruktur ist die for-Schleife. Eine Schleife dient dazu, ein oder mehrere Statements mehrfach zu durchlaufen. Die Festlegung, wie häufig die Statements ausgeführt werden sollen, wird über eine Schleifenbedingung getroffen.
for (Initialisierung;Bedingung;Endeanweisung) anweisungsblock
6
Vor jedem Schleifendurchlauf wird getestet, ob die Schleifenbedingung Bedingung noch erfüllt ist. Wenn ja, werden die Statements aus dem Anweisungsblock ihrer Reihenfolge nach ausgeführt. Bevor aber die Bedingung das erste Mal getestet wird, wird das Statement für die Initialisierung ausgeführt. Sind alle Statements aus dem Anweisungsblock für einen Durchlauf ausgeführt worden, wird die Endeanweisung – also einmal pro Schleifendurchlauf – ausgeführt. Enthält der Anweisungsblock mehr als ein Statement, ist er in geschweifte Klammern »{}« einzuschließen. Stehen mehrere Statements in einer Zeile, sind sie durch Semikola zu trennen.
for (i = 0;i < 20;i++) print "Schleifendurchlauf: " i
3
Dieses Beispiel zeigt die häufigste Art der Anwendung einer for-Schleife. Die Schleife im Beispiel wird zwanzigmal durchlaufen. Die Variable i wird mittels i = 0 mit dem Wert 0 initialisiert und bei jedem Schleifendurchlauf durch i++
337
KAPITEL
18
Der Reportgenerator awk
um 1 erhöht. Pro Durchlauf wird die Zeichenkette Schleifendurchlauf: gefolgt von dem Wert für i ausgegeben (0 bis 19).
while Im Gegensatz zur for-Schleife hat die while-Schleife nur eine Schleifenbedingung, aber keine Initialisierungs- oder Ende-Anweisung. Sie ist also im Prinzip eine vereinfachte for-Schleife.
6
while (Bedingung) Anweisungsblock
Vor jedem Schleifendurchlauf wird die Bedingung getestet. Ist sie erfüllt (true), werden die Statements aus dem Anweisungsblock ausgeführt. Enthält der Anweisungsblock mehr als ein Statement, ist er in geschweifte Klammern »{}« einzuschließen. Stehen mehrere Statements in einer Zeile, sind sie durch Semikola zu trennen.
3
i = 0 while (i < 20){ print "Schleifendurchlauf: " i i++ }
Die while-Schleife aus dem Beispiel leistet die gleiche Arbeit wie die forSchleife aus dem letzten Beispiel.
do Die do-Schleife ist eine while-Schleife, bei der die Schleifenbedingung nicht vor der Ausführung der Statements aus dem Anweisungsblock getestet wird, sondern nach deren Ausführung. Der Anweisungsblock der do-Schleife wird also immer mindestens einmal durchlaufen.
6 338
do Anweisungsblock while (Bedingung)
Die Sprache der Aktionen Stehen mehrere Statements in einer Zeile, sind sie durch Semikola zu trennen.
i = 0 do print i i = i + 1 while (i < 20)
3
Diese Schleife wird ebenfalls zwanzigmal durchlaufen und es werden die Werte von 0 bis 19 für i ausgegeben.
break Mit der Anweisung break wird eine Schleife ohne Testen der Schleifenbedingung sofort verlassen.
break
continue
6
Mit der Anweisung continue wird in einer while- oder for-Schleife die Bearbeitung des Anweisungsblocks abgebrochen und an den Schleifenanfang gesprungen.
continue
exit
6
Mit der Anweisung exit wird die aktuelle Verarbeitung abgebrochen und direkt zum Kriterium END gesprungen bzw. das awk-Programm verlassen, wenn eine solche nicht angegeben ist oder sich die Verarbeitung bereits in den ENDAktionen befindet.
exit
6 339
KAPITEL
18
Der Reportgenerator awk
getline Mit getline wird ein neuer Record gelesen und in $0 abgelegt. Es wird in derselben Aktion nach dem getline mit der Bearbeitung fortgefahren.
6
getline
next Mit next wird ebenfalls ein neuer Record in $0 eingelesen. Im Unterschied zu getline wird aber nicht in derselben Aktion mit der Bearbeitung fortgefahren, sondern ein neuer Durchlauf in der awk-internen Schleife begonnen. Es wird also mit der Überprüfung des ersten Kriteriums des awk-Programms für den neuen Record fortgefahren.
6
next
18.4.5
Funktionen
Neben den Ablaufstrukturen zur Steuerung der Reihenfolge, in der die Statements abgearbeitet werden, verfügt der awk auch noch über eingebaute Funktionen. Diese stellen in Abhängigkeit von an sie übergebenen Parametern bestimmte Funktionsergebnisse zur Verfügung oder geben im Falle der Ausgabefunktionen Zeichenketten auf die Ausgabe aus. Als Funktionsergebnisse sind sowohl numerische als auch textuelle Werte möglich. Nachfolgend werden die wichtigsten awk-Funktionen in alphabetischer Reihenfolge aufgelistet.
cos Diese Funktion liefert den Cosinus von x in Radian.
6 340
cos(x)
Die Sprache der Aktionen
exp Diese Funktion liefert den Exponenten von x zur Basis e (inverse Funktion zu log(x)).
exp(x)
index
6
Mit dieser Funktion kann die Position von teilstring in string bestimmt werden.
index(string,teilstring)
int
6
Diese Funktion liefert den ganzzahligen Anteil von x.
int(x)
length
6
Die Funktion length liefert als Ergebnis die Länge eines Strings.
length([string])
Wird length ohne einen String als Argument aufgerufen, liefert es die Länge des aktuellen Records.
6
log Diese Funktion liefert den natürlichen Logarithmus von x (inverse Funktion zu exp(x)).
log(x)
6 341
KAPITEL
18
Der Reportgenerator awk
print Die Funktion print gibt die übergebenen Argumente unformatiert auf das Ziel aus.
6
print [argument [argument...]] [ziel]
Als Argumente können Variablen, numerische Konstanten und konstante Zeichenketten übergeben werden. Bei Variablen wird deren Inhalt ausgegeben. Die einzelnen Argumente sind durch den OFS1 zu trennen. Als Ziel kann in der gleichen Syntax wie bei der Ausgabeumlenkung der Shell eine Datei angegeben werden. Unformatierte Ausgabe bedeutet, dass die Argumente immer in der geringstmöglichen Breite ausgegeben werden. Die Ausgabe wird immer durch einen Zeilenumbruch abgeschlossen.
printf Mit der Funktion printf kann eine formatierte Ausgabe erfolgen.
6
printf [formatstring[,argument[,argument...]]]
Mit printf können die Argumente auch in anderen Breiten als der geringstmöglichen ausgegeben werden. Außerdem erfolgt nicht automatisch ein Zeilenumbruch, vielmehr muss dieser vom Benutzer »erzwungen« werden. Für die Formatierung der Ausgabe wird ein Formatstring angegeben, der in der Regel allen konstanten Text und die Platzhalter für die Werte der nachfolgenden Argumente enthält. Enthält der Formatstring \n, erfolgt an der Stelle bei der Ausgabe ein Zeilenumbruch. Die Platzhalter sind an die der printf-Funktion der Programmiersprache C angelehnt. Folgende Platzhalter sind üblich: %[-][n]s
Der Platzhalter %s steht für eine Zeichenkette. Wird er durch einen Zahlenwert für n ergänzt, gibt n die minimale Breite in Zeichen an, mit der die Zeichenkette ausgegeben werden soll. Folgt dem % ein -, wird der String linksbündig formatiert.
%[-][n]d
Der Platzhalter %d steht für eine ganze Zahl. Wird er durch einen Zahlenwert für n ergänzt, gibt n die minimale Breite
1. Output Fieldseparator, siehe auch Variablen des awk.
342
Die Sprache der Aktionen in Zeichen an, mit der die ganze Zahl ausgegeben werden soll. Folgt dem % ein -, wird die Zahl linksbündig formatiert. %[-][n[.m]]f
Der Platzhalter %f steht für eine gebrochen rationale Zahl. Wird er durch einen Zahlenwert für n ergänzt, gibt n die minimale Breite in Zeichen an, mit der die gebrochen rationale Zahl ausgegeben werden soll. Wird n um einen Zahlenwert für m erweitert, gibt m die minimale Breite der Gesamtbreite für die Nachkommastellen an. Folgt dem % ein -, wird die gebrochen rationale Zahl linksbündig formatiert.
Als argumente können durch Kommata getrennt Variablen, Konstanten und Ausdrücke wie z.B. die Summe zweier Variablen angegeben werden.
grad = 180.0 printf "Der Sinus von %5.1f ist %7.5f\n",grad,sin(grad)
3
Die beiden Statements aus dem Beispiel würden folgende Ausgabe erzeugen: Der Sinus von 180.0 ist 0.00000
sin Die Funktion sin liefert als Ergebnis den Sinus von x in Radian.
sin(x)
split
6
Die Funktion zerlegt eine Zeichenkette string in einzelne Words.
split(string,variable[,fieldseparator])
Die Zeichenkette wird in die durch den fieldseparator getrennten Words zerlegt. Die n Words werden in den Variablen variable[1] bis variable[n] gespeichert. Wird kein Fieldseparator angegeben, wird das Zeichen aus FS genommen. Als Ergebnis liefert die Funktion die Anzahl der Words, in welche die Zeichenkette zerlegt wurde.
anzahl = split("Dies ist ein Test",str)
6 3 343
KAPITEL
18
Der Reportgenerator awk
Als Ergebnis würde bei diesem Beispiel 4 in der Variablen anzahl gespeichert werden und str[1] enthielte den Wert Dies, str[2] den Wert ist usw.
sqrt Die Funktion sqrt liefert als Ergebnis die Quadratwurzel von x.
6
sqrt(x)
substr Um einen Teil aus einer Zeichenkette auszuschneiden, benutzt man die Funktion substr.
6 3
substr(string,m[,n])
Die Funktion liefert als Ergebnis den Teil der Zeichenkette string, der bei Zeichen Nummer m beginnt und von dort n Zeichen lang ist. Wird kein Wert für n angegeben, wird als Ergebnis die Zeichenkette vom Zeichen Nummer m bis zum Ende der Zeichenkette string geliefert.
substr("Teststring",5)
Dieser Funktionsaufruf würde als Ergebnis das Wort string liefern.
18.5
Beispiele für awk-Programme
Um den richtigen Einsatz der Programmelemente zu veranschaulichen, sollen nun ein paar kommentierte Beispielprogramme vorgestellt werden.
3 344
awk /tcsh/ /etc/passwd
Dieses awk-Programm ist ein ganz einfaches Beispiel. Es besteht im Prinzip nur aus einem Kriterium (/tcsh/) und der zugehörigen leeren Aktion. Wir erinnern uns – die leere Aktion war gleichbedeutend damit, dass Records, für die das Kriterium erfüllt ist, ausgegeben werden. Da in diesem Beispiel der awk zeilenorientiert arbeitet (das ist Default) und das Kriterium ein regulärer Aus-
Beispiele für awk-Programme druck ist, gibt dieser Aufruf des awk all jene Zeilen aus der /etc/passwd aus, in denen das Wort tcsh auftaucht. Die Aufgabe, die dieses awk-Programm löst, könnte sicherlich effizienter mithilfe eines grep-Kommandos geschehen und ist daher eher ein untypischer Vertreter.
awk '/<\!--/,/-->/' index.html
Dieses awk-Programm besteht auch wieder nur aus einem Kriterium und der dazu gehörigen leeren Aktion. Wie bereits oben erläutert, trifft dieses Kriterium auf alle Kommentarzeilen in einer HTML-Datei zu. Also würden durch dieses Kommando alle Kommentare aus der Datei index.html ausgegeben.
#!/bin/sh find . -type { for (i = printf " print "|}'
d -print | awk -F/ ' 1;i < NF -1;i++) " " $NF
3 3
Dieses Script könnte z.B. folgende Ausgabe erzeugen: |- . |- .. |- Mail |- src |- C |- Fortran |- tmp
Bei diesem Beispiel handelt es sich um ein awk-Programm, das mit einem Shell-Script gekoppelt wurde. So etwas wird häufig gemacht, um dem späteren Anwender die Kenntnis über die Aufrufsyntax des awk zu ersparen. In dem hier gezeigten Beispiel verarbeitet der awk die Ausgaben eines find-Befehls, der die relativen Pfade aller Verzeichnisse unterhalb des Working Directorys ausgibt. Der awk nimmt diese Pfadnamen, wobei jeder Pfad für ihn ein Record ist, und zerlegt sie in die einzelnen Verzeichnisnamen, aus denen sich der Pfad zusammensetzt. Damit dies so geschieht, haben wir beim Aufruf als Trenner den Slash »/« (-F/) angegeben. Das eigentliche Programm besteht aus der Aktion zum leeren Kriterium, d.h., diese Aktion wird für jede Zeile ausgeführt. Die for-Schleife erzeugt eine Einrückung und zwar jeweils um zwei Leerzeichen pro Verzeichnisnamen im
345
KAPITEL
18
Der Reportgenerator awk
Pfad. Da das printf keinen Zeilenumbruch erzwingt, kommt diese Einrückung erst bei der print-Anweisung nach der Schleife zum Tragen. In dieser print-Anweisung wird der letzte Verzeichnisname aus dem Pfad ausgegeben. Resultat dieses Scripts ist eine Ausgabe des Verzeichnisbaums unterhalb des Working Directorys, wobei durch die Tiefe der Einrückung die Position des Verzeichnisses in der Hierarchie angezeigt wird.
18.6
awk für Poweruser
Auch wenn sich unter dem Eindruck von einigen Jahren Unix in Support und Administration der Begriff des Powerusers ein wenig verschoben hat (oftmals muss man einen User schon als Poweruser hervorheben, wenn er die Dokumentation zumindest ansatzweise gelesen hat), ist dieser Abschnitt für all jene Leser gedacht, die durch die vorangegangenen Abschnitte auf den Geschmack gekommen sind und ein wenig mehr mit dem awk machen wollen, bzw. für jene, die bereits awk-Praxis besitzen, aber bei einem konkreten Problem in’s Stocken geraten sind. Diesen Usern sei gleich zu Beginn die Benutzung des nawk oder des GNU-awk (gawk) an das Herz gelegt. Zum einen bieten beide Tools verbesserte Fehlerausgaben, die das Debuggen doch erheblich vereinfachen können, zum anderen warten sie mit einer Reihe neuer Funktionen auf, die der »normale« awk vermissen lässt.
18.6.1
Arrays
Wie viele andere Programmiersprachen auch bietet der awk die Möglichkeit, Felder von Variablen zu erzeugen – sog. Arrays. Unter einem solchen Array wird eine Anzahl von Variablen verstanden, die den gleichen Namen tragen und nur durch einen Index voneinander unterschieden werden. Wir haben Arrays beim Ergebnis der Funktion split bereits kurz kennen gelernt. Die Arrays des awk verfügen über zwei besondere Eigenschaften: 1. Sie sind dynamisch, d.h. der Programmierer muss nicht im Vorfeld deklarieren, wie viele Variablen ein Array aufnehmen können soll, sondern die einzelnen Variablen werden erzeugt, sobald sie benötigt werden. 2. Wie bereits erwähnt sind die Variablen des awk typenlos und werden je nach Bedarf als Zeichenfolge oder Zahl interpretiert. Dies bedingt, dass es auch keinen Indextyp für die Indizierung eines Arrays gibt. Als Index für ein awk-Array können also beliebige Zeichenketten benutzt werden. Am besten lässt sich die Arbeit mit Arrays an einem kleinen Beispiel erläutern.
346
awk für Poweruser
#!/bin/sh tr ".,;:-" " " < $1 | awk ' { for (i=1;i<=NF;i++) words[$i]++ } END { for (word in words) printf("%-20s %5d\n",word,words[word]); } ' | sort
3
Dieses kleine in ein Shell-Script eingebettete awk-Script (der fett gedruckte Teil) benutzt die beiden oben genannten besonderen Eigenschaften. Die Aktion { for (i=1;i<=NF;i++) words[$i]++ }
wird für jede Zeile der Eingabedatei ausgeführt. Der awk zerlegt die Zeile in ihre einzelnen Worte und speichert diese in den Variablen $1 bis $NF. Die forSchleife läuft über die einzelnen Variablen, sodass $i immer den Inhalt der jeweils aktuellen Variablen enthält. Dieser Inhalt (ein Wort der Zeile) wird als Index für das Feld words benutzt. Wie man sieht, muss dieses Feld weder deklariert noch initialisiert werden – bei einer zahlenmäßigen Interpretation ist der Inhalt einer Variablen des Feldes vor dem ersten Zugriff 0 bzw. der Leerstring bei einer stringmäßigen Interpretation. Der Ausdruck words[$i]++ bedeutet, dass der Inhalt der Variablen mit dem Index $i des Feldes words um 1 inkrementiert wird. Da der Inhalt vor dem ersten Zugriff 0 ist, fungiert somit words[$i] als Zähler für das in $i gespeicherte Wort. Somit wird im Array words eine Statistik darüber gespeichert, wie oft ein Wort in der Eingabedatei vorkommt. Da das Array nicht initialisiert oder deklariert werden muss, ist es auch nicht notwendig zu wissen, welche Worte als Index vorkommen können. Aber wie kann man herausbekommen, welche Worte in der Datei enthalten waren bzw. welche Indizes verwendet wurden? Dieser Aspekt wird in der END-Aktion behandelt: END { for (word in words) printf("%-20s %5d\n",word,words[word]); }
Die Schleife for (word in words) durchläuft alle Indizes, die für das Array words verwendet worden sind. Für das Beispiel-Script sind das alle Worte, die in der Eingabedatei vorgekommen sind. Für jedes als Index benutzte Wort
347
KAPITEL
18
Der Reportgenerator awk
wird durch den printf-Befehl das Wort selbst und der Wert von words[word] ausgegeben – also die Häufigkeit des Wortes in der Eingabedatei. Neben den eindimensionalen Arrays, wie oben beschrieben, unterstützt der awk auch mehrdimensionale Arrays. Um eine Variable eines mehrdimensionalen Arrays zu definieren, gibt man zwischen den eckigen Klammern mehrere Indizes durch Komma getrennt an und zwar pro Dimension des Arrays ein Index. So würde die Anweisung arr[i,j]=20
einer Variablen aus dem zweidimensionalen Array arr den Wert 20 zuweisen.
18.6.2
Definition von Variablen auf der Kommandozeile
Immer dann, wenn man ein awk-Script in ein Shell-Script einbettet, wird man in die Situation kommen, dass die Werte von Shell-Variablen an den awk weitergegeben werden sollen. Zu diesem Zweck unterstützt der awk ein Feature, das es dem Benutzer erlaubt, solche Variablen beim Aufruf des awk in der Kommandozeile zu übergeben. Mit der Kommandozeilenoption –v var=value wird die awk-Variable var definiert und mit dem Wert value belegt. Die Variable ist anschließend in allen Aktionen des awk verfügbar.
3
#!/bin/sh . . awk –v parmeter1=$1 .
In diesem kleinen Auszug wird z.B. der erste Übergabeparameter des ShellScripts, in welches das awk-Script eingebettet ist, in der Variablen parameter1 an den awk übergeben.
18.6.3
Funktionen selbst gemacht
Je mehr man mit dem awk arbeitet, desto größer und komplexer werden die eigenen awk-Scripts. Häufig benötigt man wiederkehrende Funktionalitäten in unterschiedlichen Aktionen. Solche Passagen eines awk-Programms lassen sich wie in jeder anderen Programmiersprache auch in einer Funktion zusammenfassen. Funktionen sollten im awk vor den Kriterien und Aktionen definiert werden, um ein übersichtliches awk-Programm zu erzeugen. Eine Funktion wird wie folgt definiert:
348
awk für Poweruser
function name ([parameter[,parameter...]]) { Anweisungsblock }
6
Eine solche Funktion kann dann genauso aufgerufen werden wie eine der eingebauten Funktionen des awk, die in Abschnitt 18.4.5 vorgestellt wurden.
function concat (str1,str2) { result=sprintf("%s%s",str1,str2) return result }
3
Diese Funktion hängt einfach zwei Strings hintereinander und gibt als Ergebnis den zusammengefügten String zurück. Leider unterstützt der awk nur unzulänglich die Sammlung selbst geschriebener Funktionen in Libraries. Zwar kann bei einigen Versionen des awk die Option -f gefolgt von einer Scriptdatei mehrfach in der Kommandozeile angegeben werden (nach dem ersten -f z.B. die Library-Datei und nach einem weiteren -f die eigentliche Scriptdatei), aber die Kopplung eines Scripts mit der Kommandozeile und der Option -f ist nicht möglich. Also wird in der Regel der gesamte Code der Funktionen mit in das awk-Script geschrieben. Spätestens bei der intensiven Nutzung von Funktionen sollte Gebrauch von Kommentaren gemacht werden, damit auch später noch klar ist, wofür die einzelne Funktion bestimmt sind. Einen Kommentar gibt man im awk ein, indem man ein Hash (»#«) Zeichen eingibt. Jeder nachfolgende Text bis zum Zeilenende ist dann Kommentar.
18.6.4
Pipes und Ausgabeumlenkungen
Im Laufe dieses Kapitels ist vielen sicherlich schon aufgefallen, dass awk Scripts häufig in Shell-Scripts eingebettet werden, um die Funktionalität der Shell auszubauen. Viele Dinge die sich mit reinen Shell-Kommandos nur schwer bewerkstelligen lassen, sind im awk ein Kinderspiel (z.B. Rechnen mit gebrochen rationalen Zahlen). Aber wie sieht es umgekehrt aus? Kann man auch Shell-Kommandos aus dem awk heraus aufrufen? Die Antwort ist ein klares JA – der awk kann Shell-Kommandos ausführen und er kann die Ergebnisse einer solchen Ausführung auch einlesen und weiterverarbeiten. Darüber hinaus stellt er dem Programmierer den Zugriff auf Dateien über Ein-/Ausgabe-Funktionen zur Verfügung.
349
KAPITEL
18
Der Reportgenerator awk
Viele dieser Möglichkeiten beruhen auf dem Einsatz der getline-Funktion, die schon im Abschnitt 18.4.4 vorgestellt wurde. Dort wurde sie noch als Ablaufstruktur bezeichnet, weil sie die Möglichkeit bietet, eine Zeile aus der Eingabedatei zu lesen, ohne dabei den Automatismus des awk zu bemühen. In diesem Abschnitt sollen nun noch ein paar weitere Fähigkeiten von getline vorgestellt werden. Neben der Möglichkeit, »außerhalb der Reihe« eine Zeile aus der Eingabedatei zu lesen, kann getline auch aus einer anderen Datei lesen, die der awk noch nicht zuvor geöffnet hatte. Meist geschieht dies mit einem Konstrukt wie folgt:
3
while ( (getline < "/home/lutz/data") > 0) print
In diesem Beispiel wird solange aus der Datei /home/lutz/data mit getline gelesen (<), wie das Funktionsergebnis von getline größer Null (> 0) ist. Das ist genau solange der Fall, wie getline noch eine Zeile aus der Datei lesen kann. Diese gelesene Zeile wird in $0 eingelesen und in ihre Einzelworte ($1 $NF) zerlegt. Im Beispiel wird einfach im Body der Schleife die Funktion print aufgerufen, die ohne weitere Parameter den Inhalt von $0 ausgibt. Die Anführungszeichen um den Dateinamen sind wichtig, da awk andernfalls versuchen wird den Namen als Variablennamen zu interpretieren. Aber getline kann noch mehr. Es muss nämlich keine Datei sein, die den Input für getline zur Verfügung stellt, sondern es kann auch einfach ein ShellKommando diesem Zweck dienen. Allerdings verwendet man dann kein Eingabeumlenkungszeichen (<) sondern ein Pipe. Auch hier sagt ein kleines Beispiel mehr als tausend gut gemeinte Erklärungen:
3
while ("ls -l" | getline) print
Ähnliches Konstrukt, ähnliche Wirkung – das Shell Komando ls -l wird ausgeführt, der dabei erzeugte Output wird zeilenweise von getline in $0 eingelesen, in Worte zerlegt und durch das print im Schleifenbody ausgegeben. Die Formulierung der Schleifenabbruchbedingung ist diesmal ein wenig kürzer ausgefallen, weil durch die Assoziation der beiden Wahrheitswerte true und false mit Zahlen (false = 0 und true verschieden von Null) diese Schreibweise äquivalent zur der obigen ist, bei der der Returnwert von getline explizit abgefragt wurde.
350
Aufgaben Nachdem man mit getline per Eingabeumlenkung (<) aus einer Datei lesen kann, ist es nicht besonders überraschend zu erfahren, dass auch aus dem awk heraus per Ausgabeumlenkung in Dateien geschrieben werden kann. Im Prinzip ist die Syntax identisch mit der aus der Shell.
printf("Hello world\n") > "/home/lutz/output.txt"
Wen wundert es da, wenn nun auch noch das Anhängen an eine bereits bestehende Datei mit dem append (>>) aus der Shell ebenfalls vom awk beherrscht wird?
Aber Vorsicht – im Gegensatz zur Shell, wo der Interpreter die Ein-/Ausgabeumlenkungen vor Ausführung des Kommandos aus dem Kommando herausfiltert und somit die Position nahezu egal ist, ist der awk hier fest an die oben beschrieben Syntax gebunden.
3 2
Übungen
18.7
Aufgaben
1. Probieren Sie die Beispiele aus dem Kapitel zur awk-Programmierung an geeigneten Dateien aus. 2. Geben Sie die folgenden beiden Dateien auf Ihrem Rechner ein und rufen Sie dann den awk in der Form awk -f rechne stunden
auf. Vollziehen Sie nach, wie das awk-Script rechne arbeitet.
rechne # Beispiel awk-Script rechne # # NR == 1 { # In der ersten Zeile stehen die Projekte for (i = 1;i <= NF;i++) { projekt[i] = $i; stunden[i] = 0.0; } anzahl = NF; gesamt = 0.0; }
351
KAPITEL
18
Der Reportgenerator awk
NR > 2 { # In der zweiten Zeile steht eine Trennlinie und # ab der dritten Zeile beginnen die Daten for (i = 1; i <= NF;i++) { stunden[i] += $i; gesamt += $i; } } END
{ # Ausgabe des Endergebnisses printf("%-20s%-10sProzent\n","Projekt","Stunden"); printf("-------------------------------------\n"); for (i = 1;i <= anzahl;i++) { anteil = (stunden[i] * 100.0) / gesamt; printf("%-20s %6.2f %6.2f%%\n",projekt[i],stunden[i],anteil); } printf(" ------\n"); printf(" %6.2f\n",gesamt); }
stunden Programmierung Fortbildung sonstiges Schulungen -------------------------------------------------3.5 0.0 0.0 5.75 0.5 2.0 3.0 4.5 0.0 0.0 0.0 8.75 2.0 0.0 1.75 5.5
3. Erstellen Sie nach dem Muster des Scripts rechne ein reines awk-Script, welches folgende Aufgabe löst: Vier Freunde verbringen einen gemeinsamen Urlaub in Dänemark. Jeder legt während des Urlaubs unterschiedliche Beträge aus, wobei die einzelnen Beträge sowohl in Dänischen Kronen (DKr) als auch in DM anfallen können. Die Ausgaben für den Urlaub werden in einer Datei als Tabelle abgelegt, welche über drei Spalten (Name, Betrag, Währung) verfügt. Ihr Script soll nun berechnen, wie viel insgesamt ausgegeben wurde und wie viel jeder einzelne nachzahlen muss oder wiederbekommt. Das Ergebnis muss nur in DM ausgegeben werden (1 DM = 3,811333 DKr). Die Namen der vier Freunde sind in das Script zu integrieren.
352
Aufgaben
18.7.1
Lösungen
1. Zu dieser Übung können Sie im vorangegangenen Kapitel noch einmal nachschlagen, wie die awk-Kommandos und das Script funktionieren. 2. Das Beispiel-Script rechne unterteilt sich in drei Kriterien und die zugehörigen Aktionen. Schauen wir uns nun jedes Kriterium mit seiner Aktion einzeln an: Das Kriterium NR == 1 ist genau dann erfüllt, wenn die Zeilennummer der aktuell bearbeiteten Zeile (dieser Wert steht in der Variablen NR) gleich 1 ist. Das bedeutet, die zugehörige Aktion wird nur für die erste Zeile der zu bearbeitenden Datei ausgeführt. Wenn wir uns die Datei Stunden anschauen, stellen wir fest, dass in dieser Zeile die Projekte unserer Stundenabrechnung stehen. Was macht die zugehörige Aktion mit dieser Zeile? Die Aktion beginnt mit einer for-Schleife, deren Schleifenvariable i die Werte zwischen 1 und NF annimmt. Wir erinnern uns, die Variable NF steht für Number of Fields und beinhaltet die Anzahl der Worte in der aktuellen Zeile (genauer des aktuellen Records, aber Zeile und Record sind in unserem Beispiel identisch). Die Worte in der ersten Zeile sind die Namen der Projekte auf unserem Stundenzettel und damit gleichzeitig die Überschriften für unsere vier Tabellenspalten. In der Schleife werden nun zwei eindimensionale Felder initialisiert. Der Vorteil des awk liegt darin, dass wir nicht vorher festlegen müssen, wie viele Elemente jedes Feld haben wird – eine einfache Zuweisung mit dem richtigen Index reicht, um das Element anzulegen. In den vier Elementen des Feldes projekt werden die Namen der vier Projekte (Programmierung, Fortbildung, Sonstiges und Schulungen) gespeichert. Interessant ist bei dieser Zuweisung der Ausdruck $i. i ist die Schleifenvariable, welche die Werte zwischen 1 und 4 annimmt. Das $ vor dem i bewirkt, dass auf die Worte 1 bis 4 der aktuellen Zeile zugegriffen wird (diese Worte stehen in den Variablen $1 – $4) – wir sehen also, dass sich der awk ganz anders verhält als die Shell. In den ebenfalls vier Elementen des Feldes stunden sollen später die für die Projekte angefallenen Stunden summiert werden. Aus diesem Grund werden alle vier Elemente zunächst mit 0.0 initialisiert. Zum Schluss wird noch eine Variable anzahl angelegt, in der die Anzahl der Projekte gespeichert wird, und eine Variable gesamt mit 0.0 initialisiert, die dazu dienen soll, die Gesamtstunden zu addieren. Das Kriterium NR > 2 bewirkt, dass die zugehörige Aktion für alle Zeilen der Eingabedatei stunden ausgeführt wird, deren Zeilennummer größer als 2 ist. Ab Zeile 3 stehen die Stunden, die für die einzelnen Projekte verwendet worden sind. Auch in dieser Aktion finden wir wieder eine for-Schleife, die zur Bearbeitung der vier Worte in jeder der Zeilen dient. Durch den Ausdruck stunden[i] += $i wird die Anzahl aus Spalte i auf die stunden von Projekt i addiert. Das += bedeutet dabei, dass addiert werden soll.
353
KAPITEL
18
Der Reportgenerator awk
Während in dieser Zeile in die vier Projekte unterteilt wird, wird durch gesamt += $i die Gesamtsumme um den entsprechenden Wert erhöht. Das abschließende Kriterium END hat nun eine besondere Bedeutung. Während die anderen beiden Kriterien unseres awk-Scripts für jede Zeile der Eingabedatei stunden bewertet werden, ist das Kriterium END nur dann erfüllt, wenn bereits sämtliche Zeilen der Eingabedatei abgearbeitet worden sind. Das heißt, die zugehörige Aktion ist für Abschlussarbeiten gedacht. In unserem Fall sind die Abschlussarbeiten die Ausgabe der Ergebnisse. Die beiden ersten printf-Zeilen geben eine Überschrift aus. printf bietet sich hier an, um eine Formatierung der Ausgabe zu erreichen. Dann folgt eine for-Schleife über unsere vier Projekte, in der jeweils der Projektname und die aufsummierte Stundenzahl formatiert ausgegeben werden. Bitte beachten Sie, dass hier die Variable anzahl benutzt wird und nicht mehr wie zuvor die Variable NF. Die END-Aktion wird ausgeführt, nachdem die letzte Zeile verarbeitet worden ist. Auf zeilengebundene Variablen des awk kann an dieser Stelle also nicht mehr zugegriffen werden. Zum Abschluss der Aktion wird nun noch die Gesamtsumme ausgegeben. 3. Unser Ergebnis-Script für die Aufgabe 3 sollte nach dem gleichen Prinzip arbeiten wie das Beispiel-Script rechne. Das Script trägt den Namen urlaub und ist fest auf die Abrechnung dieses einen Urlaubs mit genau diesen Personen ausgelegt.
urlaub # Musterloesung awk-Script fuer die Urlaubsabrechnung # # # Initialisierungsarbeiten BEGIN { gesamt = 0.0; faktor = 3.811333; lutz = 0.0; grit = 0.0; mandy = 0.0; ralph = 0.0; } # Der Body des Scripts wird fuer jede Zeile ausgefuehrt /^[Ll]utz/ { betrag = 0.0; if ( $3 == "DKr" ) betrag = $2 / faktor; if ( $3 == "DM" ) betrag = $2; gesamt += betrag; lutz += betrag; }
354
Aufgaben /^[Gg]rit/ { betrag = 0.0; if ( $3 == "DKr" ) betrag = $2 / faktor; if ( $3 == "DM" ) betrag = $2; gesamt += betrag; grit += betrag; } /^[Mm]andy/ { betrag = 0.0; if ( $3 == "DKr" ) betrag = $2 / faktor; if ( $3 == "DM" ) betrag = $2; gesamt += betrag; mandy += betrag; } /^[Rr]alph/ { betrag = 0.0; if ( $3 == "DKr" ) betrag = $2 / faktor; if ( $3 == "DM" ) betrag = $2; gesamt += betrag; ralph += betrag; } # Ausgabe des Endergebnisses END { anteil = gesamt / 4.0; printf("Jeder hat einen Anteil von %7.2f DM von %7.2f DM zu tragen\n\n", anteil, gesamt); betrag = anteil - lutz; if ( betrag < 0.0 ) { betrag *= -1.0; printf("Lutz hat %7.2f DM gezahlt und bekommt %7.2f DM zurueck\n", lutz, betrag); } else { printf("Lutz hat %7.2f DM gezahlt und muss noch %7.2f DM nachbezahlen\n", lutz, betrag); } betrag = anteil - grit; if ( betrag < 0.0 ) { betrag *= -1.0; printf("Grit hat %7.2f DM gezahlt und bekommt %7.2f DM zurueck\n", grit, betrag); }
355
KAPITEL
18
Der Reportgenerator awk
else { printf("Grit hat %7.2f DM gezahlt und muss noch %7.2f DM nachbezahlen\n", grit, betrag); } betrag = anteil - mandy; if ( betrag < 0.0 ) { betrag *= -1.0; printf("Mandy hat %7.2f DM gezahlt und bekommt %7.2f DM zurueck\n", mandy, betrag); } else { printf("Mandy hat %7.2f DM gezahlt und muss noch %7.2f DM nachbezahlen\n", mandy, betrag); } betrag = anteil - ralph; if ( betrag < 0.0 ) { betrag *= -1.0; printf("Ralph hat %7.2f DM gezahlt und bekommt %7.2f DM zurueck\n", ralph, betrag); } else { printf("Ralph hat %7.2f DM gezahlt und muss noch %7.2f DM nachbezahlen\n", ralph, betrag); } }
kasse Name Betrag Waehrung ---------------------------------Lutz 561 DM Hausanteil Lutz 110 DM Faehre Lutz 260 DKr Tanken Lutz 560 DKr Einkaufen / Brot Lutz 57 DKr Baecker Lutz 25 DKr Abwaschzeug Grit 350 DM Hausanteil Ralph 50 DM Faehre Ralph 800 DM Hausanteil Ralph 60 DKr Parken Kopenhagen Ralph 40 DKr Baecker Ralph 29 DKr Baecker Ralph 269 DKr Einkaufen Ralph 52 DM Tanken Mandy 350 DKr Einkaufen Mandy 77 DKr Einkaufen
356
Aufgaben Das Script urlaub besteht aus sechs Kriterien. Dabei handelt es sich um das Initialisierungskriterium BEGIN, vier Kriterien zur Verarbeitung der Daten für jeweils einen der vier Freunde und das Abschlusskriterium END zur Ausgabe des Endergebnisses. In der Aktion, die nach dem Kriterium BEGIN steht, werden einige Variablen initialisiert. Die Aktion wird genau einmal vom awk ausgeführt und zwar bevor er die erste Zeile der Eingabedatei kasse gelesen hat. In der Aktion werden eine Variable gesamt, in der die gesamten angefallenen Kosten gespeichert werden, eine Variable faktor, die den Umrechnungsfaktor zwischen DM und DKr festlegt1, und vier Variablen, welche die von den einzelnen Freunden gezahlten Beträge aufnehmen sollen, initialisiert. Die vier Kriterien, die die Daten für die vier Freunde aufnehmen sollen, unterscheiden sich nur durch die Namen der vier Freunde. Aus diesem Grund schauen wir uns exemplarisch das Kriterium für Lutz und die zugehörige Aktion einmal an. Das Kriterium lautet /^[Ll]utz/ und bedeutet, dass diese Aktion für jede Zeile ausgeführt werden soll, in der der Name Lutz oder lutz am Anfang der Zeile (^) steht. Wenn wir uns die Datei kasse anschauen, sind das all jene Zeilen, in denen Zahlungen von Lutz vermerkt sind. Was macht die zugehörige Aktion? Sie initialisiert zuerst eine Hilfsvariable betrag mit 0.0. Anschließend folgen zwei if-Statements, die sich auf den Eintrag für das dritte Wort ($3) der bearbeiteten Zeile beziehen. Steht in diesem dritten Wort DM, wird der betrag gleich dem zweiten Wort der Zeile gesetzt (betrag = $2). Ist das dritte Wort gleich DKr, wird der betrag nach der Formel betrag = $2 / faktor (also dem Betrag in Dänischen Kronen geteilt durch den Umrechnungsfaktor) gebildet. Der so bestimmte betrag ist nun in DM umgerechnet und wird zum Gesamtbetrag in der Variablen gesamt und auf den persönlichen Betrag in der Variablen lutz addiert. Das END-Kriterium steht wieder für die Abschlussaktion, die ausgeführt wird, nachdem alle Zeilen verarbeitet worden sind. In der zugehörigen Aktion wird zuerst der Anteil der Gesamtsumme bestimmt, den jeder der vier Freunde bezahlen muss. Dieser Anteil wird in der Variablen anteil (anteil = gesamt / 4.0) gespeichert. Danach wird ausgegeben, wie hoch dieser Anteil für jeden einzelnen ist. Dafür wird wieder printf verwendet, um eine formatierte Ausgabe für den Betrag zu erhalten (%7.2f bedeutet als Format, dass die Zahl insgesamt siebenstellig ausgegeben wird: vier Vorkommastellen, ein Punkt und zwei Nachkommastellen). Nach dieser Ausgabe folgen wieder vier Programmblöcke, die recht ähnlich aussehen und sich wieder nur durch die Namen der vier Freunde unterscheiden. Deshalb betrachten wir auch diesmal nur den Block, der sich mit Lutz beschäftigt. 1. Da Dänemark nicht an der europäischen Währungsunion teilnimmt, wird sich so etwas auch in näherer Zukunft nicht vermeiden lassen.
357
KAPITEL
18
Der Reportgenerator awk
Als Erstes haben wir eine Zeile, in der bestimmt wird, ob die Ausgaben von Lutz (betrag = anteil – lutz) den zu zahlenden Anteil überschritten (betrag hat einen negativen Inhalt) oder unterschritten (betrag hat einen positiven Inhalt) haben. betrag beinhaltet also den Differenzbetrag, den Lutz noch zu bekommen bzw. zu bezahlen hat. Genau diese beiden unterschiedlichen Varianten deckt das nachfolgende if-Statement ab. Wenn der Inhalt von betrag kleiner als 0.0 (betrag < 0.0) ist, hat Lutz noch Geld zu bekommen, und die Kommandos zwischen dem if und dem else werden ausgeführt. Ist der betrag >= 0, hat Lutz noch Geld nachzubezahlen, und die Kommandos im else-Zweig des if-Statements werden ausgeführt. Dies geschieht für alle vier Freunde; fertig ist die Abrechnung.
358
KAPITEL 19
Das kleine 1x1 der Systemverwaltung Während früher Unix als Betriebssystem nur selten in privaten Haushalten anzutreffen war, finden sich heute dank Linux bzw. für private Zwecke frei verfügbarer Versionen kommerzieller Unix Derivate immer mehr private UnixRechner. Bei diesen Systemen ist oft der Benutzer auch gleichzeitig Administrator, d.h. er muss Benutzer und Gruppen einrichten und verwalten, Drucker anschließen oder neue Platten konfigurieren. Während die erste Auflage dieses Buches diesen Aspekt bei der Benutzung von Unix unberücksichtigt gelassen hat, haben sich doch viele Leser nach der Installation der beiliegenden CD mit Aufgaben aus der Administration konfrontiert gesehen. Aus diesem Grund ist das folgende Kapitel entstanden. Wie die Überschrift schon sagt, soll es kein Ersatz für die vielen Administrators Guides sein, die sich mit den Tiefen des Unix-Betriebssystems bzw. eines ganz bestimmten Derivats beschäftigen. Genauso wie die grundlegenden Befehle, mit denen sich dieses Buch beschäftigt, unabhängig vom Unix eines bestimmten Herstellers sind, werden die hier vermittelten Grundlagen der Systemadministration sich auch auf die Teile beschränken, die allgemeinen Charakter haben.
359
KAPITEL
19 19.1
Das kleine 1x1 der Systemverwaltung
Die Aufgaben des Systemverwalters
Je nach Nutzung eines Unix-Systems variieren die Aufgaben des Systemverwalters. Für die privat genutzten Systeme beschränken sich seine Aufgaben in der Regel auf: 1. Die Erstinstallation des Unix-Systems 2. Einspielen von neuer Software, Patchen oder Updates 3. Einrichtung von Benutzerkennungen und Gruppen 4. Den Anschluss eines Druckers 5. Den Anschluss an ein Netzwerk 6. Erweiterung der Hardware und dessen Konfiguration 7. Analyse und Beseitigung von Störungen Einmal abgesehen von der Erstinstallation, die bei jedem Unix sehr individuell verläuft (mehr zu diesem Thema im Anhang zur beiliegenden CD), gibt es für diese Aufgaben weitestgehend standardisierte Kommandos oder definierte Konfigurationsdateien. Insbesondere für das Editieren der letztgenannten empfiehlt sich ein aufmerksames Studium des Kapitels über den Unix-Standardeditor vi. Eine grundlegende Kenntnis dieses Editors ist für jeden Admin Pflicht und oft Voraussetzung für das Gelingen einer Konfigurationsaufgabe. Wie bereits in den vorangegangenen Kapiteln erwähnt, bietet Unix die Möglichkeit, für jeden Benutzer eine eindeutige Kennung zu vergeben, unter der man sich am System anmelden kann. Neben diesen »einfachen« Benutzerkennungen gibt es auf jedem Unix-System auch eine privilegierte Kennung – die des Superusers. Auf den meisten Systemen lautet der Name dieser privilegierten Kennung root.
19.2
Der Superuser
Unix ordnet jeder Benutzerkennung im System eine eindeutige Nummer zwischen 0 und 65535 zu. Diese so genannte UID (User Identification) wird über eine Datei passwd im Verzeichnis /etc auf die Namen der Benutzer abgebildet, vergleiche Kap. 4. Man nennt eine Benutzerkennung auch einen Account. Die UID des Superusers ist die 0. Diese ID ist in der Regel auch die einzige, die mehrfach vergeben wird, um mehreren Benutzern mit unterschiedlichen Benutzerkennungen und Passworten einen Zugang als Administrator zu
360
Verwaltung von Benutzern und ihren Gruppen ermöglichen. Im Gegensatz zu anderen Betriebssystemen, in denen es ein ausgefeiltes Rollenkonzept mit mehrstufigen Hierarchien von Privilegien geben kann, gibt es unter Unix nur die Unterscheidung zwischen dem Superuser mit der UID 0, der alles auf dem System sehen und verändern darf, und den anderen Usern, die fest an das Unix-Rechtekonzept gebunden sind. Vielfach wird versucht, durch zusätzliche Software (z.B. das sudo-Paket) diese simple Zweiteilung zu verfeinern. Für den Privatnutzer, der sein eigener Administrator ist, sollte aber diese zweistufige Hierarchie ausreichen. Als goldene Regel sollte er sich merken, dass er nur dann unter der Superuserkennung root arbeitet, wenn er wirklich administrative Tätigkeiten ausübt. Für die tägliche Arbeit, Spaß oder Spiel sollte ein eigener unprivilegierter Account auf dem System eingerichtet werden, denn während unter einem solchen Account das Löschen von wichtigen Systemdateien durch das Unix-Rechtekonzept unterbunden wird, kann unter Umständen ein falsch abgesetztes rm als Superuser das ganze Betriebssystem so stark beschädigen, dass die einzige Rettung eine Neuinstallation ist.
19.3
Verwaltung von Benutzern und ihren Gruppen
19.3.1
Das Userkonzept von Unix
Vom Konzept her ist Unix ein Multiuser Multitasking Betriebssystem. Als PCBenutzer mag die Multiuser-Eigenschaft auf den ersten Blick als nicht so wichtig erachtet werden, da im Normalfall nur ein Benutzer den Rechner zur gleichen Zeit verwendet. Doch auch bei einer zeitlich entkoppelten Nutzung des Rechners durch verschiedene Personen (z.B. die Mitglieder einer Familie) kann es durchaus sinnvoll sein, jedem einzelnen Benutzer eine eigene Benutzerkennung zu geben. Unter dieser Kennung kann der Benutzer seine eigenen Daten nach seinen Bedürfnissen organisieren, sein Environment auf die von ihm genutzten Programme abstimmen oder individuelle Einstellungen der grafischen Bedienoberfläche vornehmen. Was genau gehört zu einer eigenen Kennung? Um eine neue Kennung einzurichten, benötigt man: ✘ einen maximal acht Zeichen langen Benutzernamen, ✘ eine freie UID zwischen 1000 und 65535 (die UIDs von 1-100 sind für Systembenutzer reserviert und die UIDs von 101-999 sollten für technische User von Softwarepaketen frei bleiben), ✘ eine Benutzergruppe, welcher der User zugeordnet werden kann,
361
KAPITEL
19
Das kleine 1x1 der Systemverwaltung
✘ ein Home Directory, in dem der Benutzer seine Dateien ablegen kann, ✘ ein Passwort und ✘ eine Shell, mit welcher der User arbeiten soll. Genau diese sechs Angaben plus eine weitere freiwillige Angabe (der sog. Fullname – die Information, welcher reale Mensch sich hinter der Kennung verbirgt) werden in einer Datei unter Unix gespeichert, der /etc/passwd. Existiert in dieser Datei eine Zeile der Form (der Doppelpunkt fungiert als Trennzeichen zwischen den sieben Feldern): Name:Passwort:UID:GID:Fullname:Home Directory:Shell
so ist der Benutzer Name auf diesem System eingerichtet. Damit er sich auch tatsächlich auf dem System anmelden kann, muss zumindest ein Home Directory für ihn angelegt werden. Wo dieses im Unix-Verzeichnisbaum geschieht, ist abhängig vom verwendeten Unix. Nun wird sich der geneigte Leser wundern, wieso in der /etc/passwd, auf die wir ja im Laufe der Übungen in diesem Buch mehrfach lesend zugegriffen haben, eine so brisante Information wie die Passwörter der Benutzer gespeichert sein kann. Die Passwörter stehen natürlich nicht im Klartext in dieser Datei, sondern in einer verschlüsselten Form, die mittels einer modifzierten DES-Verschlüsselung erzeugt wird. Diese Form der Handhabung von Passwörtern unter Unix galt lange Zeit als sicher genug, da der Verschlüsselungsmechanismus nahezu als Einwegstraße konzipiert war, d.h. ein Passwort kann sehr schnell verschlüsselt werden, aber die verschlüsselte Zeichenkette kann nur mit unverhältnismäßig großem Aufwand wieder zurück in das Klartext-Passwort umgewandelt werden. Meldet sich ein Benutzer am System an, wird das von ihm angegebene Passwort einfach verschlüsselt und mit dem verschlüsselten Passwort aus der /etc/passwd verglichen. Da dieses Verschlüsselungsverfahren keine eineindeutige1 Abbildung ist, können durchaus zwei verschiedene Wörter als Verschlüsselung das gleiche Ergebnis haben. Für den unter Unix verwendeten Passwortvergleich ist das kein Problem, aber mit zunehmender Rechnerleistung ergibt sich hier eine Möglichkeit Passworte zu knacken. Man muss nur genug verschiedene Worte verschlüsseln und die Ergebnisse mit den Einträgen in der /etc/passwd vergleichen. Hat man ein Verschlüsselungsergebnis, dass mit einem Eintrag übereinstimmt, so hat man ein passendes Passwort in Klartext gefunden und kann sich unter dem entsprechenden Account einloggen. Um diese »Brut 1. Für die Nichtmathematiker unter uns: Eineindeutig bedeutet, dass eine Abbildung genau ein Ergebnis hat und auch nur genau für einen Eingabewert dieses Ergebnis durch die Abildung erzielt wird.
362
Verwaltung von Benutzern und ihren Gruppen Force Attack« zu verhindern, haben heutige Unix-Systeme eine gesonderte Passwortdatei – die /etc/shadow. Diese Datei ist nicht mehr für jeden Benutzer lesbar (sondern nur für root) und enthält das verschlüsselte Passwort, während in der /etc/passwd anstelle des Passwortes einfach ein x eingetragen wird.
19.3.2
Das Unix-Gruppenkonzept
Im Abschnitt über die Dateirechte wurde bereits das Thema der Unix-Gruppen angerissen. Eine Datei wurde stets einem Benutzer und einer Benutzergruppe zugeordnet und durch die drei Rechteblöcke, die Zugriffsrechte für diesen User, die Mitglieder dieser Gruppe und allen übrigen Benutzern festgelegt. Durch dieses Konzept wird gewährleistet, dass der Zugriff auf bestimmte Dateien/Programme durch den Systemverwalter reglementiert werden kann. Durch Gruppen ist es möglich, nicht nur einzelnen Benutzern gezielt Rechte einzuräumen, sondern auch einer großen Anzahl an Benutzern – einer Gruppe. Wie werden diese Gruppen verwaltet? Ähnlich wie bei der Verwaltung einzelner Benutzer wird auch hier wieder eine zentrale Systemdatei zur Speicherung aller Informationen über Gruppen benutzt. Diese Datei – die /etc/group – ist wie folgt aufgebaut: Name:Passwort:GID:Mitglied[,Mitglied[,Mitglied ...]]
Die vier Felder sind wie auch die Felder der /etc/passwd durch Doppelpunkte getrennt. Für seine interne Verwaltung verwendet Unix – wie bereits bei den Usern – nicht den symbolischen Namen, sondern eine eindeutige Nummer – die GID. Auch für die GID sind Werte zwischen 0 und 65535 möglich, wobei auch hier die GIDs von 0-99 für Systemgruppen reserviert sind. Wie wird man Mitglied in einer Unix-Gruppe? Ein User kann auf zwei Arten Mitglied einer Gruppe werden: 1. als primäres Mitglied oder 2. als sekundäres Mitglied. Von den Dateirechten unterscheiden sich diese beiden Formen der Mitgliedschaft nicht. Wenn bei einer Datei für eine bestimmte Gruppe z.B. Schreibrechte vergeben wurden, spielt es für die Inanspruchnahme dieser Rechte keine Rolle, ob der Benutzer primäres oder sekundäres Mitglied in der Gruppe ist. Die primäre Mitgliedschaft in einer Gruppe wird über die /etc/passwd für einen Benutzer eingestellt, indem die entsprechende GID in der Zeile für den Benutzer im vierten Feld vermerkt wird. Dieser Eintrag ist ein Pflichtfeld, sodass jeder Benutzer mindestens einer Unix-Gruppe angehört und zwar als
363
KAPITEL
19
Das kleine 1x1 der Systemverwaltung
Primärmitglied. Legt der Benutzer eine Datei an, wird als der Gruppeneintrag dieser neuen Datei die GID der Primärgruppe des Benutzers eingetragen. Die Primärgruppe hat also die Funktion, die Benutzer in grobe Kategorien einzuteilen, für die es interessant sein könnte, sich gegenseitig weitergehende Rechte einzuräumen (solche Gruppen wären z.B. Softwareentwickler, Vertriebsmitarbeiter o.Ä.). Die sekundäre Mitgliedschaft eines Benutzers in einer Gruppe wird über die /etc/group hergestellt. Solche Sekundärmitgliedschaften beschränken sich
im Allgemeinen auf einige wenige Benutzer pro Gruppe. Die Namen dieser Benutzer werden im vierten Feld der /etc/group durch Komma getrennt aufgelistet. Die Beschränkung auf wenige Mitglieder wird dadurch unterstrichen, dass eine Zeile in der /etc/group auf einigen Systemen maximal 512 Zeichen lang sein darf. Der Benutzer kann maximal Mitglied in 16 Gruppen (1 primäre und 15 sekundäre) sein. Wird er in mehr als 15 Gruppen in der /etc/group eingetragen, werden die 15 Gruppen ausgewählt, deren Zeilen zuerst in der /etc/group stehen. Will ein Benutzer eine Datei mit der Gruppenkennung einer seiner Sekundärgruppen anlegen, kann er dies auf zwei verschiedene Arten erreichen:
6
newgrp [-] [Gruppe]
Mit dem Kommando newgrp kann der Benutzer temporär für die aktuelle Shell eine seiner Sekundärgruppen zu seiner Primärgruppe machen. Theoretisch kann auch ein Benutzer, der nicht in dieser Sekundärgruppe ist, mit newgrp in diese wechseln, wenn er das Gruppenkennwort (zweites Feld in der /etc/ group) kennt. Allerdings wird dieser Mechanismus nur sehr selten eingesetzt. Die zweite Möglichkeit, eine Datei mit einem Gruppeneintrag einer Sekundärgruppe zu erzeugen bzw. eine solche zuzuordnen, ist, zunächst die Datei mit der ID der Default-Gruppe (die der Primärgruppe) zu erzeugen und anschließend das Kommando chgrp aufzurufen.
6 364
chgrp [-R] Gruppe Datei [Datei ...]
Während ein Benutzer bei chgrp nur solche Gruppen angeben darf, in denen er selbst Mitglied ist, kann der Superuser root für jede Datei einen beliebigen Gruppeneintrag erzeugen. Durch die Option –R kann der Gruppeneintrag ganzer Dateihierarchien rekursiv mit nur einem Kommando umgesetzt werden.
Verwaltung von Benutzern und ihren Gruppen
19.3.3
Erweitere Rechte
In Abschnitt 6.2 wurden bereits die Grundlagen des Unix-Rechtekonzepts diskutiert. Wir haben uns dabei auf die Rechte beschränkt, die für einen normalen Benutzer vorrangig von Bedeutung sind. Doch spätestens wenn man sich mit dem Thema der Systemverwaltung beschäftigt, muss man sich auch mit weiteren Rechten befassen. Um die Funktion dieser Rechte zu verstehen, müssen die Informationen aus dem Kapitel über die Prozessverwaltung ein wenig erweitert werden. Ein Prozess unter Unix läuft unter einem User- und einem Gruppenkontext, die im Normalfall durch den Benutzer bestimmt sind, der den Prozess gestartet hat. Diese UID und GID, unter welchen der Prozess agiert, stimmen also im Normalfall mit denen des Benutzers überein. Die UID, unter der ein Prozess läuft, wird auch als effektive UID (EUID) bezeichnet. Die effektive GID wird analog mit EGID bezeichnet. Nun lassen sich die EUID und EGID eines Prozesses auch durch die Dateirechte beeinflussen. Hierzu wird durch ein bestimmtes Bit der Dateirechte signalisiert, dass der Rechtekontext nicht durch den Benutzer bestimmt wird, sondern durch die UID des Eigentümers der Datei. Dieses Rechtebit nennt man SetUID Bit. Das Bit mit der gleichen Funktionalität auf Basis der GID nennt man SetGID Bit. Beiden liegt derselbe Gedanke zu Grunde – einem Benutzer temporär erweiterte Rechte zuzugestehen, während er ein ganz bestimmtes Programm benutzt. D.h. der Benutzer kann über ein Programm (eine Schnittstelle) auf Dateien lesend oder sogar schreibend zugreifen, die er nach seinem Rechtekontext vielleicht weder lesen noch verändern dürfte. Ein Beispiel hierfür ist das Kommando passwd zum Setzen von Passwörtern. Wie werden diese Bits gesetzt? Genau wie die übrigen Berechtigungsbits werden auch das SetUID und das SetGID Bit mit dem Kommando chmod gesetzt. Natürlich bestehen wieder beide Varianten: 1. Komplette Neudefinition aller Rechte: Will man zusätzlich zu den »normalen« Rechten die erweiterten SetUIDbzw. SetGID-Rechte setzen, muss man statt einer dreistelligen Oktalzahl eine vierstellige wählen. So würde z.B. das Kommando chmod 4755 xyz
für die Datei xyz das SetUID Bit setzen und das Kommando chmod 2755 uvw
das SetGID Bit für die Datei uvw.
365
KAPITEL
19
Das kleine 1x1 der Systemverwaltung
2. Hinzufügen einzelner Rechte durch symbolische Schreibweise: In der symbolischen Syntax von chmod lautet das Kommando zum Setzen des SetUID Bits chmod u+s xyz
und das Kommando zum Setzen des SetUID Bits chmod g+s uvw.
Voraussetzung für beide Rechteänderungen ist, dass bereits das Execute Bit für den Eigentümer bzw. die Gruppe gesetzt war. Durch entsprechende Kombination können auch beide Bits gleichzeitig gesetzt werden. Während das SetUID Bit nur Auswirkungen auf ausführbare Dateien hat1, hat das SetGID Bit auch eine Bedeutung für Verzeichnisse. Ist bei einem Verzeichnis das SetGID Bit gesetzt, werden Dateien, die in diesem Verzeichnis angelegt werden, gemäß der BSD-Semantik mit der gleichen Gruppenkennung wie das Verzeichnis selbst angelegt. Neben dem SetUID und dem SetGID Bit gibt es noch ein weiteres Bit, welches erweiterte Rechte vergibt – das sog. Sticky Bit. Hierbei handelt es sich eigentlich um ein Relikt aus den Tagen, als Hauptspeicher noch richtig teuer war. In diesen Tagen wurden jene Dateien mit einem Sticky Bit versehen, die nicht durch Paging bzw. Swapping aus dem Hauptspeicher ausgelagert werden sollten. So konnte der Administrator Einfluss auf die Auslagerungsstrategie seines Unix-Systems nehmen. Heute, wo PCs mit einem Hauptspeicher von 512 Mbyte und mehr keine Seltenheit mehr sind, hat das Sticky Bit nur noch eine Funktion für Verzeichnisse. Ist das Sticky Bit bei einem Verzeichnis gesetzt, darf ein Benutzer, der Schreibrecht auf das Verzeichnis besitzt, nur solche Dateien aus dem Verzeichnis löschen, für die er auch ein Schreibrecht besitzt. Ohne das Sticky Bit würde das Schreibrecht auf dem Verzeichnis bereits zum Löschen einer Datei ausreichen. Das Sticky Bit wird häufig für temporäre Verzeichnisse wie /tmp bzw. /var/tmp gesetzt, um diesen Verzeichnissen ein wenig mehr Sicherheit zu geben. Um das Sticky Bit für ein Verzeichnis abc zu setzen, können die folgenden beiden Kommandos verwendet werden: chmod 1755 abc
1. Scripts werden auf den meisten Systemen von der Funktion des SetUID und SetGID Bits ausgenommen.
366
Verwaltung von Benutzern und ihren Gruppen bzw. chmod u+t abc
Bei einem ls –l werden alle drei Bits für die erweiterten Rechte anstelle der Execution Bits dargestellt. Ist das SetUID Bit gesetzt, steht statt des x beim User ein s, ist das SetGID Bit gesetzt, steht anstelle des x bei der Gruppe ein s und ein gesetztes Sticky Bit wird durch ein t anstelle des Others x Bits angezeigt. Sind die Execution Bits an den entsprechenden Stellen nicht gesetzt, so erfolgt die Darstellung der speziellen Bits durch Großbuchstaben.
19.3.4
Gruppen anlegen
Das Anlegen einer neuen Benutzergruppe in der /etc/group ist ein Vorgang, mit dem ein privater Unix-Benutzer nicht sehr häufig konfrontiert wird. Der Vollständigkeit halber soll aber trotzdem erläutert werden, was zu tun ist, um eine neue Gruppe einzurichten. Prinzipiell ist nichts weiter zu tun als eine neue Zeile in die Datei /etc/group einzufügen. Die Zeile besteht aus den bereits in Abschnitt 19.3.2 beschriebenen vier Feldern. Für eine neue Gruppe sollten das zweite Feld (Gruppenpasswort) und das vierte Feld (Mitglieder der Gruppe) frei bleiben. Der Name der Gruppe (erstes Feld) sollte nur aus Kleinbuchstaben bestehen, maximal acht Zeichen lang sein und auf keinen Fall eine bereits vorhandene Gruppe bezeichnen. Die GID (drittes Feld) sollte zwischen 100 und 65535 liegen und ebenfalls noch nicht für eine Gruppe vergeben worden sein. Um die /etc/group editieren zu können, muss man als root angemeldet sein. Allerdings ist die Verwendung eines Editors zum Erzeugen einer neuen Gruppe nur die zweitbeste Lösung. Die meisten Unix-Systeme verfügen über ein Kommando oder eine grafische Bedienoberfläche, um Gruppen einzurichten. Da diese Werkzeuge helfen, Fehler zu vermeiden, sind sie dem Editieren von Dateien vorzuziehen. Am gebräuchlichsten zur Einrichtung von Gruppen ist das Kommando groupadd.
groupadd [-g GID] Gruppe
Durch das Kommando
root [/] 4 # groupadd –g 1001 develop
würde also die Gruppe develop mit der GID 1001 eingerichtet.
6 3 367
KAPITEL
19 19.3.5
Das kleine 1x1 der Systemverwaltung
Benutzer einrichten
Mit dem Einrichten von Benutzern verhält es sich ähnlich, wie mit der Erzeugung neuer Gruppen – im Prinzip sind nur ein bis zwei Dateien zu editieren und schon ist ein neuer Benutzer eingetragen. Allerdings gibt es im Vorfeld einige Überlegungen zu tätigen, wie z.B.: 1. Welcher Gruppe soll der neue Benutzer angehören? 2. Welche Shell soll er verwenden? 3. Wo soll sein Home Directory liegen? 4. Welches Startpasswort soll der Benutzer haben? Die Frage nach der Primärgruppe ist in der Regel recht einfach zu beantworten. Ist nicht bekannt, ob der Benutzer einer ganz bestimmten Gruppe als Primärgruppe angehören muss, sollte man einfach den Default wählen. Dieser ist auf den meisten Systemen die Gruppe mit der GID 100, die in der Regel users heißt. Die Frage nach der Shell ist schon etwas schwieriger zu beantworten, da sich die Funktionen und der Komfort der einzelnen Shells stark unterscheiden. Die meisten Benutzer bevorzugen Shells mit Comandline Editing wie die tcsh, bash oder ksh. Für einen C-Programmierer ist vermutlich die tcsh die beste Wahl, da ihre Scriptsprache der Syntax der Sprache C ähnelt. Auf jeden Fall sollten Sie keinen Benutzer mit der Benutzung der sh quälen, wenn er nicht aus masochistischen Gründen selbst darauf besteht. Die Sache mit dem Home Directory ist eine Frage, die sich wenn überhaupt nur in Abhängigkeit vom verwendeten Unix beantworten lässt. So verwendet z.B. Solaris /export/home als Stammverzeichnis für die Benutzerverzeichnisse, Irix verwendet /usr/people, HP-UX verwendet /home und Linux in der Regel ebenfalls /home. Am besten schauen Sie, was andere Benutzer haben, oder überlassen die Auswahl dem Programm zur Erstellung von BenutzerAccounts. Das Startpasswort sollte so gewählt werden, dass es nicht einfach erraten werden kann. Startpassworte, die so lauten wie die Benutzerkennung selbst, sind genauso keine gute Wahl wie der Name des neuen Benutzers oder Zeichenketten wie start. Selbst wenn ein Startpasswort eigentlich nur wenige Minuten bis Stunden gültig sein sollte, besteht bei derartig einfach herzuleitenden Passworten die Gefahr der unbefugten Benutzung. Insbesondere bei Systemen die in ein Netz integriert sind oder Zugang zum Internet haben, ist besondere Vorsicht geboten. Sichere Passworte sind in der Regel Kombinationen aus Buchstaben, Sonderzeichen und Ziffern, allerdings sollten Sie auch darauf achten, dass das Passwort gut zu tippen ist und es sich der Benutzer auch merken kann.
368
Verwaltung von Benutzern und ihren Gruppen Mehr als acht Zeichen in einem Passwort machen nur auf einigen Systemen Sinn, da der Standard-Passwortmechanismus von Unix nur die ersten acht Zeichen benutzt. Nachdem wir nun die Vorüberlegungen abgeschlossen haben, bleibt der eigentliche Vorgang des Anlegens eines neuen Benutzers. Dieser kann wieder entweder per Editor oder mit einem Kommando erfolgen. Für beide Varianten muss zunächst eine Anmeldung als User root erfolgen. Anschließend muss ermittelt werden, ob das System die Benutzer ausschließlich über die / etc/passwd verwaltet oder ob es zusätzlich eine /etc/shadow für die verschlüsselten Passworte verwendet. Im zweiten Fall sind /etc/passwd und /etc/ shadow synchron zu halten, sprich der Eintrag für den neuen Benutzer ist für beide vorzunehmen. Auf einem System, welches eine shadow-Passwortdatei führt, ist dringend davon abzuraten, die Änderungen mit einem Editor vorzunehmen. Hier sollte auf jeden Fall ein entsprechendes Kommando oder eine grafische Bedienoberfläche zum Einsatz kommen. Aus diesem Grund wird nachfolgend das manuelle Hinzufügen eines Benutzers nur für ein System beschrieben, welches eine /etc/passwd führt. Dabei sind folgende Schritte auszuführen: 1. Einfügen einer Zeile in die /etc/passwd bestehend aus den sieben Feldern wie in Abschnitt 18.3.1 beschrieben. Dabei sollten Sie darauf achten, dass in Feld zwei (verschlüsseltes Passwort) einfach ein »*« eingetragen wird und dass die UID aus Feld 3 noch nicht vergeben und im Bereich zwischen 100 und 65535 liegt. Im vierten Feld tragen Sie eine bereits existierende GID ein. In das fünfte Feld tragen Sie am besten den vollen Namen des Benutzers ein und eventuell seine Telefonnummer – verwenden Sie auf keinen Fall einen Doppelpunkt oder deutsche Umlaute im Text für das fünfte Feld. Die gewünschte Shell muss im siebten Feld eingetragen werden. 2. Anlegen eines Home Directorys im Stammverzeichnis für Benutzerverzeichnisse und Eintragen desselben im sechsten Feld der /etc/passwd 3. Kopieren der Default-Startup-Dateien in Abhängigkeit der verwendeten Shell aus /etc/skel1 in das Home Directory des neuen Users 4. Mithilfe der Kommandos chown und chgrp die Eigentümer- und Gruppeneinträge für das Home Directory und die dorthin kopierten Startupdateien – analog der /etc/passwd Einträge – setzen 5. Mit dem Kommando passwd ein Startpasswort für den neuen Benutzer setzen 1. Das Verzeichnis /etc/skel muss nicht zwangsläufig existieren oder Startup-Dateien enthalten. Mit der Zeit empfiehlt es sich aber, unter diesem oder einem ähnlichen Verzeichnis DefaultStartup-Dateien zu sammeln.
369
KAPITEL
19
Das kleine 1x1 der Systemverwaltung
Die Änderung von Eigentümereinträgen für Dateien ist dem Superuser vorbehalten, da sonst auf diesem Weg benutzergebundene Speicherplatzbeschränkungen (sog. Diskquotas) umgangen werden oder Benutzer ohne ihr Wissen mit Dingen beschenkt werden könnten, die sie gar nicht haben wollen – von Sicherheitsrisiken ganz zu schweigen. Die Syntax sieht wie folgt aus:
6 6 6
chown [-R] User Datei [Datei ...]
Auch hier steht die Option –R für die Möglichkeit, rekursiv ganzen Dateibäumen den neuen Eigentümereintrag zu geben. Allerdings sollte hier eine gewisse Vorsicht an den Tag gelegt werden, da durch eine Anwendung auf ein falsches Verzeichnis das gesamte Betriebssystem in Mitleidenschaft gezogen werden kann. Auf einigen Systemen gibt es auch ein chown, welches zusätzlich ein chgrp ausführt. Die Syntax verändert sich dann folgendermaßen:
chown [-R] User[:Gruppe] Datei [Datei ...]
Die ersten vier Schritte zum Anlegen eines neuen Benutzers lassen sich deutlich fehlertoleranter auf den meisten Unix-Systemen durch das Kommando useradd bewältigen. useradd wäre auch das Werkzeug der Wahl, um User auf einem System einzurichten, welches eine /etc/shadow verwendet.
useradd [-c Comment] [-u Uid] [-d Home Directory] [ -m ] [-g Group] [-G Group[,Group...]] [-s Shell] User
useradd kennt noch ein paar weitere Optionen, doch in der Regel reichen die oben beschriebenen vollkommen aus.
370
-c Comment
Mit dieser Option wird das Fullname-Feld (Feld fünf) gefüllt. useradd erwartet hier genau einen Parameter für den Comment – also das Quoten nicht vergessen.
-u Uid
Über diese Option kann eine bestimmte UID für den Benutzer erreicht werden. Das macht vor allem dann Sinn, wenn der User noch auf anderen Systemen arbeitet und per NFS auf Dateien des aktuellen Systems zugreifen will.
Dateisysteme ein- und abhängen
-d Home Directory
Diese Option sollte nur dann verwendet werden, wenn das Home Directory nicht unter dem Standardverzeichnis für Benutzerverzeichnisse erstellt werden soll. Es ist ein absoluter Pfad anzugeben.
-m
Diese Option besagt, dass das Home Directory des Benutzers angelegt werden soll. Eigentlich will man das immer, denn ohne Home Directory darf sich auf einigen Systemen ein Benutzer nicht mal anmelden.
-g Group
Über diesen Schalter kann man die primäre Gruppe des neuen Benutzers vorgeben. Gibt man die Option nicht an, wird die Default-Gruppe verwendet, was meist die bereits erwähnte Gruppe mit der GID 100 ist. Alternativ zum Namen der Gruppe darf auch die GID angegeben werden.
-G Group[,Group...]
Soll der Benutzer neben seiner Primärgruppe noch weiteren Gruppen angehören, können diese hier spezifiziert werden. Wie bereits erwähnt wurde, ist bei 16 Gruppen insgesamt Schluss.
-s Shell
Die Shell sollte immer mit einem absoluten Pfadnamen angegeben werden.
Auch hier folgt wieder ein kleines praktisches Beispiel, um den Gebrauch des Kommandos useradd zu verdeutlichen:
root [/] 4 # useradd –g develop –c "Brockmann, Lutz" \ -m –s /bin/tcsh lutzb
3
In diesem Beispiel wird ein User mit der Kennung lutzb angelegt, der eine tcsh als Login-Shell erhält, der primäres Mitglied in der Gruppe develop ist und für den ein Home Directory im Standardverzeichnis angelegt wird.
19.4
Dateisysteme ein- und abhängen
In den heutigen Tagen ist Plattenplatz derart günstig zu haben, dass die meisten von uns wieder zu »Jägern und Sammlern« degenerieren, die nichts wegschmeißen, in der Annahme, dass man es irgendwann noch mal gebrauchen könnte. Ich will diese Haltung nicht kritisieren – schließlich nehme ich sie selbst ein. Einzige Konsequenz dieser Sammelleidenschaft ist, dass des Öfteren neue frische Platten bzw. Dateisysteme in den Unix-Dateibaum eingebunden werden müssen, um wieder Platz für neue Exponate der Sammlung zu schaffen.
371
KAPITEL
19
Das kleine 1x1 der Systemverwaltung
Im Kapitel 7 haben wir uns ja bereits mit der Struktur des Unix-Dateibaums auseinandergesetzt und gelernt, dass entgegen des ersten Anscheins dieser Baum nicht ein Ganzes ist, sondern aus mehreren Teilen, um genau zu sein mehreren Dateisystemen, besteht, die ihrerseits ebenfalls wieder baumartig strukturiert sind. Jedes dieser Dateisysteme hat seinen Ursprung in einem Wurzelverzeichnis, oberhalb dessen alle anderen Verzeichnisse abgelegt sind. Wenn man bei dem Bild mit den Bäumen bleiben will, dann wird ein solcher neuer Teilbaum in Form eines Dateisystems in den bereits bestehenden Baum eingegliedert, in dem er an einen (idealerweise freien) Zweig des Baumes »montiert« wird. Konkret wird der neue Teilbaum an ein bereits bestehendes Verzeichnis montiert. Dieses Montieren (engl. mounten) eines Dateisystems in den bestehenden Baum ist kein unumkehrbarer Vorgang, sondern kann jederzeit, wenn das Dateisystem nicht gerade durch einen Benutzer oder einen Prozess belegt ist, auch wieder demontiert (engl. unmounten) werden. Auf dem Dateisystem, welches in den Baum eingehängt wird, werden keine Informationen über die Stelle gespeichert (den sog. Mountpoint), an der es eingehängt wird. Somit lässt sich das gleiche Dateisystem durchaus an mehreren verschieden Stellen einhängen – allerdings nur immer an einer Stelle zu einer Zeit. Da die Zuordnung der Dateisysteme über ihre Device-Dateien erfolgt, die meist recht kryptische Namen haben, muss man als Anwender schon recht gut aufpassen, dass beim »Zusammenbauen« des Dateibaums alles an der richtigen Stelle hängt. Aus diesem Grund wird das Layout des Dateibaumes in der Regel nicht von Hand, sondern automatisch beim Booten mithilfe einer Datei aufgebaut. Diese Datei trägt leider auf verschiedenen Unix-Systemen verschiedene Namen und ist auch verschieden aufgebaut. Auf den meisten System heißt sie /etc/fstab, unter Solaris heißt sie /etc/vfstab und unter HP-UX /etc/checklist. Nachfolgend wird diese Datei immer fstab genannt, um einen einheitlichen Sprachgebrauch zu haben. In der fstab werden die Dateisysteme in der Reihenfolge aufgeführt, in der sie beim Booten gemountet werden sollen. Ist für ein Dateisystem kein Eintrag vorhanden, wird es auch nicht automatisch gemountet. In der Regel wird zuerst das Dateisystem gemountet, auf dem sich die Root (/) des gesamten Dateibaums befindet. Man spricht bei der zugehörigen Partition der Platte auch von der Root Partition. Eine fstab könnte wie folgt aussehen (dieses Beispiel stammt von einer Solaris-Maschine):
372
Dateisysteme ein- und abhängen
/dev/dsk/c0t0d0s0 /dev/dsk/c0t0d0s1 /dev/dsk/c0t0d0s3 /dev/dsk/c0t0d0s4 /dev/dsk/c0t0d0s6
/dev/rdsk/c0t0d0s0 / ufs 1 yes - - swap - no /dev/rdsk/c0t0d0s /var ufs 1 yes /dev/rdsk/c0t0d0s4 /opt ufs 1 yes /dev/rdsk/c0t0d0s6 /export/home ufs 1 yes -
3
Um den Inhalt zu verstehen, bedarf es noch einiger weiterer Informationen über die Repräsentationen von Platten unter Unix. Generell werden Platten unter Unix in Partitionen unterteilt. Jede dieser Partitionen kann ein eigenes Dateisystem aufnehmen und wird unter Unix durch zwei Device-Dateien beschrieben. Der Name der Partition (c0t0d0s0) enthält bei SCSI-Platten unter Solaris z.B. Informationen über die Nummer des Controllers (c0 = Controller 0), die SCSI ID (t0 = SCSI ID 0) und die Nummer der Partition (s0 = Partition 0). Wie die Partitionen bei einem konkreten UnixSystem erzeugt werden, ist sehr unterschiedlich. Ich möchte hier daher nur auf die Manual Pages verweisen (z.B. zu format bei Solaris oder fdisk bei Linux). Je nachdem ob sich die Device-Datei im Verzeichnis /dev/dsk oder /dev/rdsk befindet, steht sie für eine unterschiedliche Form des Zugriffs auf die Platte durch das Betriebssystem. Die Device-Dateien unter /dev/rdsk bezeichnet man als Raw1 Devices. Über dieses Interface für die Platten greift nur der Kernel zu, wenn er sehr systemnahe Operationen ausführt wie z.B. das Erzeugen eines neuen Dateisystems oder das Synchronisieren des Dateisystems auf der Platte mit der im Speicher gehaltenen Version. Die Device-Dateien unter /dev/dsk bezeichnet man als Block Devices. Über diese Dateien wird normalerweise auf den Inhalt einer Partition zugegriffen. Der Zugriff über dieses Interface für Platten erfolgt blockweise und gepuffert, gemäß den Regeln des Dateisystems, und ist somit für den normalen2 Gebrauch effizienter bzw. für einen »normalen« User die einzige Möglichkeit, überhaupt auf Daten im Dateisystem zuzugreifen. Schauen wir uns nun an, was eine Zeile in der fstab zu sagen hat:
1. Raw engl. für roh – soll soviel heißen, wie direkter Zugriff auf die Platte, ungepuffert und low level. 2. Einige Datenbanksysteme wie z.B. Oracle bieten die Option ihre Datenbank Tabellen in Raw Devices zu verwalten, was für einige Varianten schneller ist als die Ablage in einem Dateisystem.
373
KAPITEL
3
19
Das kleine 1x1 der Systemverwaltung
/dev/dsk/c0t0d0s0 /dev/rdsk/c0t0d0s0 / ufs 1 yes –
Das Dateisystem auf der Partition 0 der Platte 0 am Controller 0 soll am Mountpoit / gemountet werden. Auf die restlichen vier Argumente in der Zeile (ufs 1 yes –) will ich hier nicht eingehen, da sie spezifisch für Solaris sind. Schaut man sich die restlichen Zeilen an, wird man feststellen, dass anschließend noch weitere Dateisysteme an /var, /opt und /export/home gemountet werden. Diese Zeilen werden in der angegebenen Reihenfolge durch das Kommando mount verarbeitet, mit dem diese Dateisysteme in den Dateibaum eingehängt werden. Würde man das Kommando mount für das Einhängen des Dateisystems /export/home per Hand aufrufen, würde das etwa wie folgt aussehen:
3
root [/] 4 # mount /dev/dsk/c0t0d0s6 /export/home
Eine der fünf Zeilen in fstab sieht nun ganz anders aus als die übrigen vier und wird auch ganz anders behandelt. Sie steht hier nur der Vollständigkeit halber. Die zweite Zeile, die so ganz anders aussieht, beschreibt die Swap Partition des Systems. Diese Swap Partition hat etwas mit dem Konzept des virtuellen Speichers unter Unix zu tun. In diesem Bereich lagert der Kernel gerade nicht im Hauptspeicher benötigte Teile (genauer gesagt Speicherseiten, die nicht zum augenblicklichen Working Set eines aktiven Prozesses gehören) aus, um Platz im Hauptspeicher zu haben. Ohne eine solche Swap Partition stünde Unix nur der physikalisch vorhandene Speicher zur Verfügung. Eine Swap Partition wird mit dem Kommando swapon bzw. mit swap -a aktiviert. Um ein gemountetes Dateisystem wieder abzuhängen, sollte zuerst sichergestellt werden, dass kein User oder Prozess mehr auf dem Dateisystem aktiv ist. Dazu benutzt man das Kommando fuser:
3 374
root [/] 4 # fuser /mnt
Nach dem Kommando fuser wird der Pfad des Mountpoints angegeben. Als Ergebnis erhält man eine Liste von PIDs (sofern es Prozesse gibt, die noch auf dem Dateisystem aktiv sind). Werden keine solchen Prozesse gefunden, kann das gemountete Dateisystem mit dem Kommando
Drucken unter Unix
3
root [/] 4 # umount /mnt
wieder abgehängt werden. Auf vielen Unix-Systemen kann man dem Kommando mount noch eine Option (-t oder –F) mitgeben, mit der man andere Dateisystem-Typen mounten kann. Solche Typen können z.B. auf einem Linux-System MS DOS für eine Windows 95- oder 98-Partition oder iso9660 für eine CD-ROM sein. Die genaue Ausprägung findet man in der Man Page zum Kommando mount. Um festzustellen, welche Dateisysteme gemountet sind, empfiehlt sich das Kommando df, welches wir schon in Abschnitt 7.4 kennen gelernt haben. Hier bekommt man zusätzlich zu den Informationen über Devices und Mountpoints auch mitgeteilt, wie viel Platz noch zur Verfügung steht. Will man nur wissen, welche Devices unter welchen Mountpoints gemountet worden sind, und sich zusätzlich einen Überblick über die Mountoptionen verschaffen, kann man auch einfach das Kommando mount ohne weitere Optionen aufrufen. Für eine Maschine mit HP-UX könnte das wie folgt aussehen:
root [/] 5 # mount / on /dev/vg00/lvol3 log on Tue Aug 7 16:16:15 2001 /stand on /dev/vg00/lvol1 defaults on Tue Aug 7 16:16:17 2001 /var on /dev/vg00/lvol8 delaylog,nodatainlog on Tue Aug 7 16:16:25 /usr on /dev/vg00/lvol7 delaylog,nodatainlog on Tue Aug 7 16:16:25 /tmp on /dev/vg00/lvol4 delaylog,nodatainlog on Tue Aug 7 16:16:26 /opt on /dev/vg00/lvol6 delaylog,nodatainlog on Tue Aug 7 16:16:26 /home on /dev/dsk/c0t5d0 nolargefiles on Tue Aug 7 16:16:28 2001
2001 2001 2001 2001
3
Leider werden durch den Satz die Zeilen umbrochen. Eigentlich sind es sieben Zeilen, die jeweils durch das Datum und die Uhrzeit abgeschlossen werden, zu der das jeweilige Dateisystem gemountet wurde. Schaut man sich diese Zeiten bei unserem Beispiel an, liegt die Vermutung nahe, dass die Maschine am 7. August gegen 16:16 Uhr gebootet wurde.
19.5
Drucken unter Unix
Heute sind Drucker extrem preiswert. So bekommt man einen relativ guten farbigen Tintenstrahldrucker schon für unter 400 DM. Kein Wunder, dass Drucker bei diesen Preisen zur Ausstattung fast eines jeden Privatrechners gehören. Solange Betriebssysteme aus Redmond zum Einsatz kommen, ist in
375
KAPITEL
19
Das kleine 1x1 der Systemverwaltung
der Regel der Anschluss eines Druckers kein Problem, da jeder Hersteller einen Treiber für diese Betriebssysteme mitliefert. Doch wie sieht es mit den Druckqualitäten von Unix-Betriebssystemen aus? Leider recht bescheiden. An dieser Stelle ist Unix auf einer sehr frühen Evolutionsstufe stehen geblieben. Zwar kann man ohne größere Probleme auf den meisten Druckern Texte drucken, aber bei Bildern und Grafiken fehlen oft entsprechende Druckertreiber. Während bei den klassischen PC-Betriebssystemen eine Unterstützung für das Drucken eingebaut ist, auf der Applikationen aufsetzen können, verfolgt Unix eine andere Philosophie. Es stellt im Wesentlichen lediglich den Service bereit, die Daten an einen Drucker weiterzuleiten, aber die druckerspezifische Aufbereitung der Daten hat entweder die Applikation selbst oder ein entsprechender Postprozessor zu übernehmen. Dafür sorgt Unix als echtes Mehrbenutzer-Betriebssystem für eine Verwaltung, die es mehreren Benutzern möglich macht, den gleichen Drucker zu benutzen. Diese Verwaltung, auch Druckerspooler genannt, beinhaltet eine Warteschlangenverwaltung, die gleichzeitig einen oder mehrere Drucker verwalten kann. In heutigen Unix-Systemen sind zumeist Einflüsse aus beiden historischen UNIX-Linien (System V und BSD) vorhanden und alles in allem stellen sie meist eine Sammlung der besten Eigenschaften/Utilities beider Linien dar. Leider trifft das nicht auf die Druckerspooler zu. Keines der beiden Systeme hat sich in der Vergangenheit klar durchsetzen und das andere verdrängen können. Zwar ist der BSD-Druckerspooler leistungsfähiger und für die Verwaltung von Netzwerkdruckern geeignet, dennoch finden sich auch heute Systeme, die nur über einen System V-Druckerspooler verfügen, der dann aber oft um Netzwerkeigenschaften erweitert wurde. Wollte man eine ausführliche Beschreibung beider Systeme an dieser Stelle liefern, würde die zweite Ausgabe dieses Buches doppelt so dick wie die erste und der Anspruch, ein Buch über Grundlagen zu sein, ginge wohl oder übel verloren. Aus diesen Gründen habe ich mich entschlossen, nur eines der beiden Systeme zu beleuchten und das auch nur bis zu einer vertretbaren Komplexität. Natürlich ist damit nicht gewährleistet, dass mit dem hier aufgeschriebenen Wissen ein Drucker an einem beliebigen Unix-System zum Laufen zu bringen ist, aber es sollte ausreichen, um ein Verständnis davon zu vermitteln, wie ein Druckerspooler funktioniert und wie man über ihn drucken kann.
19.5.1
So geht’s
Da auf einem Unix-System mehrere Benutzer gleichzeitig arbeiten können, dürfen Hardware-Ressourcen wie der Drucker nicht exklusiv einem Benutzer zugeordnet werden, sondern die Benutzer müssen sich diese Ressource teilen. Allerdings sieht das bei einem Drucker anders aus als z.B. bei der CPU –
376
Drucken unter Unix ein Druckauftrag wird immer zusammenhängend gedruckt und nicht erst ein paar Seiten von dem einen Auftrag und dann ein paar von dem anderen. Um dies sicherzustellen und um zu verhindern, dass der Benutzer, dessen Auftrag gerade gedruckt wird, den Drucker anschließend nicht wieder für andere frei gibt, bekommt er nie wirklich Kontrolle über den Drucker. Stattdessen gibt es einen Manager, bei dem der Benutzer seinen Druckauftrag abgibt und der dafür sorgt, dass dieser Auftrag gedruckt wird. Dieser Manager ist der Drukkerspooler. Setzt man mit dem Kommando zum Drucken einen Druckauftrag ab, wird dieser Auftrag in die Warteschlage für den ausgewählten Drucker eingereiht. Dabei geht es streng nach dem Prinzip »Wer zuerst kommt, druckt zuerst«. Die Einreihung eines Druckauftrages in den Spooler mit dem Druckkommando lpr wird durch die Rückgabe einer Druckjob-ID (nachfolgend Job-ID genannt) bestätigt, mit welcher der Benutzer beim Spooler nachfragen kann, wie der Status seines Auftrages aussieht bzw. mit der er die Position seines Jobs in der Warteschlage feststellen kann. Ist sein Druckauftrag an die erste Stelle der Warteschlage gerutscht, werden die Daten vom Spooler an den Drucker über seine Gerätedatei übertragen. Damit es soweit kommt, müssen ein paar Voraussetzungen erfüllt sein: 1. Der Drucker muss dem Spooler bekannt sein. 2. Der Spooler muss eine Warteschlage für den Drucker führen und die Warteschlage muss zur Aufnahme von Druckjobs freigegeben sein. 3. Der Drucker muss zur Ausführung von Druckaufträgen freigegeben sein. 4. Der User, unter dem der Druckerspooler läuft, muss lesenden Zugriff auf die Daten, die gedruckt werden sollen, haben. Für die Umsetzung der ersten drei Punkte muss der Systemverwalter sorgen, indem er den Drucker im Druckerspooler bekannt macht, eine Warteschlage einrichtet und diese freigibt und anschließend die Ausgabe von Daten an den Drucker erlaubt. Der vierte Punkt liegt im Verantwortungsbereich des Users. Häufig wird der Druckbefehl nicht mit einer Datei bedient (für die dann die Zugriffsrechte stimmen müssen), sondern bekommt seine Daten per Pipe geliefert, sodass eventuelle Zugriffsprobleme von vorne herein ausgeschlossen sind. Wie die Umsetzung der ersten drei Punkte für einen BSD-Druckerspooler aussehen könnten, zeigt das nächste Beispiel. Dabei ist zu beachten, dass es je nach Hersteller Unterschiede zwischen den einzelnen Unix-Systemen geben kann und der Benutzer nicht umhin kommt, in den Manual Pages die genaue Syntax nachzuschlagen.
377
KAPITEL
19 19.5.2
Das kleine 1x1 der Systemverwaltung
Einen Drucker dem Spooler bekannt machen
Der eigentliche Verwalter im BSD Druckerspooling-System ist ein Prozess namens lpd. Dieser Dämon wird in der Regel beim Booten durch den init-Prozess gestartet und wartet darauf, dass Druckaufträge an ihn übergeben werden (siehe auch 19.6). Die Übergabe der Druckaufträge an den lpd erfolgt durch das Kommando lpr, mit dem der Benutzer eine Datei zum Drucker schickt. Beide greifen auf eine gemeinsame Datenbasis zurück, in der die Drucker definiert werden.
3
UNIX-Kurs [~] 164 > lpr –P hpj beispiel.txt hpj-01
Die Definition der Drucker erfolgt in der Datei /etc/printcap . Durch diese Datei werden neben dem Namen des Druckers auch sein Spooling-Verzeichnis und eventuell ein Filter festgelegt. Überhaupt gibt es eine Menge von Optionen, die für einen Drucker eingestellt werden können, als da wären: ✘ Datei und Verzeichnisinformationen ✘ Zugriffsinformationen (lokal oder über das Netzwerk erreichbar) ✘ Informationen über Geschwindigkeit und Druckprotokoll ✘ Filter ✘ Seiteninformationen All das wird durch das Setzen von Variablen festgelegt, die detailliert in der Man Page zur /etc/printcap beschrieben sind. An dieser Stelle soll uns ein Auszug aus einer /etc/printcap genügen, um deren Aufbau zu verdeutlichen:
3
378
hpj|lp|HP Laser jet plus:\ :lp=/dev/lp1:\ :sd=/usr/spool/lp1:\ :mx#0:\ :if=/usr/spool/lp1/hpjlp: hp4000n|Netzwerkdrucker:\ :sd=/var/spool/lpd/hp4000n:\ :rm=192.168.1.200:\ :rp=lp\ :sh:sf:mx#0:
Drucken unter Unix In diesem kurzen Abschnitt werden zwei Drucker definiert, ein lokaler Drucker mit dem Namen hpj (der auch gleichzeitig der Default-Drucker ist, was durch den zweiten Namen lp angezeigt wird) und ein Netzwerkdrucker mit dem Namen hp4000n. Eine Definition wird durch einen Zeilenumbruch abgeschlossen (wie auch in der Shell verhindert ein Backslash »\«, dass ein Zeilenumbruch als solcher gewertet wird und verlängert die Zeile). Die einzelnen Variablendefinitionen/Felder werden durch Doppelpunkte getrennt. Im ersten Feld stehen durch Pipe-Symbole »|« getrennt die Namen, unter denen der Drucker bekannt ist. Häufig finden sich hier mehrere alternative Namen, von denen meist einer zu einer etwas ausführlicheren Beschreibung des Druckers »missbraucht« wird. Nachfolgend werden ein paar der wichtigsten Variablen beschrieben, weitere sollten in der Man Page von printcap nachgeschlagen werden. lp
Mit dieser Variablen wird die Device-Datei festgelegt, über die der Drukker angesprochen werden kann. Eine solche wird nur von lokalen Druckern benötigt. /dev/lp1 in unserem Beispiel ist eine parallele Schnittstelle in einem Linux-System.
sd
Die Variable sd legt das Spool Directory fest, egal ob es sich um einen lokalen oder einen Netzwerkdrucker handelt. In dieses Verzeichniss werden die Druckaufträge von lpr abgelegt und zwischengespeichert, bis sie vom lpd an den Drucker geschickt werden. Wenn ein neuer Drucker in der /etc/printcap eingetragen wird, muss dieses Verzeichnis per Hand erstellt werden (mit den Rechten 775 und dem Eigentümer lp und der Gruppe lp).
lf
Bei lokalen Druckern sollte auf jeden Fall eine solche Fehlerprotokolldatei definiert werden, am besten für jeden Drucker eine individuelle Datei. Aber auch bei einem Netzwerkdrucker kann eine solche Fehlerprotokolldatei Sinn machen, um Kommunikationsprobleme zu erkennen.
rm
Handelt es sich um einen Netzwerkdrucker, wird man statt der Variablen lp die Variable rm definieren. In ihr wird entweder die IP-Adresse oder der Netzwerkname des Rechners angegeben, an den der Drucker angeschlossen ist. Handelt es sich um einen Drucker mit einem eigenen Netzwerkinterface, wird dieses in der Variablen rm definiert.
rp
Diese Variable wird zusammen mit rm benutzt um einen Remote-Drucker vollständig zu beschreiben. In rp wird gespeichert, wie der Drucker auf der Maschine heißt, an der dieser angeschlossen ist. lp bezeichnet hier wieder den Standarddrucker und ist bei Netzwerkdruckern mit einem eigenen Interface eine gute Wahl.
if
Mit if wird der Input-Filter definiert. Es gibt auch noch einen of = Output-Filter aber entgegen der Vermutung, die sich aus der Namensge-
379
KAPITEL
19
Das kleine 1x1 der Systemverwaltung
bung ableiten ließe, werden beide benutzt, um die Daten für die Ausgabe auf den Drucker aufzubereiten. Weil das so ist und ein Filter genug ist, belassen wir es beim Input-Filter. Der Filter ist, salopp ausgedrückt, so etwas wie der Druckertreiber auf anderen Systemen. Er nimmt die Daten, die gedruckt werden sollen, entgegen und bereitet sie so auf, dass der Drucker sie versteht. Hier liegt die wesentliche Schwäche der Druckerei unter Unix. Es gibt kaum Druckerfilter für Grafik oder gar farbige Grafik. Wenn man Glück hat, gibt es einen Filter für PostScript1, aber auch hier scheint die Ansicht zu gelten, dass sich am besten jede Software selbst um eine druckergerechte Aufbereitung der Daten zu kümmern hat. Also nicht wundern, wenn sich kein Eintrag für einen Filter mit der Beschreibung in der /etc/printcap finden lässt.
19.5.3
Das Drucksystem administrieren
Auch wenn die Bearbeitung der recht kryptischen /etc/printcap nicht Jedermanns Sache ist, so ist doch einer der Vorteile des BSD-Druckerspooling-Systems seine einfache Administrierbarkeit. Hat man den unangenehmen Teil hinter sich gebracht und einen Eintrag in der /etc/printcap erzeugt, muss man nur noch das Spool-Verzeichnis anlegen und das Drucken kann beginnen. Glücklicherweise gibt es heute schon auf vielen Systemen grafische oder kommandozeilenorientierte Werkzeuge, die einem die Fummlerei in der /etc/ printcap abnehmen. Für den Rest der Administration sind nur noch drei Befehle notwendig. Beginnen wir mit den beiden einfachen. Da wäre zunächst der Befehl lpq.
6
lpq [-P Drucker]
Mit diesem Befehl kann man sich die Warteschlange eines bestimmten Druckers anschauen. Gibt man keinen Drucker über die Option –P mit an, bekommt man die Warteschlange des Default-Druckers lp angezeigt. Leider unterscheidet sich die Ausgabe von lpq von System zu System doch erheblich. Die beiden wichtigen Informationen für den Admin, nämlich die Position eines Druckauftrages in der Warteschlange und seine Job-ID, sind in allen Varianten zu finden.
1. PostScript ist eine von Adobe Systems entwickelte allgemeine Seitenbeschreibungssprache, die quasi der Standard für Drucker in der Unix Welt ist.
380
Drucken unter Unix Hat man die Job-ID eines Druckauftrags mithilfe von lpq ermittelt, kann man den Job mittels lprm aus der Warteschlange löschen und so den Druck verhindern1.
lprm job-id
Jeder Benutzer darf so seine eigenen Druckaufträge wieder aus der Warteschlage entfernen. Um sich die lange Nachschlagerei mit lpq nach der Job-ID zu vermeiden, sollte man sich die Job-ID, die man von lpr nach dem Absetzen eines Druckauftrags erhält, gut merken.
6
UNIX-Kurs [~] 165 > lprm hpj-01 hpj-01 dequeued
3
Das Löschen eines Druckauftrags hat nur geklappt, wenn Sie von lprm eine Rückmeldung der Form
2
job-id dequeued
erhalten. Scheinbar ist vergessen worden, eine entsprechende Fehlermeldung in lprm einzubauen, wenn es eine Job-ID nicht gibt.
Nur der User root darf Druckaufträge von anderen Usern aus der Druckerwarteschlange löschen. Der letzte der drei Befehle zur Druckerverwaltung unter dem BSD-Druckerspooler ist das Kommando lpc. Mit lpc werden alle übrigen administrativen Tätigkeiten wie z.B. das Sperren einer Druckerwarteschlange oder das Anhalten eines Druckes durchgeführt.
lpc
lpc wird ohne Parameter aufgerufen und geht in einen eigenen Kommandomodus, der dem Administrator durch das geänderte Prompt (lpc>) angezeigt
6
1. Das sollte man schleunigst tun, wenn man aus Versehen statt seines Quellcodes das Kompilat zum Drucker geschickt hat.
381
KAPITEL
19
Das kleine 1x1 der Systemverwaltung
wird. In diesem lpc-Kommandomodus können nun eine Reihe administrativer Kommandos abgesetzt werden. status drucker
3
382
Der Status eines Druckers zeigt an, ob der Drucker drucken darf (printing is enabled/disabled) und ob seine Warteschlange Druckaufträge aufnehmen darf (queuing is enabled/disabled). Ferner bekommt man angezeigt, ob die Warteschlange Einträge enthält (no entries oder n entries wobei n die Zahl der Einträge ist).
UNIX-Kurs [~] 166 > lpc status hpj: queuing is enabled printing is enabled no entries printer idle hp4000n: queuing is enabled printing is enabled no entries printer idle
enable drucker
Dieses Kommando gibt die Warteschlange eines Druckers zur Aufnahme von Druckaufträgen frei.
disable drucker
Sperren der Warteschlange für einen Drucker
start drucker
Aktivieren des Druckers. Befinden sich Einträge in der Warteschlange, können sie jetzt auch zum Drucker geschickt werden.
stop drucker
Deaktivieren eines Druckers. Das Deaktivieren verhindert nur das Drucken auf dem Drucker. Es können weiterhin Aufträge in seine Warteschlange eingereiht werden.
down drucker
Dieses Kommando unterbindet sowohl die Ausgabe von Druckjobs auf dem Drucker sowie die Aufnahme weiterer Jobs in seine Warteschlange. Bereits aufgenommene Jobs bleiben erhalten.
up drucker
up gibt die Aufnahme von Jobs in die Warteschlange und das Drucken auf einem Drucker wieder frei.
clean drucker
Löscht alle Einträge aus der Warteschlange. Allerdings wird der aktuelle Druckjob noch abgeschlossen.
quit
Beendet den lpc-Kommandomodus
Wer boot sagt, muss auch shutdown sagen
19.6
Wer boot sagt, muss auch shutdown sagen
Der Begriff Booten kommt vom englischen bootstrapping, was so viel heißt wie sich selbst an den Schnürsenkeln hochziehen. Dieses Bild trifft ganz gut, was passiert, wenn ein Unix-System gestartet wird. Ganz am Anfang steht ein meist recht einfaches Stück Software - der boot loader, der dafür sorgt, dass der erste Prozess des Unix-Systems gestartet wird. Dieser erste Prozess ist dann Ursprung aller weiteren Prozesse, indem er sich »klont« und Aufgaben der anderen Prozesse übernimmt. Das System zieht sich also quasi selbst Stück für Stück hoch – startet einen Prozess nach dem anderen, bis ein voll funktionstüchtiges System zur Verfügung steht. Dieser Boot-Prozess ist nun nicht fest definiert, sondern kann vom Systemverwalter beeinflusst werden. So kann er z.B. festlegen, welche Prozesse auf seinem System laufen sollen, ob das Netzwerk aktiviert werden soll, ob die Prozesse einer grafischen Benutzeroberfläche gestartet werden sollen, ob es überhaupt einen Mehrbenutzerbetrieb geben soll oder ob das System in Single User Mode arbeiten soll – diese Liste ließe sich fast schier endlos fortsetzen. Aber wie kann nun der Systemverwalter in diesen Boot-Vorgang eingreifen? Der erste echte1 Prozess, der auf einem Unix-System gestartet wird, heißt init und hat stets die PID 1. Die Aktionen, die init ausführt, werden durch eine Konfigurationsdatei namens /etc/inittab gesteuert. Auf Systemen, die das Konzept der Run Level unterstützen – und das sind inzwischen nahezu alle – wird in der /etc/inittab festgelegt, in welchen Run Level gebootet wird. Schon allein diese Festlegung entscheidet, ob eine ganze Reihe von Prozessen gestartet wird oder nicht. Für jeden Run Level gibt es entweder ein oder mehrere Scripts, die beim Eintreten in den Run Level ausgeführt werden und über die das Anstarten weiterer Prozesse gesteuert wird. Für die Organisation dieser Scripts haben sich unterschiedliche Systeme etabliert, von denen ich hier nur eines, nämlich das von Sun Solaris vorstellen möchte. Solaris verfügt über ein Verzeichnis mit dem Namen /etc/init.d, in dem die Start- und Stopp-Scripts für nahezu jede Software aufbewahrt werden. Neben diesem Verzeichnis existieren ebenfalls im Verzeichnis /etc Unterverzeichnisse mit den Namen rcX.d wobei das X für den Run Level steht. In diesen Verzeichnissen stehen nun Symbolische Links auf die Scripts aus /etc/init.d. So könnte es z.B. in /etc/rc2.d einen Link mit dem Namen
1. Man spricht bei dem Scheduler, der die CPU verteilt, häufig von einem spontanen Prozess, der quasi aus dem Nichts entsteht und der sich auch nicht wirklich wie ein Prozess verhält, obwohl er in der Prozessliste auftaucht.
383
KAPITEL
19
Das kleine 1x1 der Systemverwaltung
S23network geben, der auf das Script network in /etc/init.d verweist. Und in /etc/rc1.d könnte es einen Link K23network geben, der ebenfalls auf das Script network unter /etc/init.d verweist. Was bedeuten diese Namen? Alle Links, die mit einem S gefolgt von einer Nummer beginnen, sind so genannte Start-Scripts. init schaut beim Booten in einen bestimmten Run Level in das zugehörige Verzeichnis unterhalb von /etc und ruft alle Links, die mit einem S und einer Zahl beginnen in ihrer lexikalischen Reihenfolge auf und übergibt ihnen jeweils als Parameter das Wort start. Die Scripts sollten so geschrieben sein, dass sie diesen Parameter verstehen und die zugehörige Software starten (in diesem Beispiel handelt es sich um das InitialisierungsScript für das Netzwerk). Alle Links, die mit einem K gefolgt von einer Zahl beginnen, sind so genannte Kill-Scripts. Sie werden von init mit dem Parameter stop aufgerufen, wenn der entsprechende Run Level erreicht wird. Es versteht sich von selbst, dass auch dieser Parameter richtig von den Scripts behandelt werden muss. Durch diesen einfachen und zugleich übersichtlichen Mechanismus lässt sich durch den Systemverwalter der gesamte Boot-Prozess in einen bestimmten Run Level customizen. In welchen Run Level per Default gebootet wird, wird in der /etc/inittab durch eine Zeile mit dem Schlüsselwort initdefault gesteuert.
19.6.1
Ändern des aktuellen Run Levels
Eine Änderung des Run Levels im laufenden Betrieb ist eine große Ausnahme und nur in absoluten Notsituationen erforderlich. Deswegen wird dieses hier nur sehr rudimentär behandelt und am liebsten hätte ich diesen Abschnitt komplett weggelassen. Wie bereits erwähnt, werden die Run Levels von init gesteuert. Was liegt also näher, als init zu benutzen, um die Run Levels zu wechseln? Genauso wird es gemacht.
6
init run-level
Wobei folgende Run Levels in der Regel folgendermaßen definiert sind: 0
Power Off – bedeutet ein Herunterfahren des Systems und sollte nur in Notfällen verwendet werden (siehe auch 19.6.2)
1, s Single User Mode – Nur der User root darf sich anmelden. Der Single User
Mode wird dann benutzt, wenn z.B. Patches eingespielt werden oder Veränderungen am System vorgenommen werden, die Einfluss auf die anderen Benutzer haben. Auf einigen Systemen gibt es Unterschiede zwischen 1 und s.
384
Wer boot sagt, muss auch shutdown sagen
2
Mehrbenutzerbetrieb ohne Netzwerk – Dieser Modus wird heute fast nicht mehr benutzt, weil fest angeschlossene Terminals nicht mehr üblich sind
3
Mehrbenutzerbetrieb mit Netzwerk – Das ist heute der Betriebsmodus für die meisten Systeme.
Reboot – Das System wird herunter- und sofort wieder in den Default Run Level hochgefahren.
root [/] 6 # init 6
Auf einem Linux-System kann der Run Level 2 bereits Mehrbenutzerbetrieb mit Netzwerk bedeuten – der Run Level 3 gibt dann die Möglichkeit eines Logins über X-Windows an.
19.6.2
3
Das System herunterfahren
Anders als die ersten simplen Betriebssysteme, die keine richtigen oder nur sehr rudimentäre Dateisysteme kannten, verfügt Unix seit Anbeginn über ein Dateisystem mit Rechtekonzept und Pufferung der Dateisystemzugriffe. Insbesondere die Pufferung von Dateisystemzugriffen zusammen mit der Optimierung, nicht jede Veränderung der i-node Struktur gleich auf die Platte bannen zu müssen, ermöglicht dem Unix-System einen äußerst performanten Zugriff auf seine Dateien. Allerdings erkauft man sich diesen Vorteil durch einen Nachteil. Fällt einmal spontan der Strom aus, ist das Dateisystem potentiell in einem inkonsistenten Zustand, weil nur Teile der Änderungen auf die Platte geschrieben worden sein können. Für diesen Fall gibt es Kommandos zur Beseitigung des Zustandes, die Unix spezifisch sind (z.B. fsck bei Solaris). Bei produktiven Unix-Systemen schützt man sich vor solchen spontanen Stromausfällen, indem man die Rechner mit einer USV (Unterbrechungsfreie Stromversorgung) ausstattet. Viel wichtiger ist allerdings ein physischer Zugangsschutz, der Unbefugte davon abhält, den Ausschalter zu betätigen. Durch den Einsatz spezieller Dateisysteme (sog. journaling filesystem) kann man aber auch derartige Situationen entschärfen. Für den Privatmann sind solche Sicherungen nicht umsetzbar, deshalb muss man sich selbst zum Schutze seiner Daten den Zwang auferlegen, nicht wie beim guten alten DOS-PC den Ausschalter zu betätigen oder den ResetKnopf zu drücken, wenn der Rechner nicht so will, wie man selbst.
385
KAPITEL
19
Das kleine 1x1 der Systemverwaltung
Ein Unix-System egal welchen Herstellers sollte immer kontrolliert heruntergefahren werden. Dazu gibt es ein Kommando, welches der Benutzer root ausführen kann.
6
shutdown –h shutdown –r
shutdown mit der Option –h fährt das System herunter. Bei Verwendung der Option –r statt –h wird das System rebootet. Auf den meisten Systemen kann man noch eine Zeit angeben, zu welcher der Shutdown erfolgen soll bzw. die gewartet wird, bevor er ausgeführt wird. Da hier aber die Syntax nicht einheitlich ist, verweise ich für solche Optionen auf die Manual Pages der jeweiligen Systeme.
3
root [/] 7 # shutdown -h
Nachdem root shutdown aufgerufen hat, geht alles weitere automatisch. Die anderen Benutzer werden gewarnt, die Platten werden mit den Informationen aus dem Speicher synchronisiert, die Kill-Scripts aus dem Run Level 0 werden ausgeführt usw. Schon allein die Schilderung macht klar, dass dieser Prozess ein wenig länger dauert. Das ist aber hinnehmbar, weil Unix-Systeme nicht so häufig neu gebootet werden müssen bzw. in der Regel nicht jeden Tag abgeschaltet werden. Soll es trotzdem mal schnell gehen, gibt es noch andere Möglichkeiten, ein System neu zu starten bzw. herunterzufahren. Allerdings ist hier Vorsicht geboten. Wird für den Reboot das gleichnamige Kommando
6
reboot
verwendet, so werden z.B. die Scripts aus /etc/rcX.d beim Herunterfahren nicht ausgeführt. Datenbanken quittieren so etwas meist durch ein Recover beim Hochfahren, was mitunter ganz schön lange dauern kann. Gleiches gilt für das Kommando
386
Wer boot sagt, muss auch shutdown sagen
Halt
das Gegenstück zu reboot, wenn es nicht um ein schnelles Rebooten, sondern um ein schnelles Herunterfahren des Systems geht.
Achten Sie also bei der Verwendung der Kommandos reboot und halt darauf, brisante Applikationen wie z.B. Datenbanken vorher per Hand herunterzufahren. Auch die Synchronisation von Platten und Speicherinhalt durch das Kommando sync ist vor der Ausführung eines der beiden Kommandos anzuraten.
6 2
387
ANHANG
Installation von Solaris 8 Für die Installation von Solaris 8 benötigen Sie keine Unix-Vorkenntnisse. Bei meinen Tests mit zugegebenermaßen recht aktueller Hardware sind keine Probleme aufgetreten. Solaris 8 lässt sich ohne weiteres als zweites Betriebssystem installieren. Allerdings gibt es dabei je nach Betriebssystem einiges zu beachten. Deshalb möchte ich bei derartigen Fragestellungen auf die entsprechende Internetseite http://www.sun.drydog.com/faq/9.html verweisen.
Voraussetzungen Hardware-Anforderungen Prozessor
Ihr Rechner sollte mindestens über einen Intel Pentium oder einen vergleichbaren Prozessor verfügen. Solaris 8 unterstützt die 32-Bit-Prozessor-Familie von Intel, also Pentium, Pentium Pro, Pentium II, Pentium II Xeon, Pentium III, Pentium III Xeon, Celeron oder die kompatiblen Prozessoren von Cyrix und AMD.
Speicher
Minimum sind 64 MByte RAM. Empfehlen würde ich allerdings 128 oder noch besser 256 MByte. Maximal werden im allgemeinen Betrieb bis zu 32 Gbyte Speicher unterstützt.
Bus
Solaris 8 unterstützt ISA-, PCI-, VLB- und SCSI-Systeme.
Platten
Solaris 8 unterstützt IDE-, Enhanced-IDE- und SCSI-Platten.
389
Installation von Solaris 8
Plattenplatz
Minimal müssen Sie für End User-Installation mit 650 MByte rechnen. Es empfiehlt sich allerdings, für Ihr Solaris 7 eine Partition oder eine Platte mit 1 Gbyte zu spendieren, denn schließlich wollen Sie ja auch noch ein paar Daten ablegen.
Mögliche Probleme
Nicht alle Hardware-Konfigurationen werden problemlos von Solaris 8 unterstützt. Um hier Genaueres zu erfahren, empfiehlt sich eine Recherche auf der Webpage von Sun für die Hardware Compatibility List (hcl) von Solaris 8 (http:// soldc.sun.com/support/drivers/hcl/8/701/p2.html#TOC-1).
Installationsmedien Zur Installation ist nur die CD-ROM notwendig, welche dem Buch beiliegt. Sollte Ihr System allerdings nicht über die Möglichkeit verfügen, von einer CD-ROM zu booten, benötigen Sie noch eine Bootdiskette, die Sie von der Seite http://soldc.sun.com/support/drivers/dca_diskettes herunterladen können, und das Hilfsprogramm dd.exe, welches Sie unter http:// soldc.sun.com/support/drivers/tools downloaden können. Mit dem Buch wird das Solaris 8 Release 07/01 für Intel ausgeliefert. Wenn Sie die Bootdiskette erzeugen müssen, kopieren Sie diese beiden Dateien in ein Verzeichnis auf einem Windows 98-, Windows NT 4.0- oder Windows 2000-Rechner. Legen Sie eine formatierte 3,5"-Diskette in Ihr Diskettenlaufwerk (in dem nachfolgenden Beispiel wird davon ausgegangen, dass das Diskettenlaufwerk das Laufwerk A: ist). Öffnen Sie ein Command-Fenster, wechseln Sie mit dem Befehl cd verzeichnisname in das Verzeichnis, in das Sie die Dateien kopiert haben, und geben Sie folgendes Kommando (c:> ist das Prompt) ein: c:\verzeichnisname> dd.exe s8_0701.3 A:
Nach einigen Sekunden ist die Bootdiskette erzeugt.
Installation Wenn Sie alle Voraussetzungen erfüllt haben, können Sie zur Installation schreiten. Ich werde hier nur den Standardfall einer Installation beschreiben. Sollten Sie weitere Anforderungen oder Wünsche haben, empfiehlt es sich, z.B. die Webpage http://www.sun.drydog.com/faq aufzusuchen und sich dort zu Informieren.
Partitionen Um Solaris 8 auf Ihrer Festplatte installieren zu können, benötigen Sie eine Partition von mindestens 650 Mbyte Größe, ich empfehle Ihnen aber mindestens 1 Gbyte zu verwenden. Solaris legt innerhalb dieser Partition noch eigene Slices an, die wie in Kapitel 19 beschrieben benannt werden.
390
Installation
Booten Solaris 8 installiert im Boot-Sektor Ihrer Festplatte einen Boot-Manager. Über diesen kann sowohl Solaris als auch ein anderes Betriebssystem gebootet werden. Bevor Sie Solaris auf einem Rechner installieren, auf dem bereits ein anderes Betriebssystem installiert ist, sollten Sie auf jeden Fall die Seite http:// www.sun.drydog.com/faq/9.html lesen. Ich empfehle Ihnen bei einer derartigen Konstellation dringend eine komplette Sicherung der Windows-Partitionen.
Installationsvorgang 1. Schalten Sie Ihren Rechner ein und legen Sie dann die CD-ROM Solaris 8 Software in das CD-Laufwerk (Falls Ihr Rechner nicht von CD bootet, legen Sie zuvor die Bootdiskette aus dem Abschnitt »Installationsmedien« dieses Anhangs ein. Sorgen Sie dafür, dass die Diskette keinen Schreibschutz hat.). Es erscheint zunächst ein Bildschirm, der mit »Solaris Device Configuration Assistent« überschrieben ist, mit Hinweisen, wie bei der Installation vorzugehen ist. Bestätigen Sie diesen Screen, nachdem Sie sich die Informationen aufmerksam durchgelesen haben, durch Drücken von Ê. Nun wird die Hardware Ihres Rechners durch das Installationsprogramm gescannt (»Scanning Devices«). Dieser Vorgang dauert eine Weile. Als Ergebnis wird eine Liste mit der gefundenen Hardware (»Identified Devices«) angezeigt. Drücken Sie in diesem Fenster Ê. Anschließend werden Treiber für die erkannte Hardware geladen. 2. Es erscheint der Bildschirm »Boot Solaris« zur Auswahl des Installationsmediums. Wählen Sie hier die CD-ROM aus. Dazu bewegen Sie den Cursor mit den Cursortasten auf die entsprechende Auswahl und betätigen dann die Leertaste. Drücken Sie Ê zum Fortfahren. 3. Der Bildschirm wird schwarz und nach einer Weile erscheint die Frage nach der Installationsmethode. Wählen Sie hier bitte 1 SOLARIS INTERACTIVE durch Eingabe einer 1 und drücken Sie Æ. Nun wird der Kernel gebootet. Dieser Vorgang dauert eine Weile. 4. Als Nächstes erscheint die Auswahl der Installationssprache (»Select Language«). Wählen Sie hier bitte 0 ENGLISH durch Eingabe einer 0 aus und drücken Sie dann Æ. 5. Als Nächstes wird der Zeichensatz (»Select a Locale») abgefragt. Wählen Sie hier bitte 49 U.S.A. (EN_US. ISO8859-1) durch Eingabe einer 49. Drücken Sie nach der Eingabe Æ.
391
Installation von Solaris 8 6. Den nächsten Bildschirm (»The Solaris Installation Program«) können Sie einfach mit Ê überblättern. 7. Die nun folgende Konfigurationen (»kdmconfig – Introduction«) für das Fenstersystem sollten Sie unbedingt durchführen, damit Ihr System gleich mit einer grafischen Oberfläche bootet. Es werden drei Unterpunkte angeboten: ✘ Grafikkarte/Monitor anpassen ✘ Keyboard Layout ✘ Maus/Pointing Device Befindet sich Ihre Grafikkarte und Ihr Monitor nicht unter den von Solaris 8 unterstützten Geräten, können Sie den Modus VGA 640X480 16 COLORS für die Grafikkarte wählen und IBM VGA (31,5 KHZ) oder SUPER VGA (35,5 KHZ) für den Monitor. Als virtuelle Auflösung sollten Sie auf jeden Fall 800x600 einstellen. Ist für die Tastatur nicht GENERIC GERMAN ausgewählt, sollten Sie diese Auswahl einstellen, wenn Sie eine deutsche Tastatur haben. Für die Maus wird in der Regel bereits die richtige Einstellung vorgeschlagen. Kontrollieren Sie aber die Einstellung für die Anzahl der MausTasten. Wählen Sie zum Abschluss der Einstellungen den Punkt NO - TEST/SAVE AND EXIT aus und drücken Sie Ê.
CHANGES
NEEDED
8. Es erscheint der Bildschirm »kdmconfig Window System Configuration Test«, der zum Testen der soeben gemachten Einstellungen auffordert. Starten Sie den Test durch Drücken von Ê. 9. Auf dem Testbildschirm erscheinen nun verschiedene farbige Flächen und ein Mauszeiger. Wenn sich der Mauszeiger bewegen lässt, positionieren Sie ihn über die Schaltfläche YES und klicken Sie mit der linken Maustaste. 10. Das System wechselt nun in den Grafikmodus und ein Fenster mit der Überschrift »Install Console« erscheint. Im weiteren Verlauf der Installation erscheinen eine Reihe von Fenstern, in denen nur die Default-Einstellungen bestätigt werden müssen. Auf diese Fenster möchte ich nicht weiter eingehen. Fenster, die nicht in dieser Installationsanweisung beschrieben sind, bestätigen Sie mit CONTINUE. 11. Im Fenster »Network Connectivity« klicken Sie bitte die Auswahl NO an und anschließend betätigen Sie den CONTINUE-Button.
392
Installation 12. Das nächste relevante Fenster fragt den Rechnernamen ab. Klicken Sie bitte in das Eingabefeld nach HOST NAME und geben Sie den Namen für Ihr System ein. Sie müssen hier mindestens zwei Zeichen eingeben. Der Name sollte nur aus Buchstaben, Ziffern und dem Minuszeichen bestehen. Deutsche Umlaute sollten Sie unbedingt vermeiden! Klicken Sie nach der Eingabe bitte auf CONTINUE. 13. Die nächste Auswahl, die zu treffen ist, ist die der geografischen Region. Es erscheint zunächst ein Fenster »Time Zone«. In diesem ist der Button SET... zu betätigen. Anschließend erscheint ein Fenster mit zwei Listen. In der linken Liste sind die Kontinente aufgeführt. Wählen Sie hier bitte EUROPA aus, indem Sie auf den entsprechenden Listeneintrag klicken. Wählen Sie nun auf die gleiche Art aus der rechten Liste MITTELEUROPA aus. Klicken Sie auf CONTINUE, um die Eingaben zu bestätigen. 14. Im nächsten Fenster können Sie gegebenenfalls Veränderungen am Datum und der Uhrzeit vornehmen. Klicken Sie im Anschluss auf CONTINUE, um die Einstellungen wirksam werden zu lassen. 15. Als Nächstes fragt Sie das Installationsprogramm nach der geografischen Region (»Select Geographic Region«). Wählen Sie hier bitte NORTH AMERICA (Partial / USA ISO8859-1) aus und drücken Sie dann CONTINUE. 16. Das nächste Fenster (»Select Software«) dient zur Einstellung der zu installierenden Software. Als Default wird hier END USER SYSTEM SUPPORT vorgeschlagen. Bestätigen Sie diese Auswahl, indem Sie auf CONTINUE klicken. 17. Im nächsten Fenster (»Select Disks«) werden die für die Solaris 8-Installation verfügbaren Platten angezeigt. Wählen Sie in der rechten Liste die Platte für die Installation aus und klicken Sie dann auf EDIT FDISK. Sie können nun Veränderungen an der Partitionierung Ihrer Platte vornehmen. Beachten Sie bitte, dass Größenveränderungen von Partitionen zum Verlust des Inhalts auf dieser Partition führen. Sie können sich also auf diese Art und Weise ein eventuell schon vorhandenes Betriebssystem zerstören. Stellen Sie für die Partition, auf der Sie Solaris 8 installieren wollen, SOLARIS ein. 18. Als Nächstes (»Automatically Layout File System«) werden Sie nach dem Layout für die Dateisysteme gefragt. Klicken Sie bitte auf den Button AUTO-LAYOUT. Es erscheint ein Fenster, in dem das Layout für die Dateisysteme angezeigt wird. Bestätigen Sie hier und in allen weiteren Fenstern bitte den Default durch Drücken der CONTINUE-Taste, bis Sie zum Fenster »Profil« kommen. Klicken Sie hier auf den Button BEGIN INSTALLATION. 19. Im nächsten Fenster werden Sie gefragt, ob nach der Installation ein automatischer Neustart erfolgen soll. Klicken Sie in diesem Fenster bitte auf
393
Installation von Solaris 8 den Button AUTO REBOOT. Damit dieser durchgeführt werden kann, muss die Diskette aus dem Laufwerk genommen werden. Entfernen Sie also die Diskette und bestätigen Sie das Info-Fenster durch Drücken auf OK. 20. Die Installation beginnt zu laufen und es erscheint ein Fenster, in dem der Installationsfortschritt angezeigt wird. Ist die Installation abgeschlossen, bootet der Rechner neu. Anschließend fordert Sie das System auf einem blauen Bildschirm zur Eingabe eines Passwortes für den Benutzer root auf. root ist der Unix-Systemverwalter. Sie sollten also für diesen Benutzer ein Passwort vergeben. Das Passwort muss zweimal eingegeben werden. Bitte wundern Sie sich nicht, wenn sich dabei der Cursor nicht bewegt. Haben Sie ein Passwort angegeben, erscheint der CDE-Einlogbildschirm.
Abschlussarbeiten Nachdem Sie das Kapitel über CDE in diesem Buch gelesen haben, melden Sie sich bitte als root an, suchen in den Untermenüs des CDE-Bedienpanels nach der Applikation mit dem Namen console und wählen diese aus (durch Anklicken mit der linken Maustaste). Sie erhalten daraufhin ein Shell-Fenster. In diesem Shell-Fenster geben Sie nun bitte den Befehl zum Anlegen eines neuen Users an (das Hash »#« ist das Prompt): # useradd –d /export/home –s /bin/ksh –m unixuser
Sie haben nun einen Account mit dem Namen unixuser angelegt. Vergeben Sie noch ein Passwort für diesen User mit dem Kommando (das Hash »#« ist das Prompt): # passwd unixuser
Anschließend müssen Sie ein Passwort eingeben und es einmal wiederholen. Melden Sie sich nun vom System ab und unter dem neuen Account unixuser am System an.
1
Ein gute Quelle für weitere Software ist die Seite http://www.sunfreeware.com. Hier findet man so manche nützliche und zudem kostenlose Software für Solaris 8.
Viel Spaß beim Lernen von Unix unter Solaris 8!
394
Stichwortverzeichnis Stichwortverzeichnis ! 153 * 68, 151, 183 . 65 .. 64 .cshrc 163, 164 .exrc 287 .fvwm2rc 217 .kshrc 189 .login 164 .mwmrc 214 .profile 192 .rhosts 240, 245 .tcshrc 163, 164 .Xdefaults 220 .xinitrc 218 .xsession 219 /dev/null 170 /etc/fstab 372 /etc/group 363 /etc/hosts 240, 247 /etc/init.d 383 /etc/inittab 383 /etc/passwd 112, 115, 150, 164, 182, 192, 219, 247, 312, 362 /etc/printcap 378 /etc/shadow 363 /etc/skel 369 /usr/group 33 ? 68 A Abbildungen – Ablaufdiagramm 310 – Arbeitsschritte der csh und tcsh 171 – Arbeitsschritte der ksh 198 – Aufbau der Indirektionsblöcke 90 – Aufbau eines Dateiarchivs 258 – Aufbau eines i-node 89
– awk – Ablauf einer Bearbeitung 329 – Das CDE-Shell-Fenster dtterm 222 – Das CDE-Bedienpanel 221 – Der CDE-Application-Manager 228 – Der CDE-Standardeditor dtpad 223 – Der CDE-Style-Manager 228 – Der CDE-File-Manager dtfile 224 – Der mwm-Window-Manager 215 – Der Dateibaum des Unix System V Release 4 62 – Der Window-Manager fvwm2 216 – Der Window-Manager twm 213 – Ein CDE-Menü 221 – Icon eines Shell-Fensters 41 – Innenansicht eines Verzeichnisses 91 – Innenansicht eines Verzeichnisses mit Links 94 – IP-Adressen 238 – Kommunikation der X-WindowKomponenten 212 – man-Page 47 – Modi des vi 276 – Schalenkonzept 27 – Shell-Fenster 40 – Style-Manager – – Startup-Fenster 231 Ablaufstrukturen 293 – break 308 – case 307 – continue 308 – exit 309 – for 305 – if 304
395
Stichwortverzeichnis – until 307 – while 306 Account 43, 70 Alias – permanente 163, 164, 189 Alias-Namen 137, 152, 161, 184, 188, 293 Alias-Substitution 162, 171, 188, 198 Anmelden und Arbeiten an UnixSystemen 37 ANSI 33 Anwendungsprotokoll 237 append 167, 195 Application-Manager – Desktop-Apps 232 Archivierungsbefehle 258, 259 Argumente 45 ASCII-Tabelle 115 Ausgabeumlenkung 167, 194 – mit Fehlerkanal 168, 195 Ausschneiden 111 Auto Correction 158 Auto Logoff 158 awk 327 – Ablaufstrukturen 336 – Aktion 330 – Aktion, leere 330 – Arrays 346 – Ausgabeumlenkung 351 – Definition von Kriterien 330 – Eingabeumlenkung 351 – Funktionen 348 – GNU-awk (gawk) 346 – Grundlagen 328 – Kommentar 349 – Konstanten 335 – Kriterium 329 – Kriterium, leeres 330 – mehrdimensionale Arrays 348 – nawk 346 – Programm 329 – Programmiersprache der Aktionen 334
396
– Shell-Kommandos ausführen 349 – Variablen 335 – Zuweisungen 334
B Backquotes 160, 187 Backup-Strategien 257 bash 150, 182 Bedienoberfläche 209 Benutzerkennung 43, 53, 65 Benutzernummer 112 Bereiche 142 Betriebssystemkern 60 Bildschirmsitzungen an fernen Rechnern 239 BISON 34 Boolesche Algebra 294 Bourne-Shell 149 – read 301 – test 301, 313 BSD 32, 149
C C 26, 32, 35 C++ 35 CAE 34 CDE 216, 217, 219, 220, 221, 233 – Application-Manager 227 – Bedienpanel 221, 226, 230 – Bildschirmschoner 230 – Create Action 232 – Desktop konfigurieren 228 – dtfile 223 – dtpad 222 – dtterm 222 – File-Manager 223, 233 – Hintergrundbild 229 – Menüs erweitern 232 – Mülleimer 226 – Session 231
Stichwortverzeichnis – Standardeditor 222 – Style-Manager 228 – Zeichensätze 229 Client 211, 218 Close 40 Command History 152 Command Line Editing 149, 181 Command Listing 158 Copy&Paste 38 Create Action-Utility 232 csh 149, 150, 182 – Subshell 169 C-Shell 149 Cut&Paste 248
D Dämonen 135 Dämonenprozess 114 Darstellungsprotokoll 237 DAT 256 date – Platzhalter 54 Datei 59 – Device Descriptors 60 – Directory 60 – Eigentümer 70 – Gruppe 70 – Plain File 59 – Special Files 60, 61 Dateiarchive 257 Dateibaum 60, 61 – navigieren 63 – Unix System V Release 4 61 Dateisystem 52, 59 – hierarchisches 26 Dateitransfer 241 Dateitypen 59 Dateiverwaltung 67, 74 Datenkompression 266 Datensicherung 255 Default-Shell 150, 182 DES-Verschlüsselung 362 Desktop 39
Device – Block Device 373 – Raw Device 373 Device Descriptor 60, 106, 166, 193, 265 Directory 60, 106 DISPLAY 154, 184 Domain 52, 53, 249 DOS-Datei 142 Dot-Notation 237 Double Quotes 46, 159, 187 Drucken, Job-ID 377 Druckerspooler 63, 376 dtfile 223 – kopieren 225 – löschen 226 – neues Verzeichnis 227 – verschieben 226 – Zugriffsrechte 227 dtpad 222 dtterm 222 dtwm 221
E EBCDIC 237, 243 Editor – vi 275 Ein-/Ausgabeumlenkung 165, 171, 193, 198, 262 Eingabefokus 217 Eingabeumlenkung 141, 166, 194, 249 Einsatzgebiete 28 E-Mail 52, 167, 194, 235, 249 – Adresse 52, 249 ENV 193 Environmentvariablen 152, 154, 159, 164, 183, 184 – PATH 164 Escape Character 69, 104, 150, 182 Ethernet 237 ex 32
397
Stichwortverzeichnis EXABYTE 256 Exit-Status 303, 312 Extension 59
F false 294 Fehlermeldungen – arg list too long 150, 182 – permission denied 65 FIFO 137 File Transfer Protocol 241 File-Manager – kopieren 225 – löschen 226 – neues Verzeichnis 227 – verschieben 226 – Zugriffsrechte 227 Filename Completion 158 Filesystem 87 Filter 138, 267, 286 Filterprogramme 139 Free Software Foundation 268 FreeBSD 28 Fullname 362 Functions 191 Funktionen 340 fvwm 215 fvwm2 221
G Geräteunabhängigkeit 256 GID 363 – effektive GID ( EGID ) 365 – SetGID Bit 365 GNU 268 GNU Public License 268 Grafikworkstation 28 Gruppe – Default-Gruppe 364 – primäre 363 – sekundäre 363 Gruppennummer 112
398
H Hard Link 96 Hardwarekompression 266 Hardwareschnittstellen 60 Hierarchisches Dateisystem 63 Hintergrundprozess 135, 172, 174, 199, 201 History Character 153, 159, 163 History Completion 158 History Space 159 History-Kommandos 153 History-Substitution 171 HOME 152, 154, 184 Home Directory 62, 65, 69, 112, 243, 368 HTML 126 I Iconify 40 IEEE 33 – 802.3 237 Image Backups 257 Indirektionsblock 89 Informationsdienste 246 init-process 132 i-node 88, 105, 257 Install Icon 233 Internet Protokoll 237 IP 237 J Job 172, 199 Job Control 173, 200 Job ID 172, 199 K Kanäle 166, 193 KDE 216, 219, 233 kdm 219 Kernel 60 Kommandoeingabe 44, 46 Kommandointerpreter 25 Kommandos – @ 156
Stichwortverzeichnis – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – –
alias 161, 188 basename 299 bg 173, 200 cat 51 cd 65, 80 chgrp 364, 369 chmod 295, 365 chown 369 compress 266 cp 76, 80, 93 cpio 262 cut 111, 139, 286, 313 date 54 df 97 dirname 299 du 96 echo 53, 156 egrep 108, 120 env 154, 185 exit 44 export 185 expr 299 fg 174, 201 fgrep 108, 139, 160 file 49, 51, 60, 113, 139 find 104, 151, 162, 170, 183, 263 finger 246 fold 140 ftp 241, 266 fuser 374 grep 108, 312 groupadd 367 gunzip 269 gzip 268 halt 386 head 113 history 152 jobs 173, 199 kill 133, 172, 173, 199, 200 ln 93 lpc 381 lpd 378 lpq 380
– – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – –
lpr 377 lprm 381 ls 52, 74, 93, 160 mail 52, 167, 194, 249 man 47, 48 mkdir 80 more 52, 139 mount 374 mv 77 newgrp 364 passwd 55 ping 247 ps 132, 172, 199 pwd 65 rcp 245 reboot 386 rlogin 240 rm 78, 92, 255 rmdir 80 sed 119 set 156 setenv 154 shutdown 386 sort 114, 286 startx 218 sync 387 tail 113 talk 248 tar 260 tee 141 telnet 239 tr 141, 286 umask 73 umount 374 unalias 163, 189 uname 50 uncompress 267 unset 157, 185 unsetenv 155 useradd 370 vi 222, 275 wc 139, 297 who 50 who am I 50
399
Stichwortverzeichnis – xhost 211 – xinit 218, 219 – xterm 165 – zcat 267 Kommando-Substitution 160, 188, 297 Kommandozeilenparameter 45 Kommunikationsdienste 246 Konfigurationsvariablen der csh und tcsh 158 Korn-Shell 181 ksh 150, 181, 182 – Subshell 197 L LAN 249 Leitungsprotokoll 236 Link 91 – Symbolic Link 93 – Verwendungszwecke 95 Linkcount 92 Linux 28, 233 Log-Dateien 114 Login-Shell 164, 192 Logische Operatoren 294 – NICHT 303 – ODER 303 – UND 303 M Mail-Reader 249 Main Window 39 Major Device Number 61 man-Pages 47, 48, 139 – Description 48 – Synopsis 48 Maus 38 – linke Maustaste 38 – mittlere Maustaste 38 – rechte Maustaste 39 Maximize 40 Metazeichen 120 Modifikationsdatum 263 Mountpoint 372
400
MULTICS 31 Multiprocessing 24 Multitasking 24 – kooperatives 25 – preemptives 25 Muster 108 mwm 213 N Network File System 238 Networking 235 – Grundlagen 235 Netzdienste 239 Netzklasse 238 Netzwerkadapter 235 Netzwerkprotokoll 236 NFS 238 NLS (Native Language Support) 229 Numerische Variablen 156 O Offenes System 103 Oktalzahl 71 Online-Hilfe 46 Optionen 45 Optionsblock 45 OSF 34 OSF/Motif 35, 214 OSI-7-Schichten-Modell 236 P Pager 51, 139 Parameter 45 Parent Directory 64, 92 Passwort 43, 362, 369 PATH 151, 154, 159, 183, 184 Peripheriegeräte 60 Pfad 63 – absoluter 63, 106 – relativer 64, 106 Pfade 68 – absolute 65 – relative 65
Stichwortverzeichnis Physikalisches Protokoll 236 PID 132, 133, 135, 172, 199 pine 249 Pipes 137, 141, 161, 262 Plain File 59, 106 Popup-Menü 39 POSIX 33 PostScript 380 PPID 133 Programmiersprache C 25 Prompt 44, 135, 242 Protokoll 235 Protokollstack 236 Prozesse 24, 131 Prozessverwaltung 131, 172, 199 PWD 184 Q QIC Tape 256 Quicksort 114 Quoting 46, 54, 69, 105, 110, 142, 150, 155, 159, 162, 182, 186, 245, 297, 312 R Reguläre Ausdrücke 108, 282, 284, 330 – sed 120 Reihenfolge – Interpretation durch die csh und tcsh 170 – Interpretation durch die ksh 198 Reportgenerator awk 327 Resize Handle 40 RISC 26, 35 root User 360, 386 Root-Directory 61, 63 Route 239 r-Tools 240, 245 Run Level 383, 384 S Schalenkonzept 26 Scheduler 25
Schreibschutzvariable 167, 195 Scrollbar 41 Search Path 159 sed – Adressen 122 – Scriptdatei 122 Seitenwechseleinbruch 165 Sequentielle Verkettung von Kommandos 136 Session 218, 219 SetGID Bit 365 SetUID Bit 365 sh 149, 150, 181, 182 Shell 26, 44, 64, 65, 67, 112, 368 Shell-Variablen 155, 186, 296 – autocorrect 158 – autoexpand 158 – autolist 158 – autologoff 158 – filec 158 – histchars 159 – history 159 – noclobber 167, 195 – path 159 Shell Variablen – Bourne-Shell 293 – $? 297 – $# 297 – $* 297 – $0 297 – $1,...,$n 297 Shell-Fenster 39 Shell-Scripts 149, 182 – Ablaufstrukturen 304 – Grundlagen 295 – Muster-Script 309 – Programmierung 293 – spezielle Kommandos 299 – Variablen 296 Sicherungsmedien 255 SIGKILL 134 Signale 133 Signalhandler 133 SIGTERM 134
401
Stichwortverzeichnis Single Quotes 160, 187 Sitzungsprotokoll 237 Softwarekompression 266 Sohnprozess 132 Sonderzeichen 53, 67, 69, 103 Sortieren 111 Standardausgabe 138, 166, 193 Standardeingabe 138, 166, 174, 193, 201 Standardfehlerausgabe 166, 194 Standard-Prompt 164 Standards 33 Sticky Bit 366 Stoppen von Prozessen 173, 200 Style Guide 214 Style-Managers – Window-Fenster 231 Subshell 169, 197 Suchen 103 Suchpfad 151, 164, 172, 183, 199 Sun Microsystems 32 SunOS 248 Superuser 360 SVID 34 Swap Space 165 Symbolic Link 93, 106 Syntax 21 SYSLOG 114 syslogd 114 system.mwmrc 214 T Tabulator 140 talk request 248 Task 24 TCP 237, 238 tcsh 149, 150, 182 – Subshell 169 telnet 218 Tenex-C-Shell 149 Textvariablen 155 ThinWire Ethernet 247 Titlebar 40
402
Transmission Control Protocol siehe TCP Transport Protokoll 237 true 294 twm 213 U Überschreibschutz 165, 193 UDP 237, 238 UI 34 UID 360 – effektive UID (EUID) 365 – SetUID Bit 365 umask 164 Umplatzierung der Parameterliste 161 Unix 36 Unix-Filesystem – Aufbau des 88 Unix-System V 33 – Release 4 33, 35 User Datagram Protocol 238 User File Creation Mask 73 V Variablenfelder 157, 159 Variablen-Substitution 171, 199 Vaterprozess 132, 172, 199 Verweis 91 Verzeichnisbaum 60 Verzeichnisverwaltung 80 vi 32 – Cursorpositionierung 277 – Dateikommandos 283 – Eingabemodus 281 – ersetzen 284 – ex-Modus 283 – Grundlagen 276 – Kommando wiederholen 279 – Kommandomodus 277 – Markieren und Kopieren 279 – Ressource-Datei .exrc 287 – Setup 287 – Statuszeilenmodus 282
Stichwortverzeichnis – suchen 284 – Undo 279 – Unix-Kommandos 286 – Zeichen und Zeilen löschen 278 Vordergrund- und Hintergrundprozesse 135 Vordergrundprozess 135, 173, 200
W Wahrheitswert 331 Wildcards 67, 68, 105, 150, 166, 172, 182, 194, 199, 244 – in Dateinamen 68 Window-Manager 211, 212, 217, 218 – dtwm 221 – fvwm2 215, 220 – mwm 213 – twm 213 Working Directory 44, 64, 65, 68, 80, 92 – initiales 65 – wechseln 65
X X-Window – Resourcedateien 220 X/OPEN 34, 262 xdm 219 Xenix 28 XFree86-Projekt 215 XPG 34 xrdb 220 X-Server 210 Xsession 219 X-Window 209 – Konfiguration 217 – Screen 210 Z Zombies 136 Zugriffsrechte 45, 70 – SetGID Bit 366 – SetUID Bit 366 – Sticky Bit 366 Zugriffsrechte Verzeichnis 70 – Ausführen 71 – Lesen 70 – Schreiben 71
403
Copyright Daten, Texte, Design und Grafiken dieses eBooks, sowie die eventuell angebotenen eBook-Zusatzdaten sind urheberrechtlich geschützt. Dieses eBook stellen wir lediglich als Einzelplatz-Lizenz zur Verfügung! Jede andere Verwendung dieses eBooks oder zugehöriger Materialien und Informationen, einschliesslich der Reproduktion, der Weitergabe, des Weitervertriebs, der Platzierung im Internet, in Intranets, in Extranets anderen Websites, der Veränderung, des Weiterverkaufs und der Veröffentlichung bedarf der schriftlichen Genehmigung des Verlags. Bei Fragen zu diesem Thema wenden Sie sich bitte an: mailto:
[email protected]
Zusatzdaten Möglicherweise liegt dem gedruckten Buch eine CD-ROM mit Zusatzdaten bei. Die Zurverfügungstellung dieser Daten auf der Website ist eine freiwillige Leistung des Verlags. Der Rechtsweg ist ausgeschlossen.
Hinweis Dieses und andere eBooks können Sie rund um die Uhr und legal auf unserer Website
(http://www.informit.de) herunterladen