Windows 2003 Shell Scripting
Netzwerke, Betriebssysteme, Sicherheit ... hierzu bietet Ihnen die Reihe net.com umfassende, praxisnahe Information. Neben Fragen der Systemverwaltung greift sie auch Themen wie Protokolle, Technologien und Tools auf. Profitieren Sie bei Ihrer täglichen Arbeit vom Praxiswissen unserer erfahrenen Autoren.
Windows Server 2003 Eric Tierling 1312 Seiten, € 59,95 [D] ISBN 3-8273-2076-3 Ausführlich widmet sich dieses Buch allen wesentlichen Aspekten von Windows Server 2003 und all seiner Editionen. Active Directory, Gruppenrichtlinien, Windows NTDomänenupgrade, TCP/IP-Dienste und Sicherheitsmerkmale sind detailliert beschrieben, um Unternehmen einen optimalen Einsatz zu ermöglichen. Clustering mit Netzwerklastenausgleich und Clusterdienst, E-Mail-Server, Group Policy Management Console, Terminaldienste, Remotedesktop und Webverwaltung, Volumen-Schattenkopie sowie die Smartcard-Integration und sichere Wireless-LAN-Unterstützung stellen weitere Highlights dieses Buches dar.
Firewalls illustriert Jörg Fritsch, Steffen Gundel 320 Seiten, € 44,95 [D] ISBN 3-8273-2043-7 Der Titel ist Programm – mithilfe von weit mehr als 100 Abbildungen erläutern die Autoren den Aufbau einer Firewall. Sie fangen mit einfachen Access-Listen an, und erweitern den Aufbau der Firewall sukzessive, damit Sie genau nachvollziehen können, wie eine Firewall Ihr Netzwerk schützt und welches dafür die optimale Größe ist.
Holger Schwichtenberg
Windows 2003 Shell Scripting
eBook Die nicht autorisierte Weitergabe dieses eBooks ist eine Verletzung des Urheberrechts!
An imprint of Pearson Education München • Boston • San Francisco • Harlow, England Don Mills, Ontario • Sydney • Mexico City Madrid • Amsterdam
Bibliografische Information Der Deutschen Bibliothek Die Deutsche Bibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie; detaillierte bibliografische Daten sind im Internet über abrufbar.
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.
10 9 8 7 6 5 4 3 2 1 07 06 05 04 ISBN 3-8273-2178-6
© 2004 by Addison-Wesley Verlag, ein Imprint der Pearson Education Deutschland GmbH, Martin-Kollar-Straße 10–12, D-81829 München/Germany Alle Rechte vorbehalten Einbandgestaltung: atelier für gestaltung, niesner & huber, Wuppertal Lektorat: Sylvia Hasselbach,
[email protected] Korrektorat: Sandra Gottmann, Bonn Herstellung: Claudia Bäurle,
[email protected] Satz: mediaService, Siegen, www.media-service.tv Druck und Verarbeitung: Kösel, Krugzell (www.Koeselbuch.de) Printed in Germany
Inhaltsverzeichnis
1
Vorwort
13
Einleitung
15
1.1 1.2 1.3 1.4
15 15 16 17 17 17 18 18 19 19 20
1.5 1.6 2
Shell Basics
21
2.1 2.2 2.3 2.4
21 21 22 23 23 24 24 25 27 27 27 28 28 28 29 29 30 30
2.5
2.6
2.7
2.8 3
Warum dieses Buch? Wer sollte dieses Buch lesen? Buchgliederung Hinweise zum Buch 1.4.1 Die Windows-Versionen 1.4.2 Schriftarten und Layout 1.4.3 Syntaxkonventionen 1.4.4 Stil und Anrede 1.4.5 Weblinks, Warenzeichen Feedback, Download der Beispiele Danksagungen
Was bedeutet Shell? Grundlagen Shell Scripts oder Batch Files? Shell starten 2.4.1 Die Befehlserweiterungen Arbeiten mit der Kommandozeile 2.5.1 Befehle eingeben 2.5.2 Kommandotypen 2.5.3 Behandlung von Sonderzeichen Hilfe erhalten 2.6.1 Hilfe zu einzelnen Befehlen 2.6.2 Das Kommando help 2.6.3 Die Online-Hilfe Verzeichniswechseln 2.7.1 cd (chdir) 2.7.2 pushd/popd 2.7.3 Aktuelles Verzeichnis feststellen Wo ist command.com?
Shell-Konfiguration 3.0.1 3.0.2
Tastenkombinationen Startparameter
31 31 32
5
Inhaltsverzeichnis
3.1
3.2
3.3
4
43
4.1 4.2
43 43 43 45 46 46 46 47 48 49 49
Dateikanäle Dateiumleitung 4.2.1 Ausgabeumleitung 4.2.2 Eingabeumleitung 4.2.3 Umleitung und der Windows Script Host Datenübergabe und Filter 4.3.1 Das Prinzip 4.3.2 find 4.3.3 sort 4.3.4 more 4.3.5 clip
Dateien im Detail
51
5.1 5.2
51 53 53 54 55 58 59 60 60 61
5.3
6
34 34 35 36 36 36 36 37 38 38 38 38 38 39 39 39 39 39 40 41
Umleitung & Filter
4.3
5
Das Shell-Fenster einrichten 3.1.1 Optionen 3.1.2 Schriftart 3.1.3 Layout 3.1.4 Farben 3.1.5 Startverzeichnis 3.1.6 Integration in den Explorer Registry Keys 3.2.1 HKEY_LOCAL_MACHINE-Einträge 3.2.2 AutoRun 3.2.3 EnableExtensions 3.2.4 DelayedExpansion 3.2.5 CompletionChar 3.2.6 PathCompletionChar 3.2.7 DefaultColor 3.2.8 HKCU\Console Settings Laufzeitkonfiguration 3.3.1 color 3.3.2 Prompt 3.3.3 Title
Warum ist type unbrauchbar? NTFS Alternate Data Streams 5.2.1 Einführung 5.2.2 NTFS-Dateien 5.2.3 Erzeugen und Abfragen von ADS 5.2.4 Auflisten und Löschen von ADS 5.2.5 Verknüpfungen und ADS 5.2.6 Problemfeld Makro-Viren 5.2.7 Weitere Informationen Echte Links
Inhaltsverzeichnis
6
Umgebungsvariablen
63
6.1
63 63 63 64 65 65 66 68 69 70 71 75 75
6.2
7
Kommandoausführung
77
7.1
77 77 78 79 81 82 82 82 82 85 88
7.2 7.3 7.4
8
9
Grundlagen 6.1.1 Umgebungstypen 6.1.2 Auflisten von Variablen 6.1.3 Vordefinierte Variablen Arbeiten mit Variablen 6.2.1 Umgebungsvariablen mit set definieren 6.2.2 Arbeiten mit setx 6.2.3 Löschen von Variablen 6.2.4 Rechnen mit set (Option /a) 6.2.5 Eingaben mit set (Option /p) 6.2.6 Ausgabe von Variableninhalten 6.2.7 Die Variable errorlevel 6.2.8 setlocal & endlocal
Ausführbarkeit von Dateien 7.1.1 Ausführbare Dateien mit pathext definieren 7.1.2 assoc & ftype Das Kommando start Das Kommando runas Prozessverwaltung mit der Shell 7.4.1 tlist oder tasklist? 7.4.2 Prozessinformationen 7.4.3 tlist 7.4.4 tasklist 7.4.5 kill und taskkill
Befehlsverknüpfung
89
8.1 8.2 8.3 8.4
89 89 90 90
Mehrfachkommandos Der Operator && Der Operator || Befehlsgruppierung
Ablaufsteuerung 9.1
9.2
Bedingte Befehlsauführung 9.1.1 Grundlagen von if 9.1.2 Formen von if Das mächtige for 9.2.1 Grundlagen 9.2.2 Einfache Schleifen mit Werte- und Dateilisten 9.2.3 Variablenersetzung bei Schleifen 9.2.4 Schleifen für Verzeichnisse und Unterverzeichnisse 9.2.5 Zählschleifen 9.2.6 Lesen aus Dateien
93 93 93 94 96 97 97 99 102 103 103
7
Inhaltsverzeichnis
9.2.7 9.2.8 9.2.9
Parsing von Zeilen Backquoting Tipps & Tricks
10 Makros 10.1 Grundlagen 10.2 Arbeiten mit Makros 10.2.1 Definieren, ändern, löschen 10.2.2 Parameter für Makros 10.3 Makros für bestimmte Programme 10.4 Makros speichern & laden 10.5 Tastenkombinationen für doskey 11 Shell Scripts (Batches) 11.1 11.2
11.3
11.4
11.5
11.6
11.7
11.8
8
Einführung Batchfiles 11.2.1 Aufbau 11.2.2 Syntax 11.2.3 Kommentare in Batches 11.2.4 Parameter 11.2.5 Ausführen von Shell Scripts Parameterchecks 11.3.1 Anzahl und Art der Parameter 11.3.2 Mehr als neun Parameter mit shift 11.3.3 Flexible Parameterprüfung Ablaufsteuerung 11.4.1 Verzweigungen 11.4.2 Schleifen 11.4.3 Unterroutinen 11.4.4 Shell Scripts beenden Selbstaufruf 11.5.1 Aufruf mit call %0 11.5.2 Aufruf mit CALL :label Synchronisation 11.6.1 Warten auf Prozesse 11.6.2 Kommunikation von Batches Selbstmodifikation 11.7.1 Grundlagen 11.7.2 Beispiel Call-Logging 11.7.3 Code und Daten kombinieren Interaktion mit dem Benutzer 11.8.1 Ein- und Ausgabe 11.8.2 Systeminformationen / Warten
106 107 108 111 111 112 112 113 114 115 116 117 117 117 117 118 118 119 119 119 119 121 122 123 123 123 125 127 127 127 129 130 130 131 132 132 133 134 137 137 142
Inhaltsverzeichnis
12 Design von Shell Scripts 12.1 Brauchen Batches ein Design? 12.2 Parameter 12.2.1 Online-Hilfe 12.2.2 Sicherheitsabfragen 12.2.3 Anzahl und Reihenfolge 12.3 Ausgabegestaltung 12.4 Modularisierung 12.4.1 Zielbetriebssystem 12.4.2 Einzelskript oder mehrere Dateien 13 Erweiterungen 13.1 RunDLL32 13.1.1 Grundlagen & Einsatzmöglichkeiten 13.1.2 Beispiele für runDLL32 13.1.3 Druckerverwaltung per rundll32 13.1.4 Die Grenzen von RunDLL32 13.2 Zusätzliche Tools 13.2.1 Support Tools 13.2.2 Resource Kit 13.2.3 Services for Unix 13.2.4 Win32-Ports der GNU-Tools 13.2.5 Tools zum Buch 13.3 Reguläre Ausdrücke 13.3.1 Grundlagen 13.3.2 Die Stolpersteine 13.3.3 Beispiele mit findstr 14 WMI und die Kommandozeile 14.1 wmic – die WMI-Konsole 14.1.1 Grundlagen 14.1.2 Hilfe erhalten 14.1.3 Aliase auflisten 14.1.4 Erste Schritte 14.1.5 Beeinflussen der Ergebnismenge 14.1.6 Zyklische Abfragen 14.1.7 Aufrufen von Methoden 14.2 wmic-Schalter 14.2.1 AGGREGATE 14.2.2 APPEND 14.2.3 AUTHLEVEL 14.2.4 FAILFAST 14.2.5 IMPLEVEL 14.2.6 INTERACTIVE 14.2.7 LOCALE
145 145 146 146 146 146 147 148 148 148 151 151 151 152 154 156 157 157 157 157 158 158 158 158 160 161 163 163 163 164 164 167 170 172 173 173 174 174 174 174 175 175 175
9
Inhaltsverzeichnis
14.2.8 NAMESPACE 14.2.9 NODE 14.2.10 OUTPUT 14.2.11 PRIVILEGES 14.2.12 RECORD 14.2.13 ROLE 14.2.14 TRACE 14.2.15 USER / PASSWORD 14.3 Ausgabeformate 14.4 Systemverwaltung mit WMIC 15 Die Shell und der WSH 15.1 Der Windows Script Host 15.2 Installationschecks 15.2.1 How not to do it 15.2.2 Test durch WSH-Aufruf 15.2.3 Test durch Registry lesen 15.3 Datenaustausch Shell – WSH 15.4 Integration WSH / Shell 15.5 Weiterführende Literatur zum WSH 16 Shell Script-Beispiele 16.1 Vorbemerkung 16.2 Systemverwaltung 16.2.1 which 16.3 Dateiverwaltung 16.3.1 Welche Datei ist neuer? 16.3.2 GetWord 16.3.3 Insert 16.3.4 Delete 16.3.5 Reverse 16.3.6 Bulk Rename 16.3.7 Textdateien nummerieren 16.3.8 uniq (Duplikate entfernen) 16.4 ActiveDirectory 16.4.1 LDAP-Suchfilter 16.4.2 CSVDE 16.4.3 Benutzer aus Datei anlegen 16.4.4 LDIFDE 16.4.5 Benutzer-Account (de)aktivieren 16.4.6 dsquery 16.4.7 dsmod 16.4.8 dsget 16.4.9 dsmove 16.4.10 dsadd
10
175 175 175 175 176 176 176 176 177 178 181 181 182 183 183 184 184 185 188 189 189 189 189 190 190 190 192 193 195 196 197 198 199 200 201 204 205 211 212 215 218 220 221
Inhaltsverzeichnis
16.4.11 dsrm 16.4.12 Passwörter per ldifde ändern 16.4.13 Gruppenmitglieder auflisten 16.5 Netzwerk 16.5.1 Netzwerkadresse berechnen 16.5.2 GetMAC für NT4 und W2K 16.5.3 Pingliste 16.5.4 Portliste aus netstat 16.6 Die Tools zum Buch 16.6.1 BinChk 16.6.2 DispChg 16.6.3 MocWall 16.6.4 XEcho 17 Referenz 17.1 17.2 17.3 17.4
Shell-Kommandos Windows 2003 Support Tools Windows 2003 Resource Kit Informationen zu einzelnen Befehlen 17.4.1 Dateiverwaltung 17.4.2 Netzwerk 17.4.3 ActiveDirectory 17.4.4 Systemverwaltung 17.4.5 Monitoring/Prozessverwaltung
222 224 225 228 228 229 231 232 235 235 236 238 240 245 245 253 255 259 259 265 267 268 268
18 Ausblick
273
A
Anhang
275
A.1 A.2
275 276
Die Aufgaben vom Anfang Literatur
Stichwortverzeichnis
279
11
Inhaltsverzeichnis
12
Vorwort Microsoft Windows hat seinen Siegeszug nicht zuletzt der einfachen Bedienung über eine graphische Benutzeroberfläche zu verdanken. Diese Eigenschaft schätzen nicht nur Endbenutzer, sondern auch Administratoren, da sie durch die grafischen Werkzeuge viele Administrationsaufgaben intuitiv ohne Kenntnisse komplexer Befehle und Parameter realisieren können. Administratoren sind es aber auch, die oftmals die graphische Benutzeroberfläche von Windows als „KlickiBunti-Schnittstelle“ verfluchen, wenn wiederkehrende Aufgaben wie das Anlegen von Benutzerkonten zu Maus-Orgien werden. Die alten DOS-Befehle sind zwar auch heute in der Form der Eingabeaufforderung in Windows enthalten, doch hat es Microsoft lange versäumt, den Befehlsumfang entsprechend der ständigen Weiterentwicklung von Windows anzupassen. Seit Ende der 90er Jahre bietet Microsoft den Windows Script Host (WSH) als Basis für die befehlbasierte Administration an. Der WSH setzt jedoch eine Affinität zur (objektorientierten) Programmierung voraus, die viele WindowsAdministration nicht besitzen. Microsoft macht kein Geheimnis daraus, dass man im Zuge der Entwicklung des Windows Server 2003 einigen Unix-Administratoren über die Schulter geschaut hat, um Ideen für die Verbesserung des befehlsbasierten Administration zusammeln. Die Erkenntnisse aus dieser Studie manifestieren sich in einer Vielzahl neuer Kommandozeilenwerkzeuge im Windows Server 2003. Armin Hanisch greift in seinem Buch „Windows Server 2003 Shell Scripting“ die traditionellen Shell-Befehle ebenso wie die neuen Funktionen der Kommandozeile auf, um daraus ein umfassendes Bild für die Verwaltung von Windows durch Kommandozeile und Batchdateien zu zeichnen. Er dokumentiert nicht nur die in der Standardinstallation von Windows Server 2003 enthaltenen Werkzeuge, sondern auch die Windows Server 2003 Support Tools und die Windows Server 2003 Resource Kit Tools. Dabei hat Herr Hanisch auch mich überrascht mit vielen Funktionsdetails, die ich bisher nur mit dem WSH für möglich hielt. „Windows Server 2003 Shell Scripting“ ist ein sehr empfehlenswertes Buch für alle, die eine automatisierte Administration von Windows mit den vergleichsweise einfachen Shell-Befehlen und ohne umfassende Programmierkenntnisse anstreben. Herr Hanisch zeigt anschaulich die Möglichkeiten und auch die Grenzen der Shell-Befehle auf. Dr. Holger Schwichtenberg Softwarearchitekt, Buchautor und Dozent Essen, im August 2004
13
1 1.1
Einleitung
Warum dieses Buch?
Möglicherweise stehen Sie in diesem Moment in einer Buchhandlung und blättern gerade die ersten Seiten dieses Buches durch. Vielleicht fragen Sie sich: „Soll ich das Buch kaufen, vermittelt es mir Informationen, die mir helfen, Zeit zu sparen oder Arbeitsabläufe zu automatisieren“? Dieses Buch soll Ihnen helfen, Zeit bei der Arbeit mit Windows 200X zu sparen, ohne programmieren lernen zu müssen. Das vorliegende Buch entstand aus der täglichen Praxis bei meiner Tätigkeit als Consultant und Trainer im Bereich Windows-Server. In den offiziellen Trainingshandbüchern finden sich keine Hinweise, wie viel Arbeit sich ein Administrator durch effiziente Nutzung der Shell sparen kann. Hier finden Sie diese Hinweise; egal, ob Sie Dateien kopieren, Konten im ActiveDirectory bearbeiten oder Prozesse überwachen. Sie hätten gerne einige Beispiele, warum die Shell von Windows Ihr Freund ist? Überlegen Sie sich an dieser Stelle einmal, welche und wie viele GUI-Aktionen zur Lösung der Aufgabe nötig wären. 왘 Kopieren Sie alle .log- und .rpt-Dateien aus dem Stammverzeich-
nis der Rechner von 192.168.1.1 bis 192.168.1.20 in das Verzeichnis logs des Laufwerks C: Ihrer Maschine. 왘 Finden Sie alle exe-Dateien in system32, die eine gleichnamige
DLL besitzen. 왘 Welche Dateitypen hat der Internet Explorer auf Ihrem System für
sich registriert? 왘 Benennen Sie alle .jpg-Dateien im Ordner c:\fotos so um, dass
diese Dateien aufsteigend nummerisch umbenannt werden. 왘 Welche Dateien in Ihrem Verzeichnis source wurden im letzten
Monat geändert? Wie groß sind diese Dateien alle zusammen? (Die Antworten finden Sie übrigens im Anhang.)
1.2
Wer sollte dieses Buch lesen?
Wenn Sie als Administrator(in) im Bereich Windows (ab Windows 2000) tätig sind, werden Sie von diesem Buch profitieren. Es vermittelt Ihnen als erstes deutschsprachiges Werk einen Gesamtüberblick über die Möglichkeiten (und Grenzen) der Windows Shell. Sie erfahren, wie Sie die Arbeiten schneller erledigen und Aufgaben automati-
15
1 Einleitung
sieren. Im Gegensatz zum Windows Script Host müssen Sie nicht programmieren können, um die Möglichkeiten der Shell zu nutzen, die Lernkurve ist also viel flacher. Die zweite Gruppe, denen das Buch bei der Arbeit helfen wird, sind die so genannten „Power User“, seien es Entwickler oder Profis im Bereich Microsoft Office. Hier erfahren Sie, wie Sie Aufgaben im Bereich Dateimanagement schneller erledigen, eigene Befehle erstellen und Tausende von Mausklicks durch wiederholbare Shell Scripts sparen. Sie erhalten Hinweise zur Lösung von immer wieder anfallenden Problemstellungen und erfahren, welche zusätzlichen, freien Tools verfügbar sind. Sie programmieren nicht und administrieren hauptsächlich keine Windows-Server, sondern Unix, Linux, VMS oder andere? Dann erhalten Sie hier einen detaillierten Einblick für Umsteiger in die Windows Shell. Sie erfahren, welche Konzepte aus anderen Systemen übernommen wurden; wie und ob Sie Shell Scripts von Ihrem System nach Windows übernehmen können und welche Tools bereits für Sie verfügbar sind. Aber auch wenn Sie regelmäßig mehrere Systeme überwachen müssen, automatisierte Setups für mehr als ein Betriebssystem auf verschiedenen Hardware-Plattformen bereitstellen müssen, finden Sie hier Lösungen.
1.3
Buchgliederung
Dieses Buch ist in drei Abschnitte gegliedert. Im ersten Abschnitt stelle ich Ihnen die grundlegenden Konzepte der Shell vor. Dort erfahren Sie alles über die Themen Ein-/Ausgabeumleitung, Ablaufsteuerung, Prozessverwaltung. Makros und andere Bereiche. Im zweiten Abschnitt dreht sich alles um das Thema Shell Scripts (Batch Files), von den Grundlagen bis hin zu selbstmodifizierenden Scripts. Dieser Abschnitt enthält auch eine Reihe von Shell Scripts, die komplett dokumentiert sind und Aufgabenstellungen aus der Praxis lösen. Hier lernen Sie, wie an solche Probleme heranzugehen ist und welche Alternativmöglichkeiten der Lösung bestehen. Der dritte Teil ist eine Mischung aus Referenz und Tipps zu den einzelnen Kommandos der Windows Shell. Sie erhalten eine kompakte Liste aller Kommandos mit einer Zeile pro Befehl sowie zu ausgewählten Kommandos ausführlichere Erläuterungen und Hinweise zur optimalen Nutzung.
16
Hinweise zum Buch
1.4
Hinweise zum Buch
1.4.1
Die Windows-Versionen
Das Buch trägt zwar den Titel „Windows 2003 Shell Scripting“, einen Großteil der hier zu findenden Informationen können Sie ohne weiteres auch in Windows 2000 oder Windows XP anwenden. Im dritten Teil des Buches finden Sie eine Kurzliste der Befehle, aus der Sie entnehmen können, ab welcher Windows-Version ein Kommando zum Standardumfang der Shell gehört. Für einige komplexere Themen finden Sie in den jeweiligen Kapiteln auch eine Beschreibung, wie sich die gleiche Funktionalität auch vor Windows 2003 realisieren lässt. Viele Kommandos sind auch in den früheren Versionen schon über Updates, Resource Kits oder Entwicklungen von Drittherstellern verfügbar, die Basis des Buches bildet aber der Befehlssatz für die Shell, wie er seit Windows 2003 (in der Standardinstallation plus den Support Tools) verfügbar ist.
1.4.2
Schriftarten und Layout
Alle im Fließtext vorkommenden Befehle sind in einer eigenen Schriftart gesetzt. So können Sie Kommandos wie cls oder tracert leicht identifizieren. Einträge in Menüs wie DATEI / SPEICHERN oder EIGENSCHAFTEN werden ebenfalls besonders hervorgehoben. Sollten Sie Tastenkombinationen im Fließtext finden, sehen diese so aus: Drücken Sie (Entf) oder (Strg)+(A). Besonders wichtige Informationen oder potenziell gefährliche Befehle sind mit diesem Icon hervorgehoben.
So sind Hinweise und Bemerkungen zu einzelnen Befehlen oder für bestimmte Windows-Versionen gekennzeichnet Alle Listings und interaktiven Kommandos in diesem Buch sind so gesetzt, dass eine Listingzeile mit einer Zeilenschaltung abgeschlossen wird, wie das Beispiel unten zeigt. echo zeile 1 echo Zeile 2
Sollte eine Zeile länger sein als die Zeilenbreite des Buchlayouts erlaubt, dann finden Sie in der Marginalspalte einen Hinweis, dass es sich um eine logische Eingabezeile handelt.
17
1 Einleitung Eine Zeile
tasklist /fo list /fi "username ne NT AUTHORITY\*" | find /i "Image name:"
Bei längeren Auflistungen von Kommandos, die länger als eine Zeile sind, finden Sie den Hinweise im laufenden Text.
1.4.3
Syntaxkonventionen
Ein Kommando der Windows Shell besteht in der Regel aus dem Kommando selbst sowie einer mehr oder weniger langen Reihe möglicher Optionen und Parameter. Alle optionalen Angaben werden in eckige Klammern eingeschlossen: kommando [/S]
Das bedeutet, dass die Option /S auch weggelassen werden kann. Alle Platzhalter für Dateinamen, Suchstrings und andere Informationen werden durch einen symbolischen Namen in spitzen Klammern ersetzt. kommando
Das bedeutet die Angabe des Dateinamens nach dem Kommando. Ist die Angabe optional, wird der Platzhalter wie oben in eckige Klammern gesetzt: kommando [ ]
Alternativen sind durch einen senkrechten Strich voneinander getrennt: kommando [ /T "user" | "system" ]
Das bedeutet, dass Sie nach der Option /T entweder "user" oder "system" angeben müssen oder die Option komplett weglassen.
1.4.4
Stil und Anrede
Ich habe in diesem Buch versucht, die Windows Shell und ihre Möglichkeiten so zu beschreiben, dass Sie als Leser möglichst viel Nutzen davon haben. Das Thema selbst ist schon technisch genug, daher wollte ich nicht noch bei Stil und Anrede dafür sorgen, dass beim Lesen der Staub aufsteigt. Einige Anmerkungen und Kommentare geben nur meine persönliche Meinung wieder. So weit als möglich habe ich diese in Fußnoten gefasst, um den Lesefluss nicht stören. Die gerade aktuelle Mode, möglichst in jeder zweiten Zeile einen Marginaltext zu verfassen, habe ich aus Gründen der Lesbarkeit vermieden. Falls Sie also eine Randbemerkung oder ein Icon finden, ist es an dieser Stelle auch angebracht.
18
Feedback, Download der Beispiele
Üblicherweise benutze ich im Buch zwar die männliche Anrede, dies allerdings nur aus Gründen der Lesbarkeit. Dieses Buch ist nicht geschlechtsspezifisch. Einige der besten und kreativsten Leute im Bereich der Softwareentwicklung sind Frauen (fast alle meine Assembler-Kenntnisse stammen von einer netten Studienkollegin). Vielleicht würde manche Software und mancher Server besser laufen, wenn wir einen höheren Frauenanteil in der Branche hätten. Ich denke aber nicht, das ein Konstrukt wie „der/die Administrator(In)“ in Büchern besser lesbar ist.
1.4.5
Weblinks, Warenzeichen
Die in diesen Unterlagen enthaltenen Daten und Angaben, einschließlich URLs und anderer Verweise, können sich mit vorheriger Ankündigung ändern. Auf die Verfügbarkeit externer Weblinks sowie die dort bereitgestellten Inhalte hat der Autor keinen Einfluss und gibt diese Daten ohne Gewähr oder Haftung und rein zu Zwecken der Information an. Alle in diesen Unterlagen aufgeführten Produkt- und Firmennamen sind unter Umständen Marken oder geschützte Zeichen der einzelnen Firmen. Die Verwendung von Namen ohne eine entsprechende Kennzeichnung bedeutet nicht, dass diese Namen und Bezeichnungen frei von Schutzrechten sind. Microsoft, MS-DOS, Windows, Windows NT, ActiveDirectory, Windows 2000, Windows XP, Windows 2003, VBScript und Windows Script Host sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern.
1.5
Feedback, Download der Beispiele
Ich freue mich über Feedback zu diesem Buch, Fehlerhinweise und Vorschläge für Ergänzungen. Bitte senden Sie diese per E-Mail an die Adresse
[email protected] oder per normaler Post an den Verlag. Die Beispiele und Tools, die in diesem Buch verwendet werden, finden Sie auf der Homepage des Autors. Die URL für die Seiten zum Buch lautet http://www.ArminHanisch.de/books/shellbook.html. Haben Sie bitte Verständnis dafür, dass ich nicht jedes zweizeilige Kommando in das Archiv gepackt habe; der Download bedeutete mehr Arbeit als das eigene Eintippen. Alle Beispielcodes und die Tools sind Freeware. Die Scripts dürfen von Ihnen benutzt, verändert und an eigene Anforderungen angepasst werden. Für alle Scripts und Programme gilt, dass trotz sorgfältiger Prüfung keine Garantie für die
19
1 Einleitung
Funktion in einer bestimmten Systemkonfiguration übernommen werden kann. Die Benutzung erfolgt auf Ihr eigenes Risiko. Alles, was ich garantiere, ist die Tatsache, dass die Programme und Scripts Platz auf Ihrem Datenträger belegen werden. Insbesondere weise ich darauf hin, dass diese Shell Scripts und die Programme für die Benutzung durch erfahrene Anwender und Administratoren gedacht sind. Ich übernehme keine Verantwortung für Schäden oder Datenverlust, die aus dem unsachgemäßen Einsatz von Programmen, Scripts und Listings aus diesem Buch resultieren.
1.6
Danksagungen
Ohne meinen Vater Winfried würde es dieses Buch sicher nicht geben. Er hat mir die Faszination des Amateurfunks gezeigt und mich 1979 auf die Ham-Radio am Bodensee mitgenommen. Dort war dann ein PET 2001 interessanter als alle Kurzwellengeräte. Dies war der Anfang von allem. Kein Buch wird vom Autor alleine geschrieben. Auch zum Gelingen dieses Buches haben viele Leute beigetragen, die mich unterstützten, mit Ideen versorgten, antrieben und ihre Meinung und wertvolle Anregungen einfließen ließen. Ein besonderes Dankeschön allen Seminarteilnehmern meiner Shell-Kurse, die mich immer wieder aufforderten, meine Erfahrungen als Buch zu veröffentlichen. Viele Anregungen stammen aus den Kursen und aus Support Scripts zu Kundenprojekten. Besonders bedanken möchte ich mich beim Verlagsteam von AddisonWesley, insbesondere bei Sylvia Hasselbach für die professionelle Betreuung und bei Sandra Gottmann für das Korrektorat. Dank auch an die „Beta-Leser“, Freunde und Kollegen, die trotz Familie, Projekten, Gartenarbeit und eigenen Verpflichtungen Zeit fanden, das Manuskript Probe zu lesen. Vor allem haben Michael Schad, Alexander Tihme und Heinz Fischer zum Gelingen dieses Buches beigetragen. Besonders bedanken möchte ich mich auch bei Dr. Holger Schwichtenberg für das Fachlektorat und die einleitenden Worte zum Buch. Den meisten Dank schulde ich meiner Frau Andrea, die auch dieses Mal wieder mit großer Geduld, Espresso und liebevollen Nackenmassagen dafür gesorgt hat, dass ich nie die Lust am Schreiben verloren habe.
20
2 2.1
Shell Basics
Was bedeutet Shell?
Der Ausdruck shell stammt aus den 70er-Jahren, als die ersten Time Sharing-Rechner erschienen, an denen interaktiv gearbeitet werden konnte. Er trifft mit seiner wörtlichen Übersetzung „Muschel“ den Kern der Sache recht genau. Eine Shell ist das Programm, über das ein Benutzer mit dem System kommuniziert. Ein Synonym im Deutschen ist Kommandoprozessor oder Kommandointerpreter. Da sich ein solches Programm logisch gesehen „über“ bzw. „um“ das System legt und wie eine Muschel die Perle umschließt, wird das Programm zum Starten und Verwalten von Programmen, dem Dateimanagement und anderen Sachen eben Shell genannt. Das Programm, das unter Windows beim Start einer Benutzersitzung automatisch geladen wird, ist der Windows Explorer. Dieses GUIProgramm bietet aber keine Möglichkeit der direkten Kommandoeingabe. Obwohl theoretisch auch der Kommandoprozessor cmd.exe direkt nach dem Login geladen werden könnte, ist dies (noch) nicht praktikabel, da unter Windows einige Funktionen nur über das GUI erreichbar sind. Daher wird cmd.exe wohl in den meisten Fällen nach dem Login durch den Benutzer oder über die Autostart-Funktion aktiviert werden. Wenn in diesem Buch der Ausdruck „Shell“ verwendet wird, ist also immer cmd.exe gemeint. Im Gegensatz zu Unix wird bei Windows nach der Installation keine alternative Shell mitgeliefert, die anstelle von cmd.exe benutzt werden könnte. Es gibt aber eine ganze Reihe von Herstellern, die Programme zu diesem Zweck anbieten oder Shells aus der Unix-Welt nach Windows portiert haben. Alle Beispiele und Scripts in diesem Buch können mit der Standard-Shell cmd.exe durchgeführt werden. Für eine Arbeitszeit sparende Systemverwaltung über die Kommandozeile sind also keine besonderen Installationen notwendig.
2.2
Grundlagen
Warum die Shell nutzen? Heute sind moderne Betriebssysteme doch intuitiv über eine grafische Oberfläche bedienbar, niemand muss sich mehr irgendwelche Optionen merken, alles wird einfach per Mausklick an die richtige Stelle geschoben – oder?
21
2 Shell Basics
Für den Anwender mag dies zutreffen. Es gibt allerdings zwei große Gruppen, die heute und auch in Zukunft komplexere Kommandos ausführen müssen: Administratoren und Softwareentwickler. Sie werden täglich damit konfrontiert, schnell und flexibel spezialisierte Operationen mit Prozessen und Dateien durchführen zu müssen, einer Aufgabe, für die eine grafische Oberfläche nur bedingt geeignet ist. Warum dann cmd? Sicherlich existiert mittlerweile eine ganze Reihe guter Portierungen von Unix-Software für die Windows-Plattform, gerade auch im ToolBereich. Als Beispiel unter vielen sei die cygwin-Distribution genannt, die neben der von Unix bekannten bash („bourne again shell“) weit über 100 Unix-Kommandos mitbringt. Es existiert aber auch eine Reihe nativer Win32-Ports der GNU-Shell Utilities, die außer der Visual C++Laufzeitbibliothek keine weitere Installation benötigen und somit auf einem Client ohne Installation über eine Serverfreigabe aufgerufen werden können. Dennoch ist für die meisten Aufgabenstellungen heute keine weitere Software mehr nötig als die Windows Shell cmd.exe und evtl. noch die Kommandos aus den Support-Tools und dem Resource Kit. Gerade bei Windows 2003 steht also einer kommandozeilenorientierten Verwaltung der Maschine immer weniger im Weg.
2.3
Shell Scripts oder Batch Files?
Nicht alle Aufgaben können mit einem einzigen Kommando auf der Befehlszeile erledigt werden. Daher ist wie auch bei Windows eine Möglichkeit vorhanden, mehrere Kommandos in einer Datei zusammenzufassen und diese zusammen ablaufen zu lassen. Während die Unix-Leute bei dieser Möglichkeit von so genannten Shell Scripts sprechen, hat sich in Windows der Ausdruck Batch Files eingebürgert. Gemeint ist in beiden Fällen das Gleiche: eine Reihe von Kommandos, die in einer Datei gespeichert ist, die durch die Angabe ihres Dateinamens gestartet und ausgeführt wird. Auch hier im Buch wird Shell Script und Batch File synonym verwendet. Weitere Begriffe mit der gleichen Bedeutung sind Stapeldatei, Shell-Prozedur, Batch oder einfach (und ungenau) nur Script. Der Ausdruck Windows-Script oder VB-Script bezeichnet etwas anderes, nämlich eine Befehlsdatei für den Windows Script Host. Mit mehreren Sprachen und mehr Funktionen für Systemaufrufe ausgestattet, spricht der WSH eher die Programmierer unter den Administratoren an. Wie überall in der IT wird mehr Funktionalität mit einer steileren Lernkurve erkauft, bietet dann aber auch mehr Möglichkeiten der Problemlösung. Daher ist die Frage nicht entweder Shell Scripts oder Windows Script Host, sondern beide ergänzen sich ideal. So weit für den Einstieg, in Kapitel 15 („Die Shell und der WSH“) gehe ich im Detail auf die Frage „Shell, WSH oder beide?“ ein.
22
Shell starten
2.4
Shell starten
Für das von cmd.exe bereitgestellte Befehlsfenster existiert eine ganze Reihe synonymer Bezeichnungen. Ganz gleich, ob in der Literatur von der Eingabeaufforderung, dem Shell-Fenster, dem DOS-Fenster, dem englischen console window oder dem Konsolenfenster die Rede ist – alle bezeichnen das gleiche Objekt. Ich habe mich im Buch bemüht, möglichst immer den Begriff Shell-Fenster bzw. Shell zu verwenden. Sollte trotzdem einmal eine Bezeichnung aus der obigen Liste auftauchen, wissen Sie nun, dass es mein Fehler war und ich dennoch von cmd.exe und seinem Fenster schreibe. Jeder Administrator, Entwickler oder Power User sollte mindestens ein Shell-Fenster offen haben, da viele Sachen damit leichter von der Hand gehen. Beim Starten einer Instanz der Shell haben Sie eine ganze Reihe von Möglichkeiten, Optionen anzugeben, welche das Verhalten von cmd.exe genauer steuern. Eine der einfachsten Möglichkeiten, an ein Shell-Fenster zu kommen, ist die Benutzung der Tastenkombination (ÿ)+(R) (oder dem Klick auf die Schaltfläche START und dann AUSFÜHREN). In der erscheinenden Dialogfläche geben Sie cmd ein, und drücken Sie die Eingabetaste. Als Ergebnis erhalten Sie ein Shell-Fenster.
2.4.1
Die Befehlserweiterungen
Viele Befehle der Shell existieren bereits seit der IT-Steinzeit, also seit MS-DOS 2.x, und dürfen daher aus Gründen der Abwärtskompatibilität eigentlich nicht in ihrer Funktion verändert werden. Aus diesem Grund hat Microsoft das Konzept der erweiterten Möglichkeiten für den Befehlsprozessor eingeführt. Dies sind Aktualisierungen an vielen Kommandos, die per Default bei der Shell aktiviert sind (und ohne guten Grund auch nicht deaktiviert werden sollten, da Sie viel an Funktionalität einbüßen). Da die Shell mit jeder Windows-Version seit Windows NT 4 deutlich erweitert wurde, existieren verschiedene Versionen dieser Erweiterungen. Bei NT4 war dies die Version 1, bei Windows 2000 die Version 2 usw., daher existiert eine automatisch belegte Umgebungsvariable (s. Abschnitt 6.1.3), mit der festgestellt werden kann, welche Version der Befehlserweiterungen aktiv sind. Sind die Befehlserweiterungen der Shell nicht aktiv, existiert diese Variable nicht. Für Windows 2000 liefert die Abfrage folgende Ausgabe: c:\tmp>echo %CMDEXTVERSION% 2
Für sämtlichen Code in diesem Buch wird davon ausgegangen, dass die Befehlserweiterungen wie nach einer Standardinstallation aktiviert sind.
23
2 Shell Basics
2.5
Arbeiten mit der Kommandozeile
2.5.1
Befehle eingeben
Was Sie nach dem Start des Shell-Fensters vor sich haben, sieht ungefähr so aus wie die folgende Abbildung (grafisch gesehen eher langweilig): Abbildung 2.1: Das Shell-Fenster in seiner ganzen Pracht
Die Angabe vor dem blinkenden Cursor ist die Systemmeldung (engl. prompt), die ohne Veränderungen einfach aus dem aktuellen Verzeichnis, gefolgt von einem Größer-Zeichen, besteht. Im nächsten Kapitel erfahren Sie, wie Sie diese Meldung verändern können. Nach dem Größer-Zeichen beginnt die Eingabezeile für Kommandos. Diese Kommandos können ab Windows 2000 bis zu etwa 2000 Zeichen lang sein, so dass auch längere Pfadangaben oder komplexe Kommandos kein Problem darstellen. Wollen Sie ein eingegebenes Kommando ausführen lassen, drücken Sie einfach die Eingabetaste. Das Kommando wird ausgeführt, etwaige Ausgabe werden im Shell-Fenster ausgegeben, danach erscheint wieder die Systemmeldung, und Sie können das nächste Kommando eingeben. Die folgende Bildschirmausgabe zeigt dies (alle Eingaben sind fett markiert und wurden mit der Eingabetaste (Enter) abgeschlossen):
24
Arbeiten mit der Kommandozeile c:\tmp> time /t 18:31 c:\tmp> dir test.* Datenträger in Laufwerk C: ist Lokaler Datenträger Datenträgernummer: 8C11-3AFE Verzeichnis von C:\tmp 24.02.2004 20.12.2003
23:40 80 test.htm 00:56 160 test.reg 2 Datei(en) 240 Bytes 0 Verzeichnis(se), 2.960.219.648 Bytes frei c:\tmp>exit
Das Kommando exit beendet übrigens die aktuelle Shell und schließt Shell verlassen das Fenster wieder. Alle Eingaben müssen in einer logischen Zeile erfolgen. Dies bedeutet, dass eine Eingabe zwar durchaus länger werden kann als die Breite des Fenster und dann auch in die nächste Zeile umbrochen wird, trotzdem aber als eine Eingabezeile definiert wird. Während der Eingabe haben Sie natürlich eine Reihe von Bearbeitungsmöglichkeiten, die über das simple Verbessern mit Hilfe der Korrekturtaste weit hinausgehen. Im Abschnitt 3.0.1 erfahren Sie mehr über die verfügbaren Tastenkombinationen. Ein gerade laufendes Kommando kann in seiner Ausführung in der Abbrechen Regel abgebrochen werden. Angenommen, Sie bemerken, dass Sie die IP-Adresse für einen ping falsch angegeben haben. Mit Hilfe der Tastenkombination (Strg)+(C) oder (Strg)+(UntBr) (bzw. (Ctrl)+(Break) bei US-Tastaturen) wird das laufende Kommando beendet. In der Ausgabe erscheint als Hinweis auf den Abbruch die Zeichenfolge ^C.
2.5.2
Kommandotypen
Aus historischen Gründen (und auch im Sinne der Erweiterbarkeit) ist die Shell kein monolithischer Block. Nicht die gesamte Funktionalität steckt in cmd.exe, sondern nur die so genannten internen Kommandos. Dies sind Befehle, für die keine ausführbare Datei vorliegt, sondern die tatsächlich in cmd.exe enthalten sind (copy, dir, cd etc.). Diese Befehle umfassen die wichtigsten Kommandos für die tägliche Dateiverwaltung des Systems1. Als externe Kommandos werden alle Befehle der Shell bezeichnet, die auch in Form von Programmen oder Skripten (meist im System321
Seinen Ursprung hat dies in uralten DOS-Zeiten. Der Befehlsinterpreter sollte damals möglichst viel Funktionalität ohne Nachladen externer Programme von der Diskette beinhalten, aber auch nicht zu viel Speicher für selten benötigte Kommandos belegen.
25
2 Shell Basics
Verzeichnis) vorliegen. Dazu gehört die Mehrzahl der Befehle, von Kleinigkeiten wie find bis hin zu größeren und komplexeren Kommandos wie dsquery. 2
Die allgemeine Syntax eines Kommandos folgt prinzipiell dem unten stehenden Schema: <parameter>
Prinzipiell deshalb, weil im gesamten Windows-Bereich wohl kaum etwas Inkonsistenteres existiert als die Syntax der Windows Shell. Dies hat seinen Ursprung in der Entwicklung der Shell, weshalb ich an dieser Stelle etwas weiter ausholen möchte. Falls Sie also gerade keine ruhigen fünf Minuten haben, blättern Sie weiter, und lesen Sie diesen Abschnitt später … Auch die Shell von Windows 2003 hat ihren Ursprung in der Kommandozeile von MS-DOS. Und für die Shell von MS-DOS hatte man sich an CP/M orientiert. Da MS-DOS zu dieser Zeit (Version 1.x) noch kein hierarchisches Dateisystem hatte (jawohl, keine Unterverzeichnisse!), benötigte man auch kein Zeichen als Trennzeichen für einen Dateipfad. Was aber benötigt wurde, war ein Zeichen, mit dem eine Option gekennzeichnet wurde (um beispielsweise bei der Ausgabe einer Datei anzugeben, dass die Ausgabe nummeriert erfolgen soll). Die heute in Windows so übliche Variante mit dem Vorwärtsschrägstrich („/“) ist zu dieser Zeit entstanden. In CP/M gab es kein einheitliches Zeichen für eine Befehlsoption. Einige Kommandos nutzten das Dollarzeichen, einige andere gaben die Optionen in eckigen Klammern an, und einige benutzten den Schrägstrich2. Die damals von Microsoft für CP/M produzierten Entwicklertools nutzten allerdings alle den Schrägstrich für die Optionskennzeichnung. Es folgt der Auftritt von MS-DOS 2.x und eines hierarchischen Dateisystems mit Unterverzeichnissen. Das Thema Schrägstrich wie bei Unix war mit der Einführung dieses Zeichens für die Optionen vom Tisch. Blieb also nur ein anderes Zeichen. Dies war, weil auf US-Tastaturen leicht erreichbar, der Backslash („\“). Bis zu MS-DOS 5 existierte allerdings in der Datei config.sys ein kaum bekannter Schalter mit dem Namen SWITCHAR, der das Zeichen für Optionen (engl. switches) definierte. Eine weitere Auswirkung dieser Entscheidungen war die Wahl des Zeichens „^“ als Escape-Zeichen für die Kommandozeile (wie in echo 4 ^> 2), da der Backslash ja schon vergeben war.
2
26
Etwas Stöbern in meinen fossilen EDV-Büchern sowie bei Google brachten die Erkenntnis, dass Digital Research bei CP/M damals von TOPS, einem Betriebssystem für die PDP-Rechner, von DEC inspiriert wurde (und VMS benutzt heute noch den Schrägstrich für Optionen).
Hilfe erhalten
Mit zunehmender Funktionalität im Netzwerkbereich wurden einige Kommandos aus diesem Bereich nach DOS (und auch Windows) portiert, beispielsweise das altbekannte ping oder auch tracert, arp und alle anderen. Diese Kommandos stammen aber historisch aus dem BSD-Unix von Berkeley. Dort war schon immer das Minuszeichen die Kennung für Optionen (der Schrägstrich trennt dort ja einzelne Verzeichnisse). Aus diesem Grund verwenden alle TCP/IP-orientierten Kommandos auch in Windows 2003 noch das Minuszeichen für die Optionen. Auch die Reihenfolge Parameter und Option orientiert sich für die Netzwerkbefehle an Unix: Zuerst kommen eventuelle Optionen, danach Parameter wie Dateiname oder IP-Adresse. In Windows werden zuerst die Parameter angegeben, gefolgt von eventuellen Optionen. Um die Verwirrung komplett zu machen, hat Microsoft bei einigen neuen Shell-Kommandos begonnen, ebenfalls die Optionen vor die Parameter zu stellen. Als Resümee dieses Exkurses bleibt nur die Tatsache, dass es eben kein in sich logisches Schema für den Aufbau eines Windows Shell-Kommandos gibt und Sie im Zweifelsfall /? und, wenn dies nicht klappt, -? versuchen sollten.
2.5.3
Behandlung von Sonderzeichen
Wann immer Sie ein Zeichen mit einer besonderen Bedeutung als reinen Text eingeben möchten, müssen Sie dieses Zeichen entsprechend kennzeichnen (im Fachjargon quoten). Dafür wird ein ebenfalls ein besonderes Zeichen (ein so genanntes Escape-Zeichen) benutzt. Das Escape-Zeichen für die Shell ist das Zeichen ^ (zur Geschichte siehe den letzten Abschnitt), z.B. bei ECHO ^. So lassen sich sogar XML-Dateien notfalls per Shell erzeugen … Diese Kennzeichnung ist später auch bei allen anderen Operatoren und vor allem beim Backquoting (Abschnitt 9.2.8) notwendig. Falls Sie ein „^“ ausgeben wollen, verdoppeln Sie das Zeichen einfach.
2.6
Hilfe erhalten
2.6.1
Hilfe zu einzelnen Befehlen
Mittlerweise hat Microsoft versucht, die Kommandos der Shell so weit wie möglich zu vereinheitlichen. Dies bedeutet auch, dass nun für jedes Kommando eine Beschreibung der Syntax und ein kleiner Hilfetext abrufbar ist. Dazu rufen Sie das entsprechende Kommando mit der Option /? auf.
27
2 Shell Basics
Einzige Ausnahme: die Befehle aus dem Netzwerkbereich, die historisch alle der Unix-Welt entstammen. Hier ist das Optionszeichen das Minuszeichen, daher gilt für ping und Konsorten der Aufruf mit -?.
2.6.2
Das Kommando help
In der Shell existiert ein Kommando mit dem Namen help, dass Sie entweder ohne Parameter oder mit dem Namen eines Kommandos aufrufen können. Ohne Parameter erhalten Sie eine lange Liste aller internen Kommandos der Shell. Geben Sie ein Kommando aus dieser Liste als Parameter an, erhalten Sie die Online-Hilfe zu diesem Kommando. Toll, wo ist dann das Problem? Ganz einfach: help gibt eine unvollständige Liste der Kommandos aus, nicht alle verfügbaren Befehle für die Shell sind dort enthalten. Insbesondere fehlen die meisten Netzwerkkommandos (von ping über nbtstat bis arp). Daher können Sie sich für eine Liste der Kommandozeilenprogramme nicht allein auf help verlassen.
2.6.3
Die Online-Hilfe
Die Online-Hilfe aus dem Help and Support Center enthält nicht nur eine vollständige Auflistung aller Befehle, die für die Shell zur Verfügung stehen, sondern auch Hinweise, Erläuterungen und Beispiele. Alle Unix-Umsteiger, die an man gewohnt sind, müssen hier also doch auf eine GUI-Anwendung umsteigen … Im Gegensatz zur landläufigen Meinung ist diese Hilfe zur Kommandozeile wesentlich besser als ihr Ruf. Sie enthält neben der reinen Referenz auch grundlegende Informationen und viele Beispiele sowie versteckte Tipps, die wirklich Zeit sparen. Lassen Sie die Hilfe also nicht einfach links liegen.
2.7
Verzeichniswechseln
Bei der Arbeit mit dem Shell-Fenster beziehen sich alle Kommandos, die Sie ohne Pfad eingeben, auf das aktuelle Verzeichnis. Dies ist die in der Systemmeldung angegebene Kombination aus Laufwerk und Pfad. Aus diesem Grund ist dieses auch in der Systemmeldung enthalten. Möchten Sie in einem anderen Verzeichnis weiterarbeiten, müssen Sie erst dorthin wechseln. Dies geschieht entweder über die Eingabe des Laufwerksbuchstabens, gefolgt von einem Doppelpunkt und der Eingabetaste, oder über eines der unten erläuterten Kommandos zum Wechsel des aktuellen Verzeichnisses.
28
Verzeichniswechseln
Lange Dateinamen, die Leerzeichen enthalten, müssen bei Kommandos mit der Shell in doppelte Anführungszeichen eingeschlossen werden, da sonst der Dateiname nicht korrekt erkannt wird. Schließlich ist das Leerzeichen für die Shell auch eines der Trennzeichen für Befehle und Optionen.
2.7.1
cd (chdir)
Das Kommando cd (für change directory) wechselt in der Shell das aktuelle Verzeichnis zum angegebenen Pfad. Wird kein Pfad angegeben, so erhalten Sie als Ausgabe das aktuelle Verzeichnis angezeigt. Es gibt für cd (und einige wenige andere Kommandos) einen Sonderfall bei der Behandlung von langen Dateinamen mit Leerzeichen. Diese müssen bei aktivierten Befehlserweiterungen (siehe Abschnitt 2.4.1) nicht mit doppelten Anführungszeichen umschlossen sein, da cd alle Zeichen bis zum Ende der logischen Eingabezeile als Pfadangabe auffasst. Geben Sie trotzdem die Anführungszeichen immer an, dann müssen Sie sich keine Ausnahmen merken. cd c:\tmp cd "c:\program files\win32\drivers\etc“
Falls das aktuelle Laufwerk ein anderes ist als das im cd-Kommando angegebene, erfolgt nur der Wechsel des Pfades. Das aktuelle Laufwerk bleibt das gerade eingestellte Laufwerk, wie der folgende Konsolenmitschnitt zeigt: H:\>c: C:\tmp>cd h:\buch\samples C:\tmp> h: H:\Buch\Samples
Wie Sie erkennen, bleibt nach einem cd das aktuelle Laufwerk auf C: eingestellt.
2.7.2
pushd/popd
Die beiden Kommandos pushd und popd ersparen beim häufigen Wechsel von Verzeichnissen eine Menge Arbeit. Der erste Befehl wechselt (auch über Laufwerksgrenzen) zum angegebenen Verzeichnis, legt aber vorher das aktuelle Verzeichnis in einem Stapel ab. Nach der Eingabe von popd wird dieses Verzeichnis wieder vom Stapel gelesen und als aktuelles Verzeichnis eingestellt. Im Gegensatz zu cd wird hier bei der Angabe eines Pfads mit einem anderen Laufwerk auch das aktuelle Laufwerk gewechselt.
29
2 Shell Basics
2.7.3
Aktuelles Verzeichnis feststellen
Falls Sie die Systemmeldung mit Hilfe von prompt (s. Abschnitt 3.3.2) umgestellt haben, können Sie trotzdem jederzeit das aktuelle Laufwerk und Verzeichnis feststellen. Geben Sie dazu einfach das Kommando cd ohne Parameter ein, und Sie erhalten als Ausgabe den aktuellen Pfad der Shell. Bei aktivierten Befehlserweiterungen existiert auch eine dynamische Umgebungsvariable CD, die jeweils das aktuelle Arbeitsverzeichnis der Shell enthält. Geben Sie zum Ausprobieren einfach das folgende Kommando ein. echo Aktuelles Verzeichnis = %CD%
2.8
Wo ist command.com?
Einige Umsteiger von Windows 98 oder noch älteren Systemen werden sich vielleicht fragen, wieso cmd.exe als Shell bezeichnet wird, wenn doch seit DOS-Zeiten der Kommandointerpreter command.com war. Dieses Programm existiert auch noch, ist aber nur noch aus Gründen der Abwärtskompatibilität für alte 16-Bit-Anwendungen vorhanden. Wenn Sie command aufrufen, wird eine virtuelle DOS-Maschine gestartet (der Prozess mit dem Namen ntvdm.exe), die anschließend command.com lädt. Jeder eingegebene Befehl wird aber intern sofort wieder über eine cmd-Shell abgearbeitet. Falls Sie das selbst sehen möchten, müssen Sie nur die Prozesshierarchie ansehen. Dazu benutze ich das Programm tlist aus den Support Tools für Windows 2000 (mehr Informationen dazu erhalten Sie beim Thema „Prozessverwaltung mit der Shell“ ab Seite 82) und lasse mir mit tlist -t die Prozesshierarchie ausgeben. Nachfolgend der relevante Teil der Bildschirmausgabe: CMD.EXE (1136) C:\WINNT\system32\cmd.exe NTVDM.EXE (660) C:\WINNT\system32\command.com CMD.EXE (1536) tlist.exe (316)
Wie Sie erkennen, ist cmd.exe mit der Prozess-ID 1136 die StandardShell. Aus dieser habe ich command.com gestartet, der aber unter der Regie des 16-Bit-Subsystems läuft (ntvdm.exe mit der PID 660). Diese startet für die Abarbeitung der in ihr gestarteten Kommandos (hier unser tlist) wieder eine Instanz von cmd.exe, diesmal mit der PID 1536. Sie sehen also, es gibt (außer für alte Applikationen, die den Namen fest einprogrammiert haben) keinen Grund mehr für command.com3. 3
30
Eine „anständig“ programmierte Anwendung hatte sowieso nie den Aufruf von command.com fest einprogrammiert, sondern hat bereits zu Zeiten von MS-DOS die Umgebungsvariable comspec abgefragt, die immer den kompletten Pfad zur aktuellen Shell des Systems enthält.
3
Shell-Konfiguration
Dieses Kapitel beschreibt die Konfiguration der Shell zur Laufzeit und über Einstellungen und die Registry. Mit diesen Informationen können Sie die Shell optimal an die eigenen Wünsche anpassen. Ich habe dieses Kapitel so weit vorne angeordnet, da eine gut konfigurierte Shell die Arbeit leichter macht. Außerdem sind die Tastenkombinationen und Dinge wie die automatische Vervollständigung von Dateinamen notwendiges Handwerkszeug für die Arbeit mit der Kommandozeile.
3.0.1
Tastenkombinationen
Bei der Bearbeitung von Befehlszeile bei konsolenbasierten Programmen4 steht Ihnen eine ganze Reihe von Bearbeitungsmöglichkeiten zur Verfügung, die über simples rechts oder links mit den Cursortasten hinausgehen. Viele der weiter unten aufgeführten Kombinationen machen aber erst Sinn, wenn Sie sich mit dem Thema doskey und Makros (s. Kapitel 10) beschäftigt haben. Sollten Sie daher zur einen oder anderen Tastenkombination Fragen haben, blättern Sie ruhig vor und lesen dort nach. Die folgende Tabelle zeigt alle Tastenkombinationen, die für die Kommandozeile unterstützt werden. Tastenkombination Bedeutung (½)
Ein Kommando zurück im Stapel
(¼)
Ein Kommando vor im Stapel
(æ)
Ein Zeichen links
(Æ)
Ein Zeichen rechts
(CTRL)-links
Ein Wort links
(CTRL)-rechts
Ein Wort rechts
(CTRL)-Home
Löscht vom Cursor bis zum Zeilenanfang
(CTRL)-End
Löscht vom Cursor bis zum Zeilenende
(ESC)
Löscht die gesamte Eingabezeile
(F1)
Wiederholt die letzte Eingabe Zeichen für Zeichen
(F2)
Kopiert letzte Eingabe bis zum eingegebenen Zeichen
4
Tabelle 3.1: Tastenkombinationen für die Shell
Also nicht nur cmd.exe, sondern auch Programme wie ftp, nslookup oder andere Programme, die über die Standardeingabe bedient werden.
31
3 Shell-Konfiguration
Tastenkombination Bedeutung (F3)
Zeigt die letzte Kommandozeile wieder an
(F4)
Löscht vom Cursor bis zum angegebenen Zeichen
(F5)
Kopiert den aktuellen Befehlspuffer in die Eingabezeile
(F6)
Fügt ein Dateiendezeichen ein ((Strg)+(Z))
(F7)
Zeigt alle gespeicherten Befehle an. Wählen Sie mit (½) und (¼) den gewünschten Befehl aus, und drücken Sie zum Ausführen des Befehls die (¢). Sie können auch die vor dem Befehl stehende Nummer zusammen mit der Taste F9 verwenden.
(ALT)+(F7)
Löscht alle gespeicherten Befehle
(F8)
Zeigt alle Befehle im Stapel an, die mit den eingegebenen Zeichen beginnen
(F9)
Fordert Sie zur Eingabe einer Befehlsnummer auf und zeigt dann den Befehl an, der mit der angegebenen Nummer verknüpft ist. Mit der (¢) können Sie den Befehl ausführen. Um alle Nummern und die entsprechenden Befehle anzuzeigen, drücken Sie (F7).
(ALT)+(F10)
Löscht alle Makrodefinitionen
(Einfg)/(Ins)
Schaltet zwischen Einfügen und Überschreiben um
(Entf)/(Del)
Löscht das Zeichen rechts vom Cursor
(Œ)
Löscht das Zeichen links vom Cursor
3.0.2
Startparameter
Beim Start der Shell cmd.exe sind folgende Optionen möglich. Tabelle 3.2: Startoptionen der Shell
32
Option
Auswirkung
/C
Führt aus und beendet dann die Shell
/K
Führt aus und endet dann nicht
/S
Bestimmt Behandlung von Zeichenfolgen nach /C oder /K
/Q
Schaltet die Befehlsanzeige aus
/D
Deaktiviert eventuelle AutoRun-Befehle aus der Registrierung
/A
Ausgabe in eine Pipe oder Datei im ANSI-Format
/U
Ausgabe in eine Pipe oder Datei im Unicode-Format
Wo ist command.com?
Option
Auswirkung
/T:fg
Legt die Hinter-/Vordergrundfarben beim Start fest
/E:ON
Aktiviert die Befehlserweiterungen (Default)
/E:OFF
Deaktiviert die Befehlserweiterungen
/F:ON
Aktiviert die Ergänzung von Datei- und Verzeichnisnamen (s. )
/F:OFF
Deaktiviert die Ergänzung von Datei- und Verzeichnisnamen
/V:ON
Aktiviert verzögerte Erweiterung von Variablen (s. )
/V:OFF
Deaktiviert die verzögerte Erweiterung von Variablen (Default)
Die Option, die Sie wahrscheinlich am häufigsten benutzen werden, ist die Option /C . Erst durch diese Option lassen sich interne5 Shell-Kommandos wie Kopieroperationen auch von anderen Prozessen aus aufrufen. Als Beispiel soll in einer anderen Anwendung eine Datei von einem Share eines anderen Rechners kopiert werden. Falls Sie (als Entwickler) das für eine triviale Aufgabe halten, hier der Hintergrund aus der Praxis: Beim Microsoft SQL Server ist vor der Version 2000 kein Backup einer Datenbank auf einen UNC-Pfad möglich (wird von MS nicht unterstützt)6. Ebenso existiert vor dem SQL Server 2000 kein Assistent für das sog. Log Shipping (den Transport und die Anwendung des Transaktionsprotokolls auf einen entfernten Standby-Rechner). Bleibt also nur ein regelmäßiger Job, der das Backup erledigt, und ein anderer regelmäßiger Job auf dem StandbyServer, der die Sachen abholt7. Die Erstellung einer Routine zum binären Kopieren von Dateien in SQL ist nicht praktikabel. Die Job-Engine von SQL kann aber auch Kommandos der Shell oder andere Programme starten. Damit ist das Problem gelöst: cmd.exe /C "copy \\server\share\20040520-145320.bkup c:\logs"
Eine Zeile
Wenn Sie ganz sicher sein wollen, können Sie den direkten Aufruf von cmd.exe auch durch ein %comspec% ersetzen. Falls die Software eine 5 6
7
Zur Unterscheidung von internen und externen Kommandos siehe den Abschnitt 2.5.2. Nur der Vollständigkeit halber und weil mir Ihre Daten am Herzen liegen: Auch beim SQL-Server 2000 würde ich keinen Backup auf einen UNC-Pfad durchführen, sondern lokal sichern und dann auf den UNC-Pfad kopieren. Warum? Bei Netzwerkfehlern haben Sie mit der ersten Methode eine kaputte Datei und kein Backup, mit dem zweiten Ansatz zumindest noch lokal ein verwertbares Backup. Falls Sie als DBA mehr dazu wissen möchten, suchen Sie in der Online-Hilfe von SQL 2000 oder im Web nach dem Begriff „Log Shipping“.
33
3 Shell-Konfiguration
Abfrage des Exit-Codes unterstützt (beim SQL-Server geben Sie an, welcher Wert von Errorlevel ein erfolgreiches Kommando signalisiert), können Sie das Ergebnis abfragen. Ein Wert von 0 bedeutet erfolgreiche Ausführung. Wann immer Sie also ein Shell-Kommando benötigen, das nicht als externe Programmdatei vorliegt, können Sie /C verwenden.
3.1
Das Shell-Fenster einrichten
Dieser Abschnitt beschreibt die Einrichtungsmöglichkeiten des Konsolenfensters. Stellen Sie sich die Shell so ein, dass Sie optimal damit arbeiten können. Genau wie beim Explorer orientiert sich Microsoft eher an den Endanwendern als am Administrator, so dass auch hier die eine oder andere Änderung sinnvoll ist. Nach einer Änderung werden Sie gefragt, ob diese nur für die aktuell ausgeführte Shell oder die Verknüpfung für das Shell-Fenster geändert werden soll. Um diese Einrichtungsmöglichkeiten zu erhalten, öffnen Sie per rechtem Mausklick auf den Fenstertitel oder (Alt)+(Leertaste) das Systemmenü und wählen dann den Menüpunkt EIGENSCHAFTEN aus. Die Abbildung der Dialogbox erspare ich mir an dieser Stelle, da Sie die folgenden vier Punkte den einzelnen Reitern zuordnen können.
3.1.1
Optionen
Cursorgröße Gibt an, wie groß der Cursor im Shell-Fenster sein soll. Mehr ist dazu nicht zu sagen, suchen Sie sich eine passende Einstellung aus. Anzeigeoptionen Die normale Einstellung ist der Fenstermodus. Wenn Sie lieber den gesamten Bildschirm nutzen möchten, können Sie hier den Vollbildmodus aktivieren. Im laufenden Betrieb können Sie auch mit der Tastenkombination (Alt)+(¢) zwischen Fenstermodus und Vollbildmodus wechseln. Befehlsspeicher Hier legen Sie fest, wie viele Befehle der Befehlsspeicher enthält und wie viele Prozesse verschiedene Befehlsspeicher verwalten können. Zur Bearbeitung des Befehlsspeichers siehe Punkt 3.0.1). Bearbeitungsoptionen Die Checkbox für den Einfügemodus legt fest, ob Zeichen, die in einer Befehlszeile eingegeben werden, die bereits vorhandenen Zeichen überschreiben oder vor diesen eingefügt werden. Der Einfüge-
34
Das Shell-Fenster einrichten
modus ist Standard und auch nützlicher als das Überschreiben von Zeichen. Wenn Sie wissen möchten, welche Bearbeitungsmöglichkeiten Sie für die Befehlszeile haben, sehen Sie auf Seite 31 bei den Tastenkombinationen nach. Der QuickEdit-Modus scheint eine Art geheimer Versionszählung von Microsoft zu sein. Bei NT4 war die Option deaktiviert, bei Windows 2000 aktiviert, bei Windows XP wieder deaktiviert … Aber ernsthaft: Ist diese Option aktiviert, können Sie mit der Maus per Klicken und Ziehen einen rechteckigen Bereich des Konsolenfensters markieren. Drücken Sie nun die Eingabetaste, wird dieser Bereich als Text in die Zwischenablage übertragen. Sehr praktisch für Dokumentationen oder wenn Sie gerade ein Buch über die Windows Shell schreiben! Auch der umgekehrte Weg ist möglich. Mit einem Klick auf die rechte Maustaste wird der derzeitige Inhalt der Zwischenablage in die Befehlszeile übertragen. Sie müssen also nie wieder lange Dateinamen oder Teile der Ausgabe neu eintippen: Markieren, (¢) und die rechte Maustaste reichen. Wenn der rechte Mausklick sofort auf die Markierung folgt, können Sie sogar die Eingabetaste weglassen. Vorsicht bei Text aus der Zwischenablage, der eine oder mehrere Zeilenschaltungen enthält. Da beim Klick auf die rechte Maustaste der Inhalt in die Befehlszeile übernommen wird, gilt eine Zeilenschaltung hier als Eingabetaste, die den Befehl auslöst! Stellen Sie sich als schlimmsten Fall vor, Sie haben ein rd c:\ /s / q und eine Zeilenschaltung in der Zwischenablage und klicken auf die rechte Maustaste … – hoffentlich haben Sie ein Backup! Falls zeichenorientierte Programme genutzt werden sollen, die die Maus unterstützen, darf die Option QUICKEDIT-MODUS nicht aktiviert sein, da sonst die Maus nicht funktioniert, weil die Maussteuerung von der Shell übernommen wird.
3.1.2
Schriftart
Na ja, die Schriftart für das Konsolenfenster. Damit hätten wir diesen Punkt auch schon erledigt, gäbe es da nicht einen Stolperstein. Sie können für die Shell sowohl TrueType-Schriftarten oder eine Rasterschrift einstellen. Diese ist in verschiedenen Größen möglich, die jeweils in Pixeln für einen Buchstaben angegeben werden (z.B.: 7x9 oder 10x18). Diese Rasterschriftart zeigt die Zeichen nicht für alle Zeichensätze (Codepages) korrekt an. Falls Sie also bei einer Ausgabe statt der Umlaute nur merkwürdige Zeichen erhalten, kann es an der Auswahl der Rasterschriftart anstelle eines TrueType-Zeichensatzes liegen (siehe auch Seite 268).
35
3 Shell-Konfiguration
3.1.3
Layout
Hier wird die Größe des Konsolenfensters und die des logischen Fensters eingestellt. Die FENSTERGRÖSSE legt die physikalischen Abmessungen des Shell-Fensters in Zeichen (und damit in Abhängigkeit von der Einstellung für die Schriftart) fest. Die FENSTERPUFFERGRÖSSE legt fest, wie groß das logische Ausgabefenster ist, von dem Sie den unter FENSTERGRÖSSE festgelegten Bereich auf dem Monitor angezeigt bekommen. Diese Einstellung sollte nach Möglichkeit so lang sein, dass Sie die Ausgabe eines Kommandos durch Scrollen nach oben komplett einsehen können, auch wenn sie aus dem sichtbaren Fenster herausgerollt ist. Die FENSTERPOSITION legt die Positionierung des Shell-Fensters in Pixeln von der oberen linken Ecke des Bildschirms fest. Aktivieren Sie die Checkbox AUTOMATISCH POSITIONIEREN, wenn Sie Windows die Entscheidung überlassen wollen, wo ein neues Fenster erscheint. Wollen Sie die Position des Fensters in einem Shell-Script oder WSH-Script festlegen, finden Sie die manuell eingestellten Werte in der Registry (s. Punkt 3.2.8) unter dem Wert WindowPosition (als REG_DWORD, jeweils ein Datenwort für x und y).
3.1.4
Farben
Damit werden die Farben für Vorder- und Hintergrund des Shell-Fensters definiert. Die hier eingestellten Farben finden Sie in der Registry wieder (s. Punkt 3.2.8). Sie können die Farben aber auch jederzeit interaktiv durch das Kommando color (s. Abschnitt 3.3.1) verändern.
3.1.5
Startverzeichnis
Das voreingestellte Verzeichnis (das so genannte Arbeitsverzeichnis) wird wie bei jeder Windows-Verknüpfung in den Eigenschaften dieser Verknüpfung festgelegt. Als Standard findet sich hier das Basisverzeichnis des gerade angemeldeten Benutzers. Klicken Sie zum Ändern mit der rechten Maustaste auf den Punkt im Startmenü, und wählen Sie dann den Menüpunkt EIGENSCHAFTEN. Im danach eingeblendeten Dialogfeld können Sie alle Eigenschaften der Verknüpfung ändern. Diese Einstellung können Sie durch einen beliebigen anderen Pfad ersetzen, wobei Sie wie in der Vorgabe auch Umgebungsvariablen (s. Kapitel 6) benutzen können.
3.1.6
Integration in den Explorer
In vielen Tool-Sammlungen findet sich die Möglichkeit, den Windows Explorer so zu erweitern, dass mit einem Klick der rechten Maustaste auf ein Verzeichnis ein Shell-Fenster geöffnet werden kann. Dieses Fenster benutzt dann das im Explorer selektierte Verzeichnis als aktuelle Basis.
36
Registry Keys
Diese Funktion (und auch andere Aufrufe von Programmen) können Sie jederzeit selbst nachrüsten. Ich möchte daher an dieser Stelle Schritt für Schritt zeigen, wie Sie solche Ergänzungen selbst in die Registry eintragen können. So müssen Sie sich nicht mehr auf andere Programme verlassen. Zusätzlich wissen Sie auch, wo Sie suchen müssen, wenn etwas einmal nicht klappt. Bitte beachten Sie folgenden Hinweis: Änderungen an der Registrierung des Systems können bei Fehlern zum Ausfall des Systems bzw. Datenverlust führen! Sichern Sie vorher auf jeden Fall die Registrierung, und stellen Sie sicher, dass auch eine funktionsfähige Sicherung vorhanden ist. Testen Sie Registry-Änderungen nie an Produktivsystemen, sondern immer erst auf einem Testsystem. Um im Kontextmenü einen Eintrag zum Aufrufen der Shell zu erhalten, gehen Sie wie folgt vor: 1. Suchen Sie in der Registrierung unter HKEY_CLASSES_ROOT den Eintrag Verzeichnis und dort den Schlüssel shell. 2. Darunter legen Sie nun einen neuen Schlüssel an (der Name ist beliebig, sollte aber selbstdokumentierend sein, beispielsweise CmdShell). 3. Darunter legen Sie wieder einen Schlüssel an, der den Namen command tragen muss. 4. Im Standardwert für diesen Schlüssel command (der keinen Namen trägt) geben Sie nun die auszuführende Befehlszeile an, hier cmd.exe "%1". 5. Verlassen Sie nun den Registrierungseditor. Wenn Sie im Windows Explorer auf einen Ordner mit der rechten Maustaste klicken, ist der neue Menüeintrag (hier CmdShell) sichtbar.
3.2
Registry Keys
Für die Konfiguration der Shell findet sich in der Registry eine ganze Reihe von Einträgen. Seien Sie vorsichtig bei der direkten Änderung der Registry! Die meisten dieser Einstellungen können Sie auch ohne einen Eingriff in die Registry per Kommandozeile oder Systemmenü verändern. Dieses Kapitel ist nur für Administratoren gedacht, die aus den Einstellungen hier eigene Policies erstellen wollen. Denken Sie daran, die Registry regelmäßig und vor solchen Eingriffen zu sichern!
37
3 Shell-Konfiguration
3.2.1
HKEY_LOCAL_MACHINE-Einträge
Die nachfolgenden Einträge in der Registry existieren zweimal. Einmal unter dem Root-Key HKEY_LOCAL_MACHINE und einmal unter dem Root-Key HKEY_CURRENT_USER. Die Einträge unter dem letzten Zweig der Registry überschreiben die Einstellungen, die für die Maschine getroffen wurden. Für alle Einträge gilt unterhalb des entsprechenden Root-Keys beide Male der Pfad \Software\Microsoft\ Command Processor.
3.2.2
AutoRun
Unter diesem Schlüssel kann ein Kommando definiert werden, das beim Start der Shell automatisch ausgeführt wird. Dieses Kommando wird allerdings bei jedem Start einer Shell ausgeführt, also auch beim automatischen Aufruf einer Sub-Shell wie beim Gruppieren von Kommandos oder beim Piping! Achten Sie daher darauf, dass dieses Kommando keinen Output produziert, er würde sonst bei einer Filteraktion mit erfasst.
3.2.3
EnableExtensions
Aktiviert oder deaktiviert die Erweiterungen der Shell. Wenn die Erweiterungen aktiviert sind (was den Standard darstellt), wird der Funktionsumfang vieler Kommandos erweitert. Ob ein Kommando sich unterschiedlich verhält, wenn die Erweiterungen aktiv oder inaktiv sind, erfahren Sie aus der Online-Hilfe, wenn Sie das Kommando mit der Option /? aufrufen.
3.2.4
DelayedExpansion
Steuert die Nutzung der verzögerten Variablenexpansion (s. Abschnitt 6.2.6).
3.2.5
CompletionChar
Stellt das Zeichen ein, mit dem die automatische Vervollständigung von Datei- und Verzeichnisnamen aktiviert wird. Der nummerische Wert definiert den Zeichencode der Taste, die für die Vervollständigung benutzt wird. Daher muss es sich bei dem Wert um eine Zahl kleiner als dezimal 32 handeln (0x1F), da bei 32 die druckbaren Zeichen beginnen. Bewährt hat sich die Angabe von 9 (egal ob dezimal oder hex, da bis 9 beide Zahlensysteme übereinstimmen), da dann nicht nur die Tabulatortaste in der Shell einer sinnvollen Verwendung zugeführt wird, sondern automatisch auch die Tastenkombination Umschalt-Tab genutzt wird.
38
Laufzeitkonfiguration
Nachdem diese Funktion seit Windows XP endlich automatisch aktiviert ist, fragt sich (nicht nur) der Autor, was MS damit bezweckt hat, diese Möglichkeit seit NT 3.51 implementiert zu haben, aber dann mehr als zehn Jahre nicht zu aktivieren. Wollte man den Administratoren das Zehnfingersystem beibringen, indem alle Dateinamen mühevoll getippt werden, wenn der Schlüssel in der Registry nicht gefunden wird? Welche nicht aktivierten Arbeitserleichterungen warten noch in den Tiefen des Systems?
3.2.6
PathCompletionChar
Diese Einstellung hat die gleiche Bedeutung wie COMPLETIONCHAR, doch nur für die Vervollständigung von Verzeichnisnamen, falls Sie die beiden getrennt handhaben wollen.
3.2.7
DefaultColor
Legt die Standardfarbe für das Shell-Fenster fest. Ein Wert von 0 liest die Daten aus der Registry aus (s. nächster Absatz).
3.2.8
HKCU\Console Settings
Unter diesem Schlüssel finden Sie die Konfiguration für alle Konsolenprogramme, die Sie bereits über das Systemmenü in ihrem Aussehen und Layout konfiguriert haben. Dort liegt auch unter dem Schlüssel %SYSTEMROOT%_System32_cmd.exe die Konfiguration für die Shell. Nachdem sich alle Informationen auch über das GUI steuern lassen und die Werte relativ selbsterklärend sind, besteht kein Grund, hier mühevoll von Hand zu verändern, was auch bequem über ein Dialogfeld einstellbar ist.
3.3
Laufzeitkonfiguration
3.3.1
color
Das Kommando color stellt für die Konsole die Farben für Vorderund Hintergrund ein (analog zu der Einstellung über die Eigenschaften des Konsolenfensters). Die entsprechenden Farbwerte für den color-Befehl finden Sie in der folgenden Tabelle:
39
3 Shell-Konfiguration Tabelle 3.3: Farbcodes für das Shell-Fenster
0 = Schwarz
8 = Dunkelgrau
1 = Dunkelblau
9 = Blau
2 = Dunkelgrün
A = Grün
3 = Blaugrün
B = Zyan
4 = Dunkelrot
C = Rot
5 = Violett
D = Magenta
6 = Ocker
E = Gelb
7 = Hellgrau
F = Weiß
Ob Sie die Farben per color oder über das Systemmenü des ShellFensters einstellen, ist funktional gleichwertig. Interessanter ist die Verwendung dieses Kommandos in einem Shell Script, um so beispielsweise einen blinkenden Text zu simulieren. Allerdings eignen sich für solche Zwecke zusätzliche Tools wie xecho oder andere meist besser.
3.3.2
Prompt
Mit Hilfe von prompt lässt sich die Eingabemeldung konfigurieren, um beispielsweise auch immer die Zeit oder die Anzahl der noch auf dem Verzeichnisstapel abgelegten Verzeichnisse anzuzeigen. Wird das Kommando ohne Parameter eingegeben, wird als Meldung der aktuelle Pfad, gefolgt von einem Größer-Zeichen, eingestellt. Folgende weitere Platzhalter werden bei der Angabe akzeptiert: Tabelle 3.4: Platzhalter für prompt-Sequenzen
$A
& (Kaufmännisches Und)
$B
| (Verkettungszeichen)
$C
( (Klammer auf)
$D
Aktuelles Datum
$E
Escape-Zeichen (ASCII-Code 27)
$F
) (Klammer zu)
$G
> (Größer-als-Zeichen)
$H
Rückschritt (löscht vorangehendes Zeichen)
$L
< (Kleiner-als-Zeichen)
$N
Aktuelles Laufwerk
$P
Aktuelles Laufwerk und Pfad
$Q
= (Gleichheitszeichen)
$S
(Leerzeichen)
$T
Aktuelle Zeit
$V
Windows-Versionsnummer
$_
Wagenrücklauf und Zeilenvorschub
$$
$ (Dollarzeichen)
$+
Pro mit pushd abgelegtem Verzeichnis ein "+"-Zeichen
$M
Bei Netzwerklaufwerken den Remote-Namen, sonst Leerstring
Den Platzhalter $H benötigen Sie nur dann, wenn Sie Teile der Ausgabe anderer Platzhalter wieder löschen wollen. So gibt zum Beispiel
40
Laufzeitkonfiguration $T die komplette Zeit in der Form hh:mm:ss,cc aus (wobei cc für die
Hundertstelsekunden steht). Wollen Sie im Prompt nur die Stunden und Minuten, können Sie dies mit der Sequenz $T$H$H$H$H$H$H erreichen, die nach der Ausgabe der Uhrzeit wieder sechs Zeichen entfernt. Einige Beispiele: prompt $P$G
Liefert die Standardmeldung, z.B. C:\tmp> prompt $M $p $+ #
Liefert eine Meldung der Form \\server\share R:\ ++ # und zeigt damit an, dass zwei Verzeichnisse auf dem pushdStapel liegen und das Root-Verzeichnis des Laufwerks R: in Wirklichkeit ein Share auf einer Remote-Maschine ist. Möchten Sie beispielsweise etwas mehr *nix-Feeling? Kein Problem: prompt # %computername%: stellt als Meldung ein Hash-Zeichen gefolgt vom Maschinennamen und dem Doppelpunkt ein8.
3.3.3
Title
Gerade für Administratoren sehr praktisch ist das Kommando title, mit dessen Hilfe der Titel des Konsolenfensters definiert wird. Wer ständig mehrere Shell-Fenster geöffnet hat oder eine Shell mit seinem normalen Domain-Account und eine als Administrator benutzt, kann so eine Verwechslung auf einfache Art und Weise vermeiden. Ich habe auf den meisten Maschinen, mit denen ich arbeite, mehr als ein Shell-Fenster offen. Eines mit dem normalen Benutzerkonto und eines mit der Admin-Anmeldung. Dieses ist (per color oder per Eigenschaften im Systemmenü) allerdings mit weißer Schrift auf rotem Hintergrund konfiguriert, und mit Hilfe von title Admin-Shell!! wurde auch der Fenstertitel angepasst. So sehe ich in der Taskleiste auch bei verdeckten Fenstern ganz schnell, welche Shell ich gerade benötige. Die allgemeine Syntax ist sehr einfach: title . Eine Eingabe von title ohne Parameter bewirkt keine Änderung. Ansonsten wird jeder Text als neuer Titel des Shell-Fensters angezeigt9. title Admin-Shell
Sehr praktisch ist die Verwendung dieses Kommandos auch in Shell Scripts (Batch Files), da durch mehrere title-Kommandos in zeitlichem Abstand auch dann eine Information an den Benutzer gelangt, wenn das Shell-Fenster minimiert ist. 8
9
Ganz so vielseitig wie bei bash, tcsh oder anderen Shells des Betriebssystems mit dem Pinguin ist die Meldung allerdings nicht konfigurierbar: Derzeit fehlt die Möglichkeit der dynamischen Ausgabe von Umgebungsvariablen, und einen Platzhalter für die Kommandonummer vermisse ich auch noch. Aus Gründen, die mir noch niemand erklären konnte, werden führende Semikola, Kommata und Gleichheitszeichen vor dem Titeltext ignoriert. Rahmen Sie also Ihre Texte lieber mit Minuszeichen ein …
41
3 Shell-Konfiguration
42
4 4.1
Umleitung & Filter
Dateikanäle
Jede Konsolenanwendung besitzt drei Möglichkeiten für die Ein- und Ausgabe von Daten. Für die Eingabe den Eingabekanal, der normalerweise als Standardeingabe (StdIn) bezeichnet wird. Dieser Kanal besitzt als Kennziffer das Handle 0. Wo etwas eingegeben und verarbeitet wird, wird auch etwas ausgegeben. Für die Ausgabe stehen allerdings aus historischen Gründen zwei verschiedene Kanäle zur Verfügung: die Standardausgabe (StdOut) mit dem Handle 1 und der Standardfehlerkanal (StdErr) mit dem Handle 2. Auch StdErr liegt bei der Shell per Default auf der Konsolenausgabe, so dass Sie normale Ausgabe und Fehlermeldungen zusammen erhalten. Wie ich Ihnen weiter unten noch vorstellen werde, lassen sich mit diesem Konzept aber Fehler und normale Ausgaben recht einfach in zwei verschiedene Dateien aufteilen.
4.2
Dateiumleitung
4.2.1
Ausgabeumleitung
In vielen Fällen wird die Ausgabe eines Befehls nicht benötigt, sondern nur der Errorlevel bzw. der Exit-Code des Prozesses (mehr dazu später). Mit Hilfe der Ausgabeumleitung kann die Ausgabe dann in den „elektronischen Reißwolf“, das sog. Nul-Device geleitet werden. echo Prüfe Erreichbarkeit der Maschine ... ping -n 1 -w 250 kiste.domain.wo > nul if errorlevel 0 programm.exe kiste.domain.wo
Das obige Kommando leitet die Ausgabe des ping-Befehls in das NulDevice um, so erfolgt keine Ausgabe. Innerhalb eines Befehlsstapels wird dann geprüft, ob der ping-Befehl erfolgreich war, und anschließend ein Programm gestartet. Die Umleitung der Ausgabe wird aber auch oft zur Protokollierung von Kommandos genutzt, indem die Ausgabe nicht in die Konsole erfolgt, sondern in eine Logdatei umgeleitet wird. Auch wenn die Ausgabe eine Kommandos weiter verarbeitet werden soll, ist die Umleitung in eine Datei nützlich. So liefert das folgende Kommando eine Liste aller Dateien mit dem Namen index.html inklusive des kompletten Pfades zu dieser Datei. Damit lässt sich dann z.B. automatisiert eine Navigation erzeugen. dir index.html /b /s > indexfiles.txt
43
4 Umleitung & Filter
Soll an eine bereits bestehende Datei angefügt werden, ist das Zeichen ">" zu verdoppeln. Falls die Datei noch nicht existiert, wird diese natürlich vorher angelegt. Wird mit Hilfe des Ausgabeumleitungssymbols > eine Datei erzeugt, wird eine eventuell bereits unter diesem Namen vorhandene Datei immer ohne Rückfrage überschrieben! Wird nur das einfache oder doppelte Größer-Zeichen angegeben, gilt die Umleitung immer für das StdOut-Handle (1). Aber auch das StdErr-Handle lässt sich umleiten. Es ist sogar möglich, die Standardausgabe in eine Datei und die Fehlermeldungen in eine zweite Datei umzuleiten. Geben Sie einfach einmal in einer Shell folgendes Kommando ein: C:\tmp>xcopy NichtDa.txt datei.txt
Sie erhalten dann die unten stehende Ausgabe: Datei NichtDa.txt nicht gefunden. 0 Datei(en) kopiert
Die erste Zeile ist eine Fehlermeldung, die Sie darauf hinweist, dass die Datei NichtDa.txt nicht gefunden wurde (falls Sie Ihre Dateien so benennen, müssen Sie sich einen anderen Beispielnamen suchen). Die zweite Zeile "0 Datei(en) kopiert" ist eine reine Statusmeldung und gibt in jedem Fall (Fehler oder nicht) an, wie viele Dateien abgearbeitet wurden. Jetzt lassen sich diese beiden Informationen in verschiedene Kanäle leiten, indem beim Umleiten der Ausgabe vor dem Größerzeichen das entsprechende Handle angegeben wird: xcopy NichtDa.txt datei.txt 1> log.txt 2> err.txt
In der Datei log.txt finden Sie nun alle normalen Ausgaben (wie die Zeile "0 Datei(en) kopiert"), und in der Datei err.txt finden Sie alle Fehlermeldungen, die zum StdErr-Handle (2) geschrieben wurden. Eigentlich eine sehr feine Sache, die auch eine leichte Aufteilung von Ausgaben erlaubt, würden sich alle Kommandos daran halten. Dies ist nicht der Fall. So gibt ping beispielsweise auch bei einem nicht erreichbaren Host oder einer ungültigen Option die Meldung nach StdOut aus. Möchten Sie die Ausgabedatei nicht überschreiben, sondern erweitern, müssen Sie das Zeichen ">" nur verdoppeln. Das Kommando echo %time% >> ausgabe.txt
sorgt also dafür, dass die Datei ausgabe.txt nach jeder Ausführung des Kommandos eine Zeile mehr enthält. Sollte die Datei vorher noch nicht existiert haben, wird sie beim ersten Aufruf automatisch erzeugt.
44
Dateiumleitung
Leere Dateien erzeugen Wesentlich trickreicher ist das Erzeugen einer leeren Datei mit der Windows Shell. In vielen Fällen (z.B. für Signaldateien, siehe Kapitel 11.6.2) reicht eine leere Datei vollkommen aus. Mittlerweile ist die Platzverschwendung bei NTFS für kleine Dateien nicht mehr so schlimm als noch bei FAT (sehr kleine Dateien finden bei NTFS komplett im Eintrag des Inhaltsverzeichnisses Platz), trotzdem sind noch genügend FAT-Systeme auf Clientseite im Einsatz. Der Trick besteht darin, find (siehe Seite 47) etwas zum Suchen zu geben, das nicht gefunden wird: Mit echo. | find "xxx" > datei.ext erhalten Sie eine Datei mit der Größe 0 Byte.
4.2.2
Eingabeumleitung
Nicht jede Eingabe für ein Shell-Kommandos muss von der Kommandozeile oder vom Benutzer kommen. Mit Hilfe der Eingabeumleitung sind Sie in der Lage, diese Daten direkt aus dieser Eingabedatei an das Shell-Kommando zu übergeben. Das Symbol hierfür ist das Kleinerzeichen ( srv.txt
Eine Möglichkeit, Textdaten vom Benutzer interaktiv eingeben zu lassen, bietet entweder der Set-Befehl (s.u.) oder die Methode, von der Konsole in eine Datei zu kopieren und diese anschließend weiterzuverarbeiten. Dazu kann bereits seit uralten DOS-Zeiten über das Kommando copy con eine Datei angelegt werden. Einziger Nachteil: Der Benutzer muss die Eingabe mit der Tastenkombination (Strg)+(Z) abschließen. An diesem Zeichen (dem Dateiendezeichen in Windows) erkennt die Shell, dass die Eingabe beendet werden soll. Andere Alternativen sind die Nutzung des Windows Script Hosts oder Tools von Drittanbietern.
45
4 Umleitung & Filter
Viele Shell Scripts nutzen solche Eingabeumleitungen, um damit Konsolenprogramme automatisiert mit Input zu versorgen. Sie sollten bei der Erstellung von solchen Dateien jedoch darauf achten, dass wirklich alle Befehle darin enthalten sind. Warum? Ganz einfach: Stellen Sie sich vor, Sie haben für ftp eine Eingabedatei erstellt, um einen Dateitransfer zu automatisieren. Allerdings haben Sie am Ende der Datei das Kommando quit vergessen, um ftp wieder zu beenden. Damit hängt der Prozess sozusagen in der Luft, denn Sie haben die Eingabe umgeleitet. Eingaben von der Tastatur (StdIn) werden damit nicht mehr angenommen, aus der Datei kommt aber nichts mehr. Also bleibt nur noch der Abbruch des Prozesses per taskkill (kill bei Windows 2000) oder Task Manager.
4.2.3
Umleitung und der Windows Script Host
Falls Sie die Ein- oder Ausgabeumleitung oder Piping zusammen mit dem Windows Script Host verwenden wollen, müssen Sie beim Lesen oder Schreiben von StdIn oder StdOut im Script Host immer cscript beim Aufruf mit angeben. Andernfalls werden die entsprechenden Datei-Handles nicht erzeugt, und der Befehl schlägt fehl, wie das folgende Beispiel zeigt: C:\tmp>echo Testtext | test.vbs C:\tmp\test.vbs(1, 1) (null): Das Handle ist ungültig.
Wird dagegen der Script Host beim Aufruf mit angegeben, funktioniert alles. C:\tmp>echo Testtext | cscript test.vbs TESTEXT
4.3
Datenübergabe und Filter
4.3.1
Das Prinzip
Ein- und Ausgabe mehrerer Konsolenprogramme können direkt miteinander verbunden werden. Da die Daten in diesem Fall wie in einer Pipeline reisen, wird dies im Fachjargon auch mit dem Begriff Pipelining oder Piping bezeichnet. Hierbei wird der jeweils nächste Filter durch ein Piping-Symbol („|“) getrennt angegeben10. Dadurch werden Ausgabekanal des ersten und Eingabekanal des zweiten Kommandos miteinander verbunden, so dass Sie sich die Erzeugung von nur temporär benötigten Zwischendateien sparen. Die allgemeine Syntax lautet: kommando1 | kommando2 … | kommando n 10 Falls Sie im Rechenzentrum vor einer US-Tastatur sitzen und das Zeichen nicht finden: Halten Sie die Taste [Alt] fest, und geben Sie auf dem Zehnerblock die Zahl 124 (den Zeichencode) ein, lassen Sie [Alt] los.
46
Datenübergabe und Filter
Zur Anzeige einer nach Prozessnamen sortierten Liste der laufenden Prozesse, die nach jeder vollen Bildschirmseite stoppt, kann folgendes Kommando verwendet werden: tlist | sort /+6 | more
Besonders nützlich ist der Einsatz des Piping-Operators in Verbindung mit besonderen Shell-Kommandos, die als „Filter“ bezeichnet werden. Diese werden nachfolgend detaillierter beschrieben. Als Filter bezeichnet man Programme, die über keinerlei Benutzeroberfläche verfügen und nur über Optionen der Befehlszeile gesteuert werden. Sie lesen über die Standardeingabe, verarbeiten diese Daten und geben das Ergebnis über die Standardausgabe aus. Prinzipiell kann also jedes Programm, das dieser Logik folgt, als Filter eingesetzt werden. Was der Windows Shell auch beim Windows 2003 Server noch fehlt, sind zwei Filter, die in der Unix-Welt beinahe täglich eingesetzt werden: tail und uniq. Der erste zeigt das Ende einer Datei an (eine konfigurierbare Anzahl von Zeilen), und der zweite Filter entfernt aus einem sortierten Eingabestrom alle Duplikate. Diese beiden Filter (und noch viele Unix-Tools mehr) sind unter anderem in den Ports der GNU-Tools zu finden.
4.3.2
find
Das Kommando find sucht zeilenweise nach Texten in Dateien. Die Benutzung kann entweder als Filter mit Hilfe der Umleitungs- und Piping-Operatoren erfolgen oder als normaler Programmaufruf. Hier kann dann auch mehr als eine Datei übergeben werden, die durchsucht werden soll. find [/i] [/c] [/v] [/n] "suchtext" [datei1] [datei...]
Mögliche Optionen für find sind: /i
unterscheidet nicht zwischen Groß- und Kleinschreibung
/v
gibt nur die Zeilen aus, die den Suchtext nicht enthalten
/n
nummeriert die ausgegebenen Zeilen fortlaufend
/c
gibt nur die Anzahl der Zeilen aus, in denen der Suchtext vorkommt
Tabelle 4.1: Optionen für find
Falls bei find eine Übereinstimmung mit dem Suchtext gefunden wird, liefert das Programm einen Errorlevel (s. Abschnitt 6.2.7) von 0 (Erfolg). Wird der Suchtext nicht gefunden, liefert find einen Errorlevel von 1. Durch geschickte Kombination der Optionen von find lassen sich auch ungewöhnliche Aufgaben lösen. Dazu ein Beispiel: Nummerieren Sie die Zeilen einer Textdatei. Das Kommando dazu sieht so aus: find /n /v "@@@@@" < datei.txt
47
4 Umleitung & Filter
Als Suchstring geben Sie eine Zeichenkette an, die in der Datei nicht vorkommt (hier "@@@@@"). Der Schalter /v sorgt dafür, dass alle nicht zutreffenden Zeilen ausgegeben werden (also alle), während /n für die Nummerierung sorgt. Aus der Datei Eins Zwei Drei
wird also [1]Eins [2]Zwei [3]Drei
Sollte Ihnen die Art der Nummerierung nicht gefallen, finden Sie weiter hinten im Buch im Abschnitt 16.3.7 die (zugegebenermaßen etwas komplexere) Kommandozeile, mit der Sie die eckigen Klammern gegen andere Zeichen tauschen können.
4.3.3
sort
Dieses Kommando sortiert die Standardeingabe zeilenweise und gibt diese sortierte Liste in die Standardausgabe aus. Wird eine Datei in der Kommandozeile angegeben, so wird diese anstelle von StdIn verwendet (dieses Verfahren ist schneller als das Umleiten der Standardeingabe). Ebenso ist die Verwendung der Option /O schneller als die Umleitung der Standardausgabe in eine Datei. SORT [/R] [/+n] [/L locale] [/REC recordbytes] Tabelle 4.2: Die wichtigen Optionen für sort
/R
Dreht die Sortierfolge um (reverse sort).
/+
Sortiert beginnend ab der Spalte .
/L
Ändert die Sortierfolge von der Ländereinstellung auf eine andere, derzeit ist allerdings nur "C" möglich (für die schnellste Einstellung).
/REC
Falls die zu sortierenden Zeilen länger als 4096 Zeichen sind, kann hier angegeben werden, wie lang die Zeilensätze sind (max. 65535).
/O Gibt eine Ausgabedatei für das Ergebnis der Sortierung an.
Es gibt auch noch einige weitere Optionen, die beispielsweise die Menge des maximal möglichen Speichers für die Sortierung oder die Platzierung der temporären Daten betreffen. Diese Exoten sind aber für 99,9% der Anwendungen von sort nicht notwendig. Falls Sie daran interessiert sind, geben Sie einfach das Kommando sort /? ein. Eine Möglichkeit, Duplikate aus einer Sortierdatei zu entfernen, ist übrigens auch bei Windows 2003 nicht enthalten. Verwenden Sie dazu eine der vielen Portierungen des Unix-Tools uniq, oder schla-
48
Datenübergabe und Filter
gen Sie im Abschnitt 16.3.8 nach. Dort stelle ich Ihnen ein Shell Script vor, das Duplikate aus einer sortierten Liste entfernt.
4.3.4
more
Dient dem seitenweisen Blättern durch eine Datei. Auch hier ist entweder die Verwendung als Filter oder der Aufruf als Programm mit dem Namen der Datei oder mehreren Dateien als Parameter möglich. more bietet folgende Optionen beim Aufruf: /E
Aktiviert die erweiterten Möglichkeiten.
/C
Löscht den Bildschirm, bevor eine Seite angezeigt wird.
/P
Führt Seitenvorschubzeichen aus.
/S
Fasst mehrere leere Zeilen zu einer Zeile zusammen.
/Tn
Ersetzt Tabulatorzeichen durch n Leerzeichen (Standard 8).
+
Start mit der Ausgabe in Zeile .
Tabelle 4.3: Aufrufoptionen für more
Wenn die Ausgabe am Ende der Bildschirmseite pausiert, haben Sie folgende Möglichkeiten, den weiteren Verlauf zu steuern: [ENTER]
Zeigt die nächste Zeile an.
[Leer]
Zeigt die nächste Seite an.
P
Zeigt die nächsten Zeilen an.
S
Überspringt die nächsten Zeilen.
Q
Beendet die komplette Ausgabe.
F
Zeigt die nächste Datei in der Liste an.
=
Zeigt die aktuelle Zeilennummer an.
?
Zeigt eine Hilfezeile mit diesen Möglichkeiten an.
Tabelle 4.4: Tastenkombinationen für more im interaktiven Modus
Obwohl more beim interaktiven Aufruf oder in einem Batch nach einer Bildschirmseite stoppt, wird diese Funktion bei einer umgeleiteten Ausgabe deaktiviert. Ein more < datei1.txt > datei2.txt wird also auch bei 200 Zeilen in der Datei in einem Rutsch durchlaufen.
4.3.5
clip
Der Filter clip ist bei Windows 2000 noch Bestandteil des Resource Kits, ab XP ist er im Standardumfang der Shell enthalten. Es existieren aber auch einige freie Filter mit der gleichen oder mehr Funktionalität, die von Drittanbietern programmiert wurden.
49
4 Umleitung & Filter
Alles, was an den Filter gesendet wird, landet in der Zwischenablage von Windows, während bei einer Verwendung als Quelle die Zwischenablage ausgelesen wird. Wenn sie beispielsweise die IP-Konfiguration Ihrer Netzwerkkarte in einer Dokumentation weiterverwenden wollen, reicht ein ipconfig /all | clip
und die Daten liegen in der Zwischenablage als Text. Sehr praktisch! Seien Sie vorsichtig beim Einfügen von Inhalten aus der Zwischenablage in die Shell. Jede mit einem Zeilenende (CR/LF) abgeschlossene Zeile wird als Kommando sofort ausgeführt. Mehr Informationen zur Konfiguration dieses Features finden Sie im Abschnitt 3.1.1.
50
5
Dateien im Detail
Dieses Kapitel ist aufgrund vieler Nachfragen bei Kursen ins Manuskript für das Buch gewandert. Sie werden auf den nächsten Seiten weniger neue Kommandos lernen, als vielmehr einige Aspekte von Windows besser kennen lernen, die mit der Behandlung von Dateien und Dateiinhalten zu tun haben. Gerade Administratoren, die von Unix auf Windows umsteigen (müssen), und solche, die Windows bisher nur über GUI-Tools verwaltet haben, erhalten hier Informationen, die das Verhalten des Systems hoffentlich etwas verständlicher erscheinen lassen.
5.1
Warum ist type unbrauchbar?
Ist ein ganzer Abschnitt zum Thema „Wie gebe ich eine Textdatei aus?“ sinnvoll? Ja, da sich hier wieder die historisch bedingten Inkonsistenzen der Windows Shell zeigen. Das Kommando type gibt den Inhalt einer Datei komplett auf die Standardausgabe aus, so erklärt dies zumindest die Windows-Hilfe. Zusätzlich wird dem Benutzer noch davon abgeraten, binäre Dateien mit type auszugeben, da er sonst merkwürdige Zeichen auf dem Bildschirm sehen könnte. Problematisch an type ist aber die Tatsache, dass Sie unter Umständen gar nicht den kompletten Inhalt einer Datei angezeigt bekommen! Für die Demonstrationen in diesem Kapitel habe ich eine Datei erstellt, die sich auch im Download-Archiv zu diesem Buch befindet. Was an dieser Datei so besonders ist, werde ich Ihnen gleich verraten. Doch zuerst möchte ich gerne den Inhalt der Datei ausgeben. Dazu werden die meisten Leser in der Shell sicher das Kommando type verwenden. Hier die Ausgabe: C:\tmp>type t:\Transfer\DateiEOF.txt Es war einmal ein Elch, der arbeitete aushilfsweise in einem Minijob als Rentierersatz beim Weihnachtsmann. C:\tmp>
Sollten Sie dem Inhalt der Datei keinen rechten Sinn abgewinnen, haben Sie aus zwei Gründen Recht. Erstens werde ich mit solchen Texten nie die Belletristik-Listen anführen, und zweitens fehlt ihnen
51
5 Dateien im Detail
das Happy End der Geschichte. Sie sehen hier nämlich nur einen Teil der Datei! Zum Beweis gebe ich die Datei noch einmal aus, diesmal aber mit more11: C:\tmp >more < DateiEOF.txt Es war einmal ein Elch, der arbeitete aushilfsweise in einem Minijob als Rentierersatz beim Weihnachtsmann. Ë Nach einigen Jahren hatte er so viel verdient, dass er sich auf den Bahamas zur Ruhe setzen konnte. C:\tmp>
Während type also die Ausgabe bei einem EOF-Zeichen stoppt (diese Funktionalität ist seit MS-DOS so und konnte daher aus Gründen der Abwärtskompatibilität nicht geändert werden), gibt more eine Datei wirklich bis zum tatsächlichen Ende der Datei aus. Nachdem wir nun unseren Geweihträger sozial abgesichert wissen, stellt sich die Frage, wieso die beiden Kommandos unterschiedliche Ausgaben liefern. Der Grund liegt in dem Zeichen zwischen den beiden Absätzen (dem kleinen Pfeil nach rechts bei der Ausgabe). Dies ist das Zeichen mit dem ASCII-Code 26 und wird EOF (end of file) oder Dateiendezeichen genannt. Über die Tastatur erzeugen Sie das Zeichen mit der Tastenkombination (Strg)+(Z) (da Z der 26. Buchstabe ist). Wie der Name bereits sagt, dient das Zeichen als Markierung für das Ende einer Datei. Achtung, Geschichtsstunde! Falls Sie interessiert sind, ob Windows (bzw. das Dateisystem) überhaupt ein Dateiendezeichen benötigt und wieso das (Strg)+(Z) ist, lesen Sie weiter … Ein Vorfahre von MS-DOS (von dem Windows ja abstammt) war CP/M von Digital Research. Bei CP/M wurden im Inhaltsverzeichnis für eine Datei noch keine tatsächlichen Dateilängen angelegt. Stattdessen wurde dort die Länge der Dateien in Datensektoren eingetragen. Da zu Zeiten von CP/M Speicher (auch auf Disketten) knapp und teuer war, betrug die Sektorlänge 128 Byte. War der letzte Sektor einer Datei kleiner als 128 Byte, war das auch kein Problem, da die Sektoren mit einem Füllzeichen aufgefüllt wurden. Dies war das Zeichen mit dem ASCIICode 26 (eben (Strg)+(Z)). Ein Programm las also so lange komplette Sektoren, bis alle gelesen wurden oder bis im letzten Sektor ein Zeichen mit dem Code 26 gefunden wurde.
11 Die Windows Shell erlaubt auch die Syntax more ohne die Umleitung der Eingabe.
52
NTFS Alternate Data Streams
Ab MS-DOS enthielt das Verzeichnis dann die tatsächliche Länge der Datei in Byte, und damit wurde ein spezielles Zeichen als Kennung für das Ende einer Datendatei unnötig. Wenn Sie heute über die Konsole eine Datei eingeben (mit der Methode copy con ), wird die Eingabe zwar mit Strg-Z abgeschlossen, aber dieses Zeichen wird nur benötigt, damit die Shell erkennt, dass Sie keine weiteren Zeichen eingeben wollen. Das Zeichen 26 selbst wird nicht mehr in die Datei geschrieben. Machen Sie den Test: Kopieren Sie Daten aus der Konsole in eine Datei, und sehen Sie sich das Ergebnis mit einem Hex-Editor (oder debug) an. Sie werden dort kein EOF-Zeichen finden. Heutige Dateisysteme wie NTFS verwalten sowieso mehr als einen Datenstrom und sind intern ganz anders organisiert. Aber alte Gewohnheiten wie Strg-Z leben lange …
5.2
NTFS Alternate Data Streams
Eigentlich ist dies kein direktes Thema für das Shell Scripting. Allerdings sind die Möglichkeiten, die sich durch diese Funktion von NTFS ergeben, für Administratoren so wichtig, dass ich es an dieser Stelle aufgenommen habe. Nicht nur für den Umgang mit der Shell, sondern auch aus Gründen der Sicherheit Ihrer Server sollten Sie sich das folgende Kapitel durchlesen, wenn Ihnen der Begriff alternata data stream noch nichts sagt.
5.2.1
Einführung
In einem meiner Windows 2000-Kurse wurde ich von einem Kursteilnehmer gefragt, ob ich mit der unten abgebildeten Dialogbox etwas anfangen könne: Abbildung 5.1: Die mysteriöse Abfrage
Diese Abfrage taucht immer dann auf, wenn Sie eine Datei von einem NTFS-Datenträger auf einen Datenträger mit einem anderen Dateisystem (z.B. FAT32) verschieben oder kopieren. Diese „nicht beibehaltenen“ Informationen sind so genannte alternate data streams (ab hier als
53
5 Dateien im Detail
ADS bezeichnet), ein Standardfeature von NTFS, das trotz seines mittlerweile fortgeschrittenen Alters immer noch recht unbekannt ist12.
5.2.2
NTFS-Dateien
Eine NTFS-Datei wird nicht einfach wie bei FAT als ein Strom von Bytes auf der Platte und ein paar Metadaten im Verzeichniseintrag aufgefasst. Unter NTFS besteht jeder Eintrag im Verzeichnis (der so genannten master file table, abgekürzt MFT) aus einem Datensatz mit einer festen Länge von 1 KByte. Daher wird für kleine Dateien (wie der berühmten test.txt mit drei Zeilen) auch kein Platz verschwendet. Diese Datei passt mit allen Metadaten komplett in den Datensatz in der MFT. Die Identifikation einer Datei erfolgt durch einen 64 Bit großen Wert, der aus 48 Bit für die Dateinummer (die Position in der MFT, gezählt ab 0) und 16 Bit für eine Sequenznummer besteht. Die Sequenznummer wird immer dann um eins erhöht, wenn die gleiche Dateinummer auf einem Datenträger wieder verwendet wird. Die Datei selbst ähnelt (ebenso wie das gesamte Design von NTFS) eher den Objekten einer relationalen Datenbank. Eine Datei wird als eine Kombination von Attributen und ihren Werten aufgefasst, stellt logisch also eine Tabelle dar. Die Daten der Datei (der Inhalt) sind dabei nur ein Teil einer Reihe von Attributen. Dieses (intern mit dem Attributnamen $DATA) Attribut wird als unbenanntes Datenattribut oder auch als Hauptdatenstrom bezeichnet. Diese Attribute können optional noch eine zusätzliche Namensbezeichnung tragen. Da der Hauptdatenstrom keinen optionalen Namen trägt, wird er eben auch als unbenanntes Datenattribut bezeichnet. Weitere Attribute speichern Metadaten wie beispielsweise die Angaben im Verzeichnis (Zeit, System, Schreibgeschützt, Letzter Zugriff) unter dem Attribut $STANDARD_ INFORMATION, den Dateinamen im Unicode-Format ($FILE_NAME) und so weiter13. Wenn Sie mehr darüber erfahren möchten, finden Sie im Buch „Inside Windows 2000“ (Daten im Anhang) eine detaillierte Beschreibung des NTFS-Dateisystems. Der für uns interessante Punkt ist nun die Tatsache, dass durchaus mehr als ein Attribut $DATA vorhanden sein kann. Diese weiteren werden dann zur Unterscheidung mit einem Namen versehen und als alternate data streams (zusätzliche Datenströme oder Datenattribute) bezeichnet. In der Auflistung im Verzeichnis (egal ob im Explorer oder per dir) wird immer nur das unbenannte Datenattribut verwendet. 12 Was natürlich auch daran liegen kann, dass Microsoft keinerlei Tools (noch nicht einmal auf Shell-Ebene) für die Bearbeitung bereitstellt und die ADS in Dokumentationen für Administratoren mit dem Hinweis „this is a developer feature“ abtut. 13 Interessant ist auch die Tatsache, dass diese Attribute über ein „in_use“-Flag verwaltet werden. Wird also ein Attribut gelöscht, wird das entsprechende „in_use“-Flag gelöscht, die Daten sind nach wie vor aber noch vorhanden.
54
NTFS Alternate Data Streams
5.2.3
Erzeugen und Abfragen von ADS
Die einfachste Möglichkeit, einen Datenstrom mit einem eigenen Namen zu erzeugen, besteht in der Verwendung der normalen Ausgabeumleitung. Hier wird eine Versionskennzeichnung als eigener Datenstrom an die Datei report.txt angefügt. echo Ver 1.2.0 - 2003-08-23 > report.txt:version
Eine Erweiterung dieses Datenstroms geschieht wie bei einer regulären Datei über ein Anfügen. echo Ver 1.2.1 - 2003-08-26 >> report.txt:version
Auch Windows selbst nutzt diese Möglichkeit der zusätzlichen Datenströme. Haben Sie sich nicht schon einmal gefragt, wo die ganzen Daten der Dateiinformation bleiben, die Sie über die rechte Maustaste und den Eigenschaftsdialog eingeben können (Autor, Titel, Stichwörter etc.)? Auch dafür werden die ADS genutzt, allerdings mit einem vordefinierten Namen. Dieser Name entspricht dem der COMDokumente (z.B. Office-Dateien) für Zusammenfassungen und lautet ^ESummaryInformation. Das „^E“ zu Beginn steht für das Zeichen mit dem ASCII-Code 5 ((Strg)+(E)) und wird auf der Konsole beim Eintippen so angezeigt14. Machen Sie den Test: Geben Sie für eine NTFS-Datei einige Informationen für eine Datei ein, und sehen Sie sich dann diesen Datenstrom an. Leider ist dieser binär kodiert und nicht direkt lesbar, Sie werden aber die Wörter für Titel und Stichwörter erkennen: more < report.txt:^ESummaryInformation
Diese Funktionalität ist direkt in die Low-Level-Dateiroutinen von Windows integriert. Alles, was einen Dateinamen akzeptiert, akzeptiert üblicherweise auch einen Stromnamen (mit Ausnahme von type!). Daher ist auch Notepad ein tauglicher Editor für zusätzliche Datenströme: notepad buget.txt:revision15
Da type auch hier nicht zu gebrauchen ist, empfehle ich Ihnen an dieser Stelle, sich an die Benutzung von more zu gewöhnen. Falls Sie jetzt einwenden möchten, dass ich alternativ ja auch per doskey einen Alias für type erzeugen kann, der einfach more aufruft: Erstens kann more in der Syntaxvariante more [datei] (ohne das Kleinerzeichen) auch nichts mit ADS anfangen15, und zweitens ändert dies auch das Verhalten des Befehls (type bleibt schließlich nicht nach jeder Seite stehen und wartet). 14 In der Literatur (z.B. der WSH-Dokumentation) wird bei Tastenkombinationen ^ üblicherweise als Präfix für Control ((Strg)), % für (Alt) und + für (ª) verwendet. 15 Falls jemand bei Microsoft mitliest: Warum eigentlich? Es wäre wirklich schön, wenn die Shell wenigstens innerhalb eines Kommandos konsistent wäre.
55
5 Dateien im Detail
Dies ist ein Feature des Dateisystems (übrigens bereits seit NT 3.x!), daher ist der einzige Nachteil der, dass beim Kopieren oder Verschieben auf einen Datenträger mit einem anderen Dateisystem (FAT32, ISO-CD etc.) die Daten in der ADS unwiederbringlich verloren gehen. Bleibt die Datei aber während ihrer gesamten Lebensdauer auf einem NTFS-Volume, ist dies eine ideale Möglichkeit, unabhängig vom Dateninhalt zusätzliche Metadaten zu hinterlegen. Dies funktioniert übrigens auch, wenn der unbenannte Datenstrom leer ist, wie die folgende Sequenz von Befehlen zeigt: C:\tmp>echo. | find "nix" > x.x C:\tmp>dir x.x Datenträger in Laufwerk C: ist Lokaler Datenträger Datenträgernummer: 8C3F-34DE Verzeichnis von C:\tmp 20.06.2004
22:31 1 Datei(en) 0 Verzeichnis(se),
0 x.x 0 Bytes 2.930.911.744 Bytes
frei C:\tmp>echo Version 1 der Datei > x.x:Revision C:\tmp>dir x.x Datenträger in Laufwerk C: ist Lokaler Datenträger Datenträgernummer: 8C3F-34DE Verzeichnis von C:\tmp 20.06.2004
22:32 1 Datei(en) 0 Verzeichnis(se),
0 x.x 0 Bytes 2.930.911.744 Bytes
frei C:\tmp>more < x.x:revision Version 1 der Datei C:\tmp>
Diese Daten sind nicht auf reine Textinformationen begrenzt und stellen ein potenzielles Sicherheitsproblem dar, solange die Datei auf einem NTFS-Datenträger verbleibt. Anhand eines einfachen Beispiels möchte ich Ihnen das demonstrieren: Legen Sie eine Textdatei report.txt an (mit Notepad oder was Sie gerade benutzen). und geben Sie zwei oder drei Zeilen Text ein. Anschließend sehen Sie nach, wie groß die Datei ist: Listing 5.1: Erzeugen der Datei report.txt
56
C:\tmp>echo Windows trennt echo seine Zeilen > report.txt C:\tmp>echo durch die Kombination CR und LF. >> report.txt C:\tmp>dir report.txt Datenträger in Laufwerk C: ist Datengrab
NTFS Alternate Data Streams Datenträgernummer: 8BBF-50DE Verzeichnis von C:\tmp 18.06.2004
22:41 1 Datei(en) 0 Verzeichnis(se),
70 report.txt 70 Bytes 2.929.150.464 Bytes
frei C:\tmp>
Mit den obigen Daten ist die Datei 70 Byte groß, wie die Ausgabe von dir auch anzeigt. Jetzt ergänzen wir die Datei um einen ADS, diesmal aber binärer Natur, und sehen uns dann noch einmal die Größe an16: C:\tmp>type c:\winnt\system32\notepad.exe > report.txt:machwas.exe C:\tmp>dir report.txt Datenträger in Laufwerk C: ist Datengrab Datenträgernummer: 8BBF-50DE Verzeichnis von C:\tmp 18.06.2004
22:41 1 Datei(en) 0 Verzeichnis(se),
70 report.txt 70 Bytes 2.929.150.464 Bytes
frei C:\tmp>
Wir haben eine komplette Kopie von Notepad als ADS in die Datei report.txt integriert, und die Anzeige teilt uns mit, dass die Datei immer noch die Größe von 70 Byte besitzt! Was dir (und die anderen Tools) ausgibt, ist immer die Größe des Hauptdatenstroms, und diese hat sich ja auch nicht verändert17. Nun aber zum interessanten Teil: Wie kann diese ausführbare Datei, die in report.txt klebt, aktiviert werden? Der normale Weg über report.txt:machwas.exe
funktioniert nicht, und es wird eine Fehlermeldung ausgegeben. Grund ist der Parser der Shell, der einen Doppelpunkt beim Starten eines Programms zwar akzeptiert, aber nur als zweites Zeichen hinter dem Laufwerksbuchstaben. Daher müssen wir etwas kreativer werden und eines der neuen Shell-Kommandos nutzen: start .\report.txt:machwas.exe
16 type funktioniert hier, da kein EOF an unpassender Stelle steht, falls Sie sich das gerade gefragt haben. Ansonsten empfehle ich die Benutzung von Tools wie cat. 17 Die gute Nachricht für alle besorgten Administratoren: das Quota Management von Windows rechnet ab Windows 2000 korrekt die gesamte Größe der Datei inklusive aller Datenströme. Nur per dir die Größe zu addieren reicht aber nicht mehr.
57
5 Dateien im Detail
Dieses Kommando startet den Datenstrom machwas.exe in der Datei report.txt, wobei das „.\“ angegeben werden muss, da start den Dateinamen sonst als URL auffasst. Falls Sie eine solche Datei gestartet haben, sehen Sie dies ab Windows XP auch im Task-Manager bzw. bei der Ausgabe von tasklist: Abbildung 5.2: Eine Datei mit ADS im Task-Manager
Die Abbildung oben zeigt in der markierten Zeile den Namen der Datei und den ADS, so dass Sie zumindest wissen, wo Sie suchen müssen. Mit WMI ist eine Remote-Abfrage von Prozessen, die einen Doppelpunkt im Namen tragen, dann auch kein Problem mehr. Um einen Kollegen zu zitieren, der eine solche Query regelmäßig laufen ließ: „Du hast keine Ahnung, was Du da alles findest!“ … Seien Sie also vorsichtig, wenn Sie Dateien auf NTFS-Datenträgern haben. Jeder mit Schreibrechten kann sich einen ADS anlegen und nutzen. Ein Teilnehmer hat mir von einem Benutzer erzählt, der in seinem Home-Verzeichnis eine Textdatei mit einigen Telefonnummern liegen hat. Dahinter in einem ADS steckt eine 300 MByte große ZIP-Datei mit MP3!
5.2.4
Auflisten und Löschen von ADS
In Windows existieren keine Tools, um für eine bestimmte Datei oder ein Verzeichnis aufzulisten, ob und welche Datenströme in einer NTFSDatei vorhanden sind (schließlich ist das ja ein „Developer-Feature“). Es gibt aber im Web mittlerweile eine ganze Reihe von Freeware-Tools, die genau diese Funktionalität bieten und ADS auch wieder aus einer Datei entfernen können. Als Beispiel (für die Kommandozeile) möchte
58
NTFS Alternate Data Streams
ich an dieser Stelle wieder einmal ein Tools von www.sysinternals.com empfehlen. Dieses Tools heißt auch streams und ist (etwas versteckt) bei den Utilities für Windows 2000 und aufwärts unter der Rubrik „Miscellaneous“ (Verschiedenes) und dort noch einmal bei „Miscellaneous“. im Archiv streams.zip zu finden. Eine Alternative ist LADS von www.heysoft.de oder eine Suche in Google. Eine andere Möglichkeit zum Löschen aller ADS: Kopieren Sie die Datei auf eine FAT32-Partition. Falls keine Dialogbox wie oben erscheint, waren keine ADS enthalten. Erscheint die Dialogbox, bestätigen Sie den Verlust der ADS und haben anschließend auf dem FAT32-Datenträger eine Datei, die wieder nur aus dem Hauptdatenstrom besteht und gesäubert wieder zurück auf die NTFS-Partition kopiert werden kann. Haben Sie nur noch NTFS, auch kein Problem. Dazu muss nur der Hauptdatenstrom ausgegeben und in eine Datei umgeleitet werden. Diese Datei wird dann über die alte Datei kopiert. Für Textdateien ist dies unkritisch, achten Sie nur darauf, dass auch alle Zeichen ausgegeben werden (nicht type verwenden, siehe Abschnitt 5.1). ren datei_mit_ads.txt temp.txt more < temp.txt > datei_mit_ads.txt del temp.txt
Problematischer wird es mit Binärdateien wie Programmen. Hier muss ein Tool verwendet werden, das eine Datei 1:1 auf der Konsole ausgibt, damit die umgeleitete Datei auch wieder eine exakte Kopie des Inhalts darstellt. Bei früheren Windows-Version existierte im Resource Kit zu diesem Zweck eine Portierung des Unix-Kommandos cat. Falls Sie kein altes Resource Kit haben, kein Problem: Bei den GNU-Ports der wichtigsten Unix Text-Tools ist ebenfalls ein cat enthalten: ren datei_mit_ads.txt temp.txt cat --binary temp.txt > datei_mit_ads.txt del temp.txt
5.2.5
Verknüpfungen und ADS
Bei Windows 2000 war es noch ohne Probleme möglich, eine Verknüpfung anzulegen und nachträglich das Ziel vom Dateinamen auf Dateinamen und ADS-Namen abzuändern. Damit waren auch ADS in Dateien per Verknüpfung ausführbar. Bei Windows 2003 ist dieses Verhalten geändert worden18. Sie können zwar noch eine Verknüpfung anlegen und diese nachträglich so abändern, dass auf den ADS verwiesen wird. Beim Starten der Verknüpfung per Doppelklick aber wird diese wieder auf den Namen der Datei geändert, und Sie erhalten die Dialogbox, die nach dem für diese Datei zuständigen Programm fragt. 18 Ob dies absichtlich geschah oder nur als Nebeneffekt einer anderen Änderung, konnte ich nicht herausfinden.
59
5 Dateien im Detail
5.2.6
Problemfeld Makro-Viren
Die wirkliche Sicherheitsproblematik liegt aber auch in der Möglichkeit, Code für den Windows Script Host in einem ADS zu verstecken. Es existieren bereits Viren, die eine solche Technik nutzen, daher sollten Sie sich als Administrator mit dieser Möglichkeit beschäftigen. Zuerst stecke ich einen einfachen Scriptcode in einen ADS: Eine Zeile
echo MsgBox "Viele Gruesse vom WSH!!" > list.txt:script.vbs
Dieses Script kann wie jedes andere Programm mit dem im vorletzten Abschnitt beschriebenen Kommando gestartet werden. Also wird ein böswilliger Benutzer versuchen, diesen Code zu verbergen: Eine Zeile
echo MsgBox "Viele Gruesse vom WSH!!" > list.txt:Version
Da der Datenstrom nun keine Erweiterung mehr besitzt, muss beim WSH die zu verwendende Engine mit //E angegeben werden: cscript //E:vbs.\list.txt:Version
Um unauffällig zu bleiben, wird dann oft ein Name gewählt, der auch dem misstrauischen Admin nicht auffällt: Eine Zeile
echo MsgBox "Viele Gruesse vom WSH!!" > list.txt:^ESummaryInformation cscript //E:vbs.\list.txt: ^ESummaryInformation
5.2.7
Weitere Informationen
Wie Sie sehen, sind ADS bei weitem nicht nur ein Feature für Entwickler, sondern gerade Administratoren sollten wissen, welche Möglichkeiten jeder normale Benutzer hat, Daten auf relativ unauffällige Weise zu verstecken. Sinnvoll genutzt bieten sich für Admins und Supporter einige Möglichkeiten, Daten auf NTFS-Datenträgern mit Zusatzinformationen auszustatten. Auf jeden Fall sollte das Thema aus den dunklen Ecken undokumentierter Funktion herausgeholt und auch in Schulungen vermittelt werden. Weitere Informationen, vor allem über die technische Realisierung von ADS, den Aufbau von NTFS-Dateieinträgen und die Möglichkeiten, ADS in eigenen Anwendungen zu nutzen, finden Sie in der MSDN-Library (http://msdn.microsoft.com) oder im Web (geben Sie als Suchbegriff "alternate data streams" (mit den Anführungszeichen) ein. Google beispielsweise liefert dann Hunderte von Treffern vom White Paper über C++ Sourcecode bis zu Tools zum Auslesen von ADS.
60
Echte Links
5.3
Echte Links
NTFS ist in der Lage, so genannte hard links zu erstellen. Dies ist ebenfalls ein kaum genutztes Feature von NTFS, das auch andere Dateisysteme (z.B. unter Linux) bieten. Hier kann für eine bestehende Datei ein zusätzlicher Verzeichniseintrag geschaffen werden (der in einem zusätzlichen Attribut $FILE_NAME des MFT-Eintrags gespeichert wird). Der Pfad kann dabei durchaus ein anderer sein. Ab diesem Zeitpunkt ist die Datei ebenfalls über diesen Namen ansprechbar, wobei das Dateisystem keinen Unterschied zwischen den beiden Namen macht. Im Gegensatz zu den bekannten Verknüpfungen (den shortcuts) wird dafür auch keine zweite Datei angelegt. Die Erzeugung eines solchen Links übernimmt (neben anderen Aufgaben) das Kommando fsutil. Im folgenden Beispiel werde ich zuerst eine Datei anlegen und dann einen hard link darauf setzen: C:\tmp>echo Das ist eine Datei > c:\tmp\test.txt C:\tmp>pushd d:\docs D:\docs>fsutil hardlink create demo.txt c:\tmp\test.txt Hardlink created for D:\docs\demo.txt c:\tmp\ cmds.txt D:\docs>dir Volume in drive D is Bunker Volume Serial Number is 2834-CA45 Verzeichnis of D:\docs 05.07.2003 05.07.2003 11.06.2003
23:44 . 23:44 .. 20:06 691 demo.txt 1 File(s) 691 bytes 2 Dir(s) 1,558,760,480 bytes free
D:\docs>
Wie Sie sehen, existiert nun eine Datei demo.txt, die ganz normal behandelt werden kann. Aus diesem Grund ist für das Löschen von echten Links auch kein besonderes Kommando notwendig. Sie löschen einfach mit einer der vielen Möglichkeiten von Windows die Datei. Falls dieser Eintrag für das Attribut $FILE_NAME nicht der letzte der Datei war, bleibt die Datei noch erhalten, nur der Link ist weg. Erst wenn das letzte $FILE_NAME-Attribut aus der Datei entfernt wird, wird die Datei tatsächlich gelöscht. Dies erlaubt das völlig transparente Einbinden von hard links in die Arbeit mit Windows.
61
5 Dateien im Detail
62
6
Umgebungsvariablen
Das Konzept der Umgebungsvariablen ist auch aus anderen Betriebssystemen bekannt. Dynamische Informationen oder Daten, die einfach abrufbar sein sollen, werden in der sog. Umgebung einer Session oder eines Prozesses abgelegt. Mit Hilfe von Shell-Kommandos oder GUI-Tools kann der Benutzer oder ein Prozess diese Werte auslesen und verändern. Eine ganze Reihe von Variablen wird vom System beim Start automatisch belegt, vom Installationsverzeichnis des laufenden Windows-Systems bis hin zur Prozessoridentifikation. Die Notation für diese Variablen folgt dem Schema name=wert und kennt als Datentyp nur Zeichenketten.
6.1
Grundlagen
6.1.1
Umgebungstypen
Es gibt mehrere Umgebungsvarianten. So besitzt jeder Prozess einen Speicherbereich, in dem die Umgebung für diesen Prozess definiert ist. Jeder Benutzer bekommt ebenfalls einen Umgebungsbereich (aus dem dann die Umgebung für die vom Benutzer gestarteten Prozesse erzeugt wird). Schließlich existiert noch ein Umgebungsbereich, der die Variablen enthält, die systemweit definiert sind und beim Login für jeden Benutzer kopiert werden. Ein normaler Benutzer kann daher die vom System geerbten Umgebungsvariablen zwar ändern, allerdings für seine Session und die darin laufenden Prozesse. Nur Administratoren sind in der Lage, die Einstellungen für Systemvariablen zu verändern. Nachdem jede Shell, die gestartet wird, einen eigenen Prozess darstellt, wirken sich Änderungen, die Sie in einer Shell treffen, auch nicht auf die Umgebung in einer anderen Shell aus.
6.1.2
Auflisten von Variablen
Mit Hilfe der Kommandos set und setx werden die Variablen auf Kommandozeilenebene verwaltet. In den meisten Fällen werden Sie mit set bestens zurechtkommen. setx (seit Windows 2003 im Standardumfang der Shell, vorher im Resource Kit) benötigen Sie nur dann, wenn Sie Änderungen an den Systemvariablen durchführen wollen.
63
6 Umgebungsvariablen
Die Eingabe von set ohne weitere Parameter listet alle definierten Variablen und ihre derzeitigen Inhalte auf. Da diese Ausgabe durchaus mehrere Bildschirmseiten lang sein kann, können Sie als Parameter eine Zeichenkette angeben. Es werden dann alle Variablen ausgegeben, deren Name mit dieser Zeichenkette beginnt. Daher erhalten Sie bei der Angabe set path auch immer zwei Zeilen; es existiert neben der Variablen path auch eine vordefinierte Variable pathext, deren Name ebenfalls mit der Zeichenkette „path“ beginnt. Path=C:\WINNT\system32;C:\WINNT;C:\Programme\Support Tools\ PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH
Wird keine Variable mit dem angegebenen Namensbeginn gefunden, erhalten Sie eine Fehlermeldung. Mit Hilfe des Kommandos if und der Option defined können Sie testen, ob eine Variable mit dem angegebenen Namen existiert oder nicht.
6.1.3
Vordefinierte Variablen
Die bei den Befehlserweiterungen aktivierten, automatisch erzeugten Variablen können vom Benutzer durch eine eigene Definition überschrieben werden und enthalten dann natürlich die vom Benutzer zugewiesenen Werte. Dies gilt auch für ERRORLEVEL. Die nachfolgende Tabelle zeigt eine Beispielausgabe der vordefinierten Variablen auf einer Maschine: Tabelle 6.1: Liste der vordefinierten Umgebungsvariablen
64
Variablenname
Beispielinhalt
ALLUSERSPROFILE
Profilpfad zum Default-Benutzerprofil
APPDATA
Pfad zu den Anwendungsdaten des aktuellen Benutzers
CD
Aktuelles Verzeichnis
CMDCMDLINE
Befehlszeile zum laufenden Kommandoprozessor
CMDEXTVERSION
Version der Befehlserweiterungen
CommonProgramFiles
C:\Programme\Gemeinsame Dateien
COMPUTERNAME
ORION
ComSpec
C:\WINNT\system32\cmd.exe
DATE
Datum
ERRORLEVEL
Exit-Code des letzten Kommandos
HOMEDRIVE
C:
HOMEPATH
\Dokumente und Einstellungen\Administrator
LOGONSERVER
\\ORION
Arbeiten mit Variablen
Variablenname
Beispielinhalt
NUMBER_OF_PROCESSORS
1
OS
Windows_NT
Os2LibPath
C:\WINNT\system32\os2\dll;
Path
C:\WINNT\system32;C:\WINNT;C:\WINNT\ System32\Wbem;
PATHEXT
.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;. WSF;.WSH
PROCESSOR_ARCHITECTURE
x86
PROCESSOR_IDENTIFIER
x86 Family 15 Model 0 Stepping 10, GenuineIntel
PROCESSOR_LEVEL
15
PROCESSOR_REVISION
000a
ProgramFiles
C:\Programme
PROMPT
$P$G
RANDOM
Zufallszahl zwischen 0 und 32767
SystemDrive
C:
SystemRoot
C:\WINNT
TEMP
C:\tmp
TIME
Aktuelle Zeit
TMP
C:\tmp
USERDOMAIN
ORION
USERNAME
Administrator
USERPROFILE
C:\Dokumente und Einstellungen \Administrator
windir
C:\WINNT
6.2
Arbeiten mit Variablen
6.2.1
Umgebungsvariablen mit set definieren
Sie können jederzeit noch eigene Umgebungsvariablen erzeugen. Innerhalb des Namens darf kein Gleichheitszeichen vorkommen, da dieses den Namen vom zugewiesenen Wert trennt. Variablennamen unterscheiden nicht zwischen Groß- und Kleinschreibung. Um einer Variablen einen neuen Wert zuzuweisen oder eine Variable neu anzulegen, geben Sie nach dem Namen der Variablen ein Gleichheitszeichen gefolgt vom Inhalt der Variablen an: SET database=Northwind
65
6 Umgebungsvariablen
Dies setzt den Inhalt der Variablen database auf den Wert „Northwind“. Beachten Sie, dass sämtliche führenden Leerzeichen (die nach dem „=“) mit zum Inhalt der Variablen werden. Ebenso werden nachfolgende Blanks nicht abgeschnitten, wenn diese angegeben werden. Alle Änderungen, die Sie mit set durchführen, gelten nur für die Umgebung (environment) des laufenden Prozesses (hier der Shell). In einem anderen Shell-Fenster oder den Systemeigenschaften werden Sie diese Änderungen also nicht wiederfinden.
6.2.2
Arbeiten mit setx
Seit Windows 2003 existiert eine Möglichkeit, auch von der Shell aus globale Änderungen am Environment durchzuführen. Dafür dient das Kommando setx. Vor Windows 2003 bleibt Ihnen nur der Weg über die Systemeigenschaften (für die es mit der Kombination Windows-Taste + Pause übrigens einen praktischen Shortcut gibt) oder der undokumentierte Weg über die Registry und die dort verankerten globalen Umgebungsvariablen. setx ist ein relativ komplexes Kommando und erlaubt das Erzeugen oder Verändern von Umgebungsvariablen der System- oder Benutzerumgebung. Während für die Benutzerumgebung mit set schon immer ein Kommando vorhanden war, besteht erst seit setx offiziell die Möglichkeit der Bearbeitung von Systemvariablen.
Drei Optionen von setx möchte ich gerne vorab erläutern, da diese sonst die Kommandosyntax unnötig verlängern würden. Für die Kommunikation mit anderen Maschinen oder die Nutzung eines alternativen Benutzerkontexts wird eine Möglichkeit der Authentifizierung benötigt. Hierzu dienen drei Optionen: Tabelle 6.2: Authentifizierungsoptionen für setx
/S <system>
Name des Remote-Systems
/U [<domain>\]<user> Benutzerkontext, unter dem das Kommando
läuft /P <password>
Passwort für Benutzer. Wird erfragt, falls fehlend
Die restliche Syntax beschränkt sich auf drei Aufrufmöglichkeiten: 1. SETX var value [/M] 2. SETX var /K regpath [/M] 3. SETX /F file {var {/A x,y | /R x,y string}[/M] | /X} [/ D delimiters]
Hier steht var immer für den Namen der Umgebungsvariablen und value für den zugewiesenen Wert. Die Angabe der Option /M bewirkt
66
Arbeiten mit Variablen
eine Änderung der Systemumgebung (das „M“ steht für machine wide), so dass die Änderungen in der Registry unter HKEY_LOCAL_ MACHINE abgelegt werden und nicht unter HKEY_CURRENT_USER. Normales Setzen von Variablenwerten Die erste Möglichkeit entspricht der Benutzung von set mit dem Unterschied der Option /M zum Ändern der Systemumgebung. Deshalb schenke ich mir hier weitere Erläuterungen. Variablen aus der Registry setzen Die zweite Aufrufmöglichkeit stellt eine deutliche Arbeitsersparnis gegenüber den Vorgängerversionen von Windows 2003 dar. Die Option /K (für key) liest einen Registry-Schlüssel aus und verwendet dessen Wert als neuen Inhalt der Variablen. setx tzone /K HKEY_LOCAL_MACHINE\System\ CurrentControlSet\Control\TimeZoneInformation\ StandardName
Eine Zeile
Vor Windows 2003 war für eine solche Aktion etwas mehr Aufwand Windows 2000 nötig. Zuerst musste mit Hilfe des Kommandos reg aus den Support Tools der entsprechende Schlüssel abgefragt werden: reg query HKLM\System\CurrentControlSet\Control\ TimeZoneInformation /v StandardName
Eine Zeile
Diese Ausgabe musste von allen Zeilen außer der Datenzeile befreit werden. Dazu wird per find die Zeile mit dem Datentyp gesucht (die alle mit "REG_" beginnen): reg query HKLM\System\CurrentControlSet\Control\ TimeZoneInformation /v StandardName | find "REG_" > %temp%\tmp.dat
Eine Zeile
Diese Datei wird nun per for gelesen und in eine Zuweisung der Variablen verwandelt: for /F "tokens=1,2,*" %f in (%temp%\tmp.dat) do @set tzone=%h
Eine Zeile
Variablen aus einer Datei setzen Die Syntaxvariante Nummer 3 schließlich erlaubt das Setzen von Umgebungsvariablen aus einer Datei. Aus diesem Grund existiert auch eine ganze Reihe von Optionen, mit denen die Dateiposition, Begrenzungszeichen oder Suchstrings definiert werden können.
67
6 Umgebungsvariablen Tabelle 6.3: Die Optionen für die Dateioperationen von setx
Option
Bedeutung
/F
Gibt den Namen der zu lesenden Datei an
/A x, y
Absolute Positionsangabe in der Datei (Zeile x, Wort y)
/R x, y <string>
Relative Positionsangabe zu <string> (Zeile x, Wort y)
/X
Gibt die Datei mit Positionsangaben aus (nur mit /F, /D)
/D <delims>
Definiert die Trennzeichen zwischen Wörtern
Achten Sie darauf, dass alle Zeilen- und Wortangaben nullbasiert sind! Hierzu ein Beispiel: Um den Wert der aktuell zugewiesenen IPAdresse in eine Umgebungsvariable zu bekommen, gibt es zwei Möglichkeiten. Die einfachere ist die für Windows 2003 (die für Windows 2000 finden Sie im Praxisteil19). Dazu wird mit ipconfig die IP-Konfiguration ausgegeben und in eine Datei umgeleitet. Anschließend muss nur noch bestimmt werden, welche Position in der Datei die IP-Adresse hat, und die setxAnweisung erzeugt werden. ipconfig > %temp%\tmp.dat
Jetzt lassen wir mit setx /X /F %temp%\tmp.dat die Dateipositionen ausgeben und erfahren, dass die IP-Adresse in Zeile 7, Position 14 liegt. setx ipaddr /F %temp%\tmp.dat /A 7, 14
6.2.3
Löschen von Variablen
Zum Löschen einer Variablen geben Sie den Namen gefolgt vom Gleichheitszeichen ein und drücken die Enter-Taste. Damit wird der Inhalt der Variablen und damit auch die Variable selbst gelöscht: set database=
Ein Setzen der Umgebungsvariablen mit SET erfolgt immer nur für die laufende Shell. Sind noch andere Fenster mit der Eingabeaufforderung geöffnet, übernehmen diese die Änderungen nicht. Möchten Sie Änderungen systemweit durchführen, existiert dafür seit Windows 2003 das Kommando setx. Ein mehrmaliges Löschen einer Variablen generiert übrigens keine Fehlermeldung. 19 Falls Sie neugierig geworden sind: Es funktioniert mit find und einer forSchleife, also sind Sie mit Windows 2000 nicht im Nachteil. Bevor Sie nachsehen, versuchen Sie doch, den Batch selbst zu bauen …
68
Arbeiten mit Variablen
6.2.4
Rechnen mit set (Option /a)
Die Option /a bewirkt eine Auswertung des Ausdrucks rechts vom Gleichheitszeichen als nummerischen Ausdruck. Damit sparen Sie sich in den meisten Fällen den Aufruf des Windows-Taschenrechners. Mögliche Operatoren für die Berechnung von Ausdrücken (in abnehmender Priorität): Operator
Bedeutung
()
– Gruppierung
* / % + -
– arithmetische Operatoren
|
^
Tabelle 6.4: Die Liste der Operatoren für das Kommando set /a
– UND, ODER, exkl. ODER
= *= /= %= += -= – Zuordnungsabkürzung (analog zu C++) &= ^= |= = – Zuordnung (analog zu C++) ,
– Trennung von Ausdrücken
Besitzt ein Zeichen des Ausdrucks eine besondere Bedeutung auf der Kommandozeile (wie z.B. das Zeichenpaar >>), so muss der Ausdruck komplett in doppelte Anführungszeichen eingeschlossen werden. Alle Berechnungen erfolgen mit Integer-Arithmetik, d.h., es werden keine Nachkommastellen verwendet. Ein set /a 14 / 3 ergibt als Ausgabe den Wert 4. Alle Zeichenfolgen im Ausdruck, die keine Zahlen oder Operatoren ergeben, werden als Namen von Umgebungsvariablen aufgefasst. Dies erspart Ihnen bei Berechnungen mit set /a das mühsame Einschließen der Variablennamen in Prozentzeichen. Die beiden folgenden Kommandos sind daher funktional völlig gleich, das zweite ist aber meiner Meinung nach leichter lesbar. set /A %disabled%=" %accountcontrol% & 0x02" set /A disabled=" accountcontrol & 0x02"
Konstante Zahlenwerte können (wie im obigen Beispiel zu sehen) in verschiedenen Zahlensystemen angegeben werden. Nummerische Werte stellen immer Dezimalzahlen dar, es sei denn, sie haben ein Präfix 0x für hexadezimale Zahlen oder 0 für oktale Zahlen. Damit stellt 0x12 dieselbe Zahl wie 18 oder 022 dar. Beachten Sie, dass die oktale Schreibweise verwirrend sein kann: So sind 08 und 09 keine gültigen Zahlen, da 8 und 9 keine erlaubten oktalen Ziffern sind20. Die Ausgabe erfolgt dagegen immer im Dezimalformat. 20 Aus diesem Grund sollten Sie auch niemals bei IP-Adressen führende Nullen angeben, viele andere Programme interpretieren diese Zahlen dann ebenfalls als oktal.
69
6 Umgebungsvariablen
Einen praktischen Einsatz findet set /a auch bei Arbeiten mit Bitflags. Im ActiveDirectory existiert für jeden Benutzer ein Attribut mit dem Namen userAccountControl. Die Werte dieses Attributs sind bitweise definiert. Das Bit mit dem Wert 2 beispielsweise legt fest, ob ein Account deaktiviert ist oder nicht. Um also einen Benutzer zu deaktivieren, müssen Sie nur den derzeitigen Wert auslesen (z.B. mit ldifde), dann per set /a den Wert 2 mit einem Oder verknüpfen und wieder zurückschreiben21. Im Kapitel 16.4.5 finden Sie die Vorstellung eines Shell Scripts, das genau diese Aufgaben erledigt.
6.2.5
Eingaben mit set (Option /p)
In vielen Fällen wird für die Ausführung eines Shell Scripts eine Eingabe vom Benutzer benötigt. Hierfür ist die Option /p gedacht. Dabei wird als Variableninhalt rechts vom Gleichheitszeichen die Meldung für den Benutzer ausgegeben, und die Eingabe des Benutzers wird anschließend der Inhalt der Variablen. Dazu ein Beispiel: set /p server=Bitte geben Sie den Servernamen ein:
Auf der Konsole wird dann der Text Bitte geben Sie den Servernamen ein: ausgegeben, und das System wartet auf eine Eingabe. Diese Eingabe kann natürlich auch per Umleitung aus einer Datei kommen. Die Variable server enthält anschließend die Eingabe des Benutzers. War die Variable vorher noch nicht belegt und der Benutzer gibt eine Leerzeile ein, wird die Variable nicht belegt. Weisen Sie daher der Variablen in einer Batchdatei immer einen Defaultwert zu, den Sie nach der Eingabemöglichkeit testen. So können Sie ohne Probleme feststellen, ob eine tatsächlich eine Eingabe erfolgt ist oder nicht. Bei einer Eingabeumleitung zusammen mit set /p wird die erste Zeile der Datei als Eingabezeile verwendet, die restlichen Zeilen werden ignoriert. Ein Pipelining funktioniert dagegen nicht. Hier als Beispiel eine kleine Datei (die auf der Autorenmaschine den Namen x.x trägt): Dies ist ein kurzer Text. Schon zu Ende ...
Zuerst versuche ich, ein Pipelining zu nutzen: type x.x | set /P zeile=Bitte eine Zeile eingeben:
Ein anschließendes set zeile liefert die Fehlermeldung „Umgebungsvariable zeile ist nicht definiert“. Klappt also nicht … 21 Oder Sie benutzen Windows 2003 und das Kommando dsmod …
70
Arbeiten mit Variablen
Nun versuche ich es mit Hilfe einer Eingabeumleitung: set /P zeile=Bitte eine Zeile eingeben: < x.x
Gebe ich nun set zeile ein, erhalte ich folgende Ausgabe: zeile=Das ist
Dieser Ansatz funktioniert ohne Probleme! Denken Sie daran, falls Sie Werte mit set über die Umleitung aus anderen Dateien setzen wollen22.
6.2.6
Ausgabe von Variableninhalten
Variablenexpansion Wird der Inhalt einer definierten Variablen für eine Ausgabe oder einen Befehl benötigt, so wird der Name der Variablen in Prozentzeichen eingeschlossen. Die Shell ersetzt dann bei der Ausführung des Kommandos diesen Ausdruck durch den Inhalt der Variablen. Der Befehl echo Die Zeit auf dem Rechner %computername% ist %time%
erzeugt so die Ausgabe (auf meinem Rechner): Die Zeit auf dem Rechner ORION ist 15:09:03,37
Ist die angegebene Variable nicht definiert, wird einfach der in Prozentzeichen eingeschlossene Name der Variablen ausgegeben und keine leere Zeichenkette! Dies ist bei der Erstellung von Batches zu beachten. Programmieren Sie eine entsprechende Abfrage, oder verwenden Sie das Kommando if defined für eine bedingte Ausführung des Befehls. Die Shell ersetzt Variablen normalerweise bei der Aktivierung eines Kommandos durch die jeweiligen Inhalte, nicht dynamisch zur Ausführungszeit. Wie Sie in Kapitel 8.1 erfahren, lassen sich mehrere Kommandos in einer Befehlszeile eingeben. Sobald Sie per Druck auf RETURN diese ausführen lassen, werden die Variablen ersetzt. Dies kann zu unerwünschten Resultaten führen. Wenn sie echo %time% & machwas.exe & echo %time% als Kommando ausführen lassen, wird zuerst die Zeit ausgegeben, dann machwas.exe ausgeführt, und danach wird wieder die Zeit ausgegeben. Trotzdem können Sie mit dieser Konstruktion nicht die Zeit für die Ausführung von machwas.exe messen, denn die Shell hat beide Variablen %time% bereits beim Start der Kommandokette expandiert, und somit erhalten Sie zweimal die gleiche Zeit. Als Lösung können Sie jeweils die Zeit mit Hilfe des Kommandos time /t ausgeben lassen, oder Sie nutzen die im nächsten Abschnitt
erläuterte verzögerte Auflösung von Variablen. 22 Ganz nebenbei ist dies eine vorzügliche Methode, um aus einer bestehenden Textdatei ohne jeden Aufwand die erste Zeile zu extrahieren.
71
6 Umgebungsvariablen
Verzögerte Variablenexpansion Der Weg aus dem obigen Dilemma nennt sich delayed expansion, also verzögerte Variablenerweiterung. Dies ist eine Funktion der Shell, die standardmäßig nicht aktiviert ist. Ein- und ausgeschaltet wird dies entweder durch die Startoption /V der Shell (s. Abschnitt 3.0.2) bzw. den Registry-Schlüssel DelayedExpansion (s. Abschnitt 3.2.1). Diese Funktion ist wohl aus gutem Grund nicht aktiviert, da sie für einen Einsteiger in die Windows Shell nicht ohne weiteres zu überblicken ist. Nach der Aktivierung der verzögerten Variablenexpansion kann der Name einer Variablen statt in Prozentzeichen auch in Ausrufezeichen eingeschlossen werden (z.B. !IPADDRESS!) und wird dann von der Shell zur tatsächlichen Ausführungszeit und nicht bei der Eingabe expandiert. Die Auswirkung möchte ich Ihnen am obigen Zeitmessungsbeispiel demonstrieren. Die Befehlszeile unten gibt die Zeit zum Zeitpunkt der Eingabe aus. Dann folgt eine Pause (Warten auf einen Tastendruck) und danach nochmals die Ausgabe einer Zeit2. echo %time% & pause & echo %time%
Wenn Sie diese Kommandozeile ausführen, erhalten Sie folgende Ausgabe23 (ganz egal, wie lange Sie auf einen Tastendruck warten): 1:46:43,90 Drücken Sie eine beliebige Taste ... 1:46:43,90
Alle zwei Ausgaben zeigen die gleiche Zeit an, da die Shell die Expansion der Variablen zur Zeit der Eingabe für den gesamten Eingabestring vornimmt. Jetzt starte ich eine neue Shell mit verzögerter Variablenauswertung (am einfachsten per DATEI/AUSFÜHREN und cmd /v:on) und gebe die Befehlszeile nochmals ein. Allerdings ersetze ich bei der ersten und zweiten Zeitausgabe die Prozentzeichen durch ein Ausrufezeichen, um die verzögerte Variablenexpansion zu nutzen. echo !time! & pause & echo !time!
Das ist die neue Ausgabe: 1:48:23,67 Drücken Sie eine beliebige Taste ... 1:49:05,53
Mit Hilfe dieser Syntax wird eine Variablen wirklich erst dann durch ihren Inhalt ersetzt, wenn das entsprechende Kommando auch ausgeführt wird. Ich weiß nicht, wie es Ihnen geht, aber dies ist das Verhalten, dass ich eigentlich als Standard von einer Shell erwarten würde … 23 Natürlich mit Ihrer Uhrzeit, nicht der hier abgedruckten.
72
Arbeiten mit Variablen
Damit lassen sich indirekte Referenzen auf Variablen auflösen. Eine indirekte Referenz ist eine Variable, die als Inhalt den Namen einer weiteren Variablen enthält, die dann den tatsächlichen Wert liefert. Bestimmte Aufgabenstellungen lassen sich nur so ohne großen Aufwand lösen: Für ein Projekt hatten wir eine schnelle Abfrage bestimmter Steuerparameter einer Maschine zu erstellen. Diese Parameter waren in verschiedenen Umgebungsvariablen gespeichert (einer der Projektmitarbeiter war ein eingefleischter Anhänger von Unix-Shells). Was wir brauchten, war also ein Shell Script (ein Batch) mit folgender Funktionalität: warten auf eine Benutzereingabe, Ausgabe in der Form „Variable x hat den Wert y“. Mit Hilfe der verzögerten Variablenexpansion ließ sich das in wenigen Zeilen lösen (hier ein vereinfachter Ausschnitt des Batches): set was= set /P was=Bitte Name der Variablen eingeben: if not defined was goto eof echo Der Inhalt von %was% = !%was%! :eof
Listing 6.1: Beispiel für eine verzögerte Variablenexpansion
Der interessante Teil ist die fett gedruckte Bezeichnung !%was%!. Was passiert an dieser Stelle? Zuerst wird beim Laden der Batchzeile sofort der Ausdruck %was% durch den Inhalt der Variablen ersetzt. Nehmen wir an, die Variable enthielt den Wert ipaddress. Also sieht die Zeile nun folgendermaßen aus: echo Der Inhalt von ipaddress = !ipaddress!
Durch die verzögerte Variablenexpansion wird nun bei der Ausführung des echo-Kommandos der Wert von ipaddress durch den Wert dieser Variablen ersetzt, und wir erhalten das gewünschte Ergebnis: Der Inhalt von ipaddress = 192.168.42.42
Insgesamt also eine sehr nützliche Einstellung, wenn auch etwas Einarbeitungszeit dazugehört. Zum Abschluss noch die Klärung einer Frage: Wie testen Sie eigentlich, ob die verzögerte Variablenexpansion eingeschaltet ist? Natürlich könnten Sie per Kommando reg einfach den entsprechenden Schlüssel in der Registry abfragen, es geht aber auch mit einer Zeile in der Shell: set was=123 if !was! == %was% echo Delayed Expansion ON!
Ist die verzögerte Auswertung nicht eingeschaltet, dann bleibt !was! einfach als Textausdruck stehen, während %was% zu 123 erweitert wird. Erweiterte Variablenexpansion Nicht in allen Fällen ist eine einfache Ersetzung des Platzhalters durch den Inhalt der Variablen ausreichend. So ist es beispielsweise oft wünschenswert, Leerzeichen aus dem Inhalt zu entfernen, nur einen Teil des Variablenwertes zu übernehmen oder anderweitige
73
6 Umgebungsvariablen
Umformungen vorzunehmen. Bei der Ausgabe aus dem vorherigen Abschnitt stört mich beispielsweise die Angabe der Hundertstelsekunden (so schnell tippe ich mit meinem 6-Finger-System auch wieder nicht, als dass ich diese Angabe wirklich brauchen würde). Mit den Befehlserweiterungen der Windows Shell ist dies kein Problem. Um dieses besondere Verhalten zu aktivieren, wird innerhalb der Prozentzeichen nach dem Namen der Variablen ein Doppelpunkt gesetzt, dem die gewünschte Operation folgt. Tabelle 6.5: Möglichkeiten der erweiterten Variablenersetzung
%var:x=y%
ersetzt jedes Auftreten des Strings x durch den String y
%var:x=%
löscht jedes Auftreten des Strings x
%var:*x=y%
ersetzt alles bis zum Auftreten von String x durch den String y
%var:~n,m%
gibt ab dem Offset n (beginnt bei 0!) genau m Zeichen aus, negative Zahlen zählen ab dem Ende
%var:~n%
gibt ab dem Offset n (beginnt bei 0!) den Rest der Zeichen aus, negative Zahlen zählen ab dem Ende
Damit können Sie das Kommando zur Zeitausgabe einfach erweitern: echo Die Zeit auf dem Rechner %computername% ist %time:~0,-3%
Das erzeugt so die Ausgabe (auf meinem Rechner): Die Zeit auf dem Rechner ORION ist 15:09:03
Denken Sie auch daran, dass diese Veränderungen nur für die Ausgabe des Variableninhalts an der Stelle dieses Platzhalters gelten, der tatsächliche Inhalt der Umgebungsvariablen wird davon nicht berührt. Damit sind Sie in der Lage, alle notwendigen Manipulationen an Variableninhalten durchzuführen, die für komplexe Befehlsabläufe benötigt werden. %time:~6,2% liefert beispielsweise die aktuellen Sekunden der Systemuhr für die automatische Vergabe von Dateinamen. Um aus einem Variableninhalt alle Leerzeichen zu entfernen, verwenden Sie den Ausdruck %varname: =%. Mit einer kreativen Anwendung der erweiterten Ersetzung sind auch fortgeschrittene Umformungen kein Problem mehr. Angenommen, in der Variablen server ist der vollqualifizierte DNS-Name eines Rechners gespeichert: set server=kiste.firma.de
Alles, was Sie für die Umwandlung in einen LDAP-String benötigen, ist eine einzige Zeile: echo cn=%server:.=,dc=%
Alle Vorkommen des Punkts werden durch die Zeichenkette ,dc= ersetzt. Hier die Ausgabe: cn=kiste,dc=firma,dc=de
74
Arbeiten mit Variablen
Mehrfaches Verwenden dieser Funktionen in einer Ersetzung sind nicht möglich. Weisen Sie das Ergebnis dieser Ersetzung einer Zwischenvariablen zu, und bearbeiten Sie diese dann weiter.
6.2.7
Die Variable errorlevel
Jedes Kommando, das von der Shell gestartet wird, wird üblicherweise irgendwann beendet. Das Ende des Kommandos oder des externen Prozesses liefert einen Code an die Shell zurück, mit dem der Erfolg oder eine bestimmte Fehlerbedingung signalisiert werden kann. Dieser Code wird als Exit-Code oder errorlevel bezeichnet und in der vordefinierten Variablen errorlevel gespeichert. So kann per Shell jederzeit festgestellt werden, ob ein Kommando erfolgreich abgearbeitet wurde oder nicht. Natürlich benötigen Sie dazu eine Dokumentation über die einzelnen Fehlercodes für den jeweiligen Prozess oder das Kommando. Innerhalb der Windows-Welt hat sich hierbei eine gewisse Konvention herausgebildet: Alle „erfolgreichen“ Aktionen liefern einen erorrlevel von 0 zurück. Ein von 0 verschiedener Wert bedeutet eine Warnung oder einen Fehler. Was nun „erfolgreich“ bedeutet, wird von den Entwicklern externer Kommandos und Applikationen definiert. So liefert das find-Kommando einen Errorlevel von 0 bei einer Übereinstimmung mit dem Suchstring und 1, wenn nichts gefunden wurde. Das Kommando xcopy.exe liefert den Errorlevel 4, wenn die Datei nicht gefunden wurde, und 1, wenn eine Datei auf sich selbst kopiert werden sollte. Für die meisten Applikationen und Tools finden Sie die Werte in der Dokumentation unter den Stichpunkten „error codes“ oder „exit codes“.
6.2.8
setlocal & endlocal
Innerhalb von Shell Scripts werden oft Änderungen an Umgebungsvariablen durchgeführt. Viele dieser Änderungen werden nur während der Laufzeit des Shell Scripts benötigt und müssten im Normalfall am Ende eines Batches aufwändig wieder rückgängig gemacht werden. Daher existiert seit Windows 2000 die Möglichkeit, mit Hilfe von setlocal den Gültigkeitsbereich von Änderungen am Environment auf die laufende Batchdatei zu beschränken. Bei Ende des Batches muss dann wieder mit Hilfe von endlocal diese Einschränkung aufgehoben werden. Falls kein endlocal erfolgt, führt die Batch-Engine implizit für jede noch offene setlocal ein endlocal aus. Achten Sie aus Gründen der Wartbarkeit aber dennoch darauf, für jedes setlocal in Ihren Shell Scripts auch ein entsprechendes endlocal zu schreiben.
75
6 Umgebungsvariablen
76
7
Kommandoausführung
7.1
Ausführbarkeit von Dateien
7.1.1
Ausführbare Dateien mit pathext definieren
Wie stellt die Shell überhaupt fest, ob ein Kommando ausführbar ist bzw. welches Programm bei der Eingabe eines nicht ausführbaren Kommandos gestartet werden soll? Unter Windows wird für diese Kennzeichnung die Erweiterung einer Datei verwendet, also der Teil des Dateinamens nach dem letzten Punkt. In anderen Betriebssystemen existiert keine solche Unterscheidung, sondern eine Datei wird einfach als „ausführbar“ markiert (so z.B. in allen Unix-artigen Betriebssystemen). Die Erweiterungen aller direkt ausführbaren Dateien werden in der Umgebungsvariablen pathext abgelegt. Mehrere Einträge werden dabei durch ein Semikolon getrennt. Hier der Inhalt dieser Variablen nach einer Standardinstallation: PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH
Alle Dateien, die eine der aufgelisteten Erweiterungen tragen, können durch die Angabe ihres Dateinamens in der Shell direkt ausgeführt werden, die Angabe der Erweiterung ist nicht notwendig. Genau hier liegt aber meiner Meinung nach ein potenzielles Sicherheitsrisiko: Wie aus der Ausgabe ersichtlich, werden auch alle Dateien des Windows Script Host (.vbs, .js, .vbe, .jse, .wsf und .wsh) einfach durch die Angabe des Namens ausgeführt. Ein kleines Beispielszenario verdeutlicht meine Bedenken gegenüber dieser Standardeinstellung: Ich möchte in der Shell nur schnell den Inhalt einer Variablen überprüfen. Gleichzeitig liegt auf meiner Maschine im aktuellen Verzeichnis oder im Suchpfad eine Datei mit dem Namen eco.vbs, die mir ein netter Zeitgenosse dort abgelegt hat. Statt des gewünschten Kommandos echo verschreibe ich mich und tippe nur eco %time%. Als Ergebnis führt das System die Datei eco.vbs aus, mit allen möglichen Konsequenzen! Daher empfehle ich Ihnen, aus der Systemvariablen pathext (per SYSTEMEIGENSCHAFTEN oder setx) die Scripterweiterungen zu entfernen. Alle VB-Scripte für den WSH bleiben natürlich immer noch nutzbar, aber ich muss jetzt die Erweiterung (z.B. .vbs) mit angeben und weiß damit, dass ich ein ActiveX-Script starte. Auf jeden Fall
77
7 Kommandoausführung
kann ich dies nicht mehr unabsichtlich durch einen kleinen Vertipper tun. Durch die Dateinamenvervollständigung ist dies auch nicht mehr Schreibarbeit, aber mein System ist etwas fehlertoleranter. Andererseits kenne ich eine Reihe von Administratoren, die in diese Liste der Erweiterungen in pathext die Erweiterung .msc aufgenommen haben. Dies sind die abgespeicherten Managementkonsolen. Nach dieser Änderung kann z.B. ACTIVE VERZEICHNIS USERS AND COMPUTERS einfach durch die Eingabe dsa gestartet werden. Sehr praktisch …
7.1.2
assoc & ftype
Was passiert, wenn ich einen Dateinamen als Kommando eingebe, dessen Erweiterung nicht in der Liste der ausführbaren Erweiterungen vorhanden ist? Dann wird das damit verknüpfte Programm gestartet. Für alle Dateien mit der Erweiterung .txt ist dies standardmäßig notepad.exe, der Editor. In der GUI ist diese Verknüpfung relativ einfach zu kontrollieren: Über den Explorer lässt sich mit EXTRAS/ORDNEROPTIONEN im Reiter DATEITYPEN diese Einordnung nachsehen und ändern. Aber auch auf Shell-Ebene existieren Kommandos für die Verwaltung dieser Zuordnung. Microsoft hat diese Funktionalität allerdings nicht ganz optimal implementiert. Es existieren zwei Kommandos, eines für die Verwaltung der registrierten Dateitypen (assoc) und ein zweites (ftype) für die Zuordnung des zu startenden Programms. Das Kommando assoc sucht für eine angegebene Erweiterung den registrierten Dateityp heraus und gibt diesen auf der Konsole aus: C:\tmp>assoc .bmp .txt=Paint.Picture
Wird keine Erweiterung angegeben, gibt assoc eine Liste aller registrierten Dateierweiterungen des Systems und der damit verknüpften Dateitypen aus. Das Kommando kann aber auch in der Form assoc .erw=dateityp verwendet werden, um die Zuordnung zu ändern. Erfolgt keine Angabe eines Dateityps, wird die Zuordnung der Erweiterung gelöscht. Damit haben wir aber erst einen Teil der Aufgabe gelöst, immerhin wissen wir nun, dass eine .bmp-Datei ein „Paint.Picture“ ist. Für den Rest ist das Kommando ftype zuständig. Dieses Kommando erwartet die Angabe eines Dateityps und gibt den zugeordneten Handler aus, also das Programm, das tatsächlich gestartet wird. Sehen wir uns die zum obigen Beispiel passende Ausgabe an: C:\tmp>ftype Paint.Picture Paint.Picture="C:\WINNT\System32\mspaint.exe" "%1"
78
Das Kommando start
Auch hier wird wieder die komplette Liste aller Handler ausgegeben, wenn beim Aufruf kein Dateityp angegeben wird. Sie wollen wissen, für welche Dateitypen auf Ihrem System der Internet Explorer zuständig ist? Kein Problem: C:\tmp>ftype | find /i "iexplore.exe" Adobe.SVGCtl="C:\Programme\IE\iexplore.exe" –nohome (viele Zeilen gelöscht) : xmlfile="C:\Programme\IE\iexplore.exe" –nohome xslfile="C:\Programme\IE\iexplore.exe" -nohome
Ich habe die Liste hier aus Platzgründen gekürzt. Durch die Kombination mit dem Filterkommando find ist es einfach, alles Vorkommen der Datei iexplore.exe (dem IE) herauszufiltern. Mehr Informationen zu den Filtern finden Sie im Kapitel 4.3.2, dort wird find ausführlich behandelt. Sicherlich denken Sie jetzt auch: „Wäre ja toll, wenn das in einem Aufruf ginge, anstatt nacheinander zwei Befehle zu benutzen und sich eine Ausgabe auch noch zu merken.“ Sie haben Recht, es ist wesentlich praktischer und ein schönes Beispiel, wie sich Batches, Makros und andere Konzepte sinnvoll einsetzen lassen. Im Kapitel über die Nutzung von for finden Sie die Lösung zu diesem Problem (Abschnitt 9.2.8). ftype kann aber auch genau wie assoc als Zuweisungskommando benutzt werden. Setzen Sie dazu hinter den Dateityp ein Gleichheitszeichen gefolgt vom kompletten Pfadnamen des auszuführenden Programms. Dies entspricht der Änderung im Windows Explorer über EXTRAS/ORDNEROPTIONEN und DATEITYPEN. Wenn Sie dort die Schaltfläche ERWEITERT anklicken, können Sie dort die Zuordnung für das open-Ereignis einstellen. Ein schönes Beispiel, wie effizient die Arbeit mit der Shell sein kann.
7.2
Das Kommando start
Das Kommando start entspricht nur ungefähr der Funktion von START/AUSFÜHREN. Darüber hinaus können Prozesse mit anderer Priorität gestartet, URLs oder Verzeichnisse geöffnet werden, und es kann auf das Ende des gestarteten Prozesses gewartet werden. Hier die komplette Syntax für start: START ["Titel"] [/Dpath] [/I] [/MIN] [/MAX] [/SEPARATE | /SHARED] [/LOW | /NORMAL | /HIGH | /REALTIME] | / ABOVENORMAL | /BELOWNORMAL] [/WAIT] [/B] [Befehl/Programm] [Parameter]
Die folgende Tabelle listet die Bedeutung der einzelnen Optionen für das Kommando start auf.
79
7 Kommandoausführung Tabelle 7.1: Optionen für das start-Kommando
Option
Bedeutung
"Titel"
Der Titel des neuen Fensters.
Pfad
Startverzeichnis.
B
Startet Anwendung, ohne ein neues Fenster zu öffnen. Die Anwendung ignoriert (STRG)+(C). Wenn die Anwendung nicht selbstständig (STRG)+(C) überprüft, ist (STRG)+(UNTBR) die einzige Möglichkeit, um die Anwendung abzubrechen.
I
Die CMD.EXE beim Aufruf übergebene Umgebung soll die neue aktuelle Umgebung sein.
MIN
Startet das Fenster minimiert.
MAX
Startet das Fenster maximiert.
SEPARATE
Startet 16-Bit-Windows-Programm in separatem Speicherbereich.
SHARED
Startet 16-Bit-Windows-Programm im gemeinsamen Speicherbereich.
LOW
Startet in IDLE-Prioritätsklasse.
NORMAL
Startet in der NORMAL-Prioritätsklasse.
HIGH
Startet in der HIGH-Prioritätsklasse.
REALTIME
Startet in der REALTIME-Prioritätsklasse.
ABOVENORMAL
Startet in der ABOVENORMAL-Prioritätsklasse.
BELOWNORMAL
Startet in der BELOWNORMAL-Prioritätsklasse.
WAIT
Startet die Anwendung und wartet auf das Ende.
Befehl/Programm
Wenn ein interner Befehl oder eine Batchdatei verwendet wird, wird das neue CMD-Fenster mit Parameter /K gestartet. Das bedeutet, dass das Fenster erhalten bleibt, nachdem der Befehl ausgeführt wurde. Wenn dies nicht der Fall ist, wird das Programm entweder als Anwendung in einem Fenster oder als Konsolenanwendung gestartet.
Parameter
Parameter, die an den Befehl oder das Programm übergeben werden sollen.
Erst mit Hilfe dieses Kommando erhalten Sie also die komplette Kontrolle über gestartete Prozesse! Diese Optionen finden Sie nicht im GUI, daher ist dies auch die einzige Möglichkeit für Benutzer, ein Programm zu starten, das mehr CPU-Leistung als andere Programme erhält. Ich empfehle Ihnen aber, die Prioritätsklasse „High“ nur mit Bedacht und „Realtime“ gar nicht einzusetzen. Mit „High“ läuft der Task-Manager und mit „Realtime“ Teile des Betriebssystems. Falls Sie sich also prozesstechnisch in die Ecke gepinselt haben, ich hatte Sie gewarnt … Noch mehr Details zu den einzelnen Optionen erhalten Sie, wenn Sie start einfach mit der Option /? aufrufen.
80
Das Kommando runas
7.3
Das Kommando runas
Falls Sie gerade vor einem Computer sitzen, wie sind Sie angemeldet? Als ganz normaler Benutzer oder mit administrativen Rechten? Was könnte im schlimmsten Fall passieren? Aus diesen Gründen haben mittlerweile fast alle Administratoren mehr als einen Account: einen ganz normalen für die tägliche Arbeit mit Office & Co. und mindestens einen weiteren, administrativen Account für Verwaltungsaufgaben. Viele Administratoren wechseln zwischen diesen beiden immer noch durch Ab- und Anmelden hin und her. Viel einfacher geht dies aber mit Hilfe des Kommandos runas, das dem Unix-Kommando su nachempfunden wurde. Hier wird ein Prozess mit den angegebenen Anmeldeinformationen gestartet, ohne dass Sie Ihre Sitzung unterbrechen müssen. Der einfachste Aufruf sieht wie folgt aus: RUNAS /user: Programm
Öffnen Sie sich doch einfach damit eine Administrator-Shell mit dem Kommando runas /user:<usr> "%systemroot%\system32\cmd.exe"
Alle Kommandos, die Sie aus dieser Shell starten, laufen im Kontext des administrativen Kontos, und Sie ersparen sich unnötiges An- und Abmelden. Damit Sie diese Shell nicht mit einer „normalen“ verwechseln, sollten Sie diese entsprechend kennzeichnen. Ich stelle dazu meist den Titel des Shell-Fensters um und wähle eine entsprechend markante Farbkombination für Vordergrund und Hintergrund. Damit fällt mir schnell auf, dass ich die Befehle nicht in der „Normaler-Benutzer-Shell“ eingebe. Tipps dazu finden Sie im Kapitel „Laufzeitkonfiguration“ (Kapitel 3.3). Natürlich können Sie beide Methoden (start und runas) kombinieren, indem Sie mit runas ein entsprechendes start-Kommando absetzen. Auch das Windows GUI unterstützt übrigens mit dem Explorer das Ausführen von Programmen in einem anderen Security-Kontext. Dazu halten Sie einfach eine der beiden (ª)-Tasten gedrückt und klicken mit der rechten Maustaste auf das Programm. Im Kontextmenü erscheint dann ein Eintrag AUSFÜHREN ALS …, mit dem Sie die gewünschten Benutzerdaten auswählen können. Dies erspart langwieriges Ab- und Anmelden, gerade bei Supporteinsätzen am Computer des Benutzers.
81
7 Kommandoausführung
7.4
Prozessverwaltung mit der Shell
Jeder Benutzer kennt sicherlich den Task-Manager, mit dem Prozesse oder widerspenstige Programme beendet und die Systemleistung verfolgt werden können. Es gibt aber auch die Möglichkeit der Prozessverwaltung per Kommandozeile, die einige Möglichkeiten bietet, die im Task-Manager nicht enthalten sind. Gerade für Administratoren, die regelmäßig auch auf entfernten Systemen beobachten müssen, welche Prozesse laufen, kann dies eine große Arbeitserleichterung sein.
7.4.1
tlist oder tasklist?
Für die Verwaltung von Prozessen stehen zwei unterschiedliche Kommandosets zur Verfügung. Bis zu Windows 2000 existieren in den Support Tools die beiden Kommandos tlist und kill. Ab Windows XP heißen diese beiden Kommando tasklist und taskkill. Dies wäre an sich nur ein kleineres Problem, allerdings unterscheiden sich tlist und tasklist auch in ihrer Funktionalität. Dies vor allem so, dass in jedem Kommando Möglichkeiten enthalten sind, die das andere nicht hat. Auch unter Windows 2003 lassen sich die Support Tools von Windows 2000 verwenden, und tlist.exe ist eines der Programme, die auch unter Windows 2003 gute Dienste leisten, wie die folgenden Abschnitte zeigen.
7.4.2
Prozessinformationen
Jeder Prozess in Windows wird durch seine Prozess-ID (pid) identifiziert. Der Name des Prozesses kann also durchaus öfter auftreten, wenn Sie zum Beispiel mehrere Notepad-Fenster öffnen.
7.4.3
tlist
Der Aufruf von tlist ohne Parameter liefert eine einfache Prozessliste analog der Auflistung im Task-Manager. Listing 7.1: Beispielausgabe von tlist
82
C:\Buecher\Shell-Buch>tlist 0 System Process 8 System 152 SMSS.EXE 192 CSRSS.EXE 212 WINLOGON.EXE NetDDE Agent 240 SERVICES.EXE 252 LSASS.EXE 436 svchost.exe 464 spoolsv.exe 620 svchost.exe 648 mdm.exe
Prozessverwaltung mit der Shell 724 764 848 980 1008 1288 1164 1316 1344 1348 1404 1408 1488 1248 444
regsvc.exe mstask.exe stisvc.exe WinMgmt.exe svchost.exe explorer.exe soundman.exe type32.exe fpassist.exe point32.exe internat.exe IWatch.exe WINWORD.EXE CMD.EXE tlist.exe
SYSTEM AGENT COM WINDOW
Program Manager Avance Sound Effect Control Panel FreePDF_Assistant
ISDNWatch Shellbuch.doc - Microsoft Word C:\WINNT\system32\cmd.exe - tlist
Sie sehen eine Liste aus pid, Prozessname und Fenstertitel, die der Ausgabe im Task-Manager ähnelt. tlist kann allerdings noch mehr: Wenn Sie eine gültige pid als Argument angeben, liefert tlist Detailinformationen zum angegebenen Prozess. C:\Buecher\Shell-Buch>tlist 1248 1248 CMD.EXE C:\WINNT\system32\cmd.exe - tlist 1248 CWD: C:\Buecher\Shell-Buch\ CmdLine: "C:\WINNT\system32\cmd.exe" VirtualSize: 11432 KB PeakVirtualSize: 11496 KB WorkingSetSize: 1120 KB PeakWorkingSetSize: 1124 KB NumberOfThreads: 1 1136 Win32StartAddr:0x4ad1a4b0 LastErr:0x000000cb State:Waiting 5.0.2195.6824 shp 0x4ad00000 cmd.exe 5.0.2195.6899 shp 0x77880000 ntdll.dll 5.0.2195.6897 shp 0x77e70000 KERNEL32.dll 5.0.2195.6897 shp 0x77e00000 USER32.dll 5.0.2195.6898 shp 0x77f40000 GDI32.DLL 5.0.2195.6876 shp 0x79350000 ADVAPI32.dll 5.0.2195.6802 shp 0x77d20000 RPCRT4.DLL 6.1.9844.0 shp 0x78000000 MSVCRT.dll
Listing 7.2: Detailinformationen zum Prozess cmd.exe
Anhand dieser Liste kann ein Administrator oder Betreuer für jeden laufenden Prozess die exakte Version einer geladenen DLL feststellen; ob eine DLL, die ersetzt werden soll, noch im Speicher liegt; wie viel Speicher der Prozess belegt und vieles mehr. Über den Schalter -m und die Angabe einer DLL lässt sich sogar mit nur einem Kommando herausfinden, welche Prozesse die angegebene DLL referenzieren: H:\Armin\Buecher\Shell-Buch>tlist -m wininet.dll WININET.dll - 1008 svchost.exe WININET.dll - 1288 explorer.exe Program Manager WININET.DLL - 1148 ccApp.exe
Listing 7.3: Wer benutzt die wininet.dll?
83
7 Kommandoausführung tlist kann helfen, ein weiteres Rätsel zu lösen. Im Task-Manger finden
Sie nach einem Rechtsklick auf einen Prozess nicht nur die Auswahl PROZESS BEENDEN, sondern auch PROZESSSTRUKTUR BEENDEN (end process tree bei einem englischen Windows). Wie stellen Sie aber fest, welche Prozesse von diesem Prozess gestartet wurden? Ganz einfach, über die Option -t von tlist. Ein Beispiel der Ausgabe von einem meiner Rechner; aus Platzgründen habe ich die Liste etwas gekürzt. Listing 7.4: Ausgabe des Prozessbaumes
H:\Armin\Buecher\Shell-Buch>tlist -t System Process (0) System (8) SMSS.EXE (152) CSRSS.EXE (192) WINLOGON.EXE (212) NetDDE Agent SERVICES.EXE (240) svchost.exe (436) spoolsv.exe (464) svchost.exe (620) mdm.exe (648) regsvc.exe (724) mstask.exe (764) SYSTEM AGENT COM WINDOW stisvc.exe (848) WinMgmt.exe (980) svchost.exe (1008) LSASS.EXE (252) explorer.exe (1288) Program Manager soundman.exe (1164) Avance Sound Effect Control Panel ccApp.exe (1148) type32.exe (1316) fpassist.exe (1344) FreePDF_Assistant point32.exe (1348) internat.exe (1404) IWatch.exe (1408) ISDNWatch WINWORD.EXE (1488) Shellbuch.doc - Microsoft Word CMD.EXE (1248) C:\WINNT\system32\cmd.exe - tlist -t tlist.exe (1448) CMD.EXE (660) C:\WINNT\system32\cmd.exe - ftp FTP.EXE (1252) CMD.EXE (1444) notepad.exe (164) Unbenannt - Editor
Man erkennt leicht, dass das System den Session Manager (smss.exe) und dieser das Windows-Subsystem (csrss.exe), den Logon-Dienst (winlogon.exe) und die lokale Sicherheitsautorität (lsass.exe) gestartet hat. Für mein Benutzerkonto sehe ich, dass der Explorer als Startprozess läuft und unter dessen Kontrolle zwei Instanzen der Shell gestartet wurden (pid 1248 und pid 660). In einer der Shells läuft ftp (pid 1252), aus dem ich per !cmd eine weitere Shell und von da aus Notepad gestartet habe. Wird nun der Prozessbaum für die pid 1444 beendet, betrifft dies auch den Notepad-Prozess mit der pid 164, da dieser von Prozess 1444 gestartet wurde.
84
Prozessverwaltung mit der Shell
Es gibt noch eine Reihe weiterer Optionen wie die Auflistung aller in einem Prozess laufenden Services oder die Suche nach Prozessnamen mit einem regulären Ausdruck. Ich überlasse Ihnen das als Übung und bin mir sicher, dass auch auf Ihrem System tlist noch eine Zukunft hat.
7.4.4
tasklist
tasklist die Variante für Windows XP und Windows 2003, die tlist eigentlich ablösen sollte. Da die Ausgabe des Prozessbaumes
und einige andere Dinge allerdings in dieser Version fehlen, sind bei mir noch beide Versionen im Einsatz. In der Ausgabe unten finden Sie die Ausgabe eines Aufrufs von tasklist: Image Name Session# Mem Usage ========================= =========== ============ System Idle Process 0 16 K System 0 216 K smss.exe 0 480 K csrss.exe 0 4,016 K winlogon.exe 0 6,220 K services.exe 0 4,740 K lsass.exe 0 29,384 K svchost.exe 0 2,676 K svchost.exe 0 3,620 K svchost.exe 0 3,968 K svchost.exe 0 2,024 K svchost.exe 0 15,092 K spoolsv.exe 0 4,668 K msdtc.exe 0 3,796 K dfssvc.exe 0 4,448 K dns.exe 0 5,680 K svchost.exe
PID Session Name ====== ================
Listing 7.5: Die Standardausgabe von tasklist
0 Console 4 Console 304 Console 428 Console 452 Console 496 Console 508 Console 680 Console 744 Console 916 Console 936 Console 964 Console 1264 Console 1300 Console 1376 Console 1412 Console 1464 Console
85
7 Kommandoausführung 0 1,636 ismserv.exe 0 3,380 ntfrs.exe 0 788 svchost.exe 0 1,260 wmiprvse.exe 0 5,112 explorer.exe 0 10,836 ctfmon.exe 0 2,100 cmd.exe 0 3,648 wpabaln.exe 0 2,300 tasklist.exe 0 3,072 wmiprvse.exe 0 4,448
K 1484 Console K 1496 Console K 1612 Console K 412 Console K 880 Console K 984 Console K 2204 Console K 2428 Console K 1012 Console K 180 Console K
Im Gegensatz zu tlist hat sich Microsoft bei tasklist einige Gedanken gemacht, wie die Informationen sinnvoll für eine Ausgabe aufbereitet werden können. Zusätzlich lassen sich mehr Daten abfragen als bei tlist. Für die Ausgabe wäre es ziemlich nachteilig, wenn alle Daten nur spaltenweise ausgegeben würden. Eine detaillierte Prozessinformation für die Zeichentabelle charmap.exe sieht beispielsweise so aus: Image Name PID Session Name Session# Mem Usage Statu s User Name CPU Time Windo w Title ========================= ====== ================ =========== ============ ===== ========== ================================================== ============ ===== ======================================================== =========== charmap.exe 2072 Console 0 3,204 K Runni ng SHELLBOOK\Administrator 0:00:00 Chara cter Map
Nicht unbedingt lesbar, oder? Daher existiert eine Option /FO (für format), bei der Sie angeben können, ob Sie die Ausgabe als Tabelle wie oben (table), als kommaseparierte Liste (csv) oder als Liste (list) erhalten wollen. Unten sehen Sie eine Ausgabe als Liste, was die Informationen wesentlich leichter erfassbar macht:
86
Prozessverwaltung mit der Shell Image Name: PID: Session Name: Session#: Mem Usage: Status: User Name: CPU Time: Window Title:
charmap.exe 2072 Console 0 3,204 K Running SHELLBOOK\Administrator 0:00:00 Character Map
Das Kommando dafür lautet tasklist
/FI "imagename eq charmap.exe" /FO list /v
Hier sehen Sie auch gleich einen wichtigen Unterschied: Für die Auswahl eines bestimmten Prozesses existiert nun ein Filterausdruck, mit dem auch komplexe Auswahlen möglich sind, z.B. alle nicht reagierenden Programme. Filtername
Operatoren
Gültige Werte
STATUS
eq, ne
running, not responding, unknown
IMAGENAME
eq, ne
Name des Programms
PID
eq, ne, gt, lt, ge, le
Prozess-ID
SESSION
eq, ne, gt, lt, ge, le
Sitzungsnummer
SESSIONNAME
eq, ne
Sitzungsname
CPUTIME
eq, ne, gt, lt, ge, le
CPU-Zeit im Format hh:mm:ss
MEMUSAGE
eq, ne, gt, lt, ge, le
Speicher in KByte
USERNAME
eq, ne
Benutzer in der Form [domain\] user
SERVICES
eq, ne
Servicename
WINDOWTITLE
eq, ne
Fenstertitel
MODULES
eq, ne
Name der DLL
Tabelle 7.2: Filteroptionen für tasklist
Endlich kann mit diesem Kommando auch ohne Probleme ein entferntes System abgefragt werden, auch mit einem anderen Benutzerkontext, ohne erst runas (s. Seite 81) bemühen zu müssen. Option
Bedeutung
/S <system>
Gibt den Namen des Remote-Systems an.
/U [domain\] user
Benutzerkontext, unter dem das Kommando ausgeführt wird.
/P <password>
Passwort für den angegebenen Benutzer, wird abgefragt, falls diese Option nicht angegeben wird.
/M <module>
Listet alle Prozesse auf, die die angegebene DLL verwenden. Wird nur /M angegeben, werden alle DLLModule gelistet.
Tabelle 7.3: Befehlsoptionen für tasklist
87
7 Kommandoausführung
Option
Bedeutung
/SVC
Zeigt die in den Prozessen laufenden Dienste an.
/V
Zeigt ausführliche Prozessinformationen an.
/FI
Definiert den Filter für die Anzeige (s.o.).
/FO
Definiert das Ausgabeformat. Gültige Werte sind die drei Zeichenketten "table", "list" oder "csv".
/NH
Unterdrückt die Ausgabe der Spaltentitel. Gilt nicht für das Ausgabeformat "list".
Möchten Sie alle Prozesse auf dem Rechner kiste sehen, die nicht vom System gestartet wurden, geben Sie folgendes Kommando ein: Eine Zeile
tasklist /s kiste /fo list /fi "username ne NT AUTHORITY\*" | find /i "Image name:"
Dieses Kommando benutzt als Ausgabeformat eine zeilenweise Liste (/fo list) und filtert nach dem Attribut username, das nicht mit einem Prozess des Betriebssystems (NT AUTHORITY\*) übereinstimmen darf. Da ich nicht an Prozess-ID, Speicherbedarf oder anderen Daten interessiert bin, wird die Ausgabe zum Schluss noch vom find-Filter bearbeitet.
7.4.5
kill und taskkill
Hit Hilfe eines dieser Kommandos kann ein Prozess beendet werden. kill erwartet die Angabe einer Prozess-ID oder eines Prozessnamens. Wird vor der pid als Option -f (für force) angegeben, erzwingt dies die sofortige Beendigung des Prozesses (Vorsicht! Datenverlust möglich). Alternativ kann für kill anstelle eines eindeutigen Prozessnamens auch ein regulärer Ausdruck als Suchmaske angegeben werden. kill beendet dann alle Prozesse, deren Name auf die Suchmaske zutrifft! Kombinieren Sie ein "*" mit der Option –f, und Sie lernen schnell, was der Ausdruck „den Ast, auf dem man sitzt, absägen“ bedeutet … Bei taskkill gelten die gleichen Optionen und Filtermöglichkeiten wie bei tasklist. Allerdings lässt sich das System hier nicht so leicht in den Abgrund reißen: Die Option /IM * (für image name all) ist nur dann erlaubt, wenn zusätzlich mit /FI ein Filter angegeben wird. Das gewaltsame Ende eines Prozesses wird hier aus Gründen der Konsistenz mit /F (statt -f bei kill) erzwungen. Prozesse auf entfernten Systemen werden immer mit dieser Option beendet. Seien Sie also vorsichtig, bevor Sie Ihrem Kollegen das Word beenden, in dem er seit drei Stunden ohne Sicherung vor sich hin tippt …
88
8
Befehlsverknüpfung
Der Exit-Code eines Prozesses kann benutzt werden, um zu steuern, ob ein weiteres Kommando ausgeführt werden soll oder nicht. So lassen sich Befehle erstellen, die in Abhängigkeit des Errorlevels bestimmte Aufgaben ausführen oder nicht. Realisiert wird dies mit der Shell über bestimmte Operatoren, welche die einzelnen Elemente des Befehls trennen.
8.1
Mehrfachkommandos
Die einfachste Form der Verknüpfung von Kommandos ist das lineare Abarbeiten von Befehlen. Dazu verbinden Sie die einzelnen Kommandos einfach mit einem einfachen kaufmännischen Und-Zeichen („&“). cls & machwas.exe & copy datei.ext ziel.dat & nochwas.bat & echo Fertig.
Das System wird nun der Reihe nach alle Kommandos ausführen. Falls eines der Kommandos in der Befehlskette fehlschlägt, wird mit dem nächsten Kommando in der Liste weitergemacht. Damit erschöpft sich die Nutzbarkeit meiner Meinung nach auf eine einfache Aneinanderreihung kleiner Sequenzen, für die eine Batchdatei zu viel Aufwand wäre. Störend ist allerdings die fehlende Möglichkeit der Fehlerbehandlung. In vielen Fällen nämlich hängt ein späteres Kommando davon ab, ob ein vorhergehender Befehl erfolgreich ausgeführt wurde. Diese Möglichkeiten haben Sie mit den nachfolgenden Operatoren.
8.2
Der Operator &&
Wird das kaufmännische Und einfach verdoppelt, wird das folgende Kommando nur dann ausgeführt, wenn der erste Befehl erfolgreich war. Wie stellt das System nun fest, ob ein Kommando erfolgreich war? Mit Hilfe des Errorlevels (s. Abschnitt 6.2.7), für den ein erfolgreiches Kommando durch einen Errorlevel von 0 definiert ist. MakeCSV.exe datei.ext && csvde -i -f datei.ext
Das obige Beispiel führt einen ActiveDirectory-Import über das Tools csvde nur dann aus, wenn der (fiktive) Prozess MakeCsv.exe mit einem Errorlevel von 0 geendet hat.
89
8 Befehlsverknüpfung
Die Anzahl der nacheinander folgenden Kommandos wird nur durch die Länge der Befehlszeile begrenzt, die bei Windows 2000 und aufwärts bei knapp zwei Kilobyte liegt, genug Platz also für längere Kommandos.
8.3
Der Operator ||
Ich bin ein Anhänger von fehleraktivierten Systemen. Dies bedeutet, dass nicht dauernd ein grünes Licht brennt, das „Alles o.k.“ signalisiert, sondern alles ist dunkel. Bei Problemen erscheint dann ein rotes Licht. So ein Ansatz spart Aufmerksamkeit. Mit Hilfe des &&-Operators lässt sich dieser Ansatz aber nicht realisieren. Daher existiert auch noch der ||-Operator. Dieser sorgt dafür, dass ein nachfolgendes Kommando nur dann ausgeführt wird, wenn das vorhergehende Kommando fehlschlägt. Als Fehlschlag ist ein Errorlevel ungleich 0 definiert. Gerade in Batchfiles macht sich die einfachere Notation bemerkbar. So müssen Sie nicht mehr in einer eigenen Zeile prüfen, sondern können eine eventuell notwendige Fehlerbehandlung gleich hinter das Kommando schreiben: MakeCSV.exe datei.ext || echo Probleme!
Unten sehen Sie zum Vergleich einen äquivalenten Ausschnitt aus einer Batchdatei: MakeCSV.exe datei.ext if errorlevel 1 echo Probleme!
Jetzt habe ich nur noch einen Wunsch: Das Kommando soll zwar im Fehlerfall einen besonderen Befehl ausführen (hier unser echo Probleme!), danach aber mit einem weiteren Kommando fortfahren. Auch dies ist mit der Shell ohne Probleme realisierbar, wie der nächste Abschnitt zeigt.
8.4
Befehlsgruppierung
Mit Hilfe der Möglichkeit der Befehlsgruppierung lassen sich auch sehr komplexe Abläufe innerhalb eines Kommandos erstellen. Genau wie in der Mathematik dienen auch hier die runden Klammern als Gruppierung für die Auswertungsreihenfolge. Jedes Klammerpaar gliedert also eine logische Befehlszeile. Wenn Sie das folgende Kommando eingeben, wird zuerst der Prozess MakeCSV.exe gestartet und dann bei Beendigung der Errorlevel überprüft. Ist dieser ungleich 0, dann erfolgt die Ausgabe mit echo, ansonsten wird csvde aufgerufen. ( MakeCSV.exe datei.ext || echo Probleme! ) && csvde -i -f datei.ext
90
Befehlsgruppierung
Natürlich können Sie mehr als eine Klammernebene schachteln. Die Grenze ist auch hier die maximale Länge der Eingabezeile bzw. das eigene Verständnis. Wenn Sie sehr komplexe Kommandos schreiben, werden Sie schnell merken, dass dadurch nicht wirklich Arbeit gespart wird. Es existiert mit den Makros aber eine Funktion, diese langen Kommandos einfach einem kurzen Makronamen zuzuweisen. Dann haben Sie die Vorteile mächtiger Befehle und einfacher Eingabe kombiniert. Mehr dazu im Kapitel 10. Diese Gruppierung gilt auch für die Umleitung von Ein- und Ausgabe. Die folgenden beiden Kommandos sind nicht funktionsgleich: 01: echo Zeile 1 && echo Zeile 2 & echo Zeile 3 > x.x 02: ( echo Zeile 1 && echo Zeile 2 & echo Zeile 3 ) > x.x
Während in der Zeile 1 nur der Text „Zeile 3“ in die Datei geschrieben wird, enthält die Datei nach der Ausführung von Zeile 2 alle drei Zeilen! Es gibt aber noch einen weiteren Einsatzzweck für die Gruppierung von Kommandos. Dieser ist notwendig, da manche Befehle der Shell ihren Ursprung weit in der DOS-Zeit haben. Die Funktionalität dieser Befehle kann aus Kompatibilitätsgründen nicht einfach mit den Befehlserweiterungen neuerer Windows-Versionen verändert werden. Daher muss unter Umständen eine Gruppierung mit den Klammern erfolgen. Sehen wir uns dies an einem Beispiel an. Welche Ausgabe produziert das folgende Kommando, wenn die aktuelle Uhrzeit 16:30 lautet? if %time:~0,2% GTR 12 echo Nachmittag else echo Vormittag
Sollen Sie jetzt vermutet haben, dass die Ausgabe Nachmittag lautet, geht es Ihnen wahrscheinlich wie den meisten Lesern. Dies wäre sinnvoll, widerspricht aber der seit DOS definierten Funktionalität des Kommandos echo. Dieses gibt den gesamten Text bis zum Zeilenende aus. Die Ausgabe lautet daher: Nachmittag else echo Vormittag
Für die korrekte Funktion muss echo in einer eigenen logischen Kommandozeile stehen. Dies kann durch eine Gruppierung mit runden Klammern erreicht werden. if %time:~0,2% GTR 12 (echo Nachmittag) else (echo Vormittag)
Wird die Kommandozeile so umgebaut, dann erhalten Sie auch die korrekte Ausgabe "Nachmittag" (zumindest war es, als ich diese Zeilen geschrieben habe, Nachmittag).
91
8 Befehlsverknüpfung
92
9
Ablaufsteuerung
Sie werden sich vielleicht wundern, wo bei interaktiven Kommandos eine Ablaufsteuerung Sinn macht. Aber nicht nur in Shell Scripts, sondern bereits bei komplexeren Kommandos oder verketteten Befehlen (die sich dann auch in Makros gießen lassen, wie Sie in Kapitel 10 erfahren) kann eine bedingte oder mehrfache Kommandoausführung Sinn machen. Den Kontrollstrukturen in Batches wird ein eigenes Kapitel (11.4) gewidmet.
9.1
Bedingte Befehlsauführung
9.1.1
Grundlagen von if
Auch bei Shell Scripts besteht die Notwendigkeit, die Abarbeitung von Kommandos von bestimmten Bedingungen abhängig zu machen. Ein Konstrukt für die Verzweigung des Ablaufs existiert in nahezu jeder Programmiersprache, allerdings in unterschiedlicher Form. Das Kommando if verfügt über eine Reihe von Optionen, die aber alle dem gleichen Muster folgen: if [NOT] [else ]
Durch die Angabe von NOT vor dem Test lässt sich jede Testbedingung in ihrer Wirkung umdrehen, d.h., ein Kommando wird dann beispielsweise ausgeführt, wenn eine Datei nicht vorhanden ist. Soll der else-Teil nicht behandelt werden, kann dieser Teil des Befehls einfach weggelassen werden. Dabei muss sowohl das Kommando1 als auch das Kommando2 in einer eigenen logischen Befehlszeile stehen. Wie bereits bei der Verkettung von Befehlen besprochen, müssen daher einige Befehle wie echo, del u.a. in Klammern gruppiert werden. Dabei darf natürlich auch ein Zeilenumbruch enthalten sein. Das folgende Beispiel ist ein gültiges Kommando und kann so beispielsweise in einem Shell Script verwendet werden. IF EXIST test.txt ( del test.txt ) ELSE ( echo test.txt fehlt )
93
9 Ablaufsteuerung
9.1.2
Formen von if
Dateiprüfung Mit dieser Form des if-Kommandos kann die Existenz von Dateien und Verzeichnissen überprüft werden. Da wird nach dem Schlüsselwort exist eine Datei- oder Pfadmaske angegeben. Ist eine dieser Maske entsprechende Datei vorhanden, wird das nachfolgende Kommando ausgeführt, andernfalls nicht. if exist c:\imp\eingabe.dat Machwas.exe eingabe.dat
Dieses Kommando führt das Programm machwas.exe nur dann aus, wenn die Datei eingabe.dat vorhanden ist. Der Test auf ein Verzeichnis ist relativ einfach, da es eine Reihe von reservierten Dateinamen gibt, die seit DOS für bestimmte logische Geräte stehen. Eines davon ist das so genannte nul device mit Namen nul. Diese Datei wird bei einem Test mit exist immer als vorhanden erkannt. Wenn ich feststellen möchte, ob das Verzeichnis e:\daten auf meinem Computer existiert, kann ich dies ganz einfach tun, indem ich in diesem Verzeichnis die Datei mit dem Namen nul suche: if exist e:\daten\nul echo Verzeichnis e:\daten ist vorhanden!
Eine andere Möglichkeit, auf das Vorhandensein eines Verzeichnisses zu testen, ist der Test auf den Dateinamen „.“, der für das aktuelle Verzeichnis steht. Da ein Verzeichniseintrag „.“ nur dann vorhanden ist, wenn das Verzeichnis existiert, ist dies als Testbedingung ebenso möglich. So können Sie in Ihren Batches Verzeichnisse sicher anlegen. Fragen Sie vorher einfach ab, ob das Verzeichnis noch nicht existiert. if not exist c:\tmp\test\. md c:\tmp\test
Test auf Variablen Die zweite Möglichkeit des if-Kommandos eignet sich dazu, das Vorhandensein einer Umgebungsvariablen abzufragen. Getestet wird hier nicht ein bestimmter Inhalt, sondern nur, ob die Variable überhaupt definiert ist. So wird beispielsweise automatisch die Variable userprofile definiert, in der der Pfad zum Profil des angemeldeten Benutzers gespeichert wird. Soll nun ein Kommando alle Verknüpfungen auf dem Desktop auflisten, muss dazu diese Variable auch definiert sein. Ansonsten würde ein Kommando in der Form dir "%userprofile%\ desktop\*.lnk" fehlschlagen. Mit einem if defined userprofile vor dem dir-Kommando kann eine entsprechende Abfrage erfolgen. Der Name der gesuchten Variable wird dabei ohne umschließende Prozentzeichen angegeben (die Anführungszeichen sind notwendig, da der Pfad ja auch Leerzeichen enthalten könnte): if defined userprofile (dir "%userprofile%\desktop\ *.lnk") else (echo Kein Profilpfad definiert!)
94
Bedingte Befehlsauführung
Auch hier sind die Klammern notwendig. Ohne die Klammern wird bei einem erfolgreichen Test das Kommando dir ausgeführt. Dieses ist aber so implementiert, dass alles bis zum Ende der logischen Zeile als Parameter und Dateisuchmaske aufgefasst wird. Daher muss das dirKommando in die runden Klammern eingeschlossen und die logische Zeile so begrenzt werden. Ebenso gibt echo alles bis zum Zeilenende als Text aus. Falls Sie nun einwenden, dass an dieser Stelle die Klammern dann überflüssig sind, haben Sie Recht. Dennoch sollten Sie sich diese Schreibweise angewöhnen. Wird später einmal die Reihenfolge der Aktionen gedreht oder ein Befehl durch Kopieren an eine andere Stelle dupliziert, könnte ohne die Klammern ein Fehler auftreten. Errorlevel testen Für den Test des Rückgabecodes eines Prozesses (der errorlevel) existiert eine weitere Variante von IF. Dies ist auch die einzige Form von IF, bei der es bei mehrfachen Tests auf die Reihenfolge der Befehle ankommt. Die allgemeine Form lautet hier: if errorlevel <wert>
Beim ursprünglichen Design der Shell (noch zu guten, alten DOS-Zeiten) ging man davon aus, dass Fehlercodes hierarchisch gestaffelt werden, also ein Errorlevel 4 einen gravierenderen Fehler als ein Errorlevel von 1 darstellt. Deshalb erfolgt der Vergleich bei if errorlevel immer mit einem Operator „größer als“. Wurde ein Prozess beendet und liefert einen Rückgabecode von 7, so wird auch der Vergleich if errorlevel 2 ein Ergebnis von logisch wahr liefern, und das Kommando würde ausgeführt. Innerhalb einer Batchdatei sollte also immer zuerst der größtmögliche Errorlevel abgefragt werden und zum Ende hin der kleinste Wert. Ihr Batchfile sollte beim Abfragen mehrerer Fehlercodes also ungefähr so aussehen: if errorlevel 8 echo Unbekannter Befehl if errorlevel 4 echo Ungültiges Verzeichnis if errorlevel 2 echo Datei nicht gefunden if errorlevel 1 echo Prozess abgebrochen echo Erfolgreich beendet
Falls Sie diesen Test auf „größer oder gleich“ nicht benutzen wollen, können Sie auch die Variable ERRORLEVEL direkt mit einem allgemeinen Vergleich testen. Diesen Ansatz stelle ich Ihnen jetzt zum Abschluss von if vor. Allgemeine Vergleiche Am flexibelsten ist if bei allgemeinen Vergleichen zweier Zeichenketten oder zweiter nummerischer Werte. Die allgemeine Syntax hierfür lautet: if [/I]
Als Operator kann einer der Operatoren aus der folgenden Tabelle verwendet werden.
95
9 Ablaufsteuerung
EQU (oder ==)
gleich
NEQ
nicht gleich
LSS
kleiner als
LEQ
kleiner als oder gleich
GTR
größer als
GEQ
größer als oder gleich
Diese etwas merkwürdige Gestaltung der Operatoren hängt damit zusammen, dass die mathematische Notation (z.B. >=) nicht möglich ist. Die eckigen Klammern werden ja in der Shell für die Umleitung von Ein- oder Ausgabekanal benötigt, daher werden die Operatoren hier in Textform verwendet. Anstelle des Operators equ kann auch das seit DOS implementierte doppelte Gleichheitszeichen verwendet werden. Auch hier sind alle Kommandos in einer Zeile ohne Umbruch einzugeben. Einige Beispiele für den Einsatz von IF: if/i
%cd% == %systemroot% goto :eof
Falls das aktuelle Verzeichnis das Systemverzeichnis von Windows ist, wird das Shell Script beendet (gute Notbremse für Löschaktionen und andere Batches). if defined lang if /i %lang% == DE (echo Willkommen) else if /i %lang% == IT (echo Benvenuto) else (echo Welcome)
Ausgabe von Meldungen je nach eingestellter Sprache (nicht optimale Lösung): if /i %username% == Administrator ...
Nur, wenn der Benutzername Administrator lautet … if %errorlevel% == 17 echo ExitCode 17
Wird nur ausgegeben, wenn der Errorlevel genau 17 ist, bei allen anderen Werten erfolgt keine Ausgabe. Das letzte Beispiel zeigt nochmals eine Abfrage von Werten für den Errorlevel, allerdings mit einem direkten Vergleich. Mit diesem Ansatz können Sie die Werte im Gegensatz zur Form IF ERRORLEVEL in beliebiger Reihenfolge abfragen.
9.2
Das mächtige for
Wie in jeder Shell und jeder Programmiersprache existiert auch in der Shell von Windows die Möglichkeit, Anweisungen mehrfach auszuführen. Prinzipiell existieren in der Windows Shell zwei Möglichkei-
96
Das mächtige for
ten, die beide ihre Berechtigung besitzen. Die eine ist die Erzeugung einer Schleife durch eine Testbedingung verbunden mit einem goto in einer Batchdatei, die andere Version nutzt die Möglichkeiten des Kommandos for. Diese Möglichkeit eignet sich auch gut für interaktive Kommandos und soll im Folgenden besprochen werden.
9.2.1
Grundlagen
Viele Programmiersprachen besitzen ein sprachliches „Schwergewicht“ in ihrem Vokabular, mit sich immer wieder neue Möglichkeiten erschließen und an dem man als Einsteiger lange hängen bleibt. Bei den Shell Scripts ist dies mit Sicherheit das Kommando for. Von einfachen Zählschleifen bis hin zu komplexen Ersetzungen und sogar dem von UnixLiebhabern immer wieder geforderten Backquoting (s. Abschnitt 9.2.8) ist alles möglich24. Aber fangen wir mit den einfachen Dingen an … Die allgemeine Syntax für das Kommando for lautet wie folgt: for [] in (<list>) do
Die Variable erhält nacheinander jeden Wert aus <list>, und für jede Ersetzung wird einmal das ausgeführt. Die Variable kann ein Buchstabe von a bis z sein, der mit einem vorangestellten Prozentzeichen gekennzeichnet wird. In Batchfiles muss dieses Prozentzeichen verdoppelt werden! Als Kommando kann jedes Kommando verwendet werden, das auch in einer einzelnen Kommandozeile gültig ist. Über den Namen der Variablen kann der jeweilige Ersetzungswert (auch mehrfach) dem Kommando als Parameter übergeben werden. Das Kommando kann auch selbst wieder eine for-Schleife sein, eine Schachtelung muss nur verschiedene Namen für die Variablen verwenden.
9.2.2
Einfache Schleifen mit Werte- und Dateilisten
Das Kommando for %f in ( eins zwei drei ) do echo %f
ergibt folgende Ausgabe: echo eins eins echo zwei zwei echo drei drei
24 iner der Testleser des Manuskripts hat es so formuliert: „for ist in Wirklichkeit die Abkürzung für ‚fast ohne Restriktionen’“.
97
9 Ablaufsteuerung
Wie Sie erkennen, wird das Kommando (hier echo) dreimal ausgeführt. Wollen Sie beispielsweise die Wertigkeit der einzelnen Bits in einem Byte ausgeben, reicht folgende Zeile: for %f in ( 0 1 2 3 4 5 6 7 ) do set /A "1 echo Das ist ein Test 18:27 Das ist ein Test
Das Zeichen „^“ vor dem kaufmännischen UND wird benötigt, da die Befehlsgruppierung erst bei der Makroexpansion aktiviert werden soll und nicht bereits bei der Definition.
111
10 Makros
10.2 Arbeiten mit Makros Die Definition eines Makros wird vor der Befehlsausführung ausgelöst. Dies bedeutet, dass Makros Vorrang vor den Kommandos der Shell besitzen, Sie also mit einem Makro time den internen Befehl time der Shell überschreiben. Dies kann unter Umständen ganz nützlich sein, wenn Sie für ihre in Teilzeit administrierenden Kollegen bestimmte Kommando sperren oder mit zusätzlichen Sicherheitsabfragen versehen möchten, will aber bedacht sein. Zusätzlich erfolgt die Expansion eines solchen Makros (bedingt durch die Natur von doskey) nur bei einer interaktiven Eingabe des Kommandos. Die schlechte Nachricht lautet daher: keine Makros in Batchfiles verfügbar. Dies beschränkt den Einsatz der Makros wirklich auf Abkürzungen bei interaktiven Sitzungen.
10.2.1
Definieren, ändern, löschen
Definieren Zur Definition eines Makros benutzen Sie das Kommando doskey, gefolgt vom Namen des Makros, danach von einem Gleichheitszeichen und dem Kommandotext. Mit der folgenden Zeile rüsten Sie auf allen Maschinen vor Windows 2003 das Kommando whoami nach: doskey whoami=@echo %username%@%userdomain% (working on %computername%, authenticated by %logonserver%)
Nun können Sie whoami wie eines der vorhandenen Shell-Kommandos verwenden: C:\Shellbuch\Samples>whoami
[email protected] (working on ORION, authenticated by \\RENNSEMMEL)
Ändern Eine erneute Definition eines gleich lautenden Alias überschreibt die alte Definition ohne vorherige Rückfrage. Eventuelle Leerzeichen im Makronamen bzw. vor dem Kommandotext werden ignoriert und führen nicht zu zwei verschiedenen Makronamen. Löschen Das Löschen einer Makrodefinition erfolgt wie das Löschen einer Umgebungsvariablen durch eine leere Zuweisung. doskey whoami=
Danach ist die Definition gelöscht. Auch hier erfolgt keine Rückfrage. C:\Shellbuch\Samples>whoami Der Befehl "whoami" ist entweder falsch geschrieben oder konnte nicht gefunden werden.
112
Arbeiten mit Makros
Damit ist in Grenzen auch eine Abfrage möglich, ob ein Makroname noch frei ist. Ein unbekannter Befehl wie im obigen Kommando liefert der Shell einen Errorlevel von 9009 zurück. Wird auf diesen Fehlercode gestestet, kann festgestellt werden, ob ein Makro geladen war und lief oder die obige Fehlermeldung erzeugt wurde.
10.2.2
Parameter für Makros
Warum benötigen Makros Parameter? Für ein Beispiel möchte ich auf die Variablenersetzung bei for-Schleifen (s. Seite 99) zurückkommen. Dort habe ich Ihnen die Nachbildung von which für die Windows Shell vorgestellt. for %f in (notepad.exe) do echo %~$PATH:f
Dieses Kommando muss nun nur noch in die Definition eines Makros mit doskey eingebunden werden und kann dann als neuer Befehl genutzt werden. doskey which=for %f in (notepad.exe) do echo %~$PATH:f
Problematisch ist allerdings, dass so immer nur gesucht werden kann, welche Datei ausgeführt wird, wenn Sie notepad.exe eingeben. Daher verfügt auch doskey über die Möglichkeit, für solche Makros Parameter zu definieren, die dann für den Dateinamen beliebige Werte erlauben. Diese Parameter werden mit den Platzhaltern $1 bis $9 angesprochen (ähnlich dem %1 bis %9 bei den Batchfiles). Der Platzhalter $T dient als Trennzeichen für mehrere Kommandos, während $* für die gesamte Eingabe dient. Hier nun die Definition des Makros mit einem Parameter für den Dateinamen: doskey which=for %f in ($1) do echo %~$PATH:f
Ein which freecell.exe würde also auch funktionieren, da der erste Parameter den Dateinamen darstellt und dieser über $1 in der Schleife gesucht wird. Mehr als neun Parameter sind allerdings nicht möglich, da im Gegensatz zu Batches keine Möglichkeit zum Shifting (s. Seite 121) existiert. Dennoch lässt sich mit Hilfe der Makros eine ganze Reihe von Definitionen für den interaktiven Betrieb erstellen. Beispielsweise existiert in manchen Unix-Shells ein automatischer Stapel für die per cd angewählten Verzeichnisse. Mit einem einfachen cd - kehren Sie zum jeweils letzten Verzeichnis zurück. Natürlich bietet auch die Windows Shell diese Funktionalität, allerdings in zwei Kommandos (pushd, pod), an die Sie sich auch noch erinnern müssen. Für meine Shell habe ich mir daher ein Makro definiert, das diese Funktionalität zusammen in einem „neuen“ cd nachbildet. doskey cd=if not $*! equ -! (pushd $*) else (popd)
113
10 Makros
Hier wird zuerst gestestet, ob die Argumente hinter dem Makronamen ungleich dem Minuszeichen sind. Falls ja, wird per pushd in das entsprechende Verzeichnis gewechselt. Falls nein, haben wir das Minuszeichen, und dementsprechend wird ein popd durchgeführt. Die nachfolgende Ausgabe zeigt den Einsatz des neuen Makros: C:\tmp>cd \DATA + C:\DATA>cd "\Dokumente und Einstellungen" ++ C:\Dokumente und Einstellungen>cd + C:\DATA>cd C:\tmp>
Zusätzlich habe ich hier den Prompt (siehe Abschnitt 3.3.2) so verändert (auf die Zeichenfolge $+ $P$G), dass ich den Zustand des Verzeichnisstapels mit einem Pluszeichen pro Ebene angezeigt bekomme. Seit ich dieses Makro im Einsatz habe, kann ich pushd und popd im Prinzip vergessen. Im Prinzip deshalb, weil ich mittlerweile auf fremden Maschinen instinktiv cd - eingebe und mich dann über die Fehlermeldung wundere …
10.3 Makros für bestimmte Programme Die Funktionalität von doskey-Makros kann jedes Programm nutzen, das sich Eingaben über die regulären Systemaufrufe des Betriebssystems holt. Aus diesem Grund können Sie beispielsweise auch bei ftp, nslookup oder anderen Konsolenprogrammen mit der Taste Cursornach-oben das letzte Kommando zurückholen. Der große Vorteil von doskey liegt nun darin, dass Makros auch ganz gezielt nur für ein bestimmtes Konsolenprogramm definiert werden können. Nur wenn das in der Makrodefinition angegebene Programm läuft, ist die Definition auch aktiv. Damit habe ich mir einen lästigen Unterschied in der Bedienung von Konsolenkommandos vom Hals geschafft: Überall wird ein Programm mit quit verlassen, egal ob ftp, telnet, netsh oder wie sie alle heißen. Nur bei nslookup muss ich exit eingeben. Mit doskey kein Problem: doskey /exename=nslookup.exe quit=exit
sorgt dafür, dass bei Eingaben ein quit durch exit ersetzt wird, wenn das Programm nslookup.exe ausgeführt wird. Denken Sie daran, dass diese Option für die Angabe des Programmnamens immer vor der eigentlichen Makrodefinition angegeben werden muss!
114
Makros speichern & laden
10.4 Makros speichern & laden Die Definition der Makros bleiben bis zum Schließen der Shell erhalten. Danach müssten Sie also alle Definitionen wieder eingeben, gäbe es da nicht eine einfache Möglichkeit, alle Definitionen in einer Datei zu sichern. Geben Sie dazu in der Kommandozeile das Kommando doskey /macros bzw. doskey /macros:all ein (auf den Unterschied der beiden Kommandos gehe ich gleich ein). Sie erhalten eine Liste aller derzeit definierten Makros, wie das folgende Beispiel zeigt: cd=if not $*! equ -! (pushd $*) else (popd) whoami=echo %username%@%userdomain% (on %computername%) test=cls && time /t
Diese Ausgabe kann per Ausgabeumleitung in eine Datei gespeichert werden und macht somit die Makrodefinitionen persistent. Über eine andere Option von doskey kann diese Liste wieder geladen und die Makros können aktiviert werden. Der Unterschied zwischen /macros und /macros:all liegt darin, dass bei der ersten Version nur die für die Shell definierten Makrodefinitionen ausgegeben werden, bei der zweiten Form dagegen alle vorhandenen Definitionen, wie die zweite Ausgabe zeigt: [nslookup.exe] quit=exit [cmd.exe] cd=if not $*! equ -! (pushd $*) else (popd) go=if not $*! equ -! (pushd $*) else (popd) test=cls && time /t
Das Format entspricht einer einfachen INI-Datei, sollte also keine großen Probleme bereiten, wenn Sie diese Datei mit einem anderen Programm bearbeiten oder ändern möchten. Geladen werden kann diese Definitionsdatei über das Kommando doskey /macrofile=
Alle eventuell bereits bestehenden Definitionen werden durch den Inhalt der Datei überschrieben. Es bietet sich an, beim Beenden der Arbeit zuerst die Definitionen mit den Makros in eine Datei zu sichern und anschließend die Shell zu beenden. Natürlich kann für diesen Zweck auch wieder das Kommando exit durch ein eigenes Makro überschrieben werden, das zuerst die Definitionen wegsichert und dann die Shell beendet. Diese Aufgabe überlasse ich Ihnen als Abschlussübung für dieses Kapitel. Alternativ kann eine Liste mit Makros auch beim Start der Shell geladen werden, indem Sie per AutoRun-Option in der Registry dort das Kommando zum Laden von Makros einbauen. Achten Sie aber darauf, dass keinerlei Output entsteht, da sonst bei jedem Start einer Shell oder Subshell (auch bei Filtern!) dieser Output mit bearbeitet wird!
115
10 Makros
10.5 Tastenkombinationen für doskey Die erweiterten Funktionen von doskey sind per Default bei der Shell aktiviert, und damit erhalten Sie einige Tastenkombinationen für die Bearbeitung der Kommandozeile, die vielen Benutzern noch unbekannt sind. Diese Liste habe ich Ihnen aus Gründen der Eingabeeffizienz gleich zu Beginn des Buches präsentiert, sehen Sie also einfach noch einmal kurz auf der Seite 31 nach.
116
11
Shell Scripts (Batches)
11.1 Einführung Auch bei Windows ist eine Möglichkeit vorhanden, mehrere Kommandos in einer Datei zusammenzufassen und diese dann ablaufen zu lassen. Während die Unix-Leute bei dieser Möglichkeit von sog. Shell Scripts sprechen, hat sich in Windows der Ausdruck Batchfiles eingebürgert. Gemeint ist in beiden Fällen das Gleiche: eine Reihe von Kommandos, die in einer Datei gespeichert ist, die durch die Angabe ihres Dateinamens gestartet und ausgeführt wird. Ich verwende die beiden Ausdrücke Shell Script und Batch(file) in diesem Buch synonym. Viele Aufgaben lassen sich sinnvoll nur mit einer Batchdatei lösen, da andernfalls immer wieder die Eingabe mehrerer Befehlszeilen nötig wäre. An dieser Stelle möchte ich Ihnen die Grundlagen der Erstellung von Shell Scripts für Windows erläutern. Weiterführende Themen wie Parameter, Ablaufsteuerung oder andere Aspekte werden später behandelt. Für den Anfang ist eine Batchdatei wirklich nur eine Datei mit einem Stapel von Befehlen, der der Reihe nach abgearbeitet wird.
11.2 Batchfiles 11.2.1
Aufbau
Batchfiles (oder auf Deutsch Stapeldateien) sind nicht formatierte Textdateien. Standardmäßig besitzen sie die Erweiterung .bat oder .cmd (beide sind völlig gleichwertig). Wie der Name bereits ausdrückt, enthalten sie eine Abfolge (einen Stapel) von Kommandos, die von der Shell ausgeführt werden. Die Shell liest so lange zeilenweise aus der Datei, bis ein Kommando gefunden wird. Wird das Ende der Datei erreicht, wird der Batch beendet. Mit Hilfe von Kontrollstrukturen lässt sich der logische Ablauf des Stapels steuern, so dass auch komplexe Aufgaben möglich sind. Als Entwicklungswerkzeug kann (bei genügender Leidensfähigkeit) auch der bordeigene Editor notepad.exe dienen, der allerdings nicht über großen Komfort verfügt. Moderne Editoren verfügen über die Möglichkeit der Syntaxhervorhebung, können Makros erstellen und
117
11 Shell Scripts (Batches)
ermöglichen das Anlegen von Textbausteinen zur Wiederverwendung von Code25.
11.2.2
Syntax
Batches sind zeilenweise aufgebaut. Jede Zeile kann einen der folgenden Inhalte haben: 왘 Leerraum
Leerzeilen werden von der Shell überlesen, sind aber zur Gliederung des Scripts ein sinnvolles Hilfsmittel. 왘 Kommentar
Kommentare werden nachfolgend detaillierter erläutert. 왘 Befehlszeile
Als Befehle zählen alle internen und externen Kommandos, jeder Programmaufruf oder der Aufruf eines anderen Batches. 왘 Sprungzieldefinition
Die Sprungzieldefinition dient der Ablaufsteuerung des Batches.
11.2.3
Kommentare in Batches
Die einfachste Möglichkeit, einen Kommentar zur Dokumentation einzubauen, besteht in der Verwendung des „Befehls“ rem. (für remark, Anmerkung). Dieses Kommando hat keinerlei Auswirkungen, es dient lediglich dazu, den Rest der Zeile als Kommentar zu kennzeichnen. Alternativ dazu kann eine Zeile auch mit zwei Doppelpunkten begonnen werden. Diese Zeilen werden bei der Ausführung des Batches nicht angezeigt, auch wenn die Ausgabe der Befehlszeilen eingeschaltet ist. Daher wird diese Art der Kommentarerstellung bevorzugt verwendet. Gewöhnen Sie sich am besten gleich zu Beginn an, Ihre Batches mit Leerzeilen zu strukturieren und mit genügend Kommentaren den Ablauf und die Funktion des Batches zu beschreiben. Nichts ist frustrierender und langweiliger, als sich nach sechs Monaten mühevoll wieder in den eigenen Code einarbeiten zu müssen, den man bei der Erstellung als so einfach ansah, dass jeder Kommentar Zeitverschwendung gewesen wäre. Beschreiben Sie daher in den Kommentaren auch nicht, was der Batch tut — das ist aus dem Code ersichtlich. Beschreiben Sie lieber, warum der Code das tut, was er tut. Diese Informationen sind es, die die Einarbeitung in fremden Code erleichtern. 25 Ich werde an dieser Stelle aus Erfahrung bei anderen Gelegenheiten keinen Editor empfehlen, da sich so leicht Religionskriege starten lassen, gegen die die Kreuzzüge wie ein missglücktes Familienpicknick wirken.
118
Parameterchecks
11.2.4
Parameter
Jedes Shell Script kann bei Bedarf auch Parameter erhalten, von einer einfachen Option über Dateinamen bis zu einem ADSI-Pfad. Diese Parameter werden dem Batch übergeben und stehen über besondere Platzhalter zur Verfügung. Die Kombination %1 steht für den ersten übergebenen Parameter, %2 für den zweiten und so weiter bis %9 für das neunte Argument. Wie Sie mehr als neuen Parameter übergeben, auf leere Parameter testen oder diese Parameter konvertieren, erfahren Sie weiter unten im Kapitel 11.3, „Parameterchecks“.
11.2.5
Ausführen von Shell Scripts
Für die Ausführung von Shell Scripts (Batches) reicht die Eingabe des Namens, da die Erweiterungen .bat und .cmd als ausführbare Dateien registriert sind. Wie Sie dies feststellen und gegebenenfalls auch ändern, habe ich im Kapitel über PATHEXT geschildert. Ein Shell Script kann selbst wieder andere Shell Scripts starten. Hierbei müssen Sie allerdings entscheiden, was mit dem aufrufenden Shell Script geschehen soll. Findet sich in einer Zeile nur der Aufruf eines anderen Shell Scripts über den Dateinamen, wird der gerade ausgeführte Batch beendet, und die Kontrolle wird dem aufgerufenen Shell Script übergeben. Wird vor dem Namen des aufgerufenen Shell Scripts das Schlüsselwort CALL angegeben, so wird dieses Shell Script ausgeführt, kehrt aber nach der Beendigung zum aufrufenden Batch zurück.
11.3 Parameterchecks 11.3.1
Anzahl und Art der Parameter
Für viele Shell Scripts sind Parameter notwendig, die erst die für die Ausführung notwendigen Daten liefern. Wie bereits oben erläutert, stehen dafür die Platzhalter %1 bis %9 zur Verfügung. Diese werden innerhalb des Scripts an der Stelle eingesetzt, an der die Parameter verwendet werden. Dies kann auch mehrmals geschehen. Eine Änderung der in %1 bis %9 enthaltenen Werte ist nicht möglich. Falls Sie die übergebenen Daten eventuell verändern wollen, müssen Sie dies über den Umweg einer Umgebungsvariablen tun. Möchten Sie auf die gesamte Parameterliste zugreifen, so existiert hierfür der Platzhalter %*. Genau wie bei Dateinamen gilt auch hier, dass Parameterwerte mit Leerzeichen in doppelte Anführungszeichen eingeschlossen werden müssen.
119
11 Shell Scripts (Batches)
Auch für die Parameter in einem Shell Script existiert die erweiterte Variablenersetzung wie bei den Umgebungsvariablen. Der einzige Unterschied liegt darin, dass Sie das Prozentzeichen nur zu Beginn des Parameters angeben und als letztes Zeichen die Nummer des Parameters. Tabelle 11.1: Erweiterte Variablenersetzung für BatchParameter
Variable
Beschreibung
%~1
entfernt etwaige umgebende Anführungszeichen aus %1
%~f1
erweitert %1 zu einer vollständig qualifizierten Pfadbezeichnung
%~d1
erweitert %1 zu einem Laufwerksbuchstaben
%~p1
erweitert %1 zu einem Pfad
%~n1
erweitert %1 zu einem Dateinamen
%~x1
erweitert %1 zu einer Dateinamenerweiterung
%~s1
erweitert den Pfad, so dass nur der kurze Dateiname enthalten ist
%~a1
erweitert %1 zu Dateiattributen
%~t1
erweitert %1 zu den Datums-/Uhrzeitangaben der Datei
%~z1
erweitert %1 zu der Größe der Datei
%~$PATH:1
durchsucht die in der Umgebungsvariablen PATH aufgeführten Verzeichnisse und erweitert %1 zu dem vollständig qualifizierten Namen des ersten gefundenen Verzeichnisses. Wurde der Name der Umgebungsvariablen nicht festgelegt oder die Datei nicht gefunden, gibt der Parameter eine leere Zeichenfolge zurück.
Einige dieser Erweiterungen funktionieren natürlich nur dann, wenn es sich bei dem Parameter auch um eine existierende Datei handelt. Ist dies nicht der Fall, so expandieren diese Erweiterungen zu einer leeren Zeichenkette. Was ich übrigens immer noch vermisse: eine einfach Möglichkeit, die Anzahl der Parameter zu bestimmen (ähnlich $# in manchen Skriptsprachen). Der Parameter %0 Zusätzlich zu den Parametervariablen existiert noch ein Platzhalter %0, der für den Batch selbst steht, also den Namen des Shell Scripts enthält. Nur so sind Selbstaufrufe (s.u.) möglich, da Sie so den Namen des Shell Scripts erfahren. Der Inhalt von %0 entspricht immer genau dem Aufruf des Shell Scripts auf der Kommandozeile. Sollten Sie also innerhalb des Batches das aktuelle Verzeichnis wechseln, kann es sein, dass ein Selbstaufruf nicht mehr einwandfrei funktioniert, da der Benutzer unter Umständen nur den Dateinamen ohne Pfad einge-
120
Parameterchecks
geben hat. Einen Ausweg bietet auch hier die erweiterte Variablenersetzung. Ersetzen Sie einfach %0 durch %~f0, und Sie erhalten den kompletten Dateipfad für das Shell Script.
11.3.2
Mehr als neun Parameter mit shift
Sollten Sie Ihrem Shell Script mehr als neun Parameter mit auf den Weg geben, existieren dafür keine Platzhalter mehr. Abgesehen davon, dass ich bei dieser Anzahl von Parametern über andere Formen der Datenübergabe nachdenken würde (z.B. eine Parameterdatei oder die Registry), können Sie auf diese Werte dennoch zugreifen. Das Kommando shift schiebt alle Parameter um eine Position nach links. Möchten Sie erst ab einer bestimmten Parameternummer schieben, geben Sie diese Zahl nach Shift als Option an, beispielsweise shift /3. Dies bewirkt, dass %1 und %2 erhalten bleiben, aus %4 wird danach der neue %3, und der alte Inhalt von %3 geht verloren. Als Beispiel unten ein Shell Script, das einfach nur seine Parameter per echo ausgibt: @echo off echo Parameter 1 = %1 echo Parameter 2 = %2 echo Parameter 3 = %3 echo Parameter 4 = %4 echo. echo Jetzt ab Position 2 shiften .... shift /2 echo Parameter 1 = %1 echo Parameter 2 = %2 echo Parameter 3 = %3 echo Parameter 4 = %4
Jetzt wird dieses Script mit einer Befehlszeile mit Parametern aufgerufen: c:\tmp>test Demo "Parameter mit Blanks" /x 1234 Parameter Parameter Parameter Parameter
1 2 3 4
= = = =
Demo "Parameter mit Blanks" /x 1234
Jetzt ab Position 2 shiften .... Parameter 1 = Demo Parameter 2 = /x Parameter 3 = 1234 Parameter 4 =
Damit sind auch mehr als neun Parameter möglich, und Sie sind in der Lage, bestimmte Parameter zu Beginn der Kommandozeile von der Verschiebung auszunehmen. Allerdings ist dies noch keine besonders
121
11 Shell Scripts (Batches)
flexible Parameterüberprüfung. Was ist beispielsweise, wenn der Benutzer eine Option statt als /debug als /DEBUG angibt und Sie nur die kleingeschriebene Variante testen? Im folgenden Abschnitt möchte ich daher eine etwas flexiblere Möglichkeit der Parameterüberprüfung vorstellen.
11.3.3
Flexible Parameterprüfung
Test auf leere Parameter Der Test, ob beim Aufruf des Scripts ein Parameter überhaupt angegeben wurde, ist eine der grundlegenden Überprüfungen vor der Ausführung irgendwelcher Aktionen. Die in der Literatur oft angegebene Standardlösung führt aber dennoch immer wieder zur Problemen. In den meisten Fällen sieht der Code nämlich wie folgt aus: if <parm> == <wert> :: beispielsweise if %1 == build goto actBuild
Problematisch wird die Sache dann, wenn kein Parameter beim Aufruf des Scripts angegeben wird. Im Beispiel oben ergibt sich dann ein syntaktischer Fehler, der den Batch abbricht. Ist %1 leer, sieht die Zeile so aus: if == build goto actBuild
Aus diesem Grund empfehlen viele Beispielskripte in Zeitschriften, den Parameter zu klammern, also links und rechts davon ein Zeichen zu setzen, so dass auch bei einem leeren Parameter ein Vergleich möglich ist. if [%1] == [build] goto actBuild :: bei leerem Parameter immer noch korrekte Syntax if [] == [build] goto actBuild
Aber auch diese Abfrage ist nicht hundertprozentig sicher, da führende oder nachfolgende Leerzeichen den Vergleich scheitern lassen. Sorgen Sie also immer dafür, dass umschließende Leerzeichen nicht auftreten, oder fügen Sie nur vor dem Parameter ein Zeichen an. Diese Technik gilt auch bei Umgebungsvariablen. Stellen Sie sich vor, Sie erfragen per set /p den Wert einer Variablen in einem Batch. Nun gibt der Benutzer aus Versehen noch ein nachfolgendes Leerzeichen mit ein. Dies zählt mit zum Inhalt der Variablen, und bei einem [%var%] schlägt dann ein Vergleich mit einem Kommando (z.B. [make]) fehl, da das Leerzeichen noch zwischen Befehlswort und schließender Klammer steht.
122
Ablaufsteuerung
Test auf Parameter an beliebiger Position Geht es nur darum festzustellen, ob eine Option angegeben wurde oder nicht (unabhängig von der Schreibweise), lässt sich dies relativ mit for lösen. In ihrer einfachsten Form läuft die Schleife einmal durch jedes Element der Werteliste in den runden Klammern. Warum also nicht mit %* die gesamte Parameterliste an eine Schleife übergeben und mit Hilfe von if auf die gesuchte Option testen? Die Möglichkeit von if, mit /i die Schreibweise zu ignorieren, spart Ihnen das Absuchen aller möglichen Schreibweisen und macht das Script leichter benutzbar. Dem folgenden Beispiel können Sie entnehmen, wie leicht sich das Vorhandensein einer Option /debug (egal ob groß, klein oder gemischt geschrieben) realisieren lässt. @echo off setlocal set debug= for %%f in (%*) do if /i %%f == /debug set debug=1 if defined debug echo Debug-Mode echo Dies wird immer ausgegeben. endlocal
Listing 11.1: Flexible Abfrage von Parametern
11.4 Ablaufsteuerung Wenn nichts anderes programmiert wurde, beginnt die Ausführung des Scriptcodes mit der ersten Zeile, die kein Kommentar oder keine Sprungzieldefinition ist. Das Script endet, wenn die letzte Zeile der Scriptdatei erreicht wurde. Da eine rein lineare Ausführung in den wenigsten Fällen ausreicht, existieren auch bei Shell Scripts Möglichkeiten, den Ablauf des Scripts zu steuern.
11.4.1
Verzweigungen
Bei Verzweigungen innerhalb von Shell Scripts gilt das Gleiche wie bei if für die interaktive Eingabe. Lesen Sie hierzu bitte im Abschnitt 9.1 nach.
11.4.2
Schleifen
FOR Schleifen dienen dazu, Kommandos mehrfach zu wiederholen. Dies kann in Form eines for-Kommando (s. Seite 96) erfolgen oder in Form einer manuell kodierten Schleife. Von for haben Sie sicher bereits im Abschnitt 96 genug gehört, so dass ich hier nur nochmals auf die einzige Besonderheit hinweisen möchte, wenn Sie for in einem Shell Script einsetzen: Die Prozentzeichen der Schleifenvariablen müssen beim Einsatz in einem Batch verdoppelt werden.
123
11 Shell Scripts (Batches)
Aus der Zeile for %f in (*.txt) do @if %~zf GTR 1048576 echo Grosse Datei
wird innerhalb des Shell Scripts die Zeile for %%f in (*.txt) do @if %%~zf GTR 1048576 echo Grosse Datei
Schleifen mit if und goto Bei einer handkodierten Schleife wird mit Hilfe einer if-Abfrage die Testbedingung geprüft und dann ggf. per goto zu einem definierten Sprungziel verzweigt. Ein möglicher Einsatzzweck dieser manuell kodierten Form einer Schleife kann beispielsweise die Feststellung des Pfadnamens einer Datei sein. Dieser lässt sich feststellen, indem vom Ende des Dateinamens aus nach einem Backslash gesucht wird. Dieser trennt dann den Dateinamen vom kompletten Pfad ab. Dafür kann for nicht benutzt werden, das entsprechende Shell Script ist aber auch so relativ kurz. Die Zeilennummern dienen nur der Orientierung, sie gehören natürlich nicht zum Batch. Üblicherweise wird für solche Shell Scripts die Kommandoanzeige per echo off ausgeschaltet, ich habe dies hier weggelassen, damit Sie die Ausführung in einem Konsolenfenster besser verfolgen können. Listing 11.2: Feststellen des Pfadanteils eines Dateinamens
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15
:: getfilepath.bat set datei=%~1 :check :: letztes zeichen holen if not defined datei goto nopath if "%datei:~-1%" == "\" goto fertig :: ein zeichen kürzen set datei=%datei:~0,-1% goto check :nopath echo Kein Pfadanteil vorhanden goto eof :fertig echo Der Pfad lautet: %datei% :eof
Nachdem der erste Parameter (der Dateiname) der Umgebungsvariablen datei zugewiesen wurde, wird in Zeile 6 die Testbedingung formuliert. Mit dieser Variablen datei wird nun im Batch gearbeitet, der Parameter 1 (%1) bleibt für den Zugriff auf den originalen Dateinamen immer erhalten. Falls das letzte Zeichen des Inhalts von datei ein Backslash ist, kann die Schleife per Sprung an die Marke fertig verlassen werden. Ist dies nicht der Fall, wird der Inhalt der Variablen von rechts um ein Zeichen gekürzt. Dies geschieht per erweiterter Variablenersetzung in der Zeile 8. Danach wird in der Zeile 9 wieder zur Marke check gesprungen, die als nächstes Kommando wieder zur Testbedingung führt.
124
Ablaufsteuerung
Nach einem Aufruf mit dem Parameter C:\Shell\Demos\test.dat lautet die Ausgabe: Der Pfad lautet: C:\Shell\Demos\
Vielleicht fragen Sie sich jetzt, wozu die Zeile 5 dient. Dies ist eine Sicherheitsabfrage, falls als Parameter ein Dateiname ohne Pfadanteil übergeben wird. Dann wird nie ein Backslash gefunden, die Variable aber immer wieder in der Schleife um ein Zeichen gekürzt. Irgendwann ist nichts mehr da zum Kürzen, und die Zeile sieht zur Laufzeit dann so aus set datei=
Damit wird die Variable gelöscht, und die Abfrage in der Zeile 5 testet genau diese Bedingung. Ist die Variable datei nicht mehr definiert, hat sie keinen Inhalt mehr. Dies bedeutet, dass kein Backslash gefunden wurde und der ursprüngliche Dateiname auch keine Pfadinformationen enthält.
11.4.3
Unterroutinen
Die Windows Shell verfügt über keine besonders ausgefeilten Möglichkeiten zur Modularisierung von Shell Scripts. Dennoch lassen sich zumindest einfach Unterroutinen erstellen. Für eine weitergehende Diskussion zum Thema Modularisierung lesen Sie bitte den Abschnitt 12.4. Bereits seit MS-DOS besteht die Möglichkeit der Verwendung des Kommandos call, um eine zweite Batchdatei aufzurufen. Nachdem die Ausführung diese Datei beendet wurde, kehrt die Ausführung zur aufrufenden Datei zurück. Ein Nachteil dieses Ansatzes war allerdings die Tatsache, dass dafür eine externe Datei aufgerufen werden musste. Viele Administratoren versuchten, durch eine geschickte Kombination von Selbstaufruf und Parametern (s. Kapitel 11.5.1) diese Beschränkung zu umgehen. Seit den Kommandoerweiterungen von Windows 2000 existiert eine einfachere Möglichkeit, mit einer Datei auszukommen, in der einzelne Unterroutinen versammelt sind. Dazu werden vor jeder Unterroutine Sprungmarken definiert. Diese werden dann mit der neuen Syntax call :label angesprungen (achten Sie auf den Doppelpunkt vor der Sprungmarke). Unten ein Beispiel für diese Möglichkeit.
125
11 Shell Scripts (Batches) Listing 11.3: Verwendung von call :label
@echo off echo Shell Script laeuft ... call :makeDC kiste.firma.de echo Ergebnis: %result% :: muss sein, damit die subroutine :: nicht noch mal ausgefuehrt wird goto :eof :makeDC echo Das hier ist eine Unterroutine set result=%1 set result=%result:.=,dc=% set result=dc=%result%
Der fett markierte Bereich im Listing zeigt den Aufruf der Unterroutine. Dieser Aufruf erzeugt einen neuen Batchkontext, dessen Ausführung sofort an der angegebenen Sprungmarke beginnt. Falls Sie so etwas noch für Windows NT4 oder Windows 98 benötigen, hier der Batch in der Oldtimer-Variante. Eine Erläuterung dieses Selbstaufrufs finden Sie im nächsten Abschnitt des Buches. @echo off if !%1 == !JUMP shift && shift && goto %2 %3 %4 %5 %6 %7 %8 %9 echo Shell Script laeuft ... call %0 JUMP makeDC kiste.firma.de echo Ergebnis: %result% :: muss sein, damit die subroutine :: nicht noch mal ausgefuehrt wird goto :eof :makeDC echo Das hier ist eine Unterroutine set result=%1 set result=%result:.=,dc=% set result=dc=%result% Listing 11.4: Der Batch in der NT4-tauglichen Version
Wie Sie unschwer erkennen, ist die seit Windows 2000 mögliche Syntax wesentlich einfacher. In der NT4-Version müssen auch noch zweimal per shift die Parameter geschoben werden, da die Selbstaufrufmarkierung JUMP und die Sprungmarke makeDC wieder aus der Parameterliste verschwinden müssen. Sobald die Ausführung dieses neuen Batchkontextes das Ende des Scripts erreicht hat, wird die Scriptausführung nach dem aufrufenden call im ursprünglichen Kontext fortgesetzt. Für die Rückgabe von Funktionswerten bei Unterroutinen benutzen Sie am besten wie im obigen Beispiel Umgebungsvariablen.
126
Selbstaufruf
11.4.4
Shell Scripts beenden
Ein Shell Script wird im einfachsten Fall dann beendet, wenn kein Code mehr vorhanden ist. Falls Sie aus Gründen der Ablauflogik ein Shell Script direkt beenden müssen, haben Sie drei Möglichkeiten: 1. Sie definieren am Ende des Scripts eine Sprungmarke (z.B. :eof) und springen dann per goto (hier: goto eof) an diese Marke. Diese Methode hat den Vorteil, auch mit Windows NT4 zu funktionieren. 2. Sie nutzen die Befehlserweiterungen ab Windows 2000 und beenden den Batch mit dem Kommando goto :eof. Beachten Sie den Doppelpunkt vor der Sprungmarke. Dies ist eine Erweiterung des Sprungkommandos (ähnlich call :label) ab Windows 2000. 3. Sie verwenden (ebenfalls ab Windows 2000) das Kommando exit mit der Option /B. Ein exit /b beendet in einem Shell Script nur den gerade laufenden Batch. Außerhalb davon wird aber nach wie vor die gerade laufende Shell beendet! Der Vorteil dieser Methode liegt darin, dass Sie bei exit einen errorlevel als Parameter angeben können, der dem aufrufenden Programm oder Shell Script übermittelt wird.
11.5 Selbstaufruf Wieso sollte sich ein Shell Script selbst aufrufen? Diese Frage hat prinzipiell die gleichen Antworten wie bei den meisten Programmiersprachen: rekursive Lösungen von Problemen. Bei Batches kommt noch ein weiterer Aspekt dazu. Erst mit den Befehlserweiterungen von Windows 2000 und aufwärts ist eine halbwegs vernünftige Modularisierung von Batches in einer Datei möglich. Vorher blieb nur der Selbstaufruf und die anschließende Verteilung per Sprung an die korrekte Codestelle. Viele Shell Scripts sind auch heute noch nach diesem Muster gestrickt, weshalb ich dieses zuerst erläutern möchte. Danach werde ich Ihnen die für Windows 2003 zeitgemäßere Lösung vorstellen.
11.5.1
Aufruf mit call %0
Vor Windows 2000 war dies die einzige Möglichkeit, einen Batch rekursiv, also selbstaufrufend zu gestalten. Falls ein Shell Script sich selbst aber aufruft, muss eine Erkennung möglich sein, dass dieser Aufruf nun programmgesteuert und nicht mehr durch den Benutzer erfolgt. Dies geschieht meist durch einen speziellen Wert als ersten Parameter, der als Markierung dient und der dann gleich zu Beginn des Shell Scripts abgefragt wird. Bei allem stellt sich aber die Frage: Wozu überhaupt das Ganze? Die Antwort ist relativ einfach. In vielen Fällen lässt sich so eine Aufteilung der Lösung in mehrere Batches vermeiden. Abgesehen von der Platzverschwendung durch die Clustergrößen heutiger Festplatten müssen Sie bei der Weitergabe auch daran denken, alle Teilskripte zu kopieren.
127
11 Shell Scripts (Batches)
Als praxistaugliches Beispiel dient für dieses Kapitel ein Shell Script, dass während eines meiner Shell-Trainings entstand. Damit lässt sich die Reihenfolge der Zeilen einer Textdatei umdrehen, um beispielsweise die Zeilen am Anfang einer Datei nach hinten zu bringen. Hier erst einmal der Code für den Aufruf mit call %0, die Erläuterung des Ablaufs folgt nach dem Listing (die Zeilennummern gehören nicht zum Code und dienen nur der Erläuterung!). Listing 11.5: Umdrehen der Zeilen einer Textdatei.
128
01 :: reverse a text file, slow but plain shell 02 03 :: test der parameter 04 if !%1 == ! goto nofile 05 06 :: ist die datei auch da? 07 if not exist %1 goto nofile 08 09 :: test auf umgebungsvariable 10 if not defined temp goto noenv 11 12 :: haben wir uns aufgerufen? 13 if !%1 == !@@@ goto procline 14 15 :: evtl. bestehende datei loeschen 16 if exist %temp%\tmp.txt del %temp%\tmp.txt 17 18 :: 19 for /F "tokens=* usebackq" %%f in (%1) do call %0 @@@ "%%f" 20 more < %temp%\tmp.txt > %1 21 del %temp%\tmp.txt 22 del %temp%\line.txt 23 goto eof 24 25 :procline 26 echo %~2 > %temp%\line.txt 27 more < %temp%\tmp.txt >> %temp%\line.txt 28 more < %temp%\line.txt > %temp%\tmp.txt 29 goto eof 30 31 :noenv 32 echo Variable TEMP nicht definiert, Abbruch. 33 goto eof 34 35 :nofile 36 echo Keine Datei angegeben, Abbruch. 37 goto eof 38 39 :notfound 40 echo Die Datei %1 existiert nicht, Abbruch. 41 goto eof 42 43 :eof
Selbstaufruf
Das Script funktioniert prinzipiell folgendermaßen: 왘 Die Schleife in Zeile 19 läuft durch alle Zeilen der Eingabedatei, deren
Name als %1 übergeben wird (Test auf Vorhandensein Zeile 3–7). 왘 Für jede Zeile ruft sich der Batch wieder selbst auf, mit "@@@" als
Kennung für den ersten Parameter. Als zweiter Parameter wird der Inhalt der jeweiligen Zeile übergeben. 왘 Durch den Test in Zeile 13 springt der Ablauf beim Selbstaufruf
sofort zum Label in Zeile 25. 왘 Jetzt wird der Inhalt der Zeile in eine temporäre Datei line.txt
geschrieben, der Inhalt der Datei tmp.txt (die die bisherigen Zeilen enthält) wird dahinter angefügt. 왘 In der Zeile 28 wird diese Datei line.txt wieder nach tmp.txt
geschrieben, so dass diese für den nächsten Durchgang wieder zur Verfügung steht. Testen Sie diesen Ablauf mit einer einfachen Textdatei, die drei Zeilen Text enthält.
11.5.2
Aufruf mit CALL :label
Wie bereits im Abschnitt 11.4.3 erläutert, ist seit Windows 2000 auch der direkte Aufruf mit call : möglich. Dabei wird der Ablauf zum angegebenen Sprungziel geleitet. Sobald die Ausführung nach dem call endet, kehrt die Befehlsausführung automatisch zur Zeile nach dem call zurück. Das Beispiel aus dem letzten Abschnitt hier noch einmal umgebaut für diese Art der Realisierung von Unterprogrammen. 01 :: reverse a text file, slow but plain shell 02 03 :: test der parameter 04 if !%1 == ! goto nofile 05 06 :: ist die datei auch da? 07 if not exist %1 goto nofile 08 09 :: test auf umgebungsvariable 10 if not defined temp goto noenv 11 12 :: evtl. bestehende datei loeschen 13 if exist %temp%\tmp.txt del %temp%\tmp.txt 14 15 :: 16 for /F "tokens=* usebackq" %%f in (%1) do call :procline "%%f" 17 more < %temp%\tmp.txt > %1 18 del %temp%\tmp.txt 19 del %temp%\line.txt 20 goto eof
Listing 11.6: Die Windows 200X-Version von reverse.bat
129
11 Shell Scripts (Batches) 21 22 :procline 23 echo %~1 > %temp%\line.txt 24 if exist %temp%\tmp.txt more < %temp%\tmp.txt >> %temp%\line.txt 25 more < %temp%\line.txt > %temp%\tmp.txt 26 goto eof 27 28 :noenv 29 echo Variable TEMP nicht definiert, Abbruch. 30 goto eof 31 32 :nofile 33 echo Keine Datei angegeben, Abbruch. 34 goto eof 35 36 :notfound 37 echo Die Datei %1 existiert nicht, Abbruch. 38 goto eof 39 40 :eof
Die Unterschiede sind vor allem der Wegfall des Tests für den Selbstaufruf (Zeilen 12–13 im Listing vorher) und die Veränderung des Parameters von %2 in %1 in Zeile 23, da der Marker "@@@" für den Selbstaufruf jetzt fehlt. Deshalb fehlt dieser auch in Zeile 16 nun beim call :procline "%%f". Ohne die Möglichkeit eines Shell Scripts, sich selbst kontrolliert aufrufen zu können, würde die Lösung vor Windows 2000 wesentlich komplexer ausfallen und nicht mehr mit einer Datei auskommen. Gut also, dass Microsoft ab Windows 2000 ein Einsehen hatte und die Modularisierung von Batches etwas einfacher gemacht hat.
11.6 Synchronisation 11.6.1
Warten auf Prozesse
Um auf der Kommandozeile auf die Beendigung eines Prozesses zu warten, starten Sie diesen mit dem Kommando start und geben die Option /wait an. Ohne diese Option arbeitet die Shell sofort das nächste Kommando ab, wie sich einfach zeigen lässt: notepad.exe && echo Fertig.
Hier wird Notepad gestartet, und im Shell-Fenster sehen Sie sofort die Ausgabe "Fertig", obwohl der Notepad-Prozess noch nicht beendet wurde. Dies führt nebenbei bemerkt die Exit-Code-Prüfung mit "&&" (s. Abschnitt 8.2) eigentlich ad absurdum, da der Prozess noch gar keinen Exit-Code geliefert hat. Deshalb ist hier start /wait notwendig.
130
Synchronisation
Innerhalb eines Shell Scripts allerdings wartet die Batch-Engine auf die Beendigung eines Prozesses, auch wenn dieser nicht mit start / wait gestartet wurde. Dazu erstelle ich einfach ein kleines Batchfile mit folgendem Inhalt: notepad.exe echo Fertig.
Wenn Sie diesen Batch nun starten, sehen Sie nur das Notepad-Fenster. Erst nachdem Sie notepad.exe beendet haben, erscheint die Ausgabe des echo-Kommandos im Shell-Fenster. Dass dies nicht unbedingt intuitiv ist, habe ich schon öfter gehört, allerdings ist wohl nicht mehr zu erwarten, dass Microsoft dieses Verhalten noch anpasst …
11.6.2
Kommunikation von Batches
Signaldateien Eine der einfachsten und ältesten Möglichkeiten, zwei Programme, Prozesse oder Shell Scripts miteinander kommunizieren zu lassen, ist die Verwendung von Dateien als Signale. Hier wird in einem Shell Script eine Datei angelegt, auf deren Existenz in einem anderen Shell Script gewartet wird. Am einfachsten erhalten Sie eine Datei per echo. > datei.ext, wobei eine leere Zeile in die Datei geschrieben wird. Falls Sie eine leere Datei bevorzugen, sehen Sie noch einmal im Kapitel über Ausgabeumleitung nach. Registry Eine andere Möglichkeit für die Kommunikation zwischen Scripts ist die Nutzung der Registry. Dies ist insofern störungsfreier als Signaldateien, da hier die Wahrscheinlichkeit für ein unabsichtliches Löschen oder Anlegen der Signaldatei durch einen Benutzer weniger wahrscheinlich ist. Verwenden Sie dazu das Kommando reg. Das Kommando waitfor Seit Windows 2003 ist es wesentlich leichter, auch maschinenübergreifende Shell Scripts zu synchronisieren. Mit dem Kommando waitfor hat Shell-Team von Microsoft eine einfach Möglichkeit geschaffen, mehrere Rechner Signale austauschen zu lassen. Um auf ein Signal zu warten, ist folgende Syntax notwendig: WAITFOR [/T timeout] signal
Der Parameter timeout ist dabei die maximale Wartezeit in Sekunden im Bereich von 1 bis 99999 (da ein Tag 86400 Sekunden lang ist, sollte dies auch für komplexere Shell Scripts ausreichen). Der Platzhalter signal wird durch den Namen des Signals ersetzt. Ein gültiger Name besteht aus einer ASCII-Zeichenkette von mindestens einem, maxi-
131
11 Shell Scripts (Batches)
mal 225 Zeichen aus den Zeichen a–z, A–Z, 0–9 sowie den ASCII-Zeichen mit einem Code von 128 bis 255. Dies schließt Zeichen wie z.B. "-", "@" oder "!" aus, da diese einen ASCII-Code von weniger als 65 besitzen! Geben Sie keinen Wert für die maximale Wartezeit an, wartet das System für immer. Um sein Signal zu senden, verwenden Sie folgende Syntax: WAITFOR [/S system [/U usr [/P [pwd]]]] /SI signal
Hier die Bedeutung der einzelnen Parameter: Tabelle 11.2: Die Optionen für das Senden per waitfor
/S system
Der Name des Computers, dem das Signal gesendet wird
/U usr
Benutzerkonto, unter dessen Kontext das Kommando läuft
/P pwd
Passwort für den angegebenen Benutzer
/SI signal
Der Name des Signals
Geben Sie keine Benutzerdaten an, wird der aktuell angemeldete Kontext verwendet. Falls Sie den Parameter /S weglassen, wird das Signal nicht an einen bestimmten Rechner, sondern per Broadcast an die komplette Domain gesendet!
11.7 Selbstmodifikation 11.7.1
Grundlagen
Wieso sollte sich ein Shell Script selbst modifizieren, und wie funktioniert so etwas überhaupt? Ein Shell Script (oder Batchfile) ist aus Sicht der ausführenden Shell nichts anderes als eine Textdatei, aus der Zeile für Zeile Befehle gelesen und nacheinander ausgeführt werden. Diese Textdatei kann das gerade laufende Script behandeln und manipulieren. Ein erstes Beispiel für die dynamische Änderung von Batchfiles zeigt das folgende Listing. Hier wird vom Benutzer per set /p eine Eingabe abgefragt, die als zusätzliche Zeile an das gerade laufen Script (%~f0) angehängt wird. Listing 11.7: Ein selbstmodifizierendes Script
@echo off cls echo Demo Selbstmodifizierendes Shell Script set /P zeile=Welches Kommando anfuegen: echo %zeile% >> %~f0 echo Das unmodifizierte Script endet hier. echo -------------------------------------
Wird dieses Script gestartet, erfolgt eine Abfrage nach einem Kommando. Als Beispiel gebe ich hier time /t für die Ausgabe der aktuellen Zeit ein. Diese Ausgabe der Zeit erfolgt auch, wie die Ausgabe unten zeigt.
132
Selbstmodifikation Demo Selbstmodifizierendes Shell Script Welches Kommando anfuegen:time /t Das unmodifizierte Script endet hier. ------------------------------------14:13
Die Batch-Engine der Shell liest Zeile für Zeile aus der Datei. Damit kann ich diese Datei zur Laufzeit ändern, solange die letzte Zeile noch nicht erreicht ist. Die angehängte oder modifizierte Zeile wird dann ganz normal ausgeführt. Nach der Ausführung sieht die Datei mit dem Shell Script folgendermaßen aus: @echo off cls echo Demo Selbstmodifizierendes Shell Script set /P zeile=Welches Kommando anfuegen: echo %zeile% >> %~f0 echo Das unmodifizierte Script endet hier. echo ------------------------------------time /t
Listing 11.8: Selbstmodifizierendes Script nach der Ausführung
Mr. Spock würde jetzt sicher sagen: „Faszinierend, Captain. Aber ich sehe keinen logischen Grund für eine Anwendung dieser Technik.“ Genau diese Gründe möchte ich Ihnen in den nächsten Abschnitten zeigen.
11.7.2
Beispiel Call-Logging
Würde es Sie nicht auch interessieren, wann manche Wartungsscripts das letzte Mal gelaufen sind? Wer ein Script aufgerufen hat, während Sie in Ihrem wohlverdienten Urlaub waren? Nichts einfacher als das … In der ersten Version zeichnet das Script alle Aufrufe in einer Art History-Liste auf. Dazu werden die Zeit der Ausführung und der Name des Benutzers als Kommentar an das Ende der Scriptdatei angefügt. @echo off echo Logging von Shell Scripts
Listing 11.9: Ein Script mit History-Funktion
:: hier den Code einbinden echo Ich arbeite .... :: logging echo ::Scriptausfuehrung um %time% durch %username% >> %~f0
Führen Sie nun das Script einige Male aus, und sehen Sie sich dann den Scriptcode an. Er sollte ungefähr so aussehen: @echo off echo Logging von Shell Scripts
Listing 11.10: Die Ausführungszeiten des Scripts
:: hier den code einbinden echo Ich arbeite ....
133
11 Shell Scripts (Batches) :: logging echo ::Scriptausfuehrung um %time% %~f0 ::Scriptausfuehrung um 14:20:35,76 ::Scriptausfuehrung um 14:20:59,67 ::Scriptausfuehrung um 14:21:02,04
durch %username% >> durch Administrator durch Administrator durch Administrator
Voilà – schon wissen Sie immer, wann ein Script ausgeführt wurde. Wollen Sie nur wissen, wann die letzte Ausführung war, muss der Code noch um das Ausfiltern des letzten Eintrags ergänzt werden. Allerdings hat dieser Ansatz einen Nachteil, der sicherheitsbewussten Administratoren sofort auffallen wird. Die Datei mit dem Script muss für den ausführenden Account schreibbar sein. Falls es sich bei den Batches um administrative Aufgabe handelt, kann man davon ausgehen. Trotzdem würde ich empfehlen, solche Logeinträge lieber dahin zu schreiben, wo sie hingehören: in eine zentrale Logdatei auf einem Server oder in das Anwendungsprotokoll der ausführenden Maschine.
11.7.3
Code und Daten kombinieren
In vielen Fällen wird nicht mit Shell Scripts, sondern auch mit Eingabedateien für die Umleitung von StdIn oder mit zusätzlichen Datendateien gearbeitet. Diese Dateien müssen bei einer Weitergabe des Shell Scripts natürlich vorhanden sein, sonst wird das Script nicht laufen. Es gibt aber eine Methode, diese Daten in die Scriptdatei zu integrieren und somit wieder mit nur einer Datei auszukommen. In manchen Shells anderer Betriebssysteme ist dieses Konzept in abgewandelter Form als ‚here document’ (ich habe keinen gängigen deutschen Begriff für dieses Konzept gefunden) bekannt, da anstelle einer Eingabeumleitung aus einer Datei der Prozess aufgerufen und die Daten im Script zwischen zwei besonderen Markierungen eingeschlossen werden. Ganz so leistungsfähig ist die Windows Shell nicht, aber die folgende Methode kommt diesem Ansatz relativ nahe. 'here documents' für Windows Dazu werden die Daten, die später in die Eingabedatei wandern sollen, in Form eines Kommentars in die Batchdatei eingeschlossen. Damit wir später feststellen können, was ein normaler Kommentar und was unsere Eingabedaten sind, wird zusätzlich zum Kommentarmarker (::) noch eine Kennung integriert (z.B. $data). So beginnt jede Zeile für die Daten mit der Zeichenkette ::$data. Welche Kennung Sie verwenden, ist unerheblich, solange diese nicht noch an anderer Stelle in der Datei auftaucht. Für unser Beispiel werde ich einige ftp-Kommandos verwenden und dann ftp mit einer Eingabeumleitung aus dieser Datei aufrufen. Ich
134
Selbstmodifikation
füge also die entsprechenden Datenzeilen in die Datei mit dem Shell Script ein: ::$data ::$data ::$data ::$data
lcd c:\tmp hash binary quit
Vor der Ausführung des ftp-Kommandos müssen diese Daten nun aus dem Shell Script extrahiert und in eine Datendatei geschrieben werden. Dazu wird die gerade laufende Script-Datei in einer forSchleife ausgelesen und jede Zeile auf die Kennung "::$data" untersucht. Stimmt dieses erste Wort überein, wird der Rest der Zeile an die Datendatei angefügt. Vor der Schleife muss ich noch dafür sorgen, dass diese Datei nicht existiert. Hier der Code für die Separation der Daten aus dem Shell Script. Dieser Code muss in jedem Shell Script laufen, das Code und Daten kombinieren will. echo Separiere Daten ... if exist %temp%\tmp.dat del %temp%\tmp.dat for /F "tokens=1,*" %%f in (%~f0) do @if /i "%%f" == "::$data" echo %%g >> %temp%\tmp.dat
Ist die Datei erstellt, kann das Kommando mit der Eingabeumleitung aufgerufen werden. echo Starte ftp ... ftp < %temp%\tmp.dat del %temp%\tmp.dat
Hier das komplette Script: @echo off ::$data lcd c:\tmp ::$data hash ::$data binary ::$data quit echo Separiere Daten ... if exist %temp%\tmp.dat del %temp%\tmp.dat for /F "tokens=1,*" %%f in (%~f0) do @if /i "%%f" == "::$data" echo %%g >> %temp%\tmp.dat echo Starte ftp ... ftp < %temp%\tmp.dat del %temp%\tmp.dat echo Fertig.
Listing 11.11: Ein ‚here’-Dokument für die Windows Shell
Das Prinzip ist durchaus ausbaufähig. Sind Sie nicht auf eine Datendatei beschränkt, verwenden Sie einfach verschiedene Kennungen (zum Beispiel ::$data1 und ::$data2). Shell Scripts & Windows Scripts in einer Datei Die nachfolgende Idee entstammt einem launigen Abend mit Kollegen und einigen guten Gläsern Rotwein. Irgendwann kam das Thema
135
11 Shell Scripts (Batches)
auf die Kombination von Daten und Shell Scripts. Einer meiner Kollegen meinte irgendwann, dass so etwas ganz nützlich sei, man aber auf keinen Fall Shell Scripts und WSH-Scripts in einer Datei kombinieren könne. Nun, es wurde eine lange Nacht, aber diese Mischung aus Code und Daten lässt sich tatsächlich auf die Spitze treiben: Es lassen sich in einer Datei sogar Shell Scripts und Scripts für den WSH mischen. Wird die Datei als Shell Script gestartet, werden die ShellBefehle ausgeführt. Übergebe ich die Datei als Parameter an cscript.exe, führt der WSH die VB-Kommandos aus. Damit stellt sich auch die Frage nach dem Sinn des Ganzen. Wozu ist diese Kombination in der Praxis nützlich? Die möglichen Einsatzgebiete sind Shell Scripts, die für einige kleine Funktionen oder die Kommunikation mit dem Benutzer auf Funktionen des Windows Script Host (WSH) angewiesen sind. Wenn es nur darum geht, eine Messagebox anzuzeigen und festzustellen, ob der Benutzer auf OK geklickt hat, reichen dafür im WSH zwei bis drei Zeilen. Diese in eine externe Datei auszulagern, macht die Wartung und die Weitergabe des Shell Scripts schon schwieriger. Falls Sie also irgendwann einmal ein Shell Script haben, dass einen Teil seiner Arbeit vom WSH erledigen lässt, können Sie beide Codeteile einfach in einer Datei ablegen. Das größte Problem war es, einen Code zu finden, den sowohl der WSH als auch die Windows Shell irgendwie akzeptieren26. Glücklicherweise ist der Doppelpunkt beim WSH ein gültiges Zeichen: Er trennt mehrere Befehle in einer Zeile. Damit ist ein Kommentar per :: in einem Shell Script immer noch eine gültige Befehlszeile für den WSH. Andersherum wird es etwas schwieriger. Ein Kommentar wird im WSH mit einem einzelnen Apostroph (') eingeleitet. Dies ist für die Shell kein gültiges Kommando. Wird die Fehlermeldung aber mit 2> nul ins Nirwana geschickt, kann dahinter mit dem Operator & ein weiteres Kommando folgen, das dann ausgeführt wird. Jede Zeile für den WSH beginnt also mit einem ::, jede Zeile für die Shell mit einem ' 2> nul &. Hierein Beispiel für ein solches ‚Mixed Content’-Script: Listing 11.12: Zwei Sprachen in einer Datei
' ' ' ' :: :: :: ::
2> 2> 2> 2>
nul nul nul nul
& & & &
@echo off echo Das ist die Windows Shell time /t ver
WScript.Echo "Das ist der WSH!!" set sh = WScript.CreateObject("WScript.Shell") sh.LogEvent 2, "Kaffee ist alle" set sh = Nothing
26 Das mehr als eine Sprache in einer Datei kein Problem sind, können Sie leicht feststellen: Suchen Sie im Web nach den Begriffen ‚polyglot’ und ‚source’. Dort finden Sie einen Quellcode, der sich mit ANSI COBOL, Pascal, Fortran, C, C++, PostScript, bash, sh und als 8086 Maschinensprache übersetzen lässt!
136
Interaktion mit dem Benutzer
Wird das Shell Script mit mixed.bat als Shell Script aufgerufen, gibt es die Zeit und die Versionsnummer von Windows aus. Mit der Befehlszeile cscript mixed.bat //E:vbscript gestartet, führt der WSH die Datei aus. Die Option //E ist notwendig, da die Datei nicht die Erweiterung .vbs besitzt. Dann erstellt der WSH einen Eintrag im Anwendungsprotokoll. Alternativ kann das Shell Script auch gleich den WSH aufrufen, wenn die beiden Abläufe verbunden sind: cscript %~f0 //e.vbscript. Damit haben Sie alle Möglichkeiten, sämtliche für ein Shell Script benötigten Daten auch tatsächlich in einer Datei zu vereinigen.
11.8 Interaktion mit dem Benutzer Die Anwendungsmöglichkeiten der Windows Shell sind auf den Einsatz als Kommandozeile für Power User und Administratoren zugeschnitten. Daher können Sie keine komfortablen Dinge wie Dialogboxen, bunte Fenster oder andere Sachen erwarten. Selbst der WSH lässt in dieser Hinsicht noch einiges zu wünschen übrig. Dennoch lassen sich mit dem vorhandenen Befehlssatz nahezu alle administrativen Aufgaben mit Eingaben versorgen.
11.8.1
Ein- und Ausgabe
set /p Die einfachste Möglichkeit einer zeilenweisen, interaktiven Eingabe bietet die Benutzung von set mit der Option /p. Informationen dazu habe ich bereits im Abschnitt 6.2.5 aufgeführt. Bei einer aktiven Eingabeumleitung (z.B. machwas.bat < x.x) wird der Text der ersten Zeile in die bei set angegebene Variable übernommen. Beim Pipelining (z.B. echo Text | machwas.bat) wird dieser Text nicht in die Variable übernommen, lediglich die Zeilenschaltung. Daher ist eine leere Eingabe von einem Piping nicht für set /p unterscheidbar! choice Die Nutzung von choice ist vor allem dann interessant, wenn Sie mehrere Auswahlmöglichkeiten anbieten wollen. Hier die allgemeine Syntax von choice: CHOICE [/C <liste>][/N][/CS] [/T [/D <default>]] [/M text]
137
11 Shell Scripts (Batches)
Die Option /C <liste> definiert die Liste der gültigen Optionen. Geben Sie hier eine Liste von Buchstaben und/oder Zahlen an, die als Auswahl akzeptiert werden sollen. Falls Sie diese Option weglassen, wird als Standard eine Ja-/Nein-Auswahl angenommen (YN beim englischen, JN beim deutschen Server). Die vom Benutzer gewählte Option wird als Errorlevel des Kommandos zurückgeliefert, wobei der Errorlevel der Zeichenposition in der Liste entspricht (1 für das erste Zeichen, 2 für das zweite usw.). Möchten Sie die Ausgabe der Auswahlmöglichkeiten unterdrücken (weil Sie beispielsweise selbst mit echo die Auswahl ausgeben), geben Sie die Option /N an. Die Option /CS (case sensitive) sorgt für die Beachtung der Schreibweise der Auswahloptionen. Eine maximale Wartezeit kann mit Hilfe der Option /T definiert werden. Maximal sind 9999 Sekunden möglich (bis dahin werden Sie sich ja wohl entschieden haben), minimal dagegen auch ein Wert von 0. Dann wird einfach die definierte Standardauswahl verwendet (dazu muss die Option /D auch angegeben sein). Für eine wirklich interaktive Auswahl sollten es also schon einige Sekunden sein. Den Standardwert für unentschiedene Benutzer können Sie mit der Option /D angeben. Dieser wird nach Ablauf der mit /T definierten maximalen Wartezeit verwendet. Die letzte Option /M erlaubt die Angabe eines Meldungstextes, der vom Kommando ausgegeben wird. Wird gleichzeitig die Option /N weggelassen, erscheint der Text vor der Liste der Auswahlmöglichkeiten. Dazu ein Beispiel: Sie wollen auf die Eingabe eines Vokals maximal zehn Sekunden warten, dann soll ein „e“ verwendet werden. Die dazu notwendige Eingabe finden Sie in der nächsten Zeile. choice /C aeiou /T 10 /D e
echo Hierzu gibt es mangels Funktionalität nicht viel zu sagen. Alles, was nach dem Kommando echo bis zum Ende der logischen Zeile folgt, wird als Meldung ausgegeben. Aus diesem Grund müssen wir bei der Nutzung neuer Befehlserweiterungen unter Umständen auch auf die runden Klammern zur Befehlsgruppierung zurückgreifen, wie das folgende Beispiel zeigt: if 4 LSS 7 echo 4 ist kleiner als 7 else echo Oops! Probleme!
138
Interaktion mit dem Benutzer
Die Ausgabe 4 ist kleiner als 7 else echo Oops! Probleme!
entspricht sicher nicht Ihren Erwartungen, aber so ist die Funktionalität von echo definiert. Daher muss um jedes echo eine eigene logische Zeile gebaut werden: if 4 LSS 7 (echo 4 ist kleiner als 7) else (echo Oops! Probleme!)
Jetzt sieht die Ausgabe so aus: 4 ist kleiner als 7
Weitere Informationen zum Thema Klammern finden Sie im Kapitel über die Befehlsgruppierung im Abschnitt 8.4. IE als Ausgabe Auch der Browser lässt sich als Ausgabemedium für längere Informationen nutzen. Mit Hilfe des Kommandos start können Sie ohne Probleme auf eine URL oder eine lokale HTML-Datei verweisen. Diese wird vom IE dann in einem neuen Fenster angezeigt. Was nicht viele Benutzer wissen: Auch die direkte Angabe von Text oder HTML-Code schluckt der IE, wenn Sie als „Protokoll“ about: voranstellen (wie bei about:blank für die leere Startseite). Geben Sie versuchsweise einmal die folgende Zeile ein: start about:^Meldung^^"Bitte warten ..."^
Eine Zeile
Das Ergebnis sehen in der nachfolgenden Abbildung: ein IE-Fenster mit dem Text als Meldung. Abbildung 11.1: Der IE als Messagebox missbraucht
Zusätzlich noch möglich, aber nicht wirklich praktikabel (auch ich nutze für so etwas die Möglichkeiten des WSH): per tasklist die Prozess-ID des IE-Fensters mit dem angegebenen Fenstertitel suchen
139
11 Shell Scripts (Batches)
lassen. Diese Ausgabe dann in eine Datei schreiben und mit einer for-Schleife das zweite Wort dieser Zeile lesen (dies ist die PID). Diesen Wert dann an taskkill übergeben und das Fenster so wieder schließen. Aber es funktioniert, und vielleicht können Sie diesen Ansatz, ein Fenster auf Kommandozeilenebene zu finden, ja einmal irgendwo brauchen … MsgBox per WSH Dies ist die sicherlich sinnvollste Methode. Dazu benötigen Sie auch keine extra VBS-Datei, die werden wir und sozusagen „on the fly“ erzeugen und danach wieder löschen: Listing 11.13: Eine Messagebox per WSH und Shell Script
echo MsgBox "Das hier ist die Meldung" > %temp%\tmp.vbs cscript %temp%\tmp.vbs del %temp%\tmp.vbs
Die Funktion MsgBox des Windows Script Host kann auch andere Aus-wahlen als eine reine Nachrichtenbox anzeigen und liefert einen Wert zurück, mit dem Sie testen können, welche Auswahl der Benutzer getroffen hat. Für unsere Zwecke reichen dazu die drei ersten Parameter des Aufrufs aus. MsgBox(<prompt>[,][, ][, , ])
Für den Parameter existiert eine Reihe vordefinierter Werte, welche die nachfolgende Tabelle angibt. Wert
Beschreibung
0
Nur Schaltfläche OK.
1
Schaltflächen OK und ABBRECHEN.
2
Schaltflächen ABBRECHEN, WIEDERHOLEN und IGNORIEREN.
3
Schaltflächen JA, NEIN und ABBRECHEN.
4
Schaltflächen JA und NEIN.
5
Schaltflächen WIEDERHOLEN und ABBRECHEN.
16
Icon für kritische Nachricht.
32
Icon für Nachfrage.
48
Icon für Warnung.
64
Icon für Information.
0
Standardauswahl ist die erste Schaltfläche.
256
Standardauswahl ist die zweite Schaltfläche.
512
Standardauswahl ist die dritte Schaltfläche.
768
Standardauswahl ist die vierte Schaltfläche.
Tabelle 11.3: Optionen für den Aufruf von MsgBox
140
Interaktion mit dem Benutzer
Der Aufruf von MsgBox liefert eine Zahl im Bereich von 1 bis 7 zurück, die folgende Bedeutung besitzt. Wert
Geklickte Schaltfläche
1
OK
2
Abbrechen (Abort)
3
Abbrechen (Cancel)
4
Wiederholen
5
Ignorieren
6
Ja
7
Nein
Tabelle 11.4: Ergebniswerte für MsgBox
Das Ergebnis dieses Aufrufs leiten wir mit dem Aufruf Wscript. Quit sofort in eine Beendigung des Scripts um, die das Ergebnis als Errorlevel zurückliefert. Dies kann dann über die Variable %errorlevel% oder eine Abfrage mit if errorlevel getestet werden. Hier das komplette Shell Script mit einem Beispiel: @echo off :: den wsh für eine messagebox missbrauchen :: script-code erzeugen echo WScript.Quit MsgBox("Weitermachen?", 4, "Auswahl") > %temp%\tmp.vbs :: script ausfuehren lassen cscript %temp%\tmp.vbs > nul :: if if if if if if if
test auf die %errorlevel% %errorlevel% %errorlevel% %errorlevel% %errorlevel% %errorlevel% %errorlevel%
eingabe des benutzers == 7 echo No button was clicked. == 6 echo Yes button was clicked. == 5 echo Ignore button was clicked. == 4 echo Retry button was clicked. == 3 echo Abort button was clicked. == 2 echo Cancel button was clicked. == 1 echo OK button was clicked.
:: scriptdatei wieder loeschen del %temp%\tmp.vbs Listing 11.14: Abfrage von MsgBox-Werten per Shell Script
141
11 Shell Scripts (Batches)
11.8.2
Systeminformationen / Warten
pause Dieses Kommando gibt eine Meldung aus und wartet, bis der Benutzer eine Taste drückt. Die Meldung kann mit Hilfe einer Ausgabeumleitung auch ins nul-Device geschickt werden. Beispiel: pause timeout Die Verwendung von choice habe ich weiter oben bereits erläutert. In vielen Fällen wäre aber eine reine Verzögerung ausreichend. Mit dem Befehl timeout können Sie die Ausführung von Batches vorübergehend anhalten. Die Syntax dieses Kommandos ist sehr einfach: TIMEOUT [/T] [/NOBREAK]
Als Parameter wird eine Zeit in Sekunden angegeben, die von -1 bis 9999 reichen kann. Der Wert -1 bedeutet, es wird so lange gewartet, bis der Benutzer eine Taste drückt, und entspricht damit funktional pause. Die Option /nobreak dient dazu, Tastendrücke innerhalb der Wartezeit zu ignorieren und wirklich zu warten, bis die angegebene Zeit abgelaufen ist. Ein Abbruch mit Hilfe von (Strg)+(C) ist aber immer möglich. ping-wait Für alle Veteranen (die Leute, die noch NT4-Systeme warten müssen) existiert noch eine andere Möglichkeit, einen Rechner warten zu lassen. Ein ping zu einer nicht vorhandenen Adresse mit einer TimeoutAngabe. ping -n 1 -w 2000 10.1.1.1
lässt den Batch ca. 2 Sekunden (2000 Millisekunden) warten. waitfor Im Abschnitt 11.6.2 auf Seite 131 habe ich bereits gezeigt, wie sich waitfor für die maschinenübergreifende Synchronisation von Shell Scripts einsetzen lässt. gettype Mit dem Kommando gettype hat Microsoft den Administratoren das Leben wesentlich leichter gemacht, wenn es nur schnell darum geht, Versionen oder Serverrollen abzufragen. GETTYPE [/S <system> [/U <user> [/P []]]] [/ROLE | /SP | /VER | /MAJV | /MINV | /TYPE | /BUILD]
142
Interaktion mit dem Benutzer
Die Parameter /S, /U und /P dienen wie bei allen neuen Kommandos konsistent der Authentifizierung bei entfernten Systemen. Falls Sie das Passwort hinter /P nicht angeben, wird es abgefragt. Die restlichen Optionen arbeiten nach folgendem Muster: Sie geben mit Hilfe der Option an, welche Information Sie abfragen wollen, und erhalten das Ergebnis als Errorlevel zurückgeliefert. Abgefragt werden können die Daten aus folgender Tabelle: /ROLE
Die Serverrolle: (DC = 1, Member-Server = 2, Workgroup = 3)
/SP
Der installierte Service-Pack (SP1 = 1, SP2 = 2 usw.)
/VER
Die BS-Version (Major * 1000, Minor * 100), für Windows 2003 (5.2) also 5200, für Windows XP (5.1) also 5100
/MAJV
Nur die Hauptversionsnummer (für 2003 ist dies 5000) als Tausender
/MINV
Die Nebenversionsnummer (0 = W2K, 100 = XP, 200 = 2003)
/BUILD
Die Buildnummer des Betriebssystems (2000 = 2195, 2003 = 3790)
/TYPE
Der Typ des Betriebssystems: 1 = Home Edition 2 = Professional 3 = Standard Server 4 = Enterprise Server 5 = Datacenter Server 6 = Web Server6 7 = Small Business Server:
Tabelle 11.5: Die Optionen für gettype
Vor Windows 2003 blieb nur das umständliche Zerlegen der Ausgabe von ver mit Hilfe einer for-Schleife. Da gettype.exe aber auch problemlos ab Windows 2000 aufwärts läuft, können Sie sich diese Arbeit sparen. Ein Aufruf ohne Parameter gibt alle Daten auf die Standardausgabe aus, wie das folgende Beispiel zeigt: C:\tmp>gettype Host Name: Name: Version: Role: Components:
bytebag Windows Server 2003, Enterprise Edition 5.2 Build 3790 Domain Controller Not Installed
Sprache Für die Feststellung der installierten Sprache (ich beschränke mich hier aus praktischen Gründen auf Deutsch und Englisch) oder der Landeskennung bzw. LCID existiert innerhalb des Standardumfangs der Windows Shell immer noch kein Kommando. Dazu müssen Sie entweder den WSH bemühen, ein externes Tools aufrufen, oder Sie
143
11 Shell Scripts (Batches)
testen anhand einer Systemausgabe, welche Sprache installiert ist. Im Windows 2003 Server Resource Kit finden Sie ein Tool mit dem Namen nlsinfo.exe, das diese Aufgabe erledigt, allerdings Raum für Verbesserungen lässt. Ein einfaches Beispiel: Wir kopieren das nul-Device und sehen nach, ob als Meldung „1 Datei(en) kopiert“ oder „1 file(s) copied“ ausgegeben wird. Der find-Filter liefert einen entsprechenden Errorlevel, und wir können eine Umgebungsvariable setzen. copy nul nul | find /i "Datei" if errorlevel 1 (set lang=EN) else (set lang=DE)
Hier liefert find einen Errorlevel von 1, wenn nichts gefunden wurde. Die Meldung enthielt nicht das Wort „Datei“, also war es wohl „file“, und wir haben einen englischen Server. Müssen Sie mehrere Sprachen unterscheiden, bleibt nur der Test für jede einzelne Sprache: set lang=?? copy nul nul | find if errorlevel 0 set copy nul nul | find if errorlevel 0 set copy nul nul | find if errorlevel 0 set copy nul nul | find if errorlevel 0 set copy nul nul | find if errorlevel 0 set
/i "datei" lang=DE /i "fichier" lang=FR /i "fichiero" lang=ES /i "file" lang=EN /i "archivio" lang=IT
Einige Seiten im Web raten dazu, doch einfach die Umgebungsvariable USERPROFILE abzufragen. Dort steht dann entweder „…\ Dokumente und Einstellungen…“ oder „…\Documents and Settings…“ im Pfad. Davon rate ich ab, da durch Gruppenrichtlinien oder andere Einstellungen bei der Anmeldung das Profil auch woanders liegen kann. Eine andere Alternative ist die Benutzung von WMI zur Abfrage der entsprechenden Informationen. Hier die entsprechende Kommandozeile: wmic os get Locale /format:list
Anschließend erhalten Sie eine Zeile in der Form Locale=#### zurück, die nur noch als Batch aufgerufen werden muss, und schon haben Sie eine passende Umgebungsvariable. Mehr über das mächtige Kommando wmic erfahren Sie im Kapitel 14.1.
144
12
Design von Shell Scripts
12.1 Brauchen Batches ein Design? Diese Frage lässt sich klar beantworten: Ja, auch Shell Scripts benötigen ein Design. Sicherlich wird niemand für einen Dreizeiler aufwändige Planung betreiben, aber sobald ein Shell Script wiederholt und produktiv eingesetzt wird, geht es nicht ohne etwas Überlegung. Gerade die strikte und nicht immer konsistente Syntax vieler Kommandos macht es nötig, bei komplexeren Abläufen etwas Zeit mit der Planung zu verbringen. Da Sie (im Gegensatz zu Programmiersprachen mit Freiform-Syntax wie SQL, Java, C# u.a.) Struktur nicht als Mittel der Gestaltung einsetzen können, sind Kommentare und ein sauberer Aufbau des Shell Scripts sehr wichtig. Benutzen Sie nach Möglichkeit Leerzeilen zur logischen Unterteilung des Scripts, und geben Sie bei produktiv genutzten Scripts in einem Kommentar zu Beginn eine Kontaktadresse per Mail oder Telefon an, damit im Zweifelsfall eine Auskunft eingeholt werden kann. Wie Sie im Verlauf des Buches gesehen haben, besteht für eine Aufgabe mit der Shell oft mehr als eine Lösungsmöglichkeit. Entscheiden Sie sich im Zweifelsfall für die lesbarere Alternative. Gerade bei Shell Scripts macht ‚Tuning’ im Sinne der Laufzeitverbesserung oft wenig Sinn. Erstens haben Sie auf die Laufzeit der externen Kommandos meist keine Einflussmöglichkeiten, und zweitens besitzt bei administrativen Scripts die Laufzeit in vielen Fällen die oberste Priorität. Was nicht bedeuten soll, dass es Ihnen egal sein kann, wie lange ein Script läuft. In der Praxis aber ziehe ich einen lesbaren (und wartbaren) Batch mit einer Laufzeit von zwölf Sekunden einem mit nur neun Sekunden Laufzeit vor, den nach dem Schreiben niemand mehr versteht. Shell Scripts leben länger als geplant und werden wesentlich öfter gelesen als geschrieben, sei es zu Wartungszwecken oder weil Teile wiederverwendet werden sollen. Wenn Sie beim Schreiben eine Minute gewinnen und Sie und Ihr Team später beim Lesen einhundert Mal fünfzehn Sekunden länger brauchen, haben Sie effektiv 24 Minuten verloren.
145
12 Design von Shell Scripts
12.2 Parameter 12.2.1
Online-Hilfe
Falls Sie selbst Shell Scripts erstellen, sollten Sie daran denken, dass produktiv genutzte Batches eine Online-Hilfe bieten sollten. Dies erspart Ihnen und Ihren Kollegen beim späteren Einsatz das mühevolle Studieren des Quelltextes. Daher empfehle ich Ihnen in Anlehnung an die Windows-Konventionen die Integration eines Parameters /?, der einen Hilfetext mit einer kurzen Beschreibung des Scripts und der Aufrufsyntax ausgibt und anschließend das Shell Script ohne weitere Aktion beendet. Eine längere Information oder Dokumentation und Beispiele können Sie direkt aus dem Shell Script erzeugen lassen, wenn Sie dazu den Ansatz eines ‚here documents’ für den Batch nutzen, den ich im Abschnitt 11.7.3 vorgestellt habe.
12.2.2
Sicherheitsabfragen
Dieses Thema ist ein zweischneidiges Schwert. Viele erfahrene Admins ärgern sich oft über die ihrer Meinung nach unnötigen Sicherheitsabfragen des Systems, da sie im täglichen Betrieb aufhalten. Dennoch sollten Sie bei der Planung Ihrer eigenen Batches daran denken, potenziell gefährliche Aktionen erst nach einer Rückfrage auszuführen. Bewährt hat sich die Integration einer besonderen Option (ähnlich /Q bei vielen Shell-Befehlen), die eine Nachfrage unterdrückt und das Shell Script im „Ich weiß schon, was ich tue“-Modus ausführt.
12.2.3
Anzahl und Reihenfolge
Können Sie sich sechs oder sieben Parameter für den Aufruf eines Kommandos auswendig merken? Ich habe ja schon Probleme, mir zu merken, dass nslookup mit exit statt mit quit beendet wird … Aber ernsthaft, planen Sie die Parameter und die Funktionalität Ihrer Shell Scripts so, dass eine vernünftige Bedienung auch nach längerer Zeit möglich ist: wichtige Parameter zuerst, möglichst nicht mehr als drei oder vier oder Parameter, eine Online-Hilfe (siehe oben). Die Vergabe von Namen für Wertparameter ist bei Shell Scripts relativ aufwändig und daher problematisch (an die allgemeine Auswertung eines Ausdrucks wie /format: decimal schreiben Sie eine ganze Zeit hin). Aus diesem Grund werden Parameter in Shell Scripts üblicherweise anhand ihrer Position identifiziert. Für einzelne Optionen (wie /Q) ist die Prüfung dagegen eher unkritisch (siehe auch Abschnitt 11.3). Seien Sie außerdem vorsichtig bei der Benennung entsprechender Optionen. Dieser Hinweis trifft zwar auf WSH-Skripte viel stärker zu,
146
Ausgabegestaltung
ist aber auch für Shell Scripts relevant. Wenn die Funktionalität erweitert wird, können Ihnen schnell die Buchstaben ausgehen! Ein schönes Beispiel dafür sind die Optionen für das Kommando ldifde, mit dem Daten aus dem Active Verzeichnis im LDIF-Formar importiert oder exportiert werden können. Für die zu exportierenden Attribute wurde die Option -l gewählt, da -a für die Authentifizierung benutzt wurde. Ein Logging muss nun mit der unlogischen Option -j gestartet werden. Sinnvoller (und nicht wesentlich schwieriger zu implementieren) wären -auth, -log und -attributes gewesen. Manchmal kann der EDV-typische Abkürzungswahn auch lästig sein …
12.3 Ausgabegestaltung Berücksichtigen Sie bei der Planung Ihrer produktiven Shell Scripts zwei Tatsachen, die jeder Administrator irgendwann leidvoll lernt: Die Ausgabe muss erstens irgendwann von einem anderen Programm, Script oder Tool weiterverarbeitet werden, und zweitens ändern sich irgendwann die Meldung bzw. wird diese übersetzt. Dies bedeutet, dass Sie sich durchaus einige Minuten Gedanken über die Gestaltung der Ausgaben Ihrer Batches machen sollten. Bewährt hat sich zum Beispiel das Voranstellen einer Klassifizierung vor den eigentlichen Text der Ausgabe, das erleichtert später wesentlich die Filterung und Weiterverarbeitung. Vergleichen Sie selbst die Möglichkeit der maschinellen Lesbarkeit der folgenden beiden Varianten: CreateUser Script 1.0 Erzeuge Benutzer aus Importdatei newcomer.txt .... Erzeuge Franz Testhuber Erzeuge Gabi Bergbauer Benutzer Becky Myers existiert bereits Kein Passwort für Benutzer Elwood Blues 3 Benutzer erzeugt
Listing 12.1: Eine normale Ausgabe
[MESSAGE] Verwende "newcomer.txt" als Importdatei [MESSAGE] Erzeuge "Franz Testhuber" [MESSAGE] Erzeuge "Gabi Bergbauer" [ERROR] Benutzer "Becky Myers" existiert bereits [WARNING] Benutzer "Elwood Blues" : kein Password [MESSAGE] Ergebnis: 3 Benutzer erzeugt
Listing 12.2: Eine wiederverwertbare Ausgabe
Die zweite Methode ist für andere Scripts oder WSH-Programme wesentlich leichter verwertbar. Erstens wird jede Ausgabezeile klassifiziert. Dies ist vor allem dann sinnvoll, wenn die Ausgabe oder Logdatei später kontrolliert werden muss. Dann ist es ein leichtes, per find oder findstr nach Fehlerzeilen zu suchen. Zusätzlich sind die Ausgaben für ein späteres Parsing so gestaltet, dass immer ein Wort vor dem aktuell verarbeiteten Element steht. Alle Elemente sind darüber hinaus in Anführungszeichen eingeschlossen, so dass auch Dateioder Benutzernamen mit Leerzeichen sauber gelesen werden können.
147
12 Design von Shell Scripts
12.4 Modularisierung 12.4.1
Zielbetriebssystem
Eine der Überlegungen für das Design eines Shell Scripts ist vor allem die Liste der Zielsysteme. Auch wenn es der Vertrieb von Microsoft gerne sehen würde, nicht alle Systeme laufen unter Windows 2003. Viele Firmen haben auf ihren Servern noch Windows 2000 installiert, die Clients haben XP, und es soll hinten in der dunklen Ecke des Rechenzentrums noch zwei oder drei Maschinen mit einem Windows NT4 geben. Dann bleibt nur der kleinste gemeinsame Nenner, also die Kommandos und Befehlserweiterungen der ältesten im Einsatz befindlichen Betriebssystemversion. Relativ unkritisch ist der Mix aus Windows XP und Windows 2003, da sich hier weniger Kommandos geändert haben als in den Versionen vorher. Aber auch Windows 2000 beherrscht bereits Dinge wie ein call :label oder verzögerte Variablenexpansion.
12.4.2
Einzelskript oder mehrere Dateien
Wenn zur Lösung eines Problems eine Kombination aus mehreren Batchdateien nötig ist, sollten Sie sich überlegen, ob sich daraus nicht eine einzige Datei mit nur noch einem Shell Script bauen lässt. Innerhalb dieser Datei kann zu Beginn eine Verteilung per Sprung an die entsprechende Unterroutine vorgenommen werden. Am Beispiel eines Scripts zur Umbenennung aller Dateien in einem Ordner möchte ich Schritt für Schritt diese Entwicklung nachvollziehen. Fangen wir mit der Aufgabenstellung an, die jeder Besitzer einer Digitalkamera kennt. Alle Dateien in einem Verzeichnis sollen aufsteigend nummeriert werden. Bevor Sie die folgenden Beispiele in diesem Kapitel nachvollziehen, erstellen Sie sich ein Spielverzeichnis, und achten Sie darauf, vor der Ausführung der Shell Scripts in dieses Verzeichnis zu wechseln! Sie wollen doch sicher nicht, dass Ihr system32-Verzeichnis aufsteigend nummerisch umbenannt wird, oder? Dazu wird zuerst eine Umgebungsvariable mit der Startnummer definiert. set num=100
Jetzt wird durch alle Bilddateien in einem Verzeichnis gelaufen und das Shell Script für die Umbenennung aufgerufen. Sollte dieses Script nicht im Befehlspfad liegen, denken Sie daran, es mit dem kompletten Pfad aufzurufen (z.B. call c:\windows\scripts\doRen.bar %f). for %f in (*.jpg) do call doRen.bat %f
148
Modularisierung
Dieses Umbenennungsscript doRen.bat ist sehr einfach und hat folgenden Inhalt: :: umbennen ren %1 Img-%num%%~x1 :: zaehler erhoehen set /A num=%num% + 1
Zuerst wird per ren[ame] die Datei, die als Parameter übergeben wurde, umbenannt, wobei der Ausdruck Img-%num%%~x1% dafür sorgt, dass die neue Datei mit "Img-" beginnt, gefolgt vom Wert der Zählervariablen und von der originalen Erweiterung der Datei (irgendwann wollen Sie mit diesem Script etwas anderes tun als .jpgDateien umbenennen, und dann muss an dieser Stelle nicht der Code geändert werden). So weit, so gut. Allerdings haben wir bis jetzt zwei interaktive Kommandos (das Setzen des Startwertes und die for-Schleife) sowie ein Shell Script. Dies soll nun in einer Datei vereinigt werden. Der erste Schritt dazu ist die Erstellung eines Batches für die Schleife (denken Sie daran, dass innerhalb eines Batches die Prozentzeichen bei for verdoppelt werden müssen!): set num=100 for %%f in (*.jpg) do call c:\tmp\doRen.bat %%f echo Fertig.
Nun zum zweiten Schritt, der Vereinigung der beiden Scriptdateien. Dazu wird später der Teil, der jetzt noch in doRen.bat steckt, per call :label aufgerufen. set num=100 for %%f in (*.jpg) do call :doRen %%f echo Fertig. goto :eof
Listing 12.3: Das umgebaute Script
:doRen :: umbennen ren %1 Img-%num%%~x1 :: zaehler erhoehen set /A num=%num% + 1
Fertig? Beinahe. Das Script funktioniert zwar in den meisten Fällen, einige Details sind aber noch zu erledigen: 1. Leerzeichen in Dateinamen müssen berücksichtigt werden. 2. Eine Sicherheitsabfrage zu Beginn wäre ganz nett. 3. Die Befehlsausgabe sollte abgeschaltet werden. 4. Das Script sollte melden, was gerade bearbeitet wird. Zu Punkt 1: Dazu wird der Dateiname im Kommando der forSchleife sicherheitshalber in doppelte Anführungszeichen eingeschlossen.
149
12 Design von Shell Scripts
Zu Punkt 2: Wir ergänzen eine Ausgabe zu Beginn und warten mit pause darauf, dass der Benutzer uns das O.K. gibt. Zu Punkt 3: Einfach: Wir ergänzen ein @echo off zu Beginn. Zu Punkt 4: Dazu wird vor dem ren per echo eine Ausgabe integriert. Hier das geänderte Script (Änderungen sind fett gedruckt): Listing 12.4: Das fertige Script in einer Datei
@echo off echo Achtung! Dieses Script aendert alle echo Dateinamen im aktuellen Verzeichnis echo in eine nummerische Form ab! echo Weiter mit bel. Taste oder [Strg-C] echo zum Abbrechen. pause > nul set num=100 for %%f in (*.jpg) do call :doRen "%%f" echo Fertig. GOTO :EOF :doRen echo Aus %1 wird Img-%num%%~x1 ... ren %1 Img-%num%%~x1 Set /A num=%num% + 1
Als kleine Übung lasse ich Ihnen noch die Erweiterung um einen beliebigen Startwert oder eine Maske für den neuen Dateinamen per Parameter. Die Integration mehrerer Kommandos oder Shell Scripts in eine einzelne Datei ist also keine relativ einfache Sache, wenn Sie Schritt für Schritt vorgehen. Damit gewinnen Sie nicht nur eine übersichtlichere Scriptsammlung, sondern müssen auch nur eine einzelne Datei auf ein anderes System übertragen.
150
13
Erweiterungen
13.1 RunDLL32 13.1.1
Grundlagen & Einsatzmöglichkeiten
Nicht alles, was an administrativen Aufgaben benötigt wird, kann die Shell leisten, aber auch der WSH hat Lücken in seinem Leistungsumfang. Einen Teil dieser offenen Punkte kann ein Kommando schließen, das als eine Art Brücke zwischen Shell und Windows agiert: rundll32. Damit ist der Aufruf einer Reihe von exportierten Funktionen in DLLs möglich. Viele Funktionen in DLLs sind für den Aufruf durch eine Programmiersprache geschrieben und erwarten Parameter in bestimmten Formaten und an bestimmten Positionen. Daher lassen sich nicht alle Funktionen in DLLs aufrufen. Was aber möglich ist, reicht für viele Aufgaben aus: so lassen sich beispielsweise Drucker installieren, Netzwerkeinstellungen aufrufen oder Verknüpfungen per Shell-Kommando erzeugen. Die generelle Syntax für die Nutzung von RunDLL32 lautet wie folgt: RUNDLL32.EXE , [Argumente]
Bei der Angabe von Funktionsnamen und Argumenten wird die Groß- und Kleinschreibung unterschieden! Wenn Sie also rundll32Kommandos eingeben, achten Sie auf die korrekte Schreibweise, sonst erhalten Sie nur eine Fehlermeldung. Beginnen wir mit einem einfachen, aber nützlichen Beispiel. Ein Shell Script, das längere Zeit läuft, stellt bei einer unbeaufsichtigten Maschine ein Sicherheitsrisiko dar. Irgendjemand könnte an der Maschine mit (Strg)+(C) das Script abbrechen und dann eigene Kommandos eingeben. Dies kann mit einem rundll32-Aufruf verhindert werden, der die Maschine sperrt (die gleiche Funktion, die Sie mit (Strg)+(Alt)+(Entf) und der Auswahl COMPUTER SPERREN erreichen. rundll32 user32.dll,LockWorkStation
Wie bereits oben erläutert, achten Sie auf die korrekte Schreibweise. Jetzt wird der Computer gesperrt, und Sie können dies in Zukunft ohne Probleme skriptgesteuert erledigen.
151
13 Erweiterungen
13.1.2
Beispiele für runDLL32
Es existiert eine ganze Reihe von Aufrufen per RunDLL32, manche sehr sinnvoll, andere sind meiner Meinung nach eher in die Kategorie ‚Angewandter Unsinn’ einzuordnen. Nachdem die Funktionalität zum Großteil als undokumentiert gilt, existiert keine komplette Liste. Einige Anregungen finden Sie aber in der nachfolgenden Aufstellung (und zusätzlich gibt es immer noch Google), die einige der sinnvoll einsetzbaren Varianten zusammenfasst. Immer eine Zeile
Ach ja: Geben Sie alle hier aufgeführten Befehle immer in einer einzigen Zeile ein. rundll32.exe shell32.dll,Control_RunDLL
Zeigt die Systemsteuerung in Explorer-Stil an. rundll32.exe shell32.dll,Control_RunDLL timedate.cpl,,1
Öffnet den Dialog für die Zeitzoneneinstellung. rundll32.exe shell32.dll,Control_RunDLL timedate.cpl,,1
Öffnet den Dialog für die Zeiteinstellung. rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,0
Hintergrundeinstellung der Anzeige rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,1
Einstellung des Bildschirmschoners rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,2
Dialog für die Anzeigedarstellung rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,3
Anzeigeeinstellungen (Auflösung, Farbtiefe etc.) rundll32.exe shell32.dll,Control_RunDLL main.cpl @0
Konfiguration der Mauseinstellungen rundll32.exe shell32.dll,Control_RunDLL main.cpl @1
Tastaturwiederholrate rundll32.exe shell32.dll,Control_RunDLL main.cpl @1,1
Regionale Einstellungen für Eingabegeräte rundll32.exe shell32.dll,Control_RunDLL main.cpl @1,2
Allgemeine Tastatureinstellungen rundll32.exe shell32.dll,Control_RunDLL main.cpl @2
152
RunDLL32
Zeigt den Drucker-Ordner an rundll32.exe shell32.dll,Control_RunDLL main.cpl @3
Schriftarten-Ordner anzeigen rundll32.exe shell32.dll,Control_RunDLL main.cpl @4
Konfiguration der Energiesparfunktionen rundll32.exe shell32.dll,Control_RunDLL intl.cpl,,0
Auswahl der Ländereinstellungen (Gebietsschema) rundll32.exe shell32.dll,Control_RunDLL intl.cpl,,1
Festlegen der Ländereinstellungen: Zahlenformate rundll32.exe shell32.dll,Control_RunDLL intl.cpl,,2
Festlegen der Ländereinstellungen: Währung rundll32.exe shell32.dll,Control_RunDLL intl.cpl,,3
Festlegen der Ländereinstellungen: Uhrzeit rundll32.exe shell32.dll,Control_RunDLL intl.cpl,,4
Festlegen der Ländereinstellungen: Datum rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl,,0
Systemeigenschaften (ÿ)+(Pause) rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl,,1
Systemeigenschaften, Reiter „Netzwerkidentifikation“ rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl,,2
Systemeigenschaften, Reiter „Hardware“ rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl,,3
Systemeigenschaften, Reiter „Benutzerprofile“ rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl,,4
Systemeigenschaften, Reiter „Erweitert“ Ich hoffe, diese Liste hat Ihnen einen Eindruck der Möglichkeiten vermittelt, die sich hinter diesem unscheinbaren Kommando verbergen. Zusätzlich zu den hier aufgeführten Funktionen lässt sich ab Windows NT auch nahezu die komplette Druckereinrichtung per Kommandozeile erledigen, indem Funktionen aus der DLL printui.dll aufgerufen werden. Der nächste Abschnitt widmet sich daher komplett dem Thema Drucker, bevor ich zum Abschluss auf die Grenzen von RunDLL32 eingehen werde.
153
13 Erweiterungen
13.1.3
Druckerverwaltung per rundll32
Sie können mit Hilfe von rundll32 die komplette Druckerverwaltung mit Hilfe der Windows Shell erledigen, von der Einrichtung eines Druckers über die Abfrage von Druckereigenschaften bis zu Kommentaren zu einem Drucker. Ab Windows 2003 können solche Aufgaben auch über die prn*-Kommandos erledigt werden. Die allgemeine Syntax für die Druckerverwaltung sieht wie folgt aus: rundll32 printui.dll,PrintUIEntry [Optionen] [@Befehlsdatei] Tabelle 13.1: Optionen für die Druckerverwaltung mit rundll32
154
Option
Bedeutung
/a[Datei]
Name der Binärdatei
/b[Name]
Basisdruckername
/c[Name]
UNC-Computername, wenn der Vorgang auf einem Remote-Computer ausgeführt wird
/dl
Löscht den lokalen Drucker.
/dn
Löscht die Netzwerkdruckerverbindung.
/dd
Löscht den Druckertreiber.
/e
Zeigt Druckeinstellungen an.
/f[Datei]
Entweder INF-Datei oder Ausgabedatei.
/ga
Fügt Druckerverbindungen pro Maschine hinzu.
/ge
Listet Druckerverbindungen pro Maschine auf.
/gd
Löscht Druckerverbindungen pro Maschine.
/h[Arch]
Treiberarchitektur Alpha | Intel | Mips | Power-PC.
/ia
Installiert Druckertreiber mit Hilfe einer INF-Datei.
/id
Installiert Druckertreiber mit Hilfe des Assistenten.
/if
Installiert Drucker mit Hilfe der angegebenen INFDatei.
/ii
Installiert Drucker mit Hilfe des Assistenten und einer INF-Datei.
/il
Installiert Drucker mit Hilfe des Assistenten.
/in
Fügt eine Netzwerkdruckerverbindung hinzu.
/j[Anbieter]
Druckanbietername
/k
Druckt eine Testseite auf dem angegebenen Drucker aus. Kann bei der Druckerinstallation nicht verwendet werden.
/l[Pfad]
Quellpfad des Druckertreibers
/m[Modell]
Modellname des Druckertreibers
/n[Name]
Druckername
RunDLL32
Option
Bedeutung
/o
Zeigt die Druckerwarteschlange an.
/p
Zeigt Druckereigenschaften an.
/q
Stiller Modus. Fehlermeldungen werden nicht angezeigt.
/r[Anschluss]
Anschlussname
/s
Zeigt Servereigenschaften an.
/Ss
Speichert Druckereinstellungen in einer Datei.
/Sr
Stellt Druckereinstellungen aus einer Datei wieder her. Speichert Optionsattribute für Druckereinstellungen oder stellt diese wieder her. Die Attribute müssen am Ende des Befehls stehen: 2 PRINTER_INFO_2 7 PRINTER_INFO_7 c Farbprofil d Druckerdaten s Sicherheitsbeschreibung g Globaler_DevMode m Minimale_Einstellungen u Benutzer-DevMode r Namenskonflikte_lösen f Namen_erzwingen p Anschluss zuordnen
/u
Verwendet den vorhandenen Druckertreiber, sofern bereits einer installiert ist.
/t[#]
Nullbasierte Indexseite zum Starten
/v[Version]
Eine der folgenden Treiberversionen: Windows 95 oder 98 | Windows NT 3.1 | Windows NT 3.5 oder 3.51 | Windows NT 3.51 | Windows NT 4.0 | Windows NT 4.0 oder 2000 | Windows 2000
/w
Fordert einen Treiber an, wenn der angegebene Treiber nicht in der INF-Datei gefunden wird.
/y
Richtet den Drucker als Standarddrucker ein.
/Xg
Liest Druckereinstellungen.
/Xs
Richtet Druckereinstellungen ein.
/z
Gibt diesen Drucker nicht automatisch frei.
/Z
Gibt diesen Drucker frei. Verwendung nur mit der Option /if möglich.
@[Datei]
Datei mit Befehlszeilenargumenten
Diese Liste müssen Sie sich nicht merken, Sie können Sie online mit folgendem Kommando abrufen: rundll32 printui.dll,PrintUIEntry /?
155
13 Erweiterungen Eine Zeile
Hier einige Beispiele aus eben dieser Online-Hilfe (auch hier gilt wieder: Alles in eine Zeile eingeben). rundll32 printui.dll,PrintUIEntry /s /t1 /n\\Computer
Zeigt die Servereigenschaften rundll32 printui.dll,PrintUIEntry /p /n\\Computer\ Drucker
Druckereigenschaften rundll32 printui.dll,PrintUIEntry /o /n\\Computer\ Drucker
Anzeige der Warteschlangenansicht rundll32 printui.dll,PrintUIEntry /if /b "Testdrucker" /f %windir%\inf\ntprint.inf /r "lpt1:" /m "Name_des_Druckers"
Startet eine INF-Installation eines Druckers rundll32 printui.dll,PrintUIEntry /dd /c\\Computer /m "AGFA-AccuSet v52.3" /h "Intel" /v "Windows 2000"
Entfernt einen Druckertreiber rundll32 printui.dll,PrintUIEntry /y /n "Drucker"
Richtet den Drucker als Standarddrucker ein rundll32 printui.dll,PrintUIEntry /Xs /n "Drucker" Comment "Mein cooler Drucker"
Legt einen Kommentar zum Drucker an Gerade für unbeaufsichtigte Installationen oder die Konfiguration von Druckern per Logon-Script ist dieses Kommando oft die einzige Möglichkeit, ohne umfangreiche WSH-Programmierung solche Aufgaben zu lösen. Nicht alles wird dadurch abgedeckt, aber ich bin mir sicher, Sie werden sich diese Befehlsliste genauer ansehen …
13.1.4
Die Grenzen von RunDLL32
Es gibt dieses alte Sprichwort vom vielen Schatten, der dort ist, wo auch viel Licht ist. So viel Schatten ist es bei RunDLL32 aber gar nicht. Eine Einschränkung haben Sie bereits erfahren: Es gibt keine Aufrufmöglichkeit für beliebige Funktionen aus DLLs, da die Parameterübergabe per Kommandozeile nicht in den entsprechenden Formaten möglich ist. Eine andere Einschränkung ist die stark schwankende Funktion vieler Aufrufe in Abhängigkeit der Betriebssystemversion. Die hier aufgeführten Aufrufe sollten alle unter Windows 2000 aufwärts funktionieren. Im Internet finden Sie noch viel mehr Funktionen, die aber
156
Zusätzliche Tools
teilweise nur unter Windows 98 oder Me funktionieren, nur unter Windows NT4 und so fort. Gerade hier ist also Ausprobieren und sorgfältiges Abwägen des Einsatzes angebracht, damit bei einem Upgrade nicht plötzlich lieb gewonnene Funktionen nicht mehr zur Verfügung stehen.
13.2 Zusätzliche Tools 13.2.1
Support Tools
Die Support Tools gehören noch zum Lieferumfang des jeweiligen Betriebssystems und finden sich auf der CD im Ordner support\ tools. Die hier installierbaren Programme dienen Administratoren und dem Support-Personal dazu, bei Problemen schneller den Fehler zu finden oder bestimmte Funktionen auszuführen, für die im Standardlieferumfang von Windows kein Programm vorhanden ist. Viele dieser Programme erleichtern die Arbeit mit der Kommandozeile oder die unbeaufsichtigte Installation eines Systems. Eine Liste der einzelnen Programme, die bei den Support Tools installiert werden, finden Sie im Referenzteil bei der Liste der Shell-Kommandos. Mit dem Server 2003 wurde der Umfang des Supports erweitert, viele Programme aus dem Resource Kit sind jetzt für jeden Admin ohne die Anschaffung des Resource Kits verfügbar.
13.2.2
Resource Kit
Beim Resource Kit handelt es sich schwerpunktmäßig schon immer mehr um Diagnose- und Systemprogramme, die eher zur Fehlersuche und für Entwickler benutzt werden. Aber auch für Admins sind einige interessante Sachen darunter. Einige der für das Shell Scripting und die Abfrage von Systeminformationen vorgesehenen Tools sind mit den Möglichkeiten von Windows 2003 nicht mehr notwendig. Tools wie now (kann bei Ausgaben durch %time% und %date% ersetzt werden), regini (Alternativen reg oder wmic) oder srvinfo (geht per WMI flexibler) sind Beispiele für solche Befehle, die heute nicht mehr so notwendig sind wie noch vor fünf Jahren. Andere Kommandos wie subinacl, gpotool oder die Diagnoseprogramme sind nach wie vor eigentlich unverzichtbar.
13.2.3
Services for Unix
Eigentlich sprengt die Aufnahme dieses Produktes den thematischen Rahmen des Buches. Die Services for Unix (SFU) sind ein komplettes Unix-Subsystem für den Windows Server. Vom Posix-kompatiblen Subsystem über mehrere Shells und weit über 300 Unix-Tools bis hin zum
157
13 Erweiterungen
NFS-Server ist alles enthalten, was ein Unix-Admin benötigt, um mit so wenig Aufwand wie möglich auf einen Windows-Rechner umzusteigen. Falls Sie dann noch einen X-Server für Windows haben, werden Sie kaum mehr merken, dass es sich nicht um eine Unix-Maschine handelt. Mehr Informationen finden Sie auf der Microsoft-Website
13.2.4
Win32-Ports der GNU-Tools
Diesen Satz von Tools aus der Unix-Welt sollten Sie sich besorgen. Es handelt sich hierbei um eine frei verfügbare Portierung der Shell Text Utilities im Rahmen des GNU-Projektes. An Systemvoraussetzungen ist nur die Microsoft C-Runtime nötig, die sowieso auf jedem WindowsSystem vorhanden ist, da auch Microsoft diese Bibliothek benötigt. Im Gegensatz zu anderen Paketen wie cygwin benötigen Sie daher für einen Roll-Out keine Vorbereitungen. Der Funktionsumfang ist allerdings auch kleiner als bei cygwin. Der Quellcode der Portierungen ist ebenfalls verfügbar, auf Sourceforge existiert ein eigenes Projekt für diese Tools. Der URL lautet http://unxutils.sourceforge.net (zum Zeitpunkt der Bucherstellung). Daher sollte auch bei Unternehmen, die sonst dem Einsatz von Tools aus den Weiten des Web kritisch gegenüberstehen, der Einsatz dieses Paketes kein Problem sein. Wenn Ihnen diese Utilities nicht mehr ausreichen, empfehle ich Ihnen die Services for Unix.
13.2.5
Tools zum Buch
Die Tools finden Sie im Download-Archiv zum Buch. Sie füllen die eine oder andere Lücke, die während der Arbeit mit der Shell und dem WSH im Lauf aufgetreten ist. Sie dürfen diese Tools, die alle Freeware sind, auf Ihren Servern einsetzen, sie kopieren und auch weitergeben. Die Nutzung dieser Programme erfolgt auf eigene Gefahr. Ich kann trotz sorgfältiger Tests keine Garantie für die Funktion der Programme übernehmen. Alles, was ich Ihnen garantiere, ist die Tatsache, dass die Dateien Platz auf Ihrem Datenträger belegen. Die Programme entstanden für den eigenen Bedarf und werden „as is“, d.h. ohne Support, zur Verfügung gestellt. Wenn Sie Ideen haben, freue ich mich über Feedback, aber es gibt derzeit keine konkreten Pläne zur Weiterentwicklung dieser Utilities. Eine detaillierte Beschreibung der einzelnen Kommandos finden Sie im Anhang.
13.3 Reguläre Ausdrücke 13.3.1
Grundlagen
Die Windows Shell bietet mit dem find-Filter eine einfache Möglichkeit der Suche nach Text. In vielen Fällen soll aber nach Informationen gesucht werden, die nicht vollständig vorliegen. Sei es, dass Sie nur
158
Reguläre Ausdrücke
noch einen Teil des Dateinamens wissen oder eine flexiblere Suche benötigen. Hier bietet sich die Nutzung von Kommandos an, die in der Lage sind, so genannte reguläre Ausdrücke zu benutzen. Das klassische Beispiel in der deutschen Literatur ist die berühmte „Meier-Suche“: In einer Datei sollen alle Meier, Maier, Meyer, Mayer, Meyr, Mayr, Mair und Meir (eher selten) gefunden werden. Mit den herkömmlichen Suchmöglichkeiten ist dies mehr als aufwändig. Bei regulären Ausdrücken wird dagegen eher eine formale Beschreibung des gesuchten Ausdrucks angegeben. Nicht jedes Zeichen wird also genau in dieser Form gesucht, bestimmte Zeichen haben eine besondere Bedeutung. Sie kennen das sicher von den Dateimasken wie datei.* oder 200?.txt. Hier haben der Stern und das Fragezeichen eine besondere Bedeutung. Bei regulären Ausdrücken ist diese Liste wesentlich umfangreicher und bietet auch mächtigere Suchmöglichkeiten. Die nachfolgende Tabelle zeigt die Möglichkeiten, die von findstr unterstützt werden, dem einzigen Kommando der Windows Shell, das zu Suchzwecken von regulären Ausdrücken Gebrauch macht. Zeichen
Gruppe
Bedeutung
.
Platzhalter
beliebiges Zeichen
*
Wiederholung kein bzw. wiederholtes Auftreten des vorhergehenden Zeichens bzw. der vorhergehenden Zeichenklasse
^
Position
Zeilenanfang
$
Position
Zeilenende
[Klasse]
Zeichenklasse
ein beliebiges Zeichen der Klasse
[^Klasse]
Zeichenklasse
alle Zeichen, die nicht in der Klasse angegeben wurden
[x-y]
Zeichenklasse
alle Zeichen im angegebenen Bereich
\x
Escape
literale Verwendung des Metazeichens x
\<xyz
Position
Wortanfang
xyz\>
Position
Wortende
Tabelle 13.2: Unterstützte reguläre Ausdrücke in Windows (findstr)
Bleiben wir beim Beispiel der Meiers: Was hier gesucht wird, ist ein Wort, das mit einem großen „M“ beginnt, danach kann ein „a“ oder ein „e“ folgen, danach ein „i“ oder ein „y“. Eventuell kann nun ein weiteres „e“ folgen, danach kommt das abschließende „r“. In die Syntax eines regulären Ausdrucks übertragen: M[ae][iy]e*r
Das Kommando finstr M[ae][iy]e*r datei.txt sucht in der Datei datei.txt nach allen Zeilen, in denen Meier in irgendeiner Schreibweise vorkommt.
159
13 Erweiterungen
Einige weitere Beispiele: dir /b | findstr "[aeiou][aeiou]"
Listet alle Dateinamen auf, in denen zwei aufeinander folgende Vokale vorkommen. Möchten Sie dagegen nach allen Dateinamen suchen, in denen der gleiche Vokal doppelt vorkommt (wie in tools.zip), dann sieht die Befehlszeile so aus: dir /b | findstr "aa ee ii oo uu"
Werden (wie hier) mehrere Suchstrings angegeben, dann verknüpft findstr diese logisch mit Order, so dass im obigen Beispiel eben jedes Vorkommen eines der Strings einen Treffer landet.
13.3.2
Die Stolpersteine
Die Beherrschung regulärer Ausdrücke ähnelt dem Versuch, Schach zu lernen. Die grundlegenden Regeln sind in einer Viertelstunde erklärt, und die nächsten dreißig Jahre versucht man zu verstehen, was eigentlich damit gemeint war … Die Problematik ist einmal, dass nicht jedes Kommando in jedem Betriebssystem den gleichen Satz so genannter „Metazeichen“ unterstützt (Zeichen mit einer speziellen Bedeutung in der Suchangabe). Einige Kommandos verarbeiten beispielsweise das Pluszeichen als „ein Zeichen oder mehrfach“, andere (wie findstr) kennen dafür kein Metazeichen. Sie können also nicht einfach einen regulären Ausdruck von einem Befehl zum anderen übertragen. Die Möglichkeiten von findstr entsprechen von der Wertung her eher einem „regular expressions light“. Zusätzlich reagieren verschiedene Portierungen von Kommandos ebenfalls anders. Ein Beispiel dafür ist das Kommando grep, das unter Unix zum Standardumfang einer Shell gehört, mittlerweile aber auch in vielen Portierungen für Windows verfügbar ist27. Eine Version kommt mit den Unix Utilties der GNU-Portierung, eine andere liefert die Firma Borland traditionell mit ihren Compilern aus. Eine dritte ist über die Services for Unix direkt von Microsoft verfügbar, und natürlich unterstützen alle drei einen unterschiedlichen Satz von Metazeichen. Wenn Sie sich mit dem Thema wirklich beschäftigen wollen (oder müssen), dann sollten Sie sich das Buch von Jeffrey Friedl besorgen (die Daten finden Sie im Literaturverzeichnis). Dies ist die vollständigste und beste Behandlung dieses Themas, die derzeit erhältlich ist, wenn auch das Schwergewicht eindeutig auf der Seite der Unix-Kommandos und perl liegt. 27 Eigentlich ist ja findstr das grep von Windows, aber erstens sucht das kein Mensch unter dem Namen „findstr“, und zweitens fehlen wie gesagt einige sinnvolle Metazeichen, daher haben die diversen grep-Ports durchaus ihre Berechtigung.
160
Reguläre Ausdrücke
13.3.3
Beispiele mit findstr
In meinen Seminaren wurde ich immer wieder gefragt, ob die Windows Shell so etwas Ähnliches wie grep oder awk28 bietet. Das Beste, was Sie in dieser Richtung bekommen, ist findstr. Dieses Programm bietet mit den oben angegebenen Suchmasken immerhin eine grundlegende Implementierung regulärer Ausdrücke. Immer dann, wenn find nicht mehr ausreicht, kommen Sie wahrscheinlich mit findstr weiter. Vor allem, falls mehr als ein Suchmuster verwendet werden soll, können Sie find schon nicht mehr benutzen. Dazu ein kleines Beispiel: Angenommen, Sie benötigen alle Dateien in einem Verzeichnis, die jeweils am 01. oder am 15. eines Monats erstellt wurden (ich gehe in diesem Beispiel von einem deutschen Windows aus, das Datumsangaben in der Form tt.mm.jjjj ausgibt). Weder mit dir noch mit find kommen Sie an dieser Stelle ans Ziel. Damit Sie die folgenden Kommandos auch ohne Computer nachvollziehen können, hier noch einmal ein kurzer Auszug aus der Ausgabe von dir: C:\tmp>dir Datenträger in Laufwerk C: ist Lokaler Datenträger Datenträgernummer: CAFE-1234
Listing 13.1: Eine Teilausgabe von dir
Verzeichnis von C:\tmp 09.07.2004 09.07.2004 15.05.2003 09.06.2003 03.02.2004 17.09.2002 01.02.2004 20.02.2004 13.12.1994 15.06.2004 01.03.2004
19:54 19:54 23:11 19:46 01:26 12:47 00:05 00:12 15:44 11:55 02:02
1.432.592 1.159.915 625.216 587.047 361.870 978.126 53.732 53.248 43
. .. 0519-0002.JPG 0609-0076.JPG 103-0397_IMG.JPG 105-0518_IMG.JPG 142.zip 165.zip ARABNEWS.TTF Batchdateien.ppt bluepixel.gif
Wie leicht zu erkennen ist, muss nach allem gesucht werden, bei dem zu Beginn der Zeile entweder 01. oder 15. vorkommt. Problematisch ist allerdings, dass es bei findstr keine Möglichkeit gibt, die Daten mit dem zu durchsuchenden Text aus einer Umleitung von StdIn (z.B. mit Piping) zu beziehen. Daher muss die Ausgabe zuerst
28 Falls Sie awk noch nicht kennen: Installieren Sie sich eine der Windows-Portierungen von awk (z.B. aus den GNU Tools), und besorgen Sie sich das Buch „awk & sed“ von Helmut Herold, ebenfalls bei Addison-Wesley erschienen. Sie werden findstr nie mehr benutzen …
161
13 Erweiterungen
in eine Datei umgeleitet und danach kann in dieser Datei gesucht werden, wie der folgende Konsolenmitschnitt zeigt: C:\tmp>dir c:\tmp > liste.txt C:\tmp>findstr "^01\. ^15\." liste.txt 15.05.2003 23:11 1.432.592 01.02.2004 00:05 361.870 15.06.2004 11:55 53.248 01.03.2004 02:02 43
0519-0002.JPG 142.zip Batchdateien.ppt bluepixel.gif
C:\tmp>
Mehr Informationen und auch einige Beispiele zu findstr finden Sie in der Online-Hilfe von Windows 2003, weshalb ich das Kapitel an dieser Stelle auch abschließen möchte.
162
14
WMI und die Kommandozeile
14.1 wmic – die WMI-Konsole Die Zielgruppe von WMIC sind vor allem Administratoren und nichtprogrammierende Supporter, denen mit diesem Programm die Möglichkeiten von WMI eröffnet werden. Über einen einfachen Zugang mit Hilfe vordefinierter Aliase besteht ein sofortiger Zugang zu den Verwaltungsfunktionen von WMI. Dennoch bietet die WMIC für fortgeschrittene Anwender auch den direkten Zugang zu einzelnen WMI-Klassen und ihren Instanzen.
14.1.1
Grundlagen
Die Bereitstellung der WMIC durch Microsoft ist eine enorme Erleichterung für die Administration größerer Systeme. Denn nun haben Sie einen Zugang zu WMI, ohne Programmierkenntnisse besitzen zu müssen! Viele Admins waren bei der Vorstellung von WMI-Scripting begeistert von den Möglichkeiten, die sich da auftaten. Allerdings hat nicht jeder die Zeit und den Elan, sich mit der WSH-Programmierung, VBScript, JavaScript und den Tücken von COM und WQL auseinander zu setzen. Dank der WMIC ist dies auch nicht mehr notwendig29. Erst jetzt kann WMI das Versprechen einlösen, das bei seiner Einführung gegeben wurde, nämlich den Admins einen leichten Zugang zu einer einheitlichen Verwaltungsschnittstelle zu gewähren. Die Windows Management Instrumentation Console (in Zukunft abgekürzt WMIC) ist die Antwort von Microsoft auf die Wünsche nichtprogrammierender Administratoren. Es handelt sich dabei um ein kommandozeilenorientiertes Programm, das ähnlich anderen solcher Kommandos (ftp, nslookup u.a.) seine Eingabe aus dem Eingabekanal bekommt (der natürlich auch umgeleitet werden kann) und seine Daten per Default in die Standardausgabe schreibt. Dieser Modus wird als interaktiver Modus bezeichnet. Zusätzlich existiert noch ein nicht interaktiver Modus, bei dem die Kommandos direkt in der Befehlszeile angegeben werden und die
29 Natürlich können Sie (falls Sie Entwickler sind) nach wie vor den WSH benutzen und dort die WMI-Objekte direkt ansprechen. Sobald Sie aber einmal gesehen haben, wie einfach sich Informationen mit der WMIC abrufen lassen, werden Sie nur noch selten WMI-Scripting einsetzen wollen.
163
14 WMI und die Kommandozeile
WMIC anschließend beendet wird. Ein Beispiel dafür ist die folgende Befehlszeile: wmic process list brief
Hier wird das Kommando (der Aufruf des Alias „process“) ausgeführt und nach StdOut ausgegeben, dann die WMIC beendet. Neben der einfachen Benutzbarkeit besticht die WMIC vor allem durch die bereits eingebauten Reporting-Möglichkeiten. So sind alle Abfragen im XML-Format mit einem Befehl in eine Datei protokollierbar. Die Formate der Ausgaben decken fast alle Anforderungen ab: Text in verschiedenen Versionen, CSV, HTML, MOF oder reines XML sind bereits enthalten. Zusätzlich lassen sich beliebige eigene Formate definieren. Durch die Unterstützung der üblichen ShellFunktionalitäten wie Ein- und Ausgabeumleitung lassen sich so HTML-Reports mit einer einzigen Befehlszeile erzeugen!
14.1.2
Hilfe erhalten
Sie können für jedes Kommando in der WMIC durch Anhängen der Zeichen /? einen Hilfetext abrufen. Diese Hilfe ist gestaffelt: Geben Sie direkt an der Eingabeaufforderung /? ein, erhalten Sie eine Liste der globalen Kommandos und Aliase. Geben Sie einen Alias gefolgt von /? ein, erhalten Sie Hilfe zu diesem Alias und so weiter. wmic:root\cli>/?
Alle Backslashes in WMIC-Abfragen müssen verdoppelt werden, da der Backslash auch als Escape-Zeichen dient!
14.1.3
Aliase auflisten
Ein Alias für die WMIC ist eine benutzerfreundliche Abkürzung für eine WMI-Abfrage. Auf diese Weise müssen Sie nicht die genaue Bezeichnung der WMI-Klasse wissen, und es können bereits Filter vordefiniert werden. Der vordefinierte Alias service beispielsweise entspricht der WQL-Abfrage „Select * from Win32_Service“. Mit der Möglichkeit der Online-Hilfe können Sie auch erfahren, welche Aliase bereits vordefiniert sind. Geben Sie dazu einfach wie oben beschrieben das Kommando /? ein. Die nachfolgende Tabelle listet die vordefinierten Aliase auf.
164
wmic – die WMI-Konsole
Alias
Verwalteter Bereich
ALIAS
Access to the aliases available on the local system
BASEBOARD
Systemplatine
BIOS
BIOS
BOOTCONFIG
Bootkonfiguration
CDROM
CD-ROM
COMPUTERSYSTEM
Computersystemdaten
CPU
CPU
CSPRODUCT
Computerproduktinformation
DATAFILE
Datendateien
DCOMAPP
DCOM-Anwendungen
DESKTOP
Desktop
DESKTOPMONITOR
Desktop-Monitor
DEVICEMEMORYADDRESS
Speicheradressen von Geräten
DISKDRIVE
Physikalische Platten
DISKQUOTA
NTFS-Plattenplatzmanagement
DMACHANNEL
DMA-Kanäle
ENVIRONMENT
Systemumgebung
FSDIR
Filesystem Verzeichnis entry management.
GROUP
Benutzergruppen
IDECONTROLLER
IDE-Controller
IRQ
IRQ-Leitungen
JOB
Geplante Aufgaben (Job Scheduler)
LOADORDER
Ausführungsabhängigkeiten von Diensten
LOGICALDISK
Logische Datenträger
LOGON
LOGON-Sitzungen
MEMCACHE
Cache-Speicher
MEMLOGICAL
Systemspeicher
MEMORYCHIP
Speicherchips
MEMPHYSICAL
Physikalischer Speicher
NETCLIENT
Netzwerk-Client
NETLOGIN
Logindaten eines Benutzers
NETPROTOCOL
Netzwerkprotokolle
NETUSE
Aktive Netzwerkverbindungen
NIC
Netzwerkkarte
Tabelle 14.1: Vordefinierte Aliase der WMI-Konsole
165
14 WMI und die Kommandozeile
166
Alias
Verwalteter Bereich
NICCONFIG
Konfiguration der Netzwerkkarte
NTDOMAIN
NT-Domäne
NTEVENT
Ereignisprotokolleinträge
NTEVENTLOG
Dateien der Ereignisprotokolle
ONBOARDDEVICE
Auf der Systemplatine integrierte Geräte
OS
Installierte Betriebssysteme
PAGEFILE
Auslagerungsdatei
PAGEFILESET
Einstellungen der Auslagerungsdatei
PARTITION
Partitionsverwaltung
PORT
E/A-Ports
PORTCONNECTOR
Physikalische Verbindungen
PRINTER
Drucker
PRINTERCONFIG
Druckerkonfiguration
PRINTJOB
Druckjobs
PROCESS
Prozesse
PRODUCT
Installierte Produkte
QFE
Hotfixes (Quick Fix Engineering)
QUOTASETTING
Einstellungen für Plattenquoten
RDACCOUNT
Remote Desktop-Berechtigungen
RDNIC
Remote Desktop-Einstellungen für einen NIC
RDPERMISSIONS
Berechtigungen für eine RDP-Sitzung
RDTOGGLE
RDP-Listener remote ein-/ausschalten
RECOVEROS
Speicherdaten bei BS-Ausfall
REGISTRY
Registry
SCSICONTROLLER
SCSI-Controller
SERVER
Serverprozess
SERVICE
Dienste
SHADOWCOPY
Schattenkopien
SHADOWSTORAGE
Speicherkonfiguration Schattenkopien
SHARE
Freigaben
SOFTWAREELEMENT
Elemente eines installierten Produktes
SOFTWAREFEATURE
Features eines Elements eines Produkts
SOUNDDEV
Audiogeräte
STARTUP
Autostart
SYSACCOUNT
Systemkonten
wmic – die WMI-Konsole
Alias
Verwalteter Bereich
SYSDRIVER
Treiber für Basisdienste
SYSTEMENCLOSURE
Physical System Enclosure Management
SYSTEMSLOT
Ports, Steckplätze
TAPEDRIVE
Bandlaufwerk
TEMPERATURE
Temperatur
TIMEZONE
Zeitzone
UPS
Unterbrechungsfreie Stromversorgung
USERACCOUNT
Benutzerkonten
VOLTAGE
Voltmeter (falls vorhanden)
VOLUME
Datenträger
VOLUMEQUOTASETTING
Quoteneinstellungen für einen best. Datenträger
VOLUMEUSERQUOTA
Quoteneinstellungen für einen best. Benutzer
WMISET
Einstellungen des WMI-Dienstes
Weitere Informationen erhalten Sie, wenn Sie nach dem Alias noch „/?“ eingeben. Aber zuerst werden wir uns an einem Beispiel ansehen, wie mit diesen Alias-Begriffen Daten abgerufen werden können. Zusätzlich zu diesen Definitionen sind noch folgende Kommandos möglich: CLASS
Erlaubt direkten Zugriff auf WMI-Klassen
PATH
Erlaubt direkten Zugriff auf Instanzen von WMI-Klassen
CONTEXT
Gibt den Status aller globalen Schalter aus
QUIT/EXIT
Beendet das Programm
14.1.4
Erste Schritte
Als Einstieg werden wir uns Informationen über die Dienste der Windows-Installation ausgeben lassen. Dazu benutzen wir den vordefinierten Alias service. wmic:root\cli>service
Anschließend erhalten Sie eine Liste mit Daten aller Dienste des Systems. Diese umfasst mit Sicherheit auch Spalten, an denen Sie momentan nicht interessiert sind. Außerdem ist das seitliche Rollen des Fensters bis zu den relevanten Informationen auch nicht unbedingt komfortabel. Aus diesem Grund werden wir die Anzahl der angezeigten Informationen etwas einschränken. Dazu müssen wir aber zuerst erfahren, welche Eigenschaften (und damit Spalten) überhaupt verfügbar sind.
167
14 WMI und die Kommandozeile Tabelle 14.2: Verfügbare Eigenschaften für Dienste
wmic:root\cli>service get /? Property get operations. USAGE: GET [<property list>] [] NOTE: <property list> ::= <property name> | <property name>, <property list> The following properties are available: Property Type Operation ======== ==== ========= AcceptPause N/A N/A AcceptStop N/A N/A Caption N/A N/A CheckPoint N/A N/A CreationClassName N/A N/A Description N/A N/A DesktopInteract N/A N/A DisplayName N/A N/A ErrorControl N/A N/A ExitCode N/A N/A InstallDate N/A N/A Name N/A N/A PathName N/A N/A ProcessId N/A N/A ServiceSpecificExitCode N/A N/A ServiceType N/A N/A StartMode N/A N/A StartName N/A N/A Started N/A N/A State N/A N/A
168
wmic – die WMI-Konsole Status N/A SystemCreationClassName N/A SystemName N/A TagId N/A WaitHint N/A
N/A N/A N/A N/A N/A
Aus dieser Liste der verfügbaren Eigenschaften wähle ich nun die beiden Spalten Name und Started aus. wmic:root\cli>service get started, name
Diese Liste lässt sich nun noch weiter einschränken, indem ich nur die Dienste aufgelistet haben möchte, deren Name mit einem „S“ beginnt. Dazu ergänze ich die obige Anfrage um eine where-Klausel. wmic:root\cli>service where (name>"S" and namevolume where (freespace > 1073741824) get caption, filesystem, freespace
Eine Zeile
Hier die entsprechende Ausgabe: Caption C:\ F:\
FileSystem NTFS NTFS
FreeSpace 2117914624 3567918713
169
14 WMI und die Kommandozeile
14.1.5
Beeinflussen der Ergebnismenge
Viele Aliase und andere Kommandos der WMIC liefern eine relativ große Datenmenge zurück. Eine Einschränkung der Ergebnismenge ist daher in den meisten Fällen sinnvoll. Dafür existieren zwei Möglichkeiten: einmal die Anzahl der Datensätze zu begrenzen und zweitens von jedem Datensatz nur bestimmte Spalten auszuwählen. Zeilenbegrenzung durch WHERE Mit Hilfe einer where-Klausel lassen sich die zurückgelieferten Zeilen begrenzen30. Nach dem Schlüsselwort where geben Sie den Ausdruck an, der auf die Ergebnismenge angewendet werden soll. Im folgenden Beispiel möchte ich alle Prozesse auflisten, deren maximale Größe des Working Sets über vier MB liegt: process where "PeakWorkingSetSize > 4194304"
Die where-Klausel muss entweder in doppelte Anführungszeichen oder in runde Klammern eingeschlossen werden. Ich empfehle Ihnen die Benutzung der doppelten Anführungszeichen. Warum? Weil Sie dann die Abfrage auch in der Shell im nichtinteraktiven Modus von WMIC nutzen können. Dazu ein Beispiel mit den runden Klammern. Eine Zeile
wmic:root\cli>process where (PeakWorkingSetSize > 4194304)
Dieses Kommando funktioniert im interaktiven Modus prima. Nun versuchen wir das Ganze aus der Shell: Eine Zeile
c:\tmp> wmic process where (PeakWorkingSetSize > 4194304)
Erkennen Sie das Problem? Die Shell versucht das Größerzeichen des Vergleichs als Umleitungsoperator zu interpretieren, das die Ausgabe des Kommandos in die Datei mit dem Namen 4194304) umleitet! Verwenden Sie stattdessen die doppelten Anführungszeichen, arbeitet das Kommando sowohl in der WMIC als auch auf der Shell problemlos. Die where-Klausel kann auch komplexer werden, wenn Sie einzelne Teilausdrücke durch logische Operatoren kombinieren: DATAFILE WHERE "PATH='\\windows\\system32\\' and Extension='exe' and FileSize > 1048576"
Hier werden drei Teilausdrücke kombiniert. Falls Sie das lesbarer finden, dürfen Sie um die einzelnen Teilausdrücke auch runde Klammern setzen. 30 Sollte Sie das an SQL erinnern, liegen Sie goldrichtig. Die Abfragesprache für WMI nennt sich sogar WQL (Windows Query Language)! Falls Sie jemals eine Select-Anweisung in SQL geschrieben haben, können Sie nach fünf Minuten auch WMI-Abfragen per WQL formulieren.
170
wmic – die WMI-Konsole
Spaltenbegrenzung durch GET & LIST Die Anzahl der Spalten kann durch die Angabe des Modifizierers LIST und eines Listenformats begrenzt werden. Hier wird dann eine im Listenformat definierte Auswahl an Spalten angeboten. Alternativ können Sie über das Verb GET auch selbst individuelle Spalten angeben, die in der Ausgabe erscheinen sollen. Hier als Beispiel eine Liste der vordefinierten Listenformate für den Alias process und welche Spalten darin enthalten sind. Format
Enthaltene Spalten
BRIEF
ThreadCount, HandleCount, Name, Priority, ProcessId, WorkingSetSize
FULL
CommandLine, CSName, Description, ExecutablePath, ExecutionState, Handle, HandleCount, InstallDate, KernelModeTime, MaximumWorkingSetSize, MinimumWorkingSetSize, Name, OSName, OtherOperationCount, OtherTransferCount, PageFaults, PageFileUsage, ParentProcessId, PeakPageFileUsage, PeakVirtualSize, PeakWorkingSetSize, Priority, PrivatePageCount, ProcessId, QuotaNonPagedPoolUsage, QuotaPagedPoolUsage, QuotaPeakNonPagedPoolUsage, QuotaPeak-PagedPoolUsage, ReadOperation Count, ReadTransferCount, SessionId, Status, TerminationDate, ThreadCount, UserModeTime, VirtualSize, WindowsVersion, WorkingSetSize, WriteOperationCount, WriteTransferCount
INSTANCE
__PATH
IO
Name, ProcessId, ReadOperationCount, ReadTransferCount, WriteOperationCount, WriteTransferCount
MEMORY
Handle, MaximumWorkingSetSize, MinimumWorkingSetSize, Name, PageFaults, PageFileUsage, PeakPageFileUsage, PeakVirtualSize, PeakWorkingSetSize, PrivatePage Count, QuotaNonPagedPoolUsage, QuotaPagedPoolUsage, QuotaPeakNonPagedPoolUsage, QuotaPeakPagedPoolUsage, VirtualSize, WorkingSetSize
STATISTICS
HandleCount, Name, KernelModeTime, MaximumWorkingSetSize, MinimumWorkingSetSize, OtherOperationCount, OtherTransferCount, PageFaults, PageFileUsage, PeakPageFileUsage, PeakVirtualSize, PeakWorkingSetSize, PrivatePageCount, ProcessId, QuotaNonPagedPoolUsage, QuotaPagedPoolUsage, QuotaPeakNonPagedPoolUsage, QuotaPeakPagedPoolUsage, ReadOperationCount, ReadTransferCount, ThreadCount, UserModeTime, VirtualSize, WorkingSetSize, WriteOperationCount, WriteTransferCount
STATUS
Status, Name, ProcessId
SYSTEM
__CLASS, __DERIVATION, __DYNASTY, __GENUS, __NAMESPACE, __PATH, __PROPERTY_COUNT, __RELPATH, __SERVER, __SUPERCLASS
Tabelle 14.3: Vordefinierte Listenformate für den process-Alias
171
14 WMI und die Kommandozeile
Wollen Sie dagegen die Liste der Spalten selbst bestimmen, können Sie die jeweilige Liste der Attribute für den Alias mit get /? abrufen: process where "PeakWorkingSetSize > 4194304" get /?
Sie erhalten dann eine Liste der möglichen Spaltennamen. Hier im Beispiel begrenze ich die Ausgabe auf den Namen, die Prozess-ID und die PeakWorkingSetSize: process get name, handle, peakworkingsetsize
Kombinationen Beide Möglichkeiten lassen sich ohne weiteres kombinieren, um wirklich nur die benötigten Daten zu erhalten. Neben einer leichteren Lesbarkeit ist dies vor allem bei Remote-Abfragen von Bedeutung, da hier die Bandbreite der Verbindung eine Rolle spielt. Anstatt unspezifisch alle Spalten von allen Datensätzen abzurufen, kann eine sinnvolle Einschränkung die Laufzeit einer Remote-Abfrage um mehr als den Faktor 10 beschleunigen. Eine Zeile
process where "PeakWorkingSetSize > 4194304" get name, handle, peakworkingsetsize
14.1.6
Zyklische Abfragen
Sowohl für die Benutzung von list als auch von get existiert eine Option, mit der Sie Abfragen zyklisch wiederholen können. Sie können dies so lange ausführen lassen, bis eine Taste gedrückt wird, oder eine definierte Anzahl von Wiederholungen festlegen. Dazu geben Sie hinter list bzw. der get-Liste folgende Option an: /every:<s> [/repeat:]
Der Wert von <s> legt das Abfrageintervall in Sekunden fest. Ohne eine weitere Angabe wird die Abfrage dauernd wiederholt. Optional können Sie mit Hilfe von /repeat: angeben, dass dieser Abfragezyklus n-mal wiederholt werden soll. Achten Sie bei Remote-Abfragen mit /every darauf, die Bandbreite der Netzwerkverbindungen nicht außer Acht zu lassen. Eine zyklische Abfrage mit einer großen Ergebnismenge benötigt zusätzlich noch eine gewisse Zeit für die Ausgabe auf der Konsole. Damit Sie eine Vorstellung bekommen, was bei einer WMI-Abfrage an Daten geliefert wird: Die Benutzung des Alias service entspricht einer ungefilterten Abfrage nach allen Instanzen der Klasse win32_ service auf der Zielmaschine. Dies liefert auf einer normalen Installation von Windows 2000 über 150 KByte an Daten! Eine Abfrage nach einem bestimmten Service bringt etwa 25 KByte. Beschränken Sie die
172
wmic-Schalter
Abfrage per get auf die Spalten mit der Startinformation (StartMode), reichen für alle laufenden Services etwa 56 KByte aus (Daten aus „WMI Scripting Primer“, Part 2, Januar 2003 / MSDN Online). Stellen Sie sich vor, Sie fragen vier Maschinen im Task von 2 Sekunden nach allen laufenden Services mit allen Spalten, weil Sie wissen möchten, wann ein Service gestartet wird. Dies sind dann geschätzt alle 2 Sekunden etwa 4 mal 100 KByte, die über das Netzwerk laufen. Wenn Sie Ihren zuständigen LAN-Admin noch nicht kennen, nach 30 Minuten einer solchen Query lernen Sie ihn kennen … – sinnvoller wäre hier die Abfrage genau des gesuchten Dienstes, und auch da nur die Spalten Running und State.
14.1.7
Aufrufen von Methoden
WMI bietet nicht nur die Abfrage von Informationen, sondern erlaubt über den Aufruf so genannter Methoden auch die Veränderung von Systemeinstellungen. Dies reicht von der Änderung einer IP-Adresse über das Beenden von Prozessen bis hin zum kompletten Herunterfahren des Rechners. Möchten Sie alle Instanzen von Notepad auf Ihrem Rechner beenden? process where name='notepad.exe' call terminate
Auch hier ist die dynamische Hilfe wieder aktiv. Wenn Sie also nicht wissen, welche Methoden aufgerufen werden können bzw. welche Parameter für den Aufruf notwendig sind, geben Sie einfach wieder „/?“ ein. nicconfig call /?
Sie wollen für eine Datei eine Operation ausführen und wissen nicht, welche Methoden unterstützt werden? Kein Problem: datafile where name='c:\\tmp\\demo.txt' call /?
14.2 wmic-Schalter Schalter beeinflussen das Verhalten der WMIC. So kann der aktive Knoten (der Rechner, auf dem die Abfragen ausgeführt werden) gewechselt werden, es besteht die Möglichkeit einer Remote-Authentifizierung, die Daten können in ein Xml-Logfile mitgeschrieben werden und vieles mehr. Aktiviert werden Schalter durch die Eingabe eines einzelnen Schrägstrichs, gefolgt vom Namen des Schalters, einem Doppelpunkt und dem zugewiesenen Wert. Zurückgesetzt wird ein Schalter durch die Zuweisung der leeren Zeichenkette (""). Ein Beispiel: /record:datei.xml
173
14 WMI und die Kommandozeile
Den aktuellen Status erhalten Sie mit dem Kommando context: Listing 14.1: Ausgabe der aktuellen Switches
wmic:root\cli>context NAMESPACE ROLE NODE(S) IMPLEVEL AUTHLEVEL LOCALE PRIVILEGES TRACE RECORD INTERACTIVE FAILFAST OUTPUT APPEND USER AGGREGATE
14.2.1
: : : : : : : : : : : : : : :
root\cimv2 root\cli BYTEBAG IMPERSONATE [AUTHORITY:N/A] PKTPRIVACY ms_409 ENABLE OFF N/A ON OFF STDOUT STDOUT N/A ON
AGGREGATE
Dieser Schalter legt fest, ob die Werte bei einer Abfrage über mehr als einen Rechner aggregiert werden. Die Einstellung on bedeutet, es erfolgt erst dann eine Ausgabe, wenn alle Rechner (die mit /node festgelegt werden) geantwortet oder einen Timeout gegliedert haben. Die Einstellung off gibt die Daten aus, sobald sie vom jeweiligen Rechner zurückgeliefert werden.
14.2.2
APPEND
Append gibt an, an welches Ziel die Ausgabe angehängt wird. Mögliche Werte sind STDOUT (Standardausgabekanal) und CLIPBOARD. Im Gegensatz zu /output wird der Inhalt vorher nicht geleert. Wird / append vor einem Kommando in der gleichen Zeile eingegeben, gilt
dies nur für das aktuelle Kommando. In einer eigenen Zeile erfolgt eine dauerhafte Umschaltung.
14.2.3
AUTHLEVEL
Folgende Werte sind für die Art der Authentifizierung möglich: Default, None (Gastzugang), Connect, Call, Pkt, Pktintegrity, Pktprivacy
14.2.4
FAILFAST
Bei on wird zuerst versucht, einen Remote-Rechner per Ping zu erreichen, bevor eine WMI-Verbindung aufgebaut wird. Dies kann bei langsamen oder unzuverlässigen Verbindungen nützlich sein oder wenn Sie sich nicht sicher sind, ob das Remote-System erreichbar ist.
174
wmic-Schalter
14.2.5
IMPLEVEL
Gibt die Art der Personifizierung an. Erlaubt sind Anonymous, Identify, Impersonate (Default), Delegate.
14.2.6
INTERACTIVE
Bei der Einstellung on werden für potenziell gefährliche Kommandos (Löschaktionen von Klassen und Instanzen) Bestätigungen verlangt.
14.2.7
LOCALE
Legt die Regionaleinstellungen fest. Die Werte folgen der Konvention MS, z.B. MS_409 für Englisch, MS_411 für Japanisch und MS_ 40B für Finnisch.
14.2.8
NAMESPACE
Gibt den WMI-Namensraum an, den ein Alias benutzen soll. Beispielsweise kann mit /NAMESPACE:SMS auf den SMS-Namespace umgeschaltet werden.
14.2.9
NODE
Definiert den Rechner, auf dem die Abfrage ausgeführt werden soll. Diese Angaben können in sehr flexibler Form erfolgen, um die Erstellung von Shell Scripts mit WMIC zu erleichtern. Eine Möglichkeit ist die direkte Angabe eines einzelnen Rechners oder einer kommagetrennten Liste von Rechnern (/node:"bytebag,kokomiko,masupilami"). Alternativ kann auch eine Datei angegeben werden, die Rechnernamen in einer kommagetrennten Liste oder in jeweils einer eigenen Zeile enthält. Dann ist als Angabe der Name der Datei mit einem "@"-Zeichen davor anzugeben (beispielsweise /node:@hostlist.dat). Mit /node:"" kann wieder der lokale Rechner eingestellt werden.
14.2.10 OUTPUT Gibt an, welches Ziel die Ausgabe erhält. Mögliche Werte sind STDOUT (Standardausgabekanal) und CLIPBOARD. Wird /output vor einem Kommando in der gleichen Zeile eingegeben, gilt dies nur für das aktuelle Kommando. In einer eigenen Zeile erfolgt eine dauerhafte Umschaltung.
14.2.11 PRIVILEGES Gibt an, ob bestimmte WMI-Privilegien aktiviert werden sollen (ON) oder nicht (OFF). Für das Herunterfahren eines entfernten Systems benötigen Sie beispielsweise das Shutdown-Privileg.
175
14 WMI und die Kommandozeile
14.2.12 RECORD Legt fest, ob die Ausgaben des Systems in eine Datei mitprotokolliert werden sollen. Als Angabe ist entweder ein Datei oder "" zum Abschalten erlaubt. Die Ausgabe erfolgt in Form einer XML-Datei. Hier ein Beispiel für eine solche Datei: <WMIRECORD USER="SHELLBOOK\Administrator"> service where (name>"S" and name
14.2.13 ROLE Derzeit ist nur eine Rolle definiert (\\root\cli). Dies bezeichnet prinzipiell den Namensraum, aus dem die Alias-Definitionen beim ersten Start von WMIC als MOF-Dateien geladen werden.
14.2.14 TRACE Erlaubt das Aktivieren (ON) oder Deaktivieren (OFF, Default) von Tracing-Informationen für jeden einzelnen WMI-Aufruf. Nur für Debugging-Zwecke sinnvoll.
14.2.15 USER / PASSWORD Erlaubt die Angabe von Benutzerinformationen, falls die bei /node angegebenen Systeme mit anderen Anmeldeinformationen verbunden werden sollen.
176
Ausgabeformate
14.3 Ausgabeformate Mit Hilfe der Option /format: kann die Ausgabe von WMIC höchst flexibel gestaltet werden, ohne eine einzige Zeile programmieren zu müssen. Stellen Sie sich folgendes Szenario vor: Einmal pro Tag möchte Ihr Chef eine Liste seiner drei Server mit dem auf allen Platten noch verfügbaren Platz im Intranet, natürlich als schöne HTML-Tabelle. Nichts leichter als das: Den ersten Teil der Aufgabe können Sie bereits erledigen. Hier ist das Kommando für die Volumes aus den drei Servern: /node:"orion,rigel,saiph" volume get caption, freespace, label
Eine Zeile
Diese Ausgabe soll nun in eine HTML-Tabelle verwandelt werden. Dazu wird hinter dem Kommando einfach die entsprechende Formatangabe ergänzt: /node:"orion,rigel,saiph" volume get caption, freespace, label /format:htable
Hier ein Beispiel mit einer Liste der laufenden Prozesse auf einer Maschine, diesmal auch gleich als nicht interaktives Kommando mit einer Umleitung in eine HTML-Datei und dem Aufruf dieser Datei: wmic process get handle,name /format:hform > x.html && x.html
Eine Zeile
Die Abbildung unten zeigt das durchaus brauchbare Ergebnis: Abbildung 14.1: Eine Prozessliste als HTML-Seite ohne Aufwand
177
14 WMI und die Kommandozeile
Folgende Standardformate sind bereits vordefiniert: 왘 CSV liefert eine kommagetrennte Liste der reinen Werte. 왘 HFORM liefert eine HTML-Ausgabe, bei der jede Instanz eine eigene Tabelle bekommt. 왘 HMOF liefert eine als HTML kodierte Ausgabe im MOF-Format (z.B. zu Dokumentationszwecken). 왘 HTABLE liefert eine HTML-Ausgabe mit einer Tabelle, bei der jede Instanz eine Zeile belegt. 왘 HXML liefert eine als HTML kodierte Ausgabe im XML-Format. 왘 LIST liefert eine Liste der Form Eigenschaft = Wert als Text. 왘 RAWXML liefert eine Ausgabe als reine XML-Datei. 왘 TABLE liefert eine spaltenausgerichtete Texttabelle. 왘 VALUE entspricht LIST. Zusätzlich können Sie sich ein eigenes Format definieren, wenn Sie eine entsprechende XSL-Datei anlegen. Als zusätzliche Angabe ist neben der Liste der obigen Formate nämlich auch die Angabe einer XSL-Datei möglich.
14.4 Systemverwaltung mit WMIC Dieser Abschnitt zeigt anhand einiger Beispiele die Möglichkeiten der Systemverwaltung mit Hilfe von WMIC (alle Kommandos sind jeweils in einer Zeile einzugeben, der Umbruch erfolgt nur im Buchlayout). /node:@"c:\computerlist.txt" os get lastbootuptime
Das Kommando holt sich aus der Textdatei c:\computerlist.txt aus einer Zeile die Computernamen und gibt für jeden Rechner das Datum des letzten Systemstarts aus. cpu get MaxClockSpeed
Hier wird die maximale Taktfrequenz des Rechners ausgegeben. Process Where Description="sqlserver.exe" Get VirtualSize /EVERY:5
Gibt alle fünf Sekunden den Verbrauch an virtuellem Speicher für den angegebenen Prozess aus. Die Ausgabe endet, wenn Sie eine Taste drücken. /node:"Orion" service where caption='TELNET' CALL STARTSERVICE
Damit startet der Telnet-Dienst auf der Maschine Orion31. 31 Wie hier zu sehen ist, kann auf die Anführungszeichen um die where-Klausel verzichtet werden, wenn der gesamte Ausdruck der where-Klausel kein Leerzeichen enthält.
178
Systemverwaltung mit WMIC WMIC DATAFILE WHERE "PATH='\\windows\\system32\\' and Extension='dll' and FileSize > 1048576" GET LastAccessed, Name, FileSize
Listet für alle DLLs aus dem system32-Ordner, die größer als ein Megabyte sind, den Namen, das Datum des letzten Zugriffs und die Dateigröße auf. NICCONFIG WHERE index=1 CALL EnableStatic ("10.0.0.2"),("255.0.0.0")
Dieses Kommando stellt für die erste Netzwerkkarte als statische IP-Adresse 10.0.0.2 mit einer Subnetmask von 255.0.0.0 ein. NICCONFIG WHERE index=1 CALL SetGateways ("10.0.0.8","10.0.0.9"),(1,2)
Hiermit legen Sie die Gateways für die Netzwerkkarte mit dem angegebenen Index fest. /NODE:@"c:\MyServerList.txt" OS WHERE (Primary="TRUE" and Locale="0409") CALL Win32ShutDown 6
Das Kommando holt aus der Datei c:\msyserverlist.txt die Namen der Server und fährt alle englischen Server aus dieser Liste herunter. WMIC /NODE:"bytebag.shellbook.com" / USER:"
[email protected]" RDTOGGLE WHERE ServerName="bytebag" CALL SetAllowTSConnections 1
Auf der Maschine bytebag werden Remote Desktop Connections erlaubt. WMIC /NAMESPACE:\\root\Verzeichnis\ldap PATH ds_user where ds_name='Franz Testhuber' get /value
Wie dieses Kommando zeigt, kann WMI auch auf Daten aus dem AD zugreifen! Ich bin mir sicher, dass Sie nach der Lektüre dieses Kapitels genauso vom Entdeckerfieber gepackt werden wie ich bei den ersten Streifzügen durch die Möglichkeiten von wmic.
179
14 WMI und die Kommandozeile
180
15
Die Shell und der WSH
So vielfältig die Möglichkeiten der Shell auch sind, es gibt Grenzen, die cmd.exe nicht überschreiten kann. Datenbankzugriffe, Steuerung von GUI-Anwendungen, COM-Interaktion oder komplexe Abläufe für eine automatisierte Administration; all dies sind Themen, die sich nur mit dem Windows Script Host behandeln lassen. Dabei schließen sich die beiden Ansätze Shell-Script und WSH-Script nicht gegenseitig aus, wie ich Ihnen in diesem Kapitel zeigen werde. Beide lassen sich wunderbar miteinander kombinieren. Zuerst möchte ich aber eine kleine Einführung in die Architektur des WSH voranstellen. Diese Einführung ist nur ein kurzer Abriss des Themas, ausführlichste Informationen finden Sie im Scripting-Buch zum WSH (Literatur [5]).
15.1 Der Windows Script Host Der Windows Script Host (WSH) ist Bestandteil jeder Installation von Windows ab der Version Windows 2000. Sollen Sie noch ein NT4-System verwalten, können Sie den WSH problemlos nachrüsten32. Der WSH besitzt eine sehr modulare Architektur (da seine Komponenten auch an den verschiedensten Stellen verwendet werden), die eine einfache Erweiterbarkeit garantiert. Auch ohne WSH-Scripts arbeitet auf Ihrem Server wahrscheinlich bereits ein Script Host: Sowohl der Internet Explorer als auch der Internet Information Server sind Script Hosts33, die Scripts ausführen können. Da Microsoft den Administratoren aber nicht zumuten wollte, für jede Aufgabe erst eine HTML-Seite zu erstellen, in der dann ein Client-Script abläuft, wurde der Windows Script Host ins System integriert. Dieser existiert in zwei verschiedenen Varianten: wscript.exe und cscript.exe. Während wscript nur mit Hilfe von Messageboxen mit dem Benutzer kommuniziert, arbeitet cscript im Konsolenfenster und mit den Kanälen für die Standardeingabe und -ausgabe. Welche Programmiersprache Sie für Ihre Scripts verwenden, ist für den WSH erst einmal zweitrangig. In der Standardinstallation sind 32 Sie sollten mindestens den Service Pack 4 und den IE 4.01 installiert haben (in der Praxis läuft wohl überall mittlerweile der SP 6a), dann können Sie den WSH 5.6 installieren. 33 Dies sind nur Beispiele, daneben existieren noch Script Host im SQL-Server, Exchange, dem MOM und andere.
181
15 Die Shell und der WSH
die beiden Sprachen VBScript (eine Art „VB light“) und JScript (die MS-Variante von ECMA-Script) enthalten. Allerdings sind auch die Sprachen als DLL modular realisiert, Sie können daher jederzeit eine weitere Sprache hinzufügen. Im Resource Kit für Windows 2000 ist beispielsweise ActiveState Perl enthalten, es gibt mittlerweile Rexx, Phyton und viele andere als Sprach-Engines für den WSH34. Diese Sprach-Engines kommunizieren mit dem Windows-System über COM mit Objektmodellen, die für die einzelnen Aufgabenbereiche Klassenbibliotheken bereitstellen. Auch hier ist also eine einfache Erweiterbarkeit gewährleistet. So ist die Nutzung der Crypto-API und die Berechnung von SHA-1 Hashes mit dem WSH nach der Registrierung der CAPICOM-DLL eine Sache von fünf Programmzeilen … Die nachfolgende Abbildung verdeutlicht den modularen und schichtweisen Aufbau der Scripting-Architektur in Windows. Abbildung 15.1: Die einzelnen Komponenten des WSH
15.2 Installationschecks Mittlerweile ist der WSH auf fast allen Systemen verfügbar, allerdings existieren da draußen immer noch verschiedene Versionen. Eine einfache Testmöglichkeit, ob ein Windows Script Host installiert ist, bestünde natürlich darin, einfach ein WSG-Script aufzurufen. In großen Installationen ist dies aber nicht praktikabel. Hier muss im LogonScript der Domäne unter Umständen für mehrere tausend Clients automatisiert getestet werden, welche Version des WSH installiert ist. Die eigentliche Installation ist letztlich nur der Aufruf des jeweiligen Paketes (die neueste Version können Sie von den MSDN-Seiten unter dem URL http://msdn.microsoft.com/scripting/ downloaden). Dabei handelt es sich um Windows Installer-Pakete, d.h., für eine unbeaufsichtigte Installation können Sie die erhaltene EXE-Datei mit dem Parameter /qb- aufrufen. Interessanter ist hingegen die Frage, ob der WSH bereits installiert ist und, wenn ja, welche Version verfügbar ist. 34 Bevor Sie nun davon träumen, Ihre Unix-Scripts einfach 1:1 zu übertragen: Backslash statt forward slash, Laufwerksbuchstaben, kein sendmail, COMObjekte erzeugen und so weiter …
182
Installationschecks
15.2.1
How not to do it
Die unsicherste Methode wäre ein reiner Check der Dateien. Sicher können Sie davon ausgehen, dass eine Datei cscript.exe im Ordner system32 (oder die Datei wshom.ocx) auf den WSH hindeutet, allerdings wissen Sie dann noch nichts über die Version. Im Zeitalter von Hotfixes und Security-Patches scheidet auch Test auf Dateigröße oder Datum aus35.
15.2.2
Test durch WSH-Aufruf
Daher sollte ein Test zweigeteilt ablaufen: zuerst ein Test auf das Vorhandensein des WSH, bei Erfolg ein zweiter Aufruf mit der Rückgabe der Versionsnummer. 1. Wir rufen cscript.exe auf. Wird kein solches Programm gefunden, setzt Windows den Errorlevel auf 9009 (unbekannter Befehl oder Dateiname) und damit auf ungleich null. Alternativ (wenn Sie sichergehen wollen, dass es sich auch um den WSH handelt) können Sie die Ausgabe des Logotextes auch an find schicken. Die Sprungmarke noWSH sollte dem Code vorangestellt werden, der beim Fehlen des WSH ausgeführt werden soll. cscript > nul if errorlevel 1 goto noWSH :: hier der Code, falls der WSH installiert ist rem ** hier die Alternative ** cscript //logo | find /I "windows script host" > nul if errorlevel 1 goto noWSH :: hier der Code, falls der WSH installiert ist
2. Jetzt muss festgestellt werden, welche Version installiert ist. Dazu erstellen Sie eine einzeilige Scriptdatei für den WSH, die das Script mit der Versionsnummer als Exit-Code beendet: Der Code lautet nur in einer Zeile WScript.Quit WScript.Version. Dieses Script wird aufgerufen, und als Errorlevel erhalten Sie die Version des WSH. echo WScript.Quit WScript.Version > %temp%\tmp.vbs cscript %temp%\tmp.vbs > nul if Errorlevel 56 goto wsh56 if Errorlevel 51 goto wsh51 if Errorlevel 10 goto wsh10 :: usw, Sie erkennen das Prinzip ....
Obwohl die gemeldete Versionsnummer der neuesten Version 5.6 ist (also eine Gleitkommazahl), meldet der WSH beim Exit-Code den Wert 56, verzehnfacht also das Ergebnis und kommt so ohne Kommastelle für die Versionsnummer aus. 35 Die Tatsache, dass auch Microsoft in den offiziellen Kursunterlagen teilweise noch diesen Ansatz empfiehlt, zeigt nur, dass auch diese Unterlagen einmal überarbeitet werden sollten …
183
15 Die Shell und der WSH
15.2.3
Test durch Registry lesen
Diese Methode besitzt den Vorteil, für administrative Konten auch leicht auf entfernten Maschinen durchführbar zu sein. Dazu wird mit dem Kommando reg zuerst ausgelesen, ob der Dateityp vbsfile registriert ist (auf dem lokalen System geht das auch einfacher mit assoc .vbs). Auf Remote-Systemen müssen Sie nur den Maschinennamen vor den Rootkey setzen. reg query HKCR\vbsfile /ve
Dies erzeugt (auf meinem W2K-System) den folgenden Output: ! REG.EXE VERSION 2.0 HKEY_CLASSES_ROOT\vbsfile REG_SZ Skriptdatei f³r VBScript
Der Errorlevel nach diesem Kommando liegt bei null. Wäre der WSH nicht installiert, sähe die Ausgabe so aus (bei einem Errorlevel von 1): Error: The system was unable to find the specified registry key or value
Da ich jahrelang selbst Admin war, weiß ich um die Bedeutung sicherheitsrelevanter Systeme (manche Leute sagen auch berufsbedingte Paranoia). Wenn Sie ganz sichergehen wollen, dass dieser WSH auch der richtige ist (also cscript.exe oder wscript.exe in system32), können Sie auch das Shell\Open-Kommando auslesen: reg query HKCR\vbsfile\Shell\Open\Command
Hier der Output, aus dem Sie das entsprechende Kommando zum Extrahieren des Dateinamens mittlerweile sicher selbst erschließen können. Eine Zeile
HKEY_CLASSES_ROOT\vbsfile\Shell\Open\Command REG_EXPAND_SZ %SystemRoot%\ System32\CScript.exe "%1" %*
15.3 Datenaustausch Shell – WSH Wenn WSH-Scripts mit Shell Scripts kommunizieren sollen, bleiben prinzipiell alle Möglichkeiten, die auch andere Programme haben. Die erste Möglichkeit wird in beiden Fällen das Ausnutzen der Kommandozeile durch die Übergabe von Parameterwerten sein. Auch das Erzeugen temporärer Textdateien im Format schluessel=wert ist eine einfache Methode. Geht es nur darum, Erfolg oder Misserfolg bzw. nummerische Werte auszutauschen, bietet sich die Nutzung der WSH-Methode WScript.Quit <wert> an. Diese beendet das laufende WSH-Script und liefert als Exit-Code den angegebenen Wert, der über die Variable Errorlevel abgefragt werden kann. Ein Beispiel für diese Lösung habe ich im Abschnitt 11.8.1 beim Thema Messagebox vorgestellt.
184
Integration WSH / Shell
Falls es die Berechtigungen zulassen, wäre auch die Nutzung der Registry (vorzugsweise unter HKEY_CURRENT_USER) eine Möglichkeit, da sowohl der WSH (über das WshShell-Objekt) als auch die Shell (mit reg) eine Möglichkeit bieten, dort Daten abzulegen. Zusätzlich hat diese Methode den Vorteil, dass keine temporären Dateien herumliegen, die ein ahnungsloser Endanwender gerade dann löscht, wenn sie benötigt werden. Bei der Erstellung administrativer Scripts mit dem WSH sollten Sie auch darauf achten, dass sich diese gut in die Shell einbinden lassen. Dies bedeutet unter anderem die Möglichkeit von Ein- bzw. Ausgabeumleitung, Nutzung des Errorlevels und sinnvolle Gestaltung der Ausgaben.
15.4 Integration WSH / Shell Das eine Koexistenz beider Angebote sehr nützlich ist, möchte ich noch an einem Beispiel zeigen, das gleichzeitig einige der Prinzipien aus dem Kapitel 12 über das Design von Shell Scripts wieder aufgreift36. Die Applikation, die auf einem Windows-Rechner (mit Ausnahme der Server) wahrscheinlich am häufigsten installiert ist, ist Microsoft Office. Innerhalb einer Office-Anwendung ist das Ändern von Dateieigenschaften auch kein Problem. Problematisch wird die Sache dann, wenn Ihre Firma eine Änderung des Namens beschließt (in Zeiten wie diesen wahrscheinlich am ehesten durch eine Übernahme; ich hoffe, dass Sie dann zu den Übernommenen gehören). Plötzlich sind Sie in der glücklichen Lage, bei mehreren hundert PowerPointShows, die überall unter Ihrem Benutzerverzeichnis liegen, in den Eigenschaften den Firmennamen ändern zu müssen. Oder Sie wissen, dass in irgendeiner dieser Dateien eine wichtige Folie liegt, können sich aber nur noch an ein Stichwort aus dem Kommentar erinnern. Die Verwaltung der Dokumenteneigenschaften geht über den Funktionsumfang der Shell hinaus. Aber dafür kann der Winodws Script Host die Funktionen der entsprechenden DLL mit der COM-Komponente nutzen. Das WSH-Script benötigt die Datei dsofile.dll, die Sie auf Ihrem System haben, wenn Office installiert wurde. Das Script ist in der Lage, Informationen aus den Dateieigenschaften auszulesen und auch zu verändern. Das Abarbeiten von Verzeichnisbäumen oder das Suchen nach Dateien ist aber als VBScript relativ aufwändig (Filesystem Object und Rekursion und Fehlerprüfung und so weiter). Hier ist die Shell in ihrem Element. Also werden wir das Beste aus 36 Gleichzeitig fällt dabei für Sie wieder ein produktiv einsetzbares Script ab, diesmal allerdings für den WSH. Meine Testleser haben behauptet, dies sei das „Quotenscript“ für den WSH …
185
15 Die Shell und der WSH
beiden Welten kombinieren: Das Script bearbeitet genau die Datei, die als Parameter in der Kommandozeile übergeben wird. Die Behandlung von ganzen Dateimasken à la *.ppt und die Abarbeitung von Verzeichnisbäumen überlassen wir dagegen einer forSchleife und damit der Shell. Hier die Syntax für das VB-Script: docprops.vbs []
Ein Aufruf mit docprops c:\tmp\demos\batchfiles.ppt liefert folgende Ausgabe: AppName: Microsoft PowerPoint Author: Armin Hanisch ByteCount: 19169 Category: CharacterCount: 0 CharacterCountWithSpaces: 0 CLSID: {64818D32-4F9B-11CF-86EA-0060C3B929B6} Comments: Einfuehrung in das Thema Company: DateCreated: 23.10.2003 22:47:53 DateLastPrinted: DateLastSaved: 24.10.2003 00:31:02 HasMacros: [ERROR] HiddenSlides: 0 Icon: 192086685 IsReadOnly: Falsch Keywords: LastEditedBy: Armin Hanisch LineCount: 0 Location: c:\tmp\demos\ Manager: MultimediaClips: 0 Name: Batchdateien.ppt PageCount: 0 ParagraphCount: 50 PresentationFormat: Bildschirmpräsentation PresentationNotes: 0 ProgID: PowerPoint.Show.8 RevisionNumber: 12 SlideCount: 8 Subject: Template: C:\Programme\Microsoft Office\Templates\ Presentation Designs\Armin.pot ThumbNail: -1423571398 Title: Batchdateien Version: WordCount: 354
Diese Ausgabe (ohne Titel, Spielereien wie Linien aus „=“ etc.) lässt sich auch wieder einfach in einem Shell Script weiterverarbeiten oder
186
Integration WSH / Shell
vorher noch per find filtern. Für unser Beispiel sind wir aber nur an der Eigenschaft Company interessiert. Daher werden wir die Befehlszeile etwas umbauen: docprops.vbs c:\tmp\demos\Batchfiles.ppt / format:"Firma={company}"
Dies gibt nur die eine Eigenschaft im definierten Format aus. Um eine Eigenschaft zu setzen, müssen dagegen der Name der Eigenschaft und der neue Wert angegeben werden: docprops.vbs Batchfiles.ppt /set:company / value:CoolPlaceToWork
Soweit fürs Erste der WSH-Teil. Sollen nun alle PowerPoint-Shows unterhalb eines Ordners abgearbeitet werden, muss dies nicht programmiert werden, schließlich hat die Shell für eine for-Schleife die Option /R: for /R h:\users\armin %f in (*.ppt) do @docprops.vbs "%f" /set:company /value:CoolPlaceToWork
Fertig! Egal, wie gut Sie als Programmierer sind, in einer Zeile bekommen Sie das im WSH nicht hin. Hier kommt es darauf an, aus jedem Werkzeug das Optimum herauszuholen. Das Script docprops.vbs finden Sie natürlich auch im Download-Archiv zum Buch. Sehen Sie sich auch einmal das Design der VBS-Datei an, was Ausgaben, Kennzeichnungen und Formatierbarkeit angeht. Je flexibler Sie die Ausgaben halten (wie hier, wo der Benutzer selbst das Format bestimmen kann), umso einfacher ist die Integration in die Shell und in andere Scripts. Wie Sie aus den vorherigen Ausführungen (und auch aus dem Inhalt des Buches) unschwer entnehmen können, ist die Frage definitiv nicht Shell oder WSH. Beide ergänzen sich in ihren Möglichkeiten. Der Vorteil des WSH liegt vor allem dort, wo Abläufe relativ komplex werden, viel Benutzerinteraktion über ein GUI gefordert ist oder der Aufruf von COM-Komponenten notwendig ist. Vorteil der Shell ist dagegen die Ausrichtung auf die Zielgruppe: Administratoren und Power User, also ein Personenkreis, der nicht programmiert. Microsoft hat spätestens seit Windows XP erkannt, dass ein System auch über die Kommandozeile administrierbar sein muss, um bei großen Installationen Abläufe automatisierbar zu halten. Mit dem Server 2003 ist die rein Shell-basierte Administration einer Maschine zwar noch nicht Realität (und für manche Aufgaben auch nicht gewünscht), aber man ist doch einen großen Schritt weiter in diese Richtung gegangen. Vor allem der Verzicht auf die Notwendigkeit von Programmierkenntnissen, eine Integration neuer Tools in die bestehende Umgebung der Shell und ein konsequenter Umbau auf Remote-Fähigkeit und WMI-Unterstützung machen die Arbeit sehr effektiv.
187
15 Die Shell und der WSH
15.5 Weiterführende Literatur zum WSH Eine weitergehende Beschäftigung mit dem Windows Script Host ist jedem professionellen Windows-Benutzer, sei es Entwickler, Admin oder Supporter, auf jeden Fall anzuraten. Sicherlich ist die Lernkurve etwas steiler als bei der guten alten Kommandozeile, Sie werden dafür mit wesentlich mehr Möglichkeiten belohnt. Außerdem können Sie die Möglichkeiten und Grenzen eines Werkzeugs erst dann beurteilen, wenn Sie es kennen. Eine detaillierte Beschreibung des WSH ist allerdings nicht Thema dieses Buches. Darüber hinaus hieße es Eulen nach Athen tragen, wenn bei Addison-Wesley nach den Büchern von Dr. Holger Schwichtenberg noch ein WSH-Buch erscheinen würde. Wenn Sie die folgenden Werke noch nicht in Ihrem Regal haben, besorgen Sie diese möglichst bald. 왘 Holger Schwichtenberg u.a., „Windows Scripting lernen“, Addi-
son-Wesley, ISBN 3-8273-2019-4 왘 Holger Schwichtenberg, „Windows Scripting“, Addison-Weshley,
ISBN 3-8273-1843-2 Oder Sie besuchen die Site http://www.windows-scripting.de
188
16
Shell Script-Beispiele
16.1 Vorbemerkung Die Scripts in diesem Abschnitt sind Lösungen für Aufgabenstellungen aus der täglichen Praxis. Die Scripts sind teilweise etwas komplexer oder setzen Kommandos auf manchmal ungewöhnliche Weise ein. Jedes Script wird kommentiert und der gewählte Ansatz besprochen. Ich nehme nicht in Anspruch, immer die optimale Lösung gewählt zu haben, und es gibt für manche Aufgaben sicher auch noch alternative Ansätze oder das Erstellen eines Scripts für den WSH. Sinn dieser Scripts ist das Verdeutlichen einer bestimmten Herangehensweise an solche Probleme und dass Sie selbst solche Shell Scripts ohne Probleme bauen können, wenn Sie sich über den Ablauf der von Ihnen gewählten Befehle im Klaren sind (das Thema Problemzerlegung und Ablaufdesign hängt nicht von der gewählten Sprache ab). Ebenso finden Sie in diesem Kapitel an der gleichen Stelle wie die Scripts zum Thema einzelne neue Kommandos von Windows 2003, die für die tägliche Arbeit wichtig sind und die seit Windows 2003 das Schreiben von komplexen Shell Scripts vermeiden helfen.
16.2 Systemverwaltung 16.2.1
which
which liefert beim Aufruf den kompletten Pfad der Datei, die ausgeführt werden würde, wenn der Dateiname eingegeben wird. Sinnvoll ist dies vor allem, wenn diese Datei mehr als einmal (in verschiedenen Verzeichnissen) existiert und Sie sich nicht sicher sind, welche Datei gestartet wird.
Parameter 왘 %1 = Dateiname, der gesucht wird
Code @for %%f in (%1) do @if "%~$PATH:f" == "" (echo Nicht im Suchpfad) else (echo Ausgeführt wird %~$PATH:f)
Funktion Mit Hilfe einer for-Schleife und dem Modifikator $~PATH wird die erste im Suchpfad passende Datei gefunden und ausgegeben. Ab Windows 2003 können Sie stattdessen auch das Kommando where benutzen.
189
16 Shell Script-Beispiele
16.3 Dateiverwaltung 16.3.1
Welche Datei ist neuer?
Parameter: 왘 %1 = Datei 1 (kann auch Pfad enthalten) 왘 %2 = Datei 2 (kann auch Pfad enthalten)
Code Listing 16.1: Welche Datei ist jünger?
@echo off dir %1;%2 /b /o-d > %temp%\tmp.dat set /P filename= < %temp%\tmp.dat echo Neueste Datei ist: %filename% del %temp%\tmp.dat
Funktion Dieses Script nutzt die Möglichkeiten von dir, mit der Option /o-d eine umgekehrt nach Erstellungsdatum sortierte Liste auszugeben. Diese Ausgabe wird mit der Option /b auf die einfache Ausgabe einer reinen Liste von Dateinamen beschränkt und in eine temporäre Datei umgeleitet. Anschließend benutze ich set mit Option /p, um eine Zeile von der Standardeingabe einzulesen und in der Variablen filename zu speichern. Die Standardeingabe wird dabei umgeleitet, so dass die Daten aus der vorher erzeugten temporären Datei stammen. Bei der Umleitung aus einer Datei liest set nur die erste Zeile. Diese enthält den Namen der jüngsten Datei, der nun nur noch ausgegeben werden muss. In der letzten Zeile wird die nicht mehr benötigte temporäre Datei gelöscht.
16.3.2
GetWord
Lesen eines Wortes aus einer bestimmten Position in einer Textdatei Parameter: 왘 %1 = Dateiname 왘 %2 = Zeilennummer 왘 %3 = Wortnummer
Code Listing 16.2: Lesen eines Wortes aus einer Textdatei
190
@echo off :: select token from input file
Dateiverwaltung set line=0 if x%1 == x goto usage if not exist %1 goto nofile :: add the delims= option between the quotes, if your input is not :: separated by white space, e.g. for /F "tokens=%3 delims=;" .... for /F "tokens=%3 usebackq" %%f in (%1) do call :procline %2 %%f set line= goto eof :procline set /a line="%line%+1" if %1 == %line% echo %2 goto eof :usage echo %0 - extract a word from a text input file echo Copyright (c) 2003 by Armin Hanisch echo. echo Usage: %0 [filename] [line#] [word#] echo. echo Words in input file are separated by white space. echo If you need different delimiters, check the code for help. echo. goto eof :nofile echo Could not find input file %1 - terminating. goto eof :eof
Funktion Mit Hilfe einer for-Schleife wird Zeile für Zeile der Datei gelesen. Durch die Angabe der Option tokens=%3 erhalten wir aber immer nur das Wort aus der Zeile, das dem Wort an der gesuchten Position (der Parameter Nummer drei) entspricht. Für jede Zeile wird die Ausführung an die Sprungmarke :procline übergeben. Der Wert für die gesuchte Zeile (der Parameter Nummer zwei, %2) und der tatsächlichen Inhalt der Zeile (%%f) werden als Parameter übergeben. An der Sprungmarke wird zuerst eine Umgebungsvariable (line) um eins erhöht und dann in einer if-Abfrage mit der gesuchten Zeilennummer verglichen. Bei Übereinstimmung wird die Zeile (die nur das gesuchte Wort enthält) ausgegeben.
191
16 Shell Script-Beispiele
Sollten die Wörter in Ihren Eingabedateien nicht durch Leerzeichen getrennt werden, können Sie der for-Schleife die Option delims hinzufügen (wie im Kommentar beschrieben) und dort eine Liste mit anderen Trennzeichen vereinbaren.
16.3.3
Insert
An eine Textdatei Inhalt anzufügen, gehört zu den leichteren Übungen (s. Ausgabeumleitung). Viele Administratoren vermissen aber eine Funktion, mit der eine Textdatei in eine andere Textdatei eingefügt werden kann. Das nachfolgende Beispiel zeigt eine Batchdatei, mit der genau diese Funktion erreicht wird: Eine Datei wird vor einer anzugebenden Zeile in eine zweite Datei eingefügt. Damit die Batchdatei möglichst universal einsetzbar bleibt, wurde auf einige, ab Windows 2000 mögliche, Optimierungen verzichtet. Damit ist der problemlose Einsatz ab Windows NT4.0 bei eingeschalteten Befehlserweiterungen möglich. Parameter 왘 %1 = Quelldatei 왘 %2 = Zieldatei 왘 %3 = Zeilennummer, vor der eingefügt werden soll
Code Listing 16.3: Einfügen einer Textdatei in eine andere Datei
@echo off if !%3 == ! goto err if not exist %1 goto err if not exist %2 goto err if not %3 GTR 0 goto err goto ok :err echo Insert a text file into another text file before line #. echo. echo Usage: %0 [source] [target] [line#] echo. echo Line number must be greater then 0 and both files must exist. echo If line number is greater then line count in target, source file echo will be appended. echo Target file will be modified, need write access for this file. echo. goto eof :ok
192
Dateiverwaltung if exist $tmp$.txt del $tmp$.txt set count=0 for /F "tokens=*" %%f in (%2) do call :tran1 "%%f" %3 more < %1 >> $tmp$.txt set count=0 for /F "tokens=*" %%f in (%2) do call :tran2 "%%f" %3 copy $tmp$.txt %2 /y if exist $tmp$.txt del $tmp$.txt goto eof :tran1 set /a count=%count%+1 if %count% GEQ %2 goto eof echo %~1 >> $tmp$.txt goto eof :tran2 set /a count=%count%+1 if %count% LSS %2 goto eof echo %~1 >> $tmp$.txt goto eof :eof
Funktion Das Script liest die Zieldatei zeilenweise mit einer for-Schleife ein. Dabei läuft in einer Umgebungsvariablen count ein Zähler mit, der die Anzahl der bereits übertragenen Zeilen zählt. Diese Zeilen werden in der temporären Datei $tmp$.txt gesammelt. Ist die Einfügezeile erreicht, wird die einzufügende Datei per more an die temporäre Datei angehängt. Danach werden in einer zweiten forSchleife alle Zeilen aus der Zieldatei an die temporäre Datei angehängt, deren Zeilennummer größer als die der Einfügezeile ist. Das Ergebnis ist eine einzelne Datei mit dem Ergebnis der Einfügeoperation. Diese wird dann anschließend noch über die Zieldatei kopiert.
16.3.4
Delete
Parameter 왘 %1 = Name der Datei, aus der eine Zeile gelöscht werden soll 왘 %2 = Nummer der zu löschenden Zeile (beginnt bei 1)
193
16 Shell Script-Beispiele
Code @echo off if !%1 == ! goto err if !%2 == ! goto err set line=0 for /F "usebackq" %%f in (%1) do call :procline %2 "%%f" goto :eof :err echo Usage: %0 [file] [line#] echo. echo Deletes line number # from the file and writes echo the result to StdOut goto :eof :procline set /a line="line+1" if not %line% EQU %1 echo %~2
Funktion Dieses Shell Script durchläuft die angegebene Datei in einer forSchleife und zählt in einer Umgebungsvariablen (line) die Anzahl der vorher durchlaufenen Zeilen mit. Alle Zeilen, bis auf diejenige mit der Nummer, die dem zweiten Parameter beim Aufruf entspricht, werden ausgegeben. Da im Befehlsteil der Schleife als erster Parameter die Nummer der zu löschenden Zeile übergeben wird und danach der Inhalt der Zeile (in Anführungszeichen, falls Leerzeichen enthalten sind), erfolgt nach der Sprungmarke :procline eine Überprüfung mit if auf den Parameter Nummer eins (%1). Solche Konstruktionen kommen in Batches öfter vor, daher sollten Sie immer wissen, ob die Abarbeitung an dieser Stelle im normalen Ablauf stattfindet oder wie hier über einen internen Aufruf per call :label. Da der Inhalt der Zeile in Anführungszeichen übergeben wurde, wird bei echo die Konstruktion %~2 gewählt, mit der die umschließenden Anführungszeichen wieder entfernt werden. Als Designalternative habe ich hier die Ausgabe der Datei nach dem Löschen der angegebenen Zeile auf die Standardausgabe gelenkt. Dies hat den Vorteil, dass der Benutzer des Scripts völlig frei in der Verwendung der Ausgabe ist. Diese kann direkt auf die Konsole gehen oder aber mit Hilfe der Umleitungssymbole oder per Piping an andere Programme oder Dateien übergeben werden. So bleibt das Script flexibel, und die Anzahl der notwendigen Parameter wird minimiert.
194
Dateiverwaltung
16.3.5
Reverse
Dieses Script dreht die Reihenfolge der Zeilen in einer Textdatei um, d.h., die letzten Zeilen werden an den Beginn der Datei versetzt und umgekehrt. Parameter 왘 %1 = Datei, deren Inhalt umgedreht werden soll
Code :: reverse a text file, slow but plain shell :: test der parameter if !%1 == ! goto nofile
Listing 16.4: Umdrehen der Zeilenfolge in einer Datei
:: ist die datei auch da? if not exist %1 goto nofile :: test auf umgebungsvariable if not defined temp goto noenv :: evtl. bestehende datei loeschen if exist %temp%\tmp.txt del %temp%\tmp.txt :: for /F "tokens=* usebackq" %%f in (%1) do call :procline "%%f" more < %temp%\tmp.txt > %1 del %temp%\tmp.txt del %temp%\line.txt goto eof :procline echo %~1 > %temp%\line.txt if exist %temp%\tmp.txt more < %temp%\tmp.txt >> %temp%\ line.txt more < %temp%\line.txt > %temp%\tmp.txt goto eof :noenv echo Variable TEMP nicht definiert, Abbruch. goto eof :nofile echo Keine Datei angegeben, Abbruch. goto eof :notfound echo Die Datei %1 existiert nicht, Abbruch. goto eof :eof
195
16 Shell Script-Beispiele
Funktion Die Funktion wurde bereits im Abschnitt 11.5.1 besprochen.
16.3.6
Bulk Rename
Parameter (keine) Code Listing 16.5: Umbenennen aller Dateien in einem Verzeichnis
@echo off echo Achtung! Dieses Script aendert alle Namen echo von JPG-Dateien im aktuellen Verzeichnis echo in eine nummerische Form ab! echo Weiter mit bel. Taste oder [Strg-C] echo zum Abbrechen. pause > nul set num=1 for %%f in (*.jpg) do call :doRen "%%f" echo Fertig. GOTO :EOF :doRen echo Aus %1 wird Img-%num%%~x1 ... ren %1 Img-%num%%~x1 Set /A num=%num% + 1
Funktion Zuerst erfolgt eine Sicherheitsabfrage, falls das Shell Script im falschen Verzeichnis ausgeführt wird. Die Umgebungsvariable num enthält den Startwert für die Nummerierung der Dateien. Achten Sie darauf, dass Sie solche Scripts mit Vorsicht einsetzen. Ich habe beim Erstellen dieses Beispiels (wahrscheinlich hatte ich zu wenig Kaffee) einmal das Windows-Verzeichnis umnummeriert! Gut, dass es nur eine VMWare-Maschine war. Aus diesem Grund ist die Suchmaske im Beispiel auch auf *.jpg eingestellt. Ändern Sie dies bei Bedarf ab. Mit Hilfe einer for-Schleife werden alle Dateien in einem Verzeichnis, die auf die Suchmaske passen (hier *.jpg), durchlaufen. Für jeden Dateinamen wird die Sprungmarke :doRen angesprungen. Da im Dateinamen auch Leerzeichen enthalten sein könnten, wird der Name in Anführungszeichen übergeben. Bei der Sprungmarke erfolgt zuerst eine Ausgabe der alten und neuen Dateinamen, dann wird mit ren und der Variablen num die Umbenennung durchgeführt. Anschließend wird der Zähler in num um eines erhöht.
196
Dateiverwaltung
16.3.7
Textdateien nummerieren
Dass Sie Textdateien einfach per find nummerieren können, haben Sie bereits im Kapitel über die Filter im ersten Teil des Buches erfahren. Vielen Benutzern allerdings gefällt die Art der Nummerierung nicht. Sehen wir uns dazu nochmals das find-Kommando und seine Ausgabe an: find /n /v "@@@@@" < datei.txt [1]Eins [2]Zwei [3]Drei
Listing 16.6: Die normale Ausgabe der Nummerierung mit find
Problematisch daran ist das fehlende Leerzeichen zwischen der Zeilenzahl und dem Text. Sie können die Ausgabe in eine neue Datei umleiten und dann mit Hilfe einer for-Schleife wieder auslesen (mit einem "]" als Trennzeichen). Es geht allerdings auch in einer Zeile, wenn Sie die Möglichkeit von Backquoting, Kommandogruppierung und erweiterter Variablenersetzung nutzen: for /F "usebackq tokens=*" %f in (`find /n /v "@@@@@" ^< datei.txt`) do @set line=%f & set line=!line:]= ! & set line=!line:[=! & echo !line!
Dies erzeugt die unten stehende Ausgabe: 1 Eins 2 Zwei 3 Drei
Sollten Sie jetzt stirnrunzelnd auf die Befehlszeile gucken, geht es Ihnen wie einigen meiner Manuskript-Testleser, deshalb möchte ich Ihnen Schritt für Schritt erläutern, was da eigentlich passiert. 왘 Die Schleife führt zuerst das Kommando find /n /v "@@@@@" ^
%temp%\tmp.txt for /F "tokens=*" %%f in (%temp%\tmp.txt) do call :procline "%%f" goto :eof :procline set line=%~1 set line=%line:]= % set line=%line:[=% echo %line%
Beachten Sie im Code die Verdopplung der Prozentzeichen bei der Variablen für die for-Schleife. Durch die zeilenweise Abarbeitung der Batch-Engine kommen wir an dieser Stelle auch ohne verzögerte Variablenexpansion aus und können die gewohnten Prozentzeichen für die Variablen benutzen. Da ich in diesem Beispiel den Output des find-Kommandos im temp-Verzeichnis ablege, kann auch auf das Backquoting verzichtet werden, und durch die Modularisierung über den Aufruf per call :label wird das Shell Script auch übersichtlicher. Entscheiden Sie selbst, welcher der beiden Ansätze für Sie sinnvoller ist. Sollten Sie auf einer IT-Party in einer dieser „Windows hat keine Shell“-Diskussionen verwickelt werden, kritzeln Sie einfach die Befehlszeilenversion auf eine Serviette, und die Diskussion ist beendet …
16.3.8
uniq (Duplikate entfernen)
Parameter 왘 %1 = Name der Datei, die sortiert ohne Duplikate ausgegeben
werden soll
198
ActiveDirectory
Code @echo off if !%1 == ! goto noparm if not exist %1 goto notfound
Listing 16.8: Die Shell-Version von uniq
setlocal set line=@@@@@ for /F "usebackq tokens=*" %%f in (`sort %1`) do call :procline "%%f" endlocal goto :eof :procline if !%line% == !%~1 goto :eof set line=%~1 echo %~1 goto :eof :noparm echo Aufruf: %~f0 [datei] echo Kein Dateiname angegeben, Abbruch. goto :eof :notfound echo Die Datei %1 wurde nicht gefunden, Abbruch. goto :eof
Funktion Die Funktion dieses Scripts ist relativ einfach, aber dennoch nützlich, da Windows ein uniq-Kommando fehlt (es sei denn, Sie rüsten dies aus einem der unter Kapitel 13.2 erwähnten Toolkits nach). Zuerst wird die Datei per sort mit Hilfe von Backquoting sortiert. Sie können natürlich auch sort direkt ohne die for-Schleife aufrufen, das Ergebnis in eine temporäre Datei schreiben und diese Datei dann per for abarbeiten. Für jede Zeile wird in der Schleife die Ausführung an der Sprungmarke :procline fortgesetzt. Dort wird eine Umgebungsvariable (line) mit dem Inhalt der aktuellen Zeile verglichen. Solange diese übereinstimmen, haben wir ein Duplikat, und die Zeile wird nicht ausgegeben. Ist die Zeile verschieden, wird diese neue Zeile in der Variablen line gespeichert und per echo ausgegeben.
16.4 ActiveDirectory Die Möglichkeiten zur Verwaltung des ActiveDirectory haben sich seit Windows 2003 deutlich verbessert. Die neuen ds*-Kommandos lassen nun erstmals das direkte Anlegen, Ändern und Löschen von Informationen im AD über die Shell zu, ohne sich mit komplexen
199
16 Shell Script-Beispiele
Shell Scripts beschäftigen zu müssen. Das komplizierteste, was Sie sich jetzt noch merken müssen, ist der LDAP-Pfad zum gewünschten Objekt.
16.4.1
LDAP-Suchfilter
Ein möglicher Stolperstein für die Arbeit mit den ActiveDirectoryKommandos ist die Definition von LDAP-Suchfiltern. Diese besitzen eine gewöhnungsbedürftige Syntax, weshalb ich eine kleine Einführung in das Thema auch der Beschreibung der AD-Kommandos voranstelle. Ein LDAP-Suchfilter besteht aus einem oder mehreren Ausdrücken in der Form ( <wert> ). Die runden Klammern müssen mit angegeben werden. Beispielsweise lautet der Standardsuchfilter für die Kommandos csvde und ldifde auf (objectClass=*), also die Suche nach allen Objekten. Die Namen der Attribute sind die tatsächlichen Schemanamen, nicht die Beschriftungen aus den Admin-Tools. Aus diesem Grund müssen Sie die Namen der Attribute unter Umständen erst mit einem ADWerkzeug wie adsiedit.msc aus den Support Tools nachschlagen. Folgende Operatoren sind in einer LDAP-Abfrage möglich: Tabelle 16.1: Relationale LDAPOperatoren
=
Beide Werte müssen übereinstimmen
~=
Ungefähre Übereinstimmung
>=
Größer gleich
= und = 20040601000000.0Z))
Achten Sie bei Abfragen mit Datumswerten darauf, diese in der korrekten Schreibweise anzugeben. Das Format lautet JJJJMMTT hhmmss.xZ, wobei x für die Sekundenbruchteile und das Z für „Zulu-Time“ (Weltzeit) steht. (&(objectClass=group)(whenCreated>=20040601000000.0Z))
Ach ja: Schreiben Sie das Z immer groß, ansonsten wird die Abfrage fehlschlagen. Ebenso dürfen in der gesamten Abfrage keine Leerzeichen vorkommen. Sehr pingelig also …
16.4.2
CSVDE
Grundlagen csvde.exe ist ein Programm, mit dem komplette Objekte aus dem ActiveDirectory exportiert oder importiert werden können. Einzelne Attribute eines bestehenden Objektes lassen sich nicht verändern, dafür wird ldifde oder dsmod benutzt. csvde.exe ist besonders dann sehr nützlich, wenn es um die Erstellung von Reports geht oder viele Benutzerdaten an Programme zur Auswertung übergeben müssen.
Hier die allgemeine Syntax von csvde: CSV Verzeichnis Exchange General Parameters ================== -i Turn on Import Mode (The default is Export) -f filename Input or Output filename -s servername The server to bind to (Default to DC of
Listing 16.9: Die Optionen von csvde.exe
37 Natürlich hätte auch (objectCategory = Person) allein ausgereicht, aber dann hätte ich den "&"-Operator nicht demonstrieren können …
201
16 Shell Script-Beispiele computer's domain) -v Turn on Verbose Mode -c FromDN ToDN Replace occurences of FromDN to ToDN -j path Log File Location -t port Port Number (default = 389) -u Use Unicode format -? Help Export Specific =============== -d RootDN The root of the LDAP search (Default to Naming Context) -r Filter LDAP search filter (Default to "(objectClass=*)") -p SearchScope Search Scope (Base/OneLevel/Subtree) -l list List of attributes (comma separated) to look for in an LDAP search -o list List of attributes (comma separated) to omit from input. -g Disable Paged Search. -m Enable the SAM logic on export. -n Do not export binary values Import ====== -k The import will go on ignoring 'Constraint Violation' and 'Object Already Exists' errors Credentials Establishment ========================= Note that if no credentials is specified, CSVDE will bind as the currently logged on user, using SSPI. -a UserDN [Password | *] authentication -b UserName Domain [Password | *]
Simple SSPI bind method
Beispiele Sehen wir uns dazu gleich ein Beispiel an. Sie werden erkennen, dass nicht viele Optionen benötigt werden, um csvde sinnvoll einzusetzen. Zuerst sollen alle Objekte im Container „users“ ausgegeben werden. Für die Authentifizierung wird das Konto des angemeldeten Benutzers verwendet, und die Ausgabe soll in der Datei ausgabe.dat landen: Eine Zeile
202
csvde -f ausgabe.dat -d "cn=users,dc=shellbook,dc=com"
ActiveDirectory
Diese Ausgabe wird allerdings nicht oft Verwendung finden, sie enthält einfach zu viele Daten. Daher noch ein Beispiel aus der Praxis. Hier sollen aus einer OU alle Kontaktdaten in eine CSV-Datei exportiert werden, damit diese in ein E-Mail-Adressbuch übernommen werden können. Aus diesem Grund sollen auch nicht wahllos alle Attribute exportiert werden, sondern nur der angezeigte Name, die E-Mail-Adresse und die Homepage. Dafür werden zwei weitere Optionen benutzt. Die Option -l definiert eine kommagetrennte Liste aus Attributnamen, und die Option -r legt einen LDAP-Suchfilter fest. csvde -f ausgabe.dat -d "ou=produktion,dc=shellbook,dc=com" -r "(objectClass=contact)" -l "displayName,wwwhomepage,mail"
Eine Zeile
Die Ausgabe des Kommandos in der Konsole sieht dann wie folgt aus: Connecting to "(null)" Logging in as current user using SSPI Exporting Verzeichnis to file ausgabe.dat Searching for entries... Writing out entries .. Export Completed. Post-processing in progress... 2 entries exported The command has completed successfully
Da wir keinen Server angegeben haben, erfolgt die Anmeldung am DC. Ohne die Optionen -a oder -b werden die Daten des angemeldeten Benutzers für die Authentifizierung verwendet. Für jeden exportierten Datensatz schreibt csvde einen Punkt nach „Writing out entries“. Da ich mit der Option -l die Liste der Attribute begrenzt habe, werden auch nur diese Attribute in die Datei geschrieben38. Hier der Inhalt der Datei: C:\tmp>more < ausgabe.dat DN,displayName,wWWHomePage,mail "CN=Norman Kerth,OU=Produktion,DC=shellbook,DC=com",Norm Kerth, http:// www.retrospectives.com,
[email protected] "CN=Julius Caesar,OU=Produktion,DC=shellbook,DC=com",Caesar, http:/ /www.caesar.spqr,
[email protected] C:\tmp>
38 Die Ausgabe des Distinguished Names (DN) erfolgt immer als erstes Attribut, damit die Ausgabe zuordnungsfähig bleibt.
203
16 Shell Script-Beispiele
Hinweise Die Werte für das Attribut userAccountControl regeln den Zustand des Kontos und sind als Bitmaske wie in der Tabelle unten definiert (Auszug, die komplette Auflistung finden Sie in der MSDN). Tabelle 16.3: Die wichtigsten Bitflags für userAccountControl
Flag
Wert (hex!)
Account disabled
2
Homedir erforderlich
8
Lockout aktiv
10
Kein Passwort erforderlich
20
Benutzer kann Passwort nicht ändern
40
Normaler Account
200
Inter-Domain Trust Account
800
Workstation Trust Account
1000
Server Trust Account
2000
Passwort läuft nie ab
10000
Trusted for delegation
80000
Passwort abgelaufen
800000
Ein normaler Benutzer, dessen Passwort nicht abläuft, besitzt also den Wert von hex 10000 und hex 200, zusammen 0x10200 oder dezimal 66048. Für den Import mit csvde (s.u.) können Sie nur einen Wert angeben, der das Flag für Account disabled gesetzt hat, z.B. 514.
16.4.3
Benutzer aus Datei anlegen
Mit Hilfe von csvde ist es also sehr einfach (sogar einfacher als mit dem WSH) möglich, Benutzer neu anzulegen. Alles, was Sie dazu benötigen, ist eine Textdatei mit den Daten für einen Account in jeder Zeile. csvde besitzt einen Nachteil: Es lassen sich keine Passwörter in der
Datei übergeben. Falls Sie also (hoffentlich) in Ihrer Domain Policy definiert haben, dass gewisse Regeln bezüglich Länge und Komplexität des Passworts zu beachten sind, können Sie die Accounts nur dann anlegen, wenn diese deaktiviert (disabled) sind. Die folgenden Attribute müssen in der Eingabedatei mindestens enthalten sein: DN, objectClass und sAMAccountName. Weitere Attribute wie wWWHomePage, department oder telephoneNumber können Sie nach Belieben ergänzen. Hier ein Beispiel für eine Eingabedatei, mit der ein Benutzer in der OU „Kurs“ angelegt wird (die zweite Zeile
204
ActiveDirectory
mit den Daten steht in einer einzigen Zeile, hier im Buch erfolgt nur ein Umbruch durch das Satzsystem): DN,objectClass,userAccountControl,sAMAccountName,user PrincipalName "CN=Student38,OU=Kurs,DC=shellbook,DC=com",user,514,stud ent38,
[email protected] Jetzt kann csvde mit diesen Daten als Eingabe gestartet werden: C:\tmp>csvde -i -f eingabe.dat Connecting to "(null)" Logging in as current user using SSPI Importing Verzeichnis from file "eingabe.dat" Loading entries.. 1 entry modified successfully. The command has completed successfully C:\tmp>
Denken Sie allerdings daran, dass vor einer Aktivierung des Account noch das Passwort so gesetzt werden muss, dass es den Regeln der aktiven Gruppenrichtlinien entspricht.
16.4.4
LDIFDE
Grundlagen Der große Unterschied zwischen csvde und ldifde liegt darin, dass beim letzteren Kommando auch einzelne Attribute eines bestehenden Objektes verändert werden können. Sogar das Löschen von Objekten aus dem Verzeichnis ist möglich. Der zweite Unterscheid ist das verwendete Format für die Eingabe und Ausgabe. Wie die Namen der beiden Kommandos bereits andeuten, verwendet csvde kommaseparierte Textdateien und ldifde das LDIF-Format für den Austausch zwischen Verzeichnisdiensten. Die allgemeine Syntax von ldifde ähnelt der von csvde stark: LDIF Verzeichnis Exchange General Parameters ================== -i Turn on Import Mode (The default is Export) -f filename Input or Output filename -s servername The server to bind to (Default to DC of computer's domain) -c FromDN ToDN Replace occurences of FromDN to ToDN -v Turn on Verbose Mode -j path Log File Location -t port Port Number (default = 389) -u Use Unicode format
Listing 16.10: Die Optionen von ldifde.exe
205
16 Shell Script-Beispiele -w timeout Terminate execution if the server takes longer than the specified number of seconds to respond to an operation (default = no timeout specified) -h Enable SASL layer encryption -? Help Export Specific =============== -d RootDN The root of the LDAP search (Default to Naming Context) -r Filter LDAP search filter (Default to "(objectClass=*)") -p SearchScope Search Scope (Base/OneLevel/Subtree) -l list List of attributes (comma separated) to look for in an LDAP search -o list List of attributes (comma separated) to omit from input. -g Disable Paged Search. -m Enable the SAM logic on export. -n Do not export binary values Import ====== -k The import will go on ignoring 'Constraint Violation' and 'Object Already Exists' errors -y The import will use lazy commit for better performance (enabled by default) -e The import will not use lazy commit -q threads The import will use the specified number of threads (default is 1) Credentials Establishment ========================= Note that if no credentials is specified, LDIFDE will bind as the currently logged on user, using SSPI. -a UserDN [Password | *] authentication -b UserName Domain [Password | *]
Simple SSPI bind method
Beispiele Zuerst soll ein einzelner Kontakt exportiert werden:
206
ActiveDirectory ldifde -f ausgabe.dat -d "cn=Julius Caesar, ou=Produktion,dc=shellbook,dc=com
Eine Zeile
Ohne eine weitere einschränkende Option werden auch hier wieder alle belegten Attribute ausgegeben. Den Inhalt der angegebenen Datei zeigt das nachfolge Listing: dn: CN=Julius Caesar,OU=Produktion,DC=shellbook,DC=com changetype: add objectClass: top objectClass: person objectClass: organizationalPerson objectClass: contact cn: Julius Caesar sn: Caesar givenName: Julius distinguishedName: CN=Julius Caesar,OU=Produktion,DC=shellbook,DC=com instanceType: 4 whenCreated: 20040705130736.0Z whenChanged: 20040705130808.0Z displayName: Caesar uSNCreated: 24659 uSNChanged: 24660 wWWHomePage: http://www.caesar.spqr name: Julius Caesar objectGUID:: yDxlB1bOEEmPvpMNpD56Ww== objectCategory: CN=Person,CN=Schema,CN=Configuration,DC=shellbook,DC=com mail:
[email protected] Listing 16.11: Inhalt der Exportdatei nach einfachem ldifde-Export
Wie bei csvde lassen sich auch hier Einschränkungen treffen, für die tatsächlich die gleichen Optionen verwendet werden. Daher kann ich das Beispiel zum Export der Maildaten von csvde weiter oben unverändert übernehmen. Ich tausche nur den Namen des Kommandos aus: ldifde -f ausgabe.dat -d "ou=produktion,dc=shellbook,dc=com" -r "(objectClass=contact)" -l "displayName,wwwhomepage,mail"
Eine Zeile
Hier der Inhalt der Exportdatei, der diesmal im LDIF-Format erstellt wird: dn: CN=Norman Kerth,OU=Produktion,DC=shellbook,DC=com changetype: add displayName: Norm Kerth wWWHomePage: http://www.retrospectives.com mail:
[email protected] Listing 16.12: Die Exportdatei im LDIF-Format
dn: CN=Julius Caesar,OU=Produktion,DC=shellbook,DC=com changetype: add
207
16 Shell Script-Beispiele displayName: Caesar wWWHomePage: http://www.caesar.spqr mail:
[email protected] Interessant wird der Einsatz dieses Kommandos vor allem dann, wenn einzelne Attribute verändert oder ganze Objekte gelöscht werden sollen. Löschen von Objekten Nachdem ich gerade die Daten der beiden Kontaktobjekte exportiert habe, ist dies ein guter Zeitpunkt, um das Löschen von Objekten zu demonstrieren. Dazu wird eine LDIF-Datei erstellt, mit der festgelegt wird, welche Objekte gelöscht werden. Der Aufbau hier ist sehr einfach, da lediglich das DN-Attribut benötigt wird. Der changetype in der LDIF-Datei wird auf delete gestellt, und das war auch schon alles. Hier der Inhalt der Datei, mit der die beiden Kontakte aus dem Verzeichnis gelöscht werden: Listing 16.13: Eine Steuerdatei zum Löschen von Daten
dn: CN=Norman Kerth,OU=Produktion,DC=shellbook,DC=com changetype: delete dn: CN=Julius Caesar,OU=Produktion,DC=shellbook,DC=com changetype: delete
Beachten Sie bei beiden Datensätzen die nachfolgende Leerzeile, sonst erhalten Sie eine Fehlermeldung. Jetzt kann damit die Löschaktion gestartet werden, wie der Ausschnitt aus dem Konsolenlog zeigt: C:\tmp>ldifde -f eingabe.dat -i Connecting to "bytebag.shellbook.com" Logging in as current user using SSPI Importing Verzeichnis from file "eingabe.dat" Loading entries... 2 entries modified successfully. The command has completed successfully C:\tmp>
Importieren von Daten So, meine Kontakte sind weg, also einfach von der vorher erzeugten Ausgabedatei wieder importieren. Beinahe! Falls Sie dies versuchen, erhalten Sie eine der vielen möglichen Fehlermeldungen: C:\tmp>ldifde -f ausgabe.dat -i Connecting to "bytebag.shellbook.com" Logging in as current user using SSPI Importing Verzeichnis from file "ausgabe.dat" Loading entries. Add error on line 1: Object Class Violation The server side error is "The object class attribute must be specified."
208
ActiveDirectory 0 entries modified successfully. An error has occurred in the program No log files were written. In order to generate a log file, please specify the log file path via the -j option.
Warum? Nun, als ich diese Beispiele geschrieben habe, ging es mir genauso39. Aber im Beispiel für den Export der Kontaktdaten hatte ich angegeben, dass ich nur die drei Attribute displayName, wWWHomepage und mail haben wollte. Mehr war also nicht in der Datei vorhanden, auch nicht die Information über die Objektklasse. Diese muss also in der Eingabedatei manuell oder per Shell Script ergänzt werden. Erst nachdem die Zeile objectClass: contact in beiden Sätzen ergänzt wurde, kann die Datei wie oben angegeben importiert werden. Allerdings fehlen jetzt die Beschreibungen für beide Kontakte, wie die Abbildung unten aus ACTIVE VERZEICHNIS USERS AND COMPUTERS zeigt: Abbildung 16.1: Die importierten Kontakte ohne Beschreibung
Damit habe ich einen guten Grund, als letztes Beispiel in diesem Abschnitt die Veränderung einzelner Attribute bei einem bestehenden Objekt zu erläutern. Ändern von Attributen Dies ist der letzte changetype in einer LDIF-Datei: modify. Damit können einzelne Attributwerte geändert werden. Auch hier sollten Sie sich genau an das vorgeschriebene LDIF-Format halten, sonst ist das einzige Ergebnis des Aufrufs von ldifde eine Fehlermeldung. Die allgemeine Form der Änderung eines Attributes sieht wie folgt aus: dn: changetype: modify replace: : 39 Was nur wieder zeigt, dass fünf Minuten langes Nachdenken locker zwei Stunden Tippen ersetzen kann …
209
16 Shell Script-Beispiele
Beachten Sie die Leerzeile nach dem Minuszeichen! Um also die beiden Beschreibungen für die Kontakte zu ändern, wird folgende Eingabedatei benötigt: Listing 16.14: Die Eingabedatei für neue Beschreibungen
dn: CN=Norman Kerth,OU=Produktion,DC=shellbook,DC=com changetype: modify replace: description description: Norm Kerth, Project Post Mortems dn: CN=Julius Caesar,OU=Produktion,DC=shellbook,DC=com changetype: modify replace: description description: Julius, der mit dem Lorbeerkranz -
Nun kann ldifde im Importmodus aufgerufen werden: C:\tmp>ldifde -i -f eingabe.dat Connecting to "bytebag.shellbook.com" Logging in as current user using SSPI Importing Verzeichnis from file "eingabe.dat" Loading entries... 2 entries modified successfully. The command has completed successfully C:\tmp>
Der nachfolgende Screenshot zeigt die geänderten Daten in ACTIVE DIRECTORY USERS AND COMPUTERS: Abbildung 16.2: Die geänderten Beschreibungen im ActiveDirectory
Hinweise Auch für ldifde gelten die unter Abschnitt 16.4.1 bei csvde zum Thema LDAP-Filter gemachten Anmerkungen.
210
ActiveDirectory
16.4.5
Benutzer-Account (de)aktivieren
Dieses Script ist wieder ein Goodie für alle Administratoren, die noch Windows 2000-Systeme betreuen, aber auch eine schöne Demonstration, wie viel Komfort die neuen Kommandos der Shell unter Windows 2003 bringen. Nachdem ich das Script vorgestellt habe, verrate ich Ihnen weiter unten, was Sie unter Windows 2003 für das gleiche Ergebnis tun müssen. Parameter 왘 %1 = der Text „enable“ oder „disable“ 왘 %2 = ADSI-Pfad zum Benutzerobjekt
Code @echo off if /i !%1 == !enable goto enable if /i !%1 == !disable goto disable echo Unbekanntes Kommando "%1", Abbruch. exit /b
Listing 16.15: Benutzerkonten deaktivieren nur mit ldifde
:enable set mask= ^& 0x8FFFFFD goto getdata :disable set mask= ^| 0x2 goto getdata :notfound echo Could not find object "%2" in AD, exiting. goto :eof :getdata ldifde -f output.ldf -d %2 -r "(objectClass=user)" -l userAccountControl > log.txt type log.txt | find /i "no entries found" > nul if not %errorlevel% == 1 goto notfound :cont for /F "tokens=1,2" %%f in (output.ldf) do if /i !%%f == !userAccountControl: set value=%%g set /A value="%value% %mask%" echo Changing userAccountControl to: %value% :: now build new ldif file type output.ldf | find /i "dn:" > input.ldf echo changetype: modify>> input.ldf echo replace: userAccountControl>> input.ldf
211
16 Shell Script-Beispiele echo userAccountControl: %value%>> input.ldf echo ->> input.ldf ldifde -i -f input.ldf
Funktion Aufgerufen wird das Script beispielsweise so: account.bat disable "CN=Franz Testhuber,cn=users,dc=shellbook,dc=com"
Windows 2003 Und hier die versprochene Kommandozeile für Windows 2003: :: aktivieren eines kontos: dsmod user "cn=User,ou=ouname,dc=domain,dc=com" disabled no :: deaktivieren eines kontos dsmod user "cn=User,ou=ouname,dc=domain,dc=com" disabled yes
Wie Sie sehen, ist die Shell mittlerweile durchaus brauchbar, und Sie müssen nicht für jede Kleinigkeit WSH-Programmierung lernen (wenn Sie etwas Zeit haben, sollten Sie dies natürlich trotzdem tun, um Ihr Wissen zu erweitern). Damit habe ich auch gleich elegant den Übergang zu den neuen ds*Kommandos von Windows 2003 geschafft, welche die Verwaltung des AD wesentlich erleichtern.
16.4.6
dsquery
Grundlagen dsquery ist sozusagen ein Vorsatzadapter zu den restlichen Kommandos. Diese erwarten nämlich immer einen DN, mit dem ein Objekt eindeutig identifiziert wird. Wenn Sie dieses Attribut nicht wissen (weil Sie beispielsweise alle Accounts deaktivieren möchten, die länger als vier Wochen nicht angemeldet waren), dann hilft Ihnen dsquery weiter. Als Ergebnis der Suche wird jeweils der DN auf die Standardausgabe ausgegeben und kann so direkt per Pipelining an dsmod und die anderen Kommandos übergeben werden.
Damit Sie nicht alle LDAP-Queries selbst erstellen müssen, existiert eine ganze Reihe von Unterkommandos für vorbereitete Suchen: Tabelle 16.4: dsquerySubkommandos
212
Kommando
Bedeutung
dsquery computer
Sucht nach Computerkonten
ActiveDirectory
Kommando
Bedeutung
dsquery contact
Sucht nach Kontakten
dsquery subnet
Sucht nach Subnets
dsquery group
Sucht nach Gruppen
dsquery ou
Sucht nach Organisationseinheiten
dsquery site
Sucht nach Sites
dsquery server
Sucht nach Domain-Controllern
dsquery user
Sucht nach Benutzerkonten
dsquery quota
Sucht nach Quoteninformationen
dsquery partition
Such nach Verzeichnispartitionen
dsquery *
Erlaubt die freie Definition beliebiger LDAPAnfragen
Beispiele Bleiben wir bei unseren Kontakten aus den Beispielen mit csvde und ldifde: Auch hier sollen wieder alle Kontakte aus der OU „produktion“ gesucht werden. Im einfachsten Fall geben Sie folgendes Kommando ein: dsquery contact
Als Ergebnis erhalten Sie folgende Ausgabe (auf meiner Maschine): "CN=Norman Kerth,OU=Produktion,DC=shellbook,DC=com" "CN=Julius Caesar,OU=Produktion,DC=shellbook,DC=com"
Wird nämlich keine Definition des Startpunkts der Suche getroffen, dann gilt Folgendes: Root der Domain und der gesamte Baum abwärts. Dies zeigt sich besonders deutlich beim Subkommando für die Benutzer: C:\tmp>dsquery user "CN=Administrator,CN=Users,DC=shellbook,DC=com" "CN=Guest,CN=Users,DC=shellbook,DC=com" "CN=SUPPORT_388945a0,CN=Users,DC=shellbook,DC=com" "CN=krbtgt,CN=Users,DC=shellbook,DC=com" "CN=Franz Testhuber,OU=Produktion,DC=shellbook,DC=com" "CN=Student37,OU=Kurs,DC=shellbook,DC=com" "CN=Student38,OU=Kurs,DC=shellbook,DC=com" C:\tmp>
Es werden die DNs aller Benutzer aus der gesamten Domain ausgegeben. Soll dies nicht der Fall sein, kann ein Startknoten angegeben werden: dsquery user "ou=produktion,dc=shellbook,dc=com"
213
16 Shell Script-Beispiele
Alternativ ist die Angabe der konstanten Werte forestroot oder domainroot möglich. Ein weiteres Beispiel zeigt, wie leicht unter Windows 2003 Abfragen des AD über die Kommandozeile fallen: Aufgelistet werden sollen die DNs aller Gruppen, in deren Namen die Zeichenfolge „domain“ vorkommt. dsquery group -name *domain*
Optionen Für jedes Subkommando ist eine Reihe von Optionen möglich, die zum Großteil über alle Subkommandos hin konsistent sind. Sie können sich die Liste der Optionen mit dem Kommando dsquery <subcmd> /? ausgeben lassen. Die wichtigsten gemeinsamen Optionen listet die folgende Tabelle auf. Einzelne Subkommandos definieren weitere Optionen, wie beispielsweise die Option -inactive <wochen> für die Subkommandos user und computer.
214
Option
Bedeutung
-scope <scopewert>
Legt die Suchtiefe fest. Mögliche Werte sind subtree, onelevel oder base.
-u <user>
Verwendet den Benutzernamen zur Anmeldung am AD
-p <password>
Verwendet das Passwort zur Anmeldung am AD
-q
Unterdrückt alle Ausgaben außer den Ergebnissen
-r
Verfolgt Verweise (referrals) im AD. Ist per Default nicht aktiv
-gc
Sucht im Global Catalog
-limit
Wichtig! Legt fest, wie viele Objekte ausgegeben werden, auf die die Suchbedingungen passen. Ist dieser Wert 0, werden alle Objekt ausgegeben. Wird diese Option nicht angegeben, dann werden nur die ersten 100 Objekte ausgegeben!
-uc[i|o]
Gibt an, dass Ein- oder Ausgaben bei Pipes im Unicode-Format vorliegen
-s <server>
Verwendet den angegebenen DC
-d <domain>
Verwendet die angegebene Domain
ActiveDirectory
Freie LDAP-Suchen Etwas mehr Erläuterung benötigt das Subkommando *, mit dem Sie in der Lage sind, beliebige Suchen im AD durchzuführen. Hier existieren zusätzliche Optionen: -filter, -attr und -l. Die Option -filter legt (wie bei csvde und ldifde) einen LDAP-Suchfilter fest, während -attr eine Liste der auszugebenden Attribute (oder * für alle) festlegt. Damit alles schön neu und damit anders bleibt, wird hier die Liste der Attribute nicht durch Kommata, sondern durch Leerzeichen getrennt40! Die Option -l schließlich schaltet vom Tabellenformat für die Ausgabe in ein Listenformat (ähnlich dem LDIF-Format) um. Damit dies alles klarer wird, auch hier wieder einige Beispiele. Als Erstes die übliche Suche nach den Kontakten, diesmal über die ganze Domain: dsquery * -filter "(objectClass=contact)"
Jetzt alle Benutzer, deren Nachname mit einem Buchstaben von L-Z beginnt: dsquery * -filter "(&(objectCategory=person)(sn>=L*))"
Eine Zeile
Als Letztes möchte ich eine Datumssuche vorstellen. Angenommen, Sie kommen frisch erholt und tatendurstig aus dem Urlaub und möchten wissen, welche Gruppen nach dem 01.06.2004 (dem ersten Tag Ihres Urlaubs) im Container „users“ erstellt wurden. Ersetzen Sie im folgenden Kommando den Domain-Namen durch den Namen Ihrer Domain. dsquery * "cn=Users,dc=shellbook,dc=com" -filter "(&(objectClass=group)(whenCreated>=20040601000000.0Z ))"
16.4.7
Eine Zeile
dsmod
dsmod erlaubt die Modifikation einzelner Attribute für bestehende Objekte im AD.
Die folgenden Optionen gelten für alle unten aufgeführten Subkommandos:
40 Falls Sie (wie bei csvde und ldifde) Kommata verwenden, erhalten Sie einfach eine leere Ausgabe, da dann als Attributname der gesamte String verwendet wird.
215
16 Shell Script-Beispiele
Option
Bedeutung
-s <server>
Verbindet mit dem DC <server>
-d <domain>
Verwendet einen DC aus der angegebenen Domain
-u <user>
Verwendet den angegebenen Benutzernamen
-p <password>
Verwendet das angegebene Passwort
-c
Continous Mode; fährt bei Fehlern mit der Abarbeitung fort, sonst wird beim ersten Fehler abgebrochen.
-q
Quiet mode; unterdrückt alle Ausgaben nach StdOut
-uc[i|o]
Legt fest, dass der Eingabekanal (uci) bzw. der Ausgabekanal (uco) oder beide (uc) Daten im UnicodeFormat liefern.
dsmod computer Folgende Attribute können für einen Computer modifiziert werden: -desc
-loc
-disabled {yes | no}
-reset
Beispiel: Eine Zeile
dsmod computer "cn=QAControl,ou=produktion, dc=shellbook,dc=com" -disabled yes
Dieses Kommando deaktiviert den Account für den Computer mit dem Hostnamen QAControl. dsmod contact Für das Verändern eines Kontaktobjektes stehen folgende Attribute zur Verfügung: -fn
-mi
-ln
-display
-desc
-office
-tel
-email <Email>
-hometel
-pager <Pager#>
-mobile
-fax
-iptel
-title <Title>
-dept
-company
216
ActiveDirectory
dsmod group Dient der Verwaltung von Gruppen und bietet die folgenden Optionen: -samid <SAMName>
-desc
-secgrp {yes | no}
-addmbr
-rmmbr
-chmbr
-scope {l | g | u}
(für -scope: l = local, g = global, u = universal)
Bei den Optionen -addmbr, -rmmbr und -chmbr kann jeweils nur eine angegeben werden. Als Liste kann für diese drei Optionen eine Reihe von DNs (mindestens einer) angegeben werden, die durch Leerzeichen getrennt werden. Die Option -chmbr ersetzt die Liste der Gruppenmitglieder komplett durch die angegebene Liste. Auch dsmod group erlaubt das Piping mit Hilfe von dsquery, allerdings gibt es hier eine Besonderheit. Falls sowohl der DN der Gruppe als auch eine der drei Optionen zur Mitgliederverwaltung verwendet werden, kann nur ein Element über die Standardeingabe gelesen werden. Mindestens ein Element (der Gruppen-DN oder die ) müssen dann in der Kommandozeile angegeben werden. Auch hierzu wieder ein Beispiel: dsmod group "cn=Kaffeetrinker,dc=shellbook,dc=com" -addmbr "cn=Franz Testhuber,cn=users, dc=shellbook,dc=com"
Eine Zeile
Dies fügt den Benutzer „Franz Testhuber“ als Mitglied zur Gruppe „Kaffeetrinker“ hinzu. Gleich noch ein Beispiel: dsquery user ou=Marketing,dc=shellbook,dc=com | dsmod group "cn=Marketing List,cn=Users, dc=shellbook,dc=com" -addmbr
Eine Zeile
Dieses Kommando sucht nach allen Benutzern in der OU „Marketing“ und fügt alle gefundenen DNs als Mitglieder der Gruppe „Maketing List“ hinzu. Da bei dsmod group der Gruppen-DN angegeben wurde, kann die Option -addmbr die Daten aus der Standardeingabe und damit von dsquery lesen. dsmod ou Neben den allgemeinen Optionen von dsmod (siehe Seite 215) existiert hier nur eine Option, mit der die Beschreibung geändert werden kann, nämlich die Option -desc .
217
16 Shell Script-Beispiele
dsmod server Hiermit werden die Domain-Controller verwaltet. Warum das Subkommando dann server und nicht dc heißt, konnte ich nicht herausfinden. Auch die Verwaltung der Domain-Controller kennt nur zwei Optionen: -desc
Setzt die Beschreibung des Servers
-isgc {yes | no}
Legt fest, ob dieser Server ein Global Catalog Server ist oder nicht
dsmod user Folgende Attribute können mit Hilfe von dsadd user gesetzt werden: -samid <SAMName>
-upn
-fn
-mi
-ln
-display
-empid <EmployeeID>
-pwd {<Password> | *}
-desc
-memberof
-office
-tel
-email <Email>
-hometel
-pager <Pager#>
-mobile
-fax
-iptel
-webpg <WebPage>
-title <Title>
-dept
-company
-mgr <Manager>
-hmdir
-hmdrv
-profile
-loscr <ScriptPath>
-mustchpwd {yes | no}
-canchpwd {yes | no}
-reversiblepwd {yes | no }
-pwdneverexpires {yes | no }
-acctexpires
-disabled {yes | no}
16.4.8
dsget
Liest einzelne Attribute für Objekte aus dem AD aus. Auch hier erfolgt wieder eine Unterteilung in die einzelnen Hauptklassen. Falls Sie Attribute für ein Objekt aus einer Klasse ausgeben wollen, die nicht in der Liste der Unterkommandos enthalten ist, müssen Sie dsquery * verwenden. Ebenso müssen Sie dsquery * verwenden, wenn Sie Attribute auslesen wollen, die nicht für die einzelnen Subkommandos vordefiniert sind. Folgende Subkommandos werden erkannt:
218
ActiveDirectory
computer
Computerattribute
contact
Kontaktattribute
subnet
Subnet-Attribute
group
Gruppenattribute
ou
OU-Attribute
server
Attribute von Domain-Controllern
site
Site-Attribute
user
Benutzerattribute
quota
Attribute von AD-Quoteneinträgen
partition
Partitionsattribute
Tabelle 16.5: Subkommandos (Klassen) für dsget
Mit Hilfe des Subkommandos und der Option /? können Sie auch hier wieder die komplette Liste aller möglichen Optionen ausgeben lassen. Auch dsget kennt den Satz von Standardoptionen für alle Subkommandos, wie in der nachfolgenden Tabelle aufgeführt. Zusätzlich existiert noch die Option -L (wie bei dsquery), mit der die Ausgabe statt in tabellarischer Form in Form einer Liste ausgegeben werden kann. Option
Bedeutung
-s <server>
Verbindet mit dem DC <server>
-d <domain>
Verwendet einen DC aus der angegebenen Domain
-u <user>
Verwendet den angegebenen Benutzernamen
-p <password>
Verwendet das angegebene Passwort
-q
Quiet mode; unterdrückt alle Ausgaben nach
Tabelle 16.6: Gemeinsame Optionen für dsget
StdOut -uc[i|o]
Legt fest, dass der Eingabekanal (uci) bzw. der Ausgabekanal (uco) oder beide (uc) Daten im UnicodeFormat liefern.
Um beispielsweise die Telefonnummer von „Franz Testhuber“ zu finden, kann ich folgendes Kommando verwenden (der Account liegt im Container „users“): dsget user "cn=Franz Testhuber,cn=users, dc=shellbook,dc=com" -tel
eine Zeile
Die Ausgabe ist kurz und prägnant: tel 123456 dsget succeeded
219
16 Shell Script-Beispiele
Um alle Mitglieder der Gruppe „Quality Control“ auszugeben, genügt folgendes Kommando: Eine Zeile
dsget group "cn=Quality Control,cn=users, dc=shellbook,dc=com" -members
Der hauptsächliche Vorteil von dsget liegt für viele Benutzer darin, dass sie die Liste der auszugebenden Attribute einfach über eine Option bestimmen können. Sie müssen nicht wie bei dsquery erst den Schemanamen des Attributes nachschlagen und in der Liste angeben. Im Gegenzug bietet dsquery dafür die komplexeren Möglichkeiten der Auswahl von Objekten und Attributen. Wenn Sie beispielsweise Daten über eine im ActiveDirectory veröffentlichte Instanz des SQL-Servers herausfinden möchten, bleibt nur dsquery, da dsget für diese Klasse kein Subkommando anbietet.
16.4.9
dsmove
Dies ist eine Möglichkeit, Objekte im AD schnell und einfach zu verschieben. Die meiste Arbeit macht das Eintippen der DNs. dsmove [-newparent <ParentDN>] [-newname ] [{-s <Server> | -d }] [-u <User>] [-p {<Password> | *}] [-q] [{-uc | -uco | -uci}] Tabelle 16.7: Optionen für dsmove
Option
Bedeutung
Der Distinguished Name des zu verschiebenden Objektes. Wird dieser nicht angegeben, wird der DN aus der Standardeingabe gelesen
-newparent
Distinguished Name des neuen ParentContainers
-newname
Evtl. neuer RDN des Objekts (move & rename)
-s <server>
Verbindet mit dem DC <server>
-d <domain>
Verwendet einen DC aus der angegebenen Domain
-u <user>
Verwendet den angegebenen Benutzernamen
-p <password>
Verwendet das angegebene Passwort
-q
Quiet mode; unterdrückt alle Ausgaben nach StdOut
-uc[i|o]
220
Legt fest, dass der Eingabekanal (uci) bzw. der Ausgabekanal (uco) oder beide (uc) Daten im Unicode-Format liefern.
ActiveDirectory
Hier funktioniert die Umleitung der Standardeingabe nur eingeschränkt, da immer nur ein Objekt verschoben werden kann41. Sehen wir uns dazu das Beispiel mit den leidlich bekannten Kontakten an: dsquery contact "ou=Produktion,dc=shellbook,dc=com" | dsmove -newparent "ou=Kurs, dc=shellbook,dc=com"
Eine Zeile
Als Ergebnis bekomme ich nur eine Fehlermeldung: dsmove failed: 'cn=student38,ou=produktion, dc=shellbook,dc=com' is an unknown parameter.
Sobald dsquery nur einen Wert liefert, funktioniert alles prima. Dann allerdings können Sie den DN genauso gut direkt angeben wie im nächsten Beispiel. dsmove "cn=student37,ou=kurs,DC=shellbook,DC=com" -newparent "ou=Produktion,DC=shellbook,DC=com"
Eine Zeile
16.4.10 dsadd Das Kommando dsadd erlaubt das Anlegen neuer Objekte im AD. Es können nicht alle möglichen Attribute gesetzt werden, aber für jedes Unterkommando existieren Optionen, um sicher mehr als 90% aller auftretenden Fälle abzudecken. Folgende Unterkommandos werden erkannt: computer
Fügt einen Computer hinzu
contact
Fügt einen Kontakt hinzu
group
Fügt eine Gruppe hinzu
ou
Fügt eine OU hinzu
user
Fügt einen Benutzer hinzu
quota
Fügt einen Quoteneintrag hinzu
Tabelle 16.8: Subkommandos für dsadd
Die allgemeine Form lautet also: dsadd <subcmd> .
Die Optionen unterscheiden sich von Subkommando zu Subkommando und können mit dem Befehl dsadd <subcmd> /? ausgelesen werden. dsadd computer "CN=QAControl,OU=Produktion,DC=shellbook,DC=com" -desc "Qualitaetskontrolle Stanze 34" -loc "Werk 1, Halle 12"
Eine Zeile
41 Falls das jemand bei Microsoft liest: Warum? Wieso kann ich nicht alle User aus einer OU in eine neue OU mit gleichem RDN verschieben? Ich mag die Shell ja auch, aber auch ich tippe ungern zu viel …
221
16 Shell Script-Beispiele
Dieses Kommando fügt ein neues Computerkonto für den Computer mit dem Namen QAControl in der OU Produktion hinzu und setzt zwei Eigenschaften für die Beschreibung und den Standort. Das Anlegen eines Benutzers folgt dem gleichen Schema. Allerdings existieren hier wesentlich mehr Optionen, um einzelne Attribute des Benutzers gleichzusetzen. Ab einer bestimmten Anzahl von Attributen, die gesetzt werden sollen, ist es allerdings eine Überlegung wert, ob nicht die beiden Kommandos csvde und ldifde sinnvoller wären. Hier eine Liste der für einen Benutzer setzbaren Attribute, die genau wie die Attribute für die restlichen Subkommandos denen von dsadd entsprechen: Tabelle 16.9: Mögliche Optionen für das Erzeugen von Benutzern
-samid <SAMName>
-upn
-fn
-mi
-ln
-display
-empid <EmployeeID>
-pwd {<Password> | *}
-desc
-memberof
-office
-tel
-email <Email>
-hometel
-pager <Pager#>
-mobile
-fax
-iptel
-webpg <WebPage>
-title <Title>
-dept
-company
-mgr <Manager>
-hmdir
-hmdrv
-profile
-loscr <ScriptPath>
-mustchpwd {yes | no}
-canchpwd {yes | no}
-reversiblepwd {yes | no }
-pwdneverexpires {yes | no }
-acctexpires
-disabled {yes | no}
Hier ein Beispiel für das Anlegen eines Benutzerkontos: Eine Zeile
dsadd user "cn=Gabi Bauer,ou=Produktion, dc=shellbook,dc=com" -samid GabiB -desc "Leitung QA-Labor" -email
[email protected] -disabled yes
Dies legt die Benutzerin Gabi Bauer mit dem SAMAccountName GabiB an, setzt einige Attribute und deaktiviert den Account.
16.4.11 dsrm Die Syntax ähnelt ein wenig den anderen AD-Kommandos:
222
ActiveDirectory dsrm [-noprompt] [-subtree [-exclude]] [-s <Server> | -d ] [-u <User>] [-p <Password> | *] [-c] [-q] [{-uc | -uco | -uci}]
Option
Bedeutung
Der Distinguished Name des zu löschenden Objektes
-noprompt
Keine Rückfrage bei Löschoperationen. Verwenden Sie diese Option mit Vorsicht!
-subtree
Löscht das Objekt und alle Unterobjekte
-subtree -exclude
Löscht alle Unterobjekte des Objekts, das Objekt selbst aber nicht
-s <server>
Verbindet mit dem DC <server>
-d <domain>
Verwendet einen DC aus der angegebenen Domain
-u <user>
Verwendet den angegebenen Benutzernamen
-p <password>
Verwendet das angegebene Passwort
-c
Continous mode; gibt zwar Fehlermeldungen aus, fährt aber mit der Abarbeitung der DN-Liste fort. Ohne diese Option bricht das Kommando beim ersten Fehler ab.
-q
Quiet mode; unterdrückt alle Ausgaben nach StdOut
-uc[i|o]
Legt fest, dass der Eingabekanal (uci) bzw. der Ausgabekanal (uco) oder beide (uc) Daten im UnicodeFormat liefern.
Tabelle 16.10: Die Optionen von dsrm
Im Gegensatz zu Kommandos wie dsmod kann dsrm nicht einfach so per Pipelining mit den entsprechenden DNs gefüttert werden. Nur wenn die Option -noprompt angegeben war, konnte ich dsrm dazu bringen, wie gewünscht zu funktionieren. dsquery contact | dsrm -noprompt -c
Dieses Kommando löscht (ohne Rückfrage!) alle Kontakte aus dem Verzeichnis der aktuellen Domain. Vorsicht also beim Nachmachen! dsrm -subtree -noprompt -c ou=Marketing,dc=microsoft,dc=com
Eine Zeile
Dieses Kommando beseitigt die Marketingabteilung von Microsoft; nur als OU und nur in deren ActiveDirectory natürlich … – die OU selbst wird dabei auch gelöscht, da die Option -subtree ohne exclude angegeben wurde.
223
16 Shell Script-Beispiele
16.4.12 Passwörter per ldifde ändern Dieser Absatz ist nur Admins interessant, die noch Windows 2000Systeme verwalten, ab Windows 2003 sollten Sie für diese Aufgabe das Kommando dsmod.exe mit der Option -pwd benutzen. Die Windows 2000-Admins sollten sich von der nachfolgenden Liste nicht abschrecken lassen. Es funktioniert, und unter Windows 2000 ist dies auf Shell-Ebene der einzige Weg, ein Passwort neu zu setzen. Falls jetzt jemand auf die Idee kommt, dass an dieser Stelle der Einsatz des WSH und ADSI vorzuziehen ist, hat er meinen Segen; ich gestehe, ich mache so etwas auch per Script Host … Damit Passwörter mit ldifde überhaupt geändert werden können, muss zwischen Client und DC eine Kommunikation per SSL über LDAP möglich sein. Dafür wird per Default der Port 636 benutzt, beide Maschinen unter Windows 2000 müssen dafür das High Encryption Pack installiert haben, da sonst keine 128-Bit-SSL-Kommunikation über LDAP möglich ist. Information über das Vorgehen finden Sie in der Knowledge Base von Microsoft unter dem Artikel Q247078. Der Name des entsprechenden Attributes lautet unicodePwd. Dieses Attribut kann nur entweder durch einen Admin oder einen Benutzer ersetzt werden, der für den Zielbenutzer das Passwort neu setzen darf. Der Inhalt dieses Attributes kann nicht gelesen oder bei der Erzeugung eines Objektes (z.B. per csvde) hinzugefügt werden. Der neue Inhalt des Passwortes muss im Unicode-Format in Anführungszeichen als Base-64-kodierter Wert (nach RFC1521) angegeben werden. Da für viele das Hauptproblem darin bestehen dürfte, einen String in den entsprechend kodierten Wert umzuwandeln, hier ein Weblink: Guillaume Bordier hat (neben einer ganzen Reihe freier Admin-Tools) auch einen Konverter für Strings und Dateien geschrieben, der genau das leistet. Seine Homepage war zur Zeit der Erstellung dieses Buches unter dem URL http://www.gbordier.com zu erreichen. Anschließend kann der konvertierte Wert in eine LDIF-Datei übernommen werden: dn: CN=Norman Kerth,OU=Produktion,DC=shellbook,DC=com changetype: modify replace: unicodePwd unicodePwd::iGAzWZCKidjJWHFKWwk= -
Nun muss ldifde noch mit dem korrekten Port aufgerufen werden: ldifde -i -f pwdneu.dat -t 636 -s dcname
Eine weitere Anleitung finden Sie in der Knowledge Base unter der Artikelnummer Q263991.
224
ActiveDirectory
16.4.13 Gruppenmitglieder auflisten Dieses Kommando gibt die Mitglieder einer Gruppe aus. Sie werden nun einwenden, dass es dafür doch seit Windows 2003 das Kommando dsget group gibt. Stimmt, aber in diesem Beispiel (bzw. für das damalige Problem) waren wir nur an den Benutzernamen (samAccountName) interessiert, und das ist auch mit dsget nicht unbedingt sehr viel kürzer, wie unten gezeigt wird. Da sich an diesem Beispiel einige Dinge gut zwischen Windows 2000 und Windows 2003 bzw. der Shell und dem WSH vergleichen lassen, fällt dieser Abschnitt etwas länger aus. Parameter Keine, da interaktives Kommando. Code (for /F "usebackq tokens=*" %f in (`net group training /domain ^| find /i /v "erfolgreich" ^| more +6`) do @for %x in (%f) do @if %x GTR "A" echo %x)
Eine Zeile
Funktion Dieses Kommando besteht logisch gesehen aus drei Teilen: einer äußeren for-Schleife, dem als Listenelement per Backquoting auszuführenden Kommando und der zweiten for-Schleife. Zuerst möchte ich das Kommando im Listenteil der ersten Schleife erläutern. `net group training /domain ^| find /i /v "erfolgreich" ^| more +6`
Das besondere Escape-Zeichen "^" wird nur benötigt, da wir dieses Kommando mit Hilfe des Backquotings in einer for-Schleife ausführen und die Piping-Symbole nicht sofort angewendet werden sollen. Genauso müssten Sie übrigens auch einen Gruppennamen mit Leerzeichen in gequotete Anführungszeichen einschließen (z.B. ^"Gruppe 42^"). Lassen wir dieses Zeichen also weg und sehen uns das Kommando noch einmal an net group training /domain | find /i /v "erfolgreich" | more +6
So sieht das schon etwas verständlicher aus. Mit Hilfe des Kommandos net group wird eine Liste der Mitglieder der Domain ausgegeben. Leider werden nicht nur die SAM-Namen der Mitglieder ausgegeben, sondern auch noch eine schöne Titelzeile mit einer Unterstreichung. Zum Ende erfolgt auch noch ein Hinweis, dass das Kommando erfolgreich beendet wurde42. 42 Auch daran sieht man, dass der Windows-Shell ein einheitliches Ausgabedesign fehlt. Beim erfolgreichen Löschen von Dateien per del erfolgt keinerlei Rückmeldung, aber eine simple Ausgabe wird kommentiert.
225
16 Shell Script-Beispiele C:\tmp>net group "Quality Control" /domain Gruppenname Quality Control Beschreibung Mitglieder -------------------------------------------------------FranzT GabiB student37 student38 Das Kommando wurde erfolgreich beendet.
Da wir nur an den reinen Daten interessiert sind, erfolgt die Bearbeitung mit find und more. Ob der Kopf der Ausgabe auch bei Ihrer Sprachversion sechs Zeilen lang ist, sollten Sie vorher testen. Danach bleiben nur noch die Zeilen mit jeweils drei Namen pro Zeile übrig. FranzT student37 student38
GabiB
Das passiert also bei der Abarbeitung der äußeren Schleife. Diese Zeilen werden zeilenweise an die zweite for-Schleife übergeben. Damit wird aus den drei Namen pro Zeile drei einzelne Zeilen mit je einem Namen. Falls Sie diese Spaltentransformation noch einmal nachlesen möchten, finden Sie diese bei for im Abschnitt 9.2.1. Die Abfrage auf „Größer als A“ dient nur dazu, die Leerzeilen aus der Ausgabe zu bekommen. Alternativ könnten Sie diese später per findstr entfernen. Windows 2003 Falls Sie nun denken, dass dies bei Windows 2003 sehr viel einfacher ist, werden Sie gleich feststellen, dass trotz aller neuen Kommandos die eine oder andere Ausgabe auch hier noch etwas Tipparbeit erfordert (wenn auch weniger als bei Windows 2000). Zuerst die Liste der Gruppenmitglieder: Diese wird per dsget group erzeugt. Dazu muss allerdings der DN der Gruppe angegeben werden. dsget group "cn=Quality Control,cn=users,dc=shellbook,dc=com" -members
Die Ausgabe liefert dann eine Liste mit jeweils einem DN pro Zeile: "CN=Gabi Bauer,OU=Produktion,DC=shellbook,DC=com" "CN=student38,OU=Produktion,DC=shellbook,DC=com" "CN=student37,OU=Produktion,DC=shellbook,DC=com" "CN=Franz Testhuber,CN=Users,DC=shellbook,DC=com"
Diese Daten lassen sich nun per Piping an ein dsget user übergeben, um den samAccountName zu erhalten: Eine Zeile
226
dsget group "cn=Quality Control,cn=users,dc=shellbook,dc=com" -members | dsget user -samid
ActiveDirectory
Auch hier ist die Ausgabe mit allerlei Dekoration verziert, wie der folgende Ausgabemitschnitt zeigt: samid GabiB student38 student37 FranzT dsget succeeded
Sowohl die Überschrift „samid“ als auch die Erfolgsmeldung am Ende der Ausgabe müssen entfernt werden, was zwei find-Aufrufe erledigen. Hier das komplette Kommando: dsget group "cn=Quality Control,cn=users, dc=shellbook,dc=com" -members | dsget user -samid | find /v "samid" | find /v "succeeded"
Eine Zeile
Wie ich Ihnen versprochen habe, ist das nicht unbedingt sehr viel kürzer als der vor Windows 2003 nötige Ansatz, wenngleich auch etwas logischer in seinem Ablauf. WSH Ich möchte diese Diskussion mit einem Verweis auf das Thema WSH abschließen, da eine solche Aufgabenstellung den Bereich berührt (ADSI-Management), bei dem der WSH auch nicht viel mehr Tipparbeit verursacht (obwohl Sie immer noch VBScript und die Grundlagen von COM und ADSI lernen müssen). Hier finden Sie die kürzeste Fassung eines Scripts für den WSH in VBSript, die ebenfalls die samAccountName-Liste der Gruppenmitglieder liefert. set grp = GetObject("LDAP://cn=Quality Control,cn=users,dc=shellbook,dc=com") for each mbr in grp.Members if LCase(mbr.Class) = "user" then WScript.Echo mbr.samAccountName end if next
Ich rate allerdings davon ab, das Script in dieser Form produktiv zu nutzen. Dies soll nur demonstrieren, wie viel Minimalaufwand Sie in etwa mit dem WSH treiben müssen. Wie mir alle WSH-Kenner zustimmen werden, ist erstens das vbs-Format veraltet, und es sollte stattdessen das flexiblere XML-Format der .wsh-Dateien benutzt werden. Zweitens ist im obigen Script keine explizite Variablendeklaration vorgesehen, und der Name der Gruppe ist nicht als Parameter auf der Kommandozeile zu übergeben, es gibt keine Fehlerprüfung und so weiter. Sollten Sie aber komplexere AD-Aufgaben haben, ist der WSH für so etwas erste Wahl und kann auch problemlos in Ihre Shell Scripts integriert werden. Mehr Informationen finden Sie in den im Anhang aufgeführten Büchern von Holger Schwichtenberg.
227
16 Shell Script-Beispiele
16.5 Netzwerk 16.5.1
Netzwerkadresse berechnen
Dieses Script ist aus reiner Faulheit entstanden. Ich benötigte für eine IP-Adresse im Dialogfeld der TCP/IP-Eigenschaften schnell den Netzwerkanteil. Leider finden sich im Dialogfeld nur die IP-Adresse und die Subnet-Maske. Dieses Script nimmt Ihnen in Zukunft die Rechnerei ab und ist gleichzeitig ein gutes Beispiel für den sinnvollen Einsatz von set /a. Parameter 왘 %1 = Ip-Adresse in dez. Punktnotation 왘 %2 = Subnetzmaske in dez. Punktnotation
Code Listing 16.16: Berechnung der Netzadresse aus IP und Subnetmask
@echo off if !%1 == ! goto noparm if !%2 == ! goto noparm setlocal :: das for-Kommando ist eine Zeile! for /F "delims=. tokens=1,2,3,4" %%f in ("%1") do for /F "delims=. tokens=1,2,3,4" %%m in ("%2") do call :doByte %%f %%g %%h %%i %%m %%n %%o %%p :: goto :eof :noparm echo Calculate network address from ip and subnet mask echo. echo Usage: %0 [ipaddr] [netmask] echo. echo Either [ipaddr] or [netmask] is missing .... goto :eof :doByte set /A byte="%1 & %5" set net=%byte% set /A byte="%2 & %6" set net=%net%.%byte% set /A byte="%3 & %7" set net=%net%.%byte% set /A byte="%4 & %8" set net=%net%.%byte% echo Network address = %net% endlocal
228
Netzwerk
Funktion Aufruf beispielsweise mit getnetwork.bat72.31.168.10 255.255.240.0
Die Ausgabe Network address = 172.31.160.0 liefert dann die Netzwerkadresse für eine bestimmte IP anhand der Subnetmaske. Die Funktion des Scripts selbst ist eigentlich nur eine einzige Demonstration der Nutzung von set für die Arbeit mit Bitoperatoren. Dazu werden die beiden Parameter anhand des Trennzeichens "." mit zwei for-Schleifen in die einzelnen Bytes aufgeteilt. Diese werden dann ab der Sprungmarke :doByte logisch UND-verknüpft, um die Netzwerkadresse zu erhalten.
16.5.2
GetMAC für NT4 und W2K
Die einfache Variante Geben die das unten stehende Kommando ein. Sie erhalten dann eine Ausgabe mit allen definierten Mac-Adressen. ipconfig /all | find /i "phys"
Das Problem an dieser Ausgabe liegt aber darin, dass Sie nicht feststellen können, welche Mac-Adresse zu welchem Netzwerkadapter gehört. Ist nur ein Adapter vorhanden, ist dies kein Problem und Sie können dieses Kommando verwenden. Ich möchte Ihnen aber nachfolgend gerne eine etwas komfortablerer Version vorstellen, die Sie im Archiv unter dem Namen getmac.bat finden. Parameter Keine Code @echo off echo Liste der Mac-Adressen fuer %computername% echo.
Listing 16.17: Ausgabe der Mac-Adressen ab Windows 2000
set action= for /F "usebackq tokens=*" %%f in (`ipconfig /all`) do call :procline "%%f" goto :eof :procline if "%action%" == "getDesc" goto getDesc if "%action%" == "getMac" goto getMac echo %1 | find /i "Verbindungsspez" > nul if errorlevel 1 goto :eof set action=getDesc
229
16 Shell Script-Beispiele goto :eof :getDesc for /F "delims=: tokens=2" %%f in ("%~1") do set output=%%f set output=%output:~1% set action=getMac goto :eof :getMac for /F "delims=: tokens=2" %%f in ("%~1") do set output=%%f = %output% echo %output% set action= goto :eof
Aufgabenstellung Ab Windows 2003 Server steht das Kommando getmac zur Verfügung, mit dessen Hilfe die Mac-Adresse des lokalen Computers ausgegeben werden kann. Diese Funktionalität soll auch unter Windows 2000 und XP verfügbar sein. Die Mac-Adresse ist durch ipconfig /all bereits seit Windows 2000 verfügbar. Aus der entsprechenden Zeile in der Ausgabe muss nun der Wert extrahiert werden. Danach ist die Ausgabe so zu filtern, dass auch nur Zeilen mit einer Ethernetadresse ausgegeben werden. Sind mehrere Adapter im System verfügbar, soll die Mac-Adresse für alle Adapter ausgegeben werden. Funktion Mit Hilfe einer for-Schleife wird die Ausgabe von ipconfig /all Zeile für Zeile bearbeitet. Jetzt müssen wir feststellen, wo die Ausgabe eines Adapter beginnt. Dies ist mit der Ausgabe eines eventuell definierten verbindungsspezifischen DNS-Suffix der Fall. Für ein deutsches Windows finden Sie den Suchbegriff im fettgedruckten Wort im Listing. Für den Einsatz mit einem englischen Windows müssen Sie dieses Wort durch die entsprechende englische Ausgabe (connection-specific DNS suffix) ersetzen. Der ganze Trick besteht nun darin, sich irgendwie zu merken, dass nach der Zeile mit dem Suffix zuerst eine Zeile mit der Beschreibung des Adapters folgt. Die Zeile nach der Beschreibung ist dann die Zeile mit der Mac-Adresse. Diese ganze Unterscheidung erfolgt im ersten Block nach der forSchleife, den ich hier nochmals zum leichteren Mitlesen aufführe: :procline if "%action%" == "getDesc" goto getDesc if "%action%" == "getMac" goto getMac echo %1 | find /i "Verbindungsspez" > nul
230
Netzwerk if errorlevel 1 goto :eof set action=getDesc goto :eof
Zuerst wird mit Hilfe der Variablen action gestestet, ob wir bereits auf eine Beschreibung oder auf eine Mac-Adresse warten. Dann erfolgt ein Sprung an die entsprechenden Sprungmarken. Ist dies noch nicht der Fall, wird mit Hilfe von find gestestet, ob in der übergebenen Zeile der Text für den verbindungsspezifischen Suffix vorkommt. Falls nicht, können wir uns weitere Aktionen schenken und beenden den Aufruf. Liefert find dagegen einen Exit-Code von 0, wird die Zeile ausgeführt, die den Inhalt von action auf den Wert „getDesc“ setzt. Beim nächsten Durchlauf wissen wir also, dass es sich um eine Beschreibungszeile handeln muss. Die beiden Codeblöcke nach :getDesc und :getMac sind sehr ähnlich. Die übergebene Zeile mit einer for-Schleife am Doppelpunkt aufgetrennt und das zweite Wort verwendet. In der Variablen output wird der String aus Mac-Adresse und Beschreibung des Adapters zusammengestellt. Nach der Ausgabe beim Block von :getMac wird die Variable action wieder gelöscht, so dass der Zyklus von neuem beginnen kann.
16.5.3
Pingliste
Code Mit dem folgenden Script können Sie feststellen, welche Rechner innerhalb des Subnets gerade online sind. Als Ergebnis erhalten Sie eine Liste mit IP-Adressen. Diese könnten dann von einem anderen Script weiterverarbeitet werden. @echo off setlocal set network=192.168.1 echo Scanning .... if exist %temp%\tmp.dat del %temp%\tmp.dat (for /L %%f in (1,1,254) do @ping -n 1 %network%.%%f | find /i "Antwort") > %temp%\tmp.dat echo == Online sind folgende Rechner == for /F "tokens=3" %%f in (%temp%\tmp.dat) do @call :output %%f endlocal goto :eof
Listing 16.18: Ping-Liste eines Subnets
:output set wert=%1 set wert=%wert:~0,-1% echo %wert%
231
16 Shell Script-Beispiele
Funktion Mit Hilfe einer Zählschleife (for /L) wird der Bereich von 1 bis 254 in Einerschritten durchlaufen. Für jeden Wert wird ein einzelnes Ping (-n 1) ausgeführt. Die Ausgabe der gesamten Schleife (deshalb die runden Klammern) wird per Piping an den find-Filter übergeben, der alle Rechner heraussucht, die geantwortet haben. Bei einem englischen Windows müssen Sie den Text „Antwort“ bei find durch „reply“ ersetzen. Durch die Option /i ist die Schreibweise (groß oder klein) gleichgültig. Das Ergebnis dieser Filterung wird in eine temporäre Datei geschrieben. Diese Datei (%temp%\tmp.dat) wird dann von einer weiteren Schleife Zeile für Zeile gelesen, wobei die Angabe "tokens=3" dafür sorgt, dass nur jeweils das dritte Wort (die IP-Adresse) gelesen wird. Mit jedem gelesenen Wort wird nun das Label :output als Unterroutine angesprungen. Der übergebene Parameter stellt die IP-Adresse dar, die allerdings am Ende noch den Doppelpunkt der ping-Ausgabe trägt. Antwort von 192.168.1.11: Bytes=32 Zeit %temp%\ x.x if exist %temp%\y.y del %temp%\y.y for /F "tokens=3,5" %%f in (%temp%\x.x) do echo %%g %%f >> %temp%\y.y sort < %temp%\y.y > %temp%\x.x set pid=-1 for /F "tokens=1,2" %%f in (%temp%\x.x) do call :procline %%g %%f endlocal if exist %temp%\x.x del %temp%\x.x if exist %temp%\y.y del %temp%\y.y goto :eof :procline if %pid% == %2 goto havePID echo. echo. echo ==== Process ==== tasklist /FI "pid eq %2" /NH /SVC echo. echo Connections: :havePID set pid=%2 echo %1 goto :eof
233
16 Shell Script-Beispiele
Funktion Zuerst benötigen wir eine Liste aller aktiven TCP-Verbindungen. Das erledigt der Aufruf von netstat -p TCP -a -o. Diese Ausgabe wird gefiltert, so dass nur die Zeilen mit der Kennung ESTABLISHED übrig bleiben. Das Ergebnis wird in eine temporäre Datei x.x geschrieben. Diese Liste muss nun umgeschichtet werden, so dass Sie die PID des Prozesses als erste Spalte enthält und danach die Adresse des entfernen Rechners. Dazu wird zuerst eine evtl. noch bestehende Datei y.y gelöscht. Danach wird mit Hilfe einer for-Schleife die Datei umgeformt und in eine zweite Datei y.y geschrieben. Eine Alternative wäre die Ausführung der for-Schleife in einer Subshell und die Umleitung der gesamten Ausgabe per einfachem ">" in die Datei. Dies erspart die Zeile mit dem Löschen der Datei y.y. Dazu müsste die for-Schleife wie folgt modifiziert werden: (for /F "tokens=3,5" %%f in (%temp%\x.x) do echo %%g %%f) > %temp%\y.y
Diese Datei muss noch sortiert werden, damit alle gleichen PIDs untereinander stehen. So kann die Ausgabe für alle Verbindungen zu einem Prozess erfolgen, bis die PID wechselt. Dazu verwenden wir sort. Nach dem Sortieren kann die Ausgabe erzeugt werden. Damit wir wissen, welche PID gerade abgearbeitet wird, wird eine Umgebungsvariable (pid) mit der jeweiligen Prozess-ID belegt. Zu Beginn schreiben wir den Startwert -1 in die Variable. In der nun folgenden for-Schleife wird die sortierte Datei x.x Zeile für Zeile eingelesen. Zuerst wird getestet, ob die in der Zeile verzeichnete PID bereits abgearbeitet wird. Schlägt dieser IF-Vergleich fehl, dann haben wir einen neuen Prozess, und es erfolgt die Ausgabe der Prozessdaten. Dazu werden per tasklist und einem Filter nach Prozess-ID der Name des Prozesses, die PID und die darin laufenden Dienste ausgegeben. Ab der Marke :havePID laufen beide Zweige der vorigen IF-Abfrage wieder zusammen. Hier wird die Adresse der verbundenen Maschine (als Kombination aus Namen und Portnummer) ausgegeben. Sollten Sie eine nummerische Ausgabe der Daten bevorzugen, ergänzen Sie beim Aufruf von netstat die Option -n für numeric output. Nach der Ausgabe erfolgt noch das obligatorische Aufräumen, bei dem die beiden temporären Dateien gelöscht und mit endlocal die Änderungen an der Umgebung wieder rückgängig gemacht werden.
234
Die Tools zum Buch
16.6 Die Tools zum Buch 16.6.1
BinChk
Dieses Kommando dient dem Test von Binärdateien auf eine Signatur an einer bestimmen Position der Datei. Entstanden ist dies bei der Suche nach einer verloren gegangenen Backup-Datei eines SQL-Servers. Das Tool eignet sich aber auch zum Feststellen, ob es sich bei einer Datei mit der Erweiterung .jpg wirklich um ein JPG-Bild handelt, und für andere Tests. Aufgerufen wird das Kommando entweder mit der Option /? für die Ausgabe einer Online-Hilfe oder wie folgt: binchk.exe <signature> [/OFS:#][/I]
Falls der Dateiname Leerzeichen enthält, wird er wie sonst bei Shell auch in doppelte Anführungszeichen eingeschlossen. Die Signatur ist der gesuchte Binärstring in der Datei. Die Option /ofs:# gibt den Offset in der Datei an, an dem nach der Signatur gesucht wird. Wird diese Option weggelassen, wird am Beginn der Datei (Offset 0) gesucht. Damit die Suche nach Texten leichter fällt, kann noch die Option /i angegeben werden. Diese sorgt dafür, dass bei Bytes im Bereich der ASCII-Buchstaben (65–90 und 97–122) keine Unterscheidung von Groß- und Kleinschreibung erfolgt. Falls Sie vom Dateiende her suche möchten, können Sie die Option /eof angeben. Die Berechnung des Offset erfolgt dann automatisch aus der angegebenen Signatur. Die Angabe der Signatur erfolgt als Zeichenkette in doppelten Anführungszeichen und definiert eine Liste von Bytewerten, die in der Datei am angegebenen Offset gesucht wird. Die Bytewerte werden durch Kommata, Strichpunkte oder Leerzeichen getrennt. Ein Bytewert kann entweder als Hexbyte in der Form 0x## (z.B. 0x3F), als Dezimalwert in der Form ### (z.B. 127), als Zeichen in der Form 'c' (z.B. 'A') oder als Metazeichen angegeben werden. Die folgende Tabelle listet die erlaubten Metazeichen auf. \DIGIT
findet alle Bytes im Bereich der ASCII-Zahlen (0–9)
\CHAR
findet alle Bytes im Bereich der Buchstaben (A–Z und a–z)
\ALPHA
findet alle alphanummerischen Bytes (a–z, A–Z und 0–9_)
\NOTNULL
findet alle Bytes, die nicht den Wert 00 haben
\ANY
findet jedes Byte
Die maximale Länge der gesuchten Signatur darf 2048 Byte nicht überschreiten.
235
16 Shell Script-Beispiele
Bei einem Treffer liefert das Programm einen Errorlevel von 0. Wurde die Signatur nicht gefunden, lautet der Errorlevel 1. Bei einem ungültigen Parameter oder einer ungültigen Signatur lautet der Errorlevel 255. Ein Beispiel: Es soll getestet werden, ob die Datei bild.jpg tatsächlich eine JPG-Datei ist. Dann können Sie diese Zeile in einen Batch einbauen: binchk bild.jpg "0xFF 0xD8 0xFF 0xE0 \any \any 'J' 'F' 'I' 'F' "43
Falls der Wert von errorlevel nach dem Kommando noch null (0) ist, dann wurde die Signatur gefunden, bei einem errorlevel von 1 wurde die Signatur nicht gefunden, und es handelt sich aller Wahrscheinlichkeit nach nicht um ein JPEG-Bild. binchk datei.zip " 'P' 'K' 03 04"
Dieses Kommando testet für die übergebene Datei den Anfang des Headers für ein gültiges ZIP-Archiv (alle .zip-Dateien beginnen mit diesen vier Bytes).
16.6.2
DispChg
Es gibt einen Befehl, den ich in meiner Administratorenzeit wirklich vermisst habe: eine Möglichkeit, im Logon-Script des Benutzers die Einstellungen für die Farbtiefe und die Bildschirmauflösung einzustellen. Auch die sonst so vielfältigen Möglichkeiten von WMI (s. Kap. 14.1) erlauben nur ein Auslesen der Daten, keine Veränderung. Mittlerweile gibt es im Web einige Programme, aber auch ich konnte nicht widerstehen und habe dafür ein Programm erstellt. Im Gegensatz zu vielen anderen Tools lassen sich hier einzelne Parameter wie Farbtiefe oder Auflösung verändern, ohne die anderen Einstellungen anzutasten. Zusätzlich können Sie über eine Option alle Möglichkeiten der Werte für die Einstellung der Grafikkarte auslesen. An dieser Stelle ein Wort der Warnung: Die Benutzung erfolgt auf eigenes Risiko. Was dispchg als mögliche Grafikmodi ausliest, ist das, was die im Rechner verbaute Grafikkarte und der Treiber leisten. Sollte der angeschlossene Monitor nicht mit den Werten zurechtkommen, kann es zu Schäden an der Hardware kommen. Moderne TFTs schalten bei Sync-Problemen normalerweise ab, dann müssen Sie allerdings „im Blindflug“ die Auflösung wieder korrigieren. Für ältere Röhrenmonitore kann ein falscher Modus die letzte Aktion gewesen sein, die sie angezeigt haben. 43 Für alle Grafikprofis: Ja, es gibt auch JPG-Dateien, wo das App0-Segment nicht direkt nach dem Header folgt. Streng genommen reicht der Test auf die ersten zwei Byte. Bei einem Treffer erfolgt ein Test auf 0xFF, 0xD9 am Ende der Datei (mit der Option /eof).
236
Die Tools zum Buch
Nachfolgend eine Liste der Optionen. Für alle Optionen können Sie die Angabe entweder mit einem vorangestellten Minuszeichen (wie in *nix) oder mit einem Schrägstrich (wie in Windows) eingeben, beide Angaben sind gültig. dispchg -list und dispchg /list sind also gleich. -?
Anzeige der Online-Hilfe.
-list
Listet alle verfügbaren Grafikmodi des Treibers auf.
-current
Zeigt die Daten des aktuellen Modus an.
-set mode=
Setzt den Grafikmodus Nummer .
-change =
Ändert einen oder mehrere Parameter, wobei für entweder xres, yres, freq oder bpp angegeben werden kann. Nach einem Gleichheitszeichen folgt der einzustellende nummerische Wert. xres und yres definieren die X- und Y-Auflösung, während freq die Bildwiederholfrequenz in Hz angibt. Die Angabe bpp (bits per pixel) setzt die Farbtiefe.
-freak
Ändert die Ausgabe so ab, dass diese durch Shell-Tools oder andere Programme leichter verarbeitet werden kann.
Tabelle 16.11: Die Optionen von dispchg
Auch hier wieder einige Beispiele: dispchg -current
Gibt die derzeitigen Einstellungen des Grafikmodus aus, wie die Ausgabe unten zeigt. DispChg 1.0 - Change & List Display Modes for WinNT, Win2000, WinXP This software is freeware - Copyright (C) 2002 Midnight! Software Special thanks to Alex for suggestions and testing. 1280 x 1024 Pixel, 32 bpp, 75 Hz
Damit lässt sich auch gleich die Wirkung der Option -freak zeigen. Diese lässt bei der Ausgabe alles weg, was die Weiterverarbeitung in einem Script oder Programm behindern könnte, und wählt als Trennzeichen das Semikolon. dispchg /current /freak
Hier die Ausgabe im Vergleich zu oben: 1280;1024;32;75
237
16 Shell Script-Beispiele
Zum Schluss noch eine Kommandozeile, mit der die Farbtiefe unabhängig von der Auflösung auf 256 Farben (8 Bit pro Pixel) eingestellt wird, falls der Grafiktreiber dies für den aktuellen Modus erlaubt: dispchg -change bpp=8
16.6.3
MocWall
Dieses Kommando dient dem programmgesteuerten Erzeugen von Hintergrundbildern, die Informationen enthalten. Ein ähnliches Programm gibt es als bginfo von www.systeminternals.com ebenfalls als Freeware. Bei mocwall liegt der Vorteil in der beliebigen Platzierung der Texte, die in die Hintergrund-Bitmap eingebaut werden, und in der Möglichkeit, einzelne bmp-Dateien in die Bitmap zu integrieren. Dazu wird eine ini-Datei zur Steuerung verwendet. Diese enthält pro Zeile eine Anweisung oder einen Kommentar, der mit einem Semikolon (";") beginnt und bis zum Ende der Zeile reicht. Folgende Kommandos sind möglich: 왘 wall <width>, , ,
Muss einmal angegeben werden und legt die Größe der zu erstellenden Bitmap fest: width Pixel breit und height Pixel hoch, mit einer Farbtiefe von bpp Bits pro Pixel. fname gibt den Dateinamen an, unter dem die Bitmap abgelegt werden soll. Soll die Bitmap so groß werden, wie die aktuell konfigurierte Bildschirmauflösung, kann für die Breite und Höhe jeweils der Wert 0 eingegeben werden. 왘 color , ,
Definiert eine Farbe mit dem angegebenen Namen und dem angegebenen RGB-Wert. Dieser Farbname kann bei den anderen Kommandos als Farbe angegeben werden. 왘 rect <x1>, , <x2>, ,
Erzeugt ein Rechteck von der Position x1, y1 bis zur Position x2, y2 in der angegebenen Farbe color. Wird für x2 bzw. y2 ein Wert von 0 angegeben, wird der Maximalwert aus der eingestellten Auflösung berechnet. Ein negativer Wert bedeutet den Abstand vom rechten bzw. unteren Rand in Pixel und erlaubt so z.B. das rechtsbündige Ausrichten von Text. 왘 frame <x1>, , <x2>, , , <width>
Erzeugt einen Rahmen von der Position x1, y1 bis zur Position x2, y2 in der Farbe color und der Breite width. Wird für x2 bzw. y2 ein Wert von 0 angegeben, wird der Maximalwert aus der eingestellten Auflösung berechnet. Ein negativer Wert bedeutet den Abstand vom rechten bzw. unteren Rand in Pixel und erlaubt so z.B. das rechtsbündige Ausrichten von Text.
238
Die Tools zum Buch 왘 pict , ,
Integriert eine Kopie der angegebenen Bitmap an der definierten Position in die Bitmap. 왘 text <x>, , , <size>, , , <style>,
Erzeugt einen Text in der Bitmap. x und y legen die Position fest. Wird für x2 bzw. y2 ein Wert von 0 angegeben, wird der Maximalwert aus der eingestellten Auflösung berechnet. Ein negativer Wert bedeutet den Abstand vom rechten bzw. unteren Rand in Pixel und erlaubt so z.B. das rechtsbündige Ausrichten von Text. Die Angabe font definiert den Namen der Schriftart, size die Größe in Point. Die Angaben für forecolor und backcolor legen die Farben fest, wobei für backcolor auch der Wert „transparent“ angegeben werden darf. style ist entweder eine leere Zeichenkette ("") oder eine Kombination aus b (bold), u (underline) oder i (italic) in Anführungszeichen. Der Text text schließlich ist der auszugebende Text. Erzeugt wird die Bitmap durch den Aufruf von mocwall.exe mit dem Namen der INI-Datei und evtl. einer oder mehreren Optionen. movwall demo.ini
Dieses Kommando legt die in der ini-Datei definierte Bitmap an und endet dann. Über die Option -set kann diese Bitmap auch sofort als aktiver Hintergrund eingestellt werden. movwall demo.ini -set
Nachfolgend ein Beispiel für eine solche ini-Datei. Erläuterungen zu den einzelnen Kommandos finden sich in den Kommentaren vor dem jeweiligen Kommando. ; zuerst definieren wir einige Farben, die spaeter benötigt werden color Schwarz 0, 0, 0 color Weiss 255, 255, 255 color Orange 255, 153, 51 color Hellblau 51, 153, 255 color Rot 255,0,0
Listing 16.19: Eine Beispieldatei für mocwall
; jetzt die ausmasse der bitmap festlegen ; 0 is allowed for wall size = will detect current screen resolution wall 1024, 768, 24, "c:\windows\wall.bmp" ; Zuerst einen Block am linken Rand einfaerben, wo die Icons liegen ; Von 0,0 150 Pixel breit bis ganz nach unten Rect 0, 0, 150, 0, hellblau ; Jetzt noch das Firmenlogo einbauen, muss bmp-format sein
239
16 Shell Script-Beispiele Pict 550, 50, "c:\logos\firma.bmp" ; jetzt wird getextet: Text -20, 450, "Arial", 14, schwarz, transparent, "", "IP Addr: %IPADDR%" Text -20, 480, "Arial", 14, schwarz, transparent, "", "%computername%" Text 250, 200, "Verdana", 24, Orange, hellblau, "b", "Armin"
Wie Sie erkennen, lassen sich in den Texten auch die Werte von Umgebungsvariablen ausgeben. Dazu wird, wie bei der Shell üblich, der Name der Variablen in Prozentzeichen eingeschlossen. Zusätzlich müssen Sie beim Aufruf von mocwall die Option -expand oder -expnice angeben. Beide erweitern die in den Texten aufgeführten Umgebungsvariablen. Die Angabe von -expand erweitert ohne weitere Veränderung alle Variablen, während -expnice eventuell vorhandene führende und folgende Leerzeichen des Variablenwertes entfernt und die Schreibweise in Kleinbuchstaben konvertiert. Durch die Nutzung von Umgebungsvariablen können Sie beliebige Informationen in die Hintergrund-Bitmap integrieren, indem Sie in einem Shell Script vorher den Wert entsprechend setzen. Achten Sie darauf, dass es sich bei der erzeugten Bitmap eben um eine statische Grafik handelt. Sollte sich z.B. eine dort angezeigte IP-Adresse ändern, muss erst wieder eine neue Bitmap erzeugt werden, bevor die neue Adresse angezeigt wird.
16.6.4
XEcho
Das Kommando xecho ist eine Erweiterung des echo-Befehls, die im Gegensatz zu diesem in der Lage ist, auch Texte ohne einen nachfolgenden Zeilenumbruch auszugeben. Zusätzlich kann die Ausgabe der Meldung in verschiedenen Farben und mit einer nummerischen Formatierung erfolgen. Doch zuerst die allgemeine Syntax von xecho: XEcho [] []
Die Nachricht ist der auszugebende Text. Wie bei allen anderen Parametern der Shell ist dieser in Anführungszeichen einzuschließen, wenn er Leerzeichen enthält. Ohne weitere Optionen wird der Text einfach ausgegeben. C:\tmp>XEcho "Es wurden 1234 Dateien gefunden" Es wurden 1234 Dateien gefunden C:\tmp>
240
Die Tools zum Buch
Wird bei xecho gar keine Nachricht angegeben, so liest das Programm eine Zeile aus der Standardeingabe und verwendet diese Daten als Nachricht. Interessant wird das Kommando erst durch seine Optionen, die in der nachfolgenden Tabelle aufgeführt werden. Tabelle 16.12: Die Optionen von xecho
/x:#
Ausgabe beginnt in Spalte #.
/y:#
Ausgabe beginnt in Zeile #.
/a:
Die Ausgabe erfolgt in der durch definierten Farbe. Die Farbcodes entsprechen dem Kommando color und sind unten nochmals aufgeführt.
/f:
Formatiert die Ausgabe mit . Erläuterungen dazu siehe unten.
/d:
Legt das Trennzeichen auf fest.
/nolf
Keinen Zeilenvorschub nach der Ausgabe der Meldung.
/?, /h
Ausgabe der Online-Hilfe.
Die für die Option /a verwendbaren Farbcodes sind wie folgt definiert. 0 = Schwarz
1 = Dunkelblau
2 = Dunkelgrün
3 = Türkis
4 = Rot
5 = Dunkelmagenta
6 = Braun
7 = Hellgrau
8 = Grau
9 = Blau
A = Grün
B = Helltürkis
C = Hellrot
D = Magenta
E = Gelb
F = Weiß
Tabelle 16.13: Farbcodes für die Option /a
Um ca. in der Mitte eines Konsolenfensters eine Meldung in weißer Schrift auf rotem Hintergrund auszugeben, verwenden Sie folgendes Kommando: XEcho "System wird gestartet..." /x:20 /Y:15 /a:4f
Die Option /nolf unterdrückt die Ausgabe eines Zeilenvorschubs, so dass nachfolgende Ausgaben (auch die anderer Programme) genau da anschließen: XEcho Hostname: /nolf & hostname Hostname:orion
Sehr flexibel lässt sich die Ausgabe mit Hilfe der beiden Optionen /d und /f steuern. Es können nämlich auch nur bestimmte Teile der Nachricht ausgegeben oder auch formatiert werden. Für die Formatierung kann ein Formatstring definiert werden, über den sich genau steuern lässt, was wie ausgegeben wird. Enthält diese Formatangabe Leerzeichen, so ist auch diese in doppelte Anführungszeichen einzuschließen. Innerhalb dieses Formats wird die Zeichenkette {} durch die Nachricht ersetzt, wie das Beispiel unten zeigt:
241
16 Shell Script-Beispiele C:\tmp>ipconfig | find "IP-Ad" | xecho /f:{} IP-Adresse. . . . . . . . . . . . : 192.168.120.254 C:\tmp>
Falls Sie nun nur die IP-Adresse ausgeben möchten, müssen Sie dies im Format nur definieren. Im obigen Beispiel eignet sich der Doppelpunkt gut als Trennzeichen, da dann die IP-Adresse das zweite Wort der Zeile darstellt. C:\tmp>ipconfig | find "IP-Ad" | xecho /f:{2:} /d:: 192.168.120.254 C:\tmp>
Der allgemeine Aufbau des Formats ist eine normale Zeichenkette, die bei Leerzeichen in Anführungszeichen eingeschlossen wird. Zusätzlich kann auf ein bestimmtes Wort der Nachricht mit folgender Syntax zugegriffen werden: {[num:][-][width][.precision][type]}
Wie bereits aus dem obigen Beispiel ersichtlich, definiert num, gefolgt von einem Doppelpunkt, das entsprechende Wort der Nachricht. Dahinter kann eine Angabe der Feldbreite erfolgen. Wird dieser ein Minuszeichen vorangestellt, erfolgt die Ausgabe linksbündig (bei Zahlen). Durch einen Dezimalpunkt kann bei Fließkommawerten die Anzahl der Nachkommastellen definiert werden, bei ganzzahligen Daten die Anzahl der Ziffern, um evtl. führende Nullen zu erzeugen. Der Typbezeichner type legt den Typ der Daten fest: Zeichenketten (s), Gleitkommazahlen (f), Ganzzahlen im Dezimalsystem (d) oder Hexwerte (x). Zusätzlich können in der Formatangabe noch folgende Sonderzeichen (escapes) verwendet werden: 왘 \t = Ergibt einen Tabsprung 왘 \r = Neue Zeile (nur CR!) 왘 \n = Neue Zeile mit Zeilenvorschub 왘 \b = Letztes Zeichen löschen 왘 \q = Doppeltes Anführungszeichen 왘 \\ = Backslash
Genug der grauen Theorie, hier folgenden einige Beispiele, mit denen Sie experimentieren können: echo 1234 | xecho /f:{1:0.4f}
Dieses Kommando formatiert die übergebene Zahl als Gleitkommazahl (Typ f) in einem Feld, das so kurz als möglich ist (Länge 0) mit vier Stellen nach dem Komma (.4) Eine Zeile
242
xecho "testdatei.dat 234" /f:"{1:-20s}\t{2:8.8d} Byte"
Die Tools zum Buch
Der Text „testdatei.dat 234“ wird so formatiert, dass das erste Wort (der Dateiname) in einem 20 Zeichen breiten Feld linksbündig als String ausgegeben wird. Danach folgt ein Tab und dann das zweite Wort, formatiert als Ganzzahl in einem acht Zeichen breiten Feld mit acht Ziffern. Hier die Ausgabe: testdatei.dat
00000234 Byte
Sie können natürlich auch mehrfach eine Formatmaske für ein Wort angeben, wie das nachfolgende Beispiel zeigt. Zur Funktion: Dieses Kommando liefert die IP-Adresse der ersten Ethernet-Karte in hexadezimaler Notation. Damit lassen sich IP-Adressen beispielsweise als 8.3-Dateiname für Logging-Zwecke verwenden. ipconfig | find /i "ip-ad" | xecho /d:: /f:{2:} | xecho /d:. /f:{1:0x}{2:0x}{3:0x}{4:0x}
Eine Zeile
Die Ausgabe ist dagegen ziemlich kurz: C0A878FE
Literale Zeichen in der Formatmaske werden direkt ausgegeben, wie das nächste Beispiel zeigt: time /t | xecho /d:: /f:"Es ist {1:2d}h und {2:2d}m nach Mitternacht."
Eine Zeile
Die Ausgabe ist dann die Kombination aus dem literalen Text und den formatierten Daten aus StdIn: Es ist
0h und 45m nach Mitternacht.
Ich bin sicher, dass Ihnen noch wesentlich mehr Möglichkeiten für die Nutzung von xecho einfallen.
243
17
Referenz
Dieses Kapitel soll Ihnen als Orientierungshilfe dienen. Hier finden Sie sowohl eine vollständige Liste der Shell-Kommandos als auch zusätzliche Informationen zu den Kommandozeilen-Tools, die von Microsoft sonst noch erhältlich sind (Support Tools, Resource Kit etc.) und die Verwaltung des Systems erleichtern. Was ich an dieser Stelle nicht getan habe, ist die so beliebte Auflistung der Syntax für jedes Kommando. Diese Information wäre bei der mittlerweile erreichten Qualität der Online-Hilfe von Windows eine reine Seitenschinderei. Die einzeilige Erklärung der einzelnen Kommandos reicht meiner Meinung nach auch für Umsteiger aus. Der dann folgende Aufruf des Kommandos mit /? zur Anzeige der Syntax ist schnell gemacht. Stattdessen habe ich nach der Kommandoauflistung noch für einige Kommandos Bemerkungen und Beispiele aufgeführt. Diese sind Produkte aus den Shell-Kursen und aus eigenen Aufzeichnungen und enthalten Informationen zu einigen eher selten verwendeten Kommandos oder zu Kommandos, die für Umsteiger aus anderen Betriebsystemen oder älteren Windows-Versionen Neues bieten.
17.1 Shell-Kommandos Die folgende Liste enthält alle Shell-Kommandos, die zum Standardumfang von Windows 2003 Server gehören. Bei jedem Kommando finden Sie in der zweiten Spalte einen Vermerk, ab welcher Version von Windows dieses Kommando in der Standardinstallation enthalten war, so dass Sie diese Liste auch mit den älteren Windows-Versionen verwenden können (Standardinstallation des Betriebssystems ohne Support Tools oder ResKit). adprep
2003 Upgrades-Vorbereitung von W2K-Domains nach W2003
arp
2000 Auflösung von IP-Adressen in Mac-Adressen
assoc
2000 Auflisten der registrierten Dateierweiterungen
at
2000 Zeitgesteuerte Ausführung von Befehlen
atmadm
2000 Monitorprogramm für den Betrieb in ATM-Netzwerken
attrib
2000 Verwalten von Dateiattributen
245
17 Referenz
XP
bootcfg
246
Verwalten der boot.ini-Einstellungen
cacls
2000 Verwaltung und Anzeige von NTFS-Zugriffsrechten
call
2000 Aufrufen einer Batchdatei
certreq
XP
Beantragt Zertifikate von einer CA
certutil
XP
Befehlszeilenprogramm für die Zertifikatsverwaltung
change
XP
Terminal Services-Einstellungen (user, logon, port)
chdir / cd
2000 Wechselt das aktuelle Verzeichnis
chkdsk
2000 Überprüft Datenträger (FAT und NTFS)
chkntfs
2000 Einstellung der NTFS-Überprüfung beim Systemstart
choice
2003 Auswahl vom Benutzer erfragen
cipher
2000 Verschlüsselt und entschlüsselt Dateien
clip
2003 Filter stellt Eingabedaten in die Zwischenablage
cls
2000 Löscht den Konsolenbildschirm
cluadmin
2003 Startet das Cluster-Verwaltungsprogramm
cluster
2003 Verwaltet Cluster von der Kommandozeile aus
cmd
2000 Die Standard-Shell für Windows
cmdkey
2003 Verwaltet servergespeicherte Benutzerkonten
cmstp
XP
color
2000 Stellt die Farben für die Konsole ein
comp
2000 Vergleicht den Inhalt von zwei oder mehr Dateien
compact
2000 Verwaltet die Komprimierung von NTFS-Dateien
compress
2000 Komprimiert Dateien (Gegenteil zu expand)
convert
2000 Konvertiert Dateisysteme nach NTFS
convlog
2000 Konvertieren von IIS-Logdateien
copy
2000 Kopiert Dateien
cprofile
XP
cscript
2000 Kommandozeilenversion des WSH
csvde
2003 Datenaustausch mit dem ActiveDirectory per CSV-Files
Verwaltet Profile für den Connection-Manager
Säubert Benutzerprofile
date
2000 Systemdatum einstellen und ausgeben
dcgpofix
2003 Stellt die GPOs wieder auf den Installationszustand ein
debug
2000 Der Standard-Debugger seit MS-DOS
Shell-Kommandos
defrag
2000 Defragmentierung des Dateisystems
del
2000 Löschen von Dateien
dfscmd
2003 Verwaltung von DFS-Servern per Kommandozeile
dir
2000 Ausgabe des Verzeichnisinhalts
diskcomp
2000 Vergleichen von Disketten
diskcopy
2000 Kopieren von Disketten
diskpart
XP
doskey
2000 Makros und History für die Kommandozeile
driverquery
XP
dsadd
2003 Objekte im ActiveDirectory anlegen
dsget
2003 ActiveDirectory-Verwaltung über die Kommandozeile
dsmod
2003 ActiveDirectory-Verwaltung über die Kommandozeile
dsmove
2003 ActiveDirectory-Verwaltung über die Kommandozeile
dsquery
2003 ActiveDirectory-Verwaltung über die Kommandozeile
dsrm
2003 ActiveDirectory-Verwaltung über die Kommandozeile
Platten- und Partitionsverwaltung (Nachfolger von fdisk) Zeigt Informationen über geladene Treiber an
echo
2000 Gibt Daten auf der Konsole aus
edit
2000 Editor für Textdateien, zeichenbasiert
edlin
2000 Konsoleneditor, funktioniert auch mit Umleitungen
endlocal
2000 Beendet eine Lokalisierung von Umgebungsänderungen
eventcreate
XP
Erzeugt in einem Logfile einen Eintrag
eventquery
XP
Fragt Daten aus Logfiles ab
eventtriggers
XP
Verwaltet Trigger für Ereignisse
evntcmd
XP
Setzt SNMP-Events in Traps um
exit
2000 Beendet die aktuelle Instanz der Shell
expand
2000 Dekomprimiert Dateien (Gegenteil zu Compress)
fc
2000 Dateivergleich
find
2000 Sucht nach Zeichen im Eingabestrom
247
17 Referenz
248
findstr
2000 Sucht nach Zeichen mit Hilfe von regulären Ausdrücken
finger
2000 Zeigt Informationen über Benutzer auf RemoteSystem
flattemp
XP
for
2000 Führt Kommandos mehrfach aus
forfiles
2003 Führt Kommandos nur für bestimmte Dateien aus
format
2000 Formatiert Datenträger mit einem Dateisystem
freedisk
2000 Prüft den freien Platz auf einem Datenträger
fsutil
XP
ftp
2000 Dateitransfer per TCP/IP
ftype
2000 Gibt zu einem registrierten Dateityp den Handler aus
getmac
XP
gettype
2003 Liefert Rückgabecode zur Bestimmung des Betriebssystems
goto
2000 Springt an eine Markierung einer Stapeldatei
gpresult
XP
Zeigt Gruppenrichtlinieneinstellungen / RSoP an
gpupdate
XP
Aktualisiert GPOs (statt secedit /refreshpolicy)
graftabl
2000 Ermöglicht die Anzeige von Grafikzeichen
help
2000 Zeigt Hilfeinformationen an
helpCtr
XP
hostname
2000 Gibt den DNS-Namen des Computers aus
if
2000 Ausführung von Befehlen abhängig von Bedingungen
iiscnfg
2003 Import und Export der IIS-Konfiguration
iisftp
2003 Verwaltung des ftp-Teils des IIS 6.0
iisftpdr
2003 Konfiguration virtueller ftp-Verzeichnisse
iisreset
2003 Zurücksetzen des IIS 6.0
iisvdir
2003 Verwaltung der virtuellen Webverzeichnisse des IIS 6.0
iisweb
2003 WebSite-Verwaltung des IIS 6.0
inuse
2003 Ersetzt geladene Systemdateien
ipconfig
2000 Anzeige und Verwaltung der TCP/IP-Konfiguration
ipxroute
2000 IPX-Router für IPX/SPX-Netzwerke
iIrftp
2000 Dateiübertragung per Infrarot-Sender
Aktiviert oder deaktiviert hierarchische temp-Ordner
Vielfältige Support-Funktionen für Dateisysteme
Liest die Mac-Adresse des Computersystems aus
Zeigt die Help and Support Center-Seiten an
Shell-Kommandos
label
2000 Vergibt eine Bezeichnung für einen Datenträger
ldifde
2003 Datenaustausch mit dem ActiveDirectory per LDIF
lodctr
XP
Lädt und registriert Leistungsindikatoren
logman
XP
Verwaltet Performancelogs (auch remote)
lpq
2000 Verwaltet Unix-Druckwarteschlangen
lpr
2000 Sendet Druckaufträge an Unix-Druckwarteschlangen
macfile
XP
md / mkdir
2000 Erzeugt ein Verzeichnis im Dateisystem
Verwaltung der Macintosh File Services
mem
2000 Gibt Informationen über den Speicher der VDM aus
mmc
2000 Startet die Microsoft Management-Konsole
mode
2000 Stellt die Geräteeigenschaften ein (Konsole, COM etc.)
more
2000 Filtert den Eingabestrom seitenweise
mountvol
2000 Hängt NTFS-Dateisysteme ein und wieder aus
move
2000 Verschiebt Dateien
mrinfo
2000 Informationen zum Multicast-Router
msiexec
2000 Verwaltung des MS-Installerdienstes per Befehlszeile
msinfo32
XP
Zeigt Systeminformationen an
nbtstat
2000 Informationen zu NetBIOS über TCP/IP
net
2000 Verwaltung von Netzwerkdiensten und Benutzern
netsh
2000 Skriptgesteuerte Verwaltung der Netzwerkkonfiguration
netstat
2000 Informationen zum TCP/IP-Verbindungsstatus
nlb
2003 Verwaltung der Netzwerklastenverteilung
nlbmgr
2003 Verwaltung der Netzwerklastverteilung für Cluster
nslookup
2000 Abfrage und Diagnose der DNS-Namensauflösung
ntbackup
2000 Datensicherungsprogramm
ntcmdprompt
2000 Startet cmd.exe statt command.com bei MS-DOS TSRs
ntdsutil
2000 ActiveDirectory-Verwaltung für erfahrene Admins
ntsd
2000 Windows System Debugger
openfiles
XP
Zeigt Informationen zu offenen Dateien an
249
17 Referenz
pagefileconfig
XP
path
2000 Setzt den Suchpfad für Befehle bzw. zeigt diesen an
pathping
2000 Kombination aus ping und tracert
pause
2000 Wartet in einer Stapeldatei auf einen Tastendruck
pbadmin
XP
pentnt
2000 Testet auf den Pentium FDIV-Bug
perfmon
2000 Startet den Systemmonitor
ping
2000 TCP/IP-Programm zum ICMP-Verbindungstest
popd
2000 Lädt eine Ebene vom Verzeichnisstapel
powercfg
2003 Konfiguriert die Energiespareinstellungen des Systems
print
2000 Sendet eine Datei zum Drucker
prncnfg
XP
Anzeige bzw. Konfiguration eines Druckers
prndrvr
XP
Verwaltung von Druckertreibern
prnjobs
XP
Druckerwarteschlangenverwaltung (Liste, Löschen, Pause)
prnmngr
XP
Druckerverbindungen und Standarddrucker verwalten
prnport
XP
TCP/IP-Ports für Netzwerkdrucker verwalten
prnqctl
XP
Hält Warteschlangen an, startet sie und druckt Testseiten
prompt
XP
Stellt das Aussehen des Konsolenprompts ein
pushd
2000 Speichert ein Verzeichnis auf dem Verzeichnisstapel
query
250
2000
Konfiguriert die Auslagerungsdatei
Verwaltung der Windows-Telefonbücher
Abfragen von Terminal Service-Sitzungen
rasdial
2000 Wählt bzw. beendet RAS-Verbindungen über Telefonbuch
rcp
2000 remote copy TCP/IP-Dienstprogramm
rd
2000 Entfernt ein Verzeichnis aus dem Dateisystem
recover
2000 Wiederherstellung von Dateien auf einem Datenträger
reg
2000 Dienstprogramm für den Registry-Zugriff
regsvr32
2000 Registriert COM-Serverkomponenten
relog
XP
Extrahiert Daten aus Performancelogs in andere Formate
Shell-Kommandos
rem
2000 Kommentarzeile in Stapeldateien
rename
2000 Ändert den Namen von Dateien und Verzeichnissen
replace
2000 Ersetzt Dateien bzw. ergänzt fehlende Dateien
reset session
XP
rexec
2000 remote exec TCP/IP-Dienstprogramm
risetup
XP
rmdir
2000 Entfernt ein Verzeichnis aus dem Dateisystem
route
2000 Ändert, erstellt oder zeigt TCP/IP-Routen an
rsh
2000 remote shell TCP/IP-Dienstprogramm
rsm
2000 Removable Storage Manager für Wechselmedien
rss
2003 Verwaltung von Wechselmedien über die Befehlszeile
runas
2000 Startet Prozesse unter einem anderen Security Context
Setzt eine Sitzung beim Terminal Server zurück
Verwaltung der Remote Installation Services
sc
2000 Service Controller-Dienstprogramm (Serviceverwaltung)
schtasks
XP
secedit
2000 Konfiguriert Systemsicherheit anhand von Schablonen
set
2000 Setzt Umgebungsvariablen bzw. zeigt diese an
setlocal
2000 Startet die Lokalisierung von Umgebungsänderungen
setx
2003 Setzt Umgebungsvariablen systemweit
sfc
2000 System File Checker zur Überprüfung von Systemdateien
shift
2000 Auswertung der Parameter einer Stapeldatei
shutdown
XP
sort
2000 Sortiert die Daten im Eingabestrom spaltenweise
start
2000 Startet Prozesse mit wählbarer Priorität
subst
2000 Ersetzt einen Pfad durch ein Laufwerk
sysocmgr
2000 Installiert optionale Windows-Komponenten nach
systeminfo
XP
Definition geplanter Aufgaben (Nachfolger von at)
Fährt das lokale oder ein Remote-System herunter
Gibt detaillierte Systeminformationen aus
251
17 Referenz
takeown
2003 Übernimmt die Eigentümerschaft einer Datei
tapicfg
2003 Konfiguriert die TAPI-Schnittstelle über Dateien
taskkill
XP
Beendet einen Prozess (alter Name: kill)
tasklist
XP
Listet Prozesse auf (alter Name: tlist)
tcmsetup
2003 Installiert oder deaktiviert einen TAPI-Client
telnet
2000 Terminalprogramm der TCP/IP-Dienstprogramme
tftp
2000 tftp-Dienstprogramm für TCP/IP
time
2000 Gibt die Systemzeit aus oder setzt diese
timeout
2003 Wartet eine einstellbare Zeit (z.B. in Stapeldateien)
title
2000 Stellt den Titel des Konsolenfensters ein
tracerpt
2000 Verarbeitet Event-Tracelogs und erstellt Analyseberichte
tracert
2000 Verfolgt die Route zu einem TCP/IP-Host
tree
2000 Gibt die Verzeichnisstruktur als grafischen Baum aus
tsecimp
2003 TAPI Server Security File Import aus XML-Dateien
type
2000 Gibt den Inhalt einer Datei auf der Konsole aus
typeperf
XP
unloadCtr
252
Gibt Leistungsdaten auf der Konsole aus
XP Entlädt Leistungsindikatoren (performance counter)
ver
2000 Gibt Versionsinformationen über das OS aus
verify
2000 Integritätsprüfung beim Dateischreiben an-/ausschalten
vol
2000 Gibt den Namen des Datenträgers aus
vssAdmin
XP
Verwaltung der Shadow Copy-Installation eines Systems
w32tm
2000 Dienstprogramm für den Windows-Zeitdienst
waitfor
2003 Wartet in einer Stapeldatei auf ein Signal
where
2003 Sucht nach den angegebenen Dateien
whoami
XP
winnt
2000 Installationsprogramm für den 16-Bit-Modus
winnt32
2000 Installationsprogramm für den 32-Bit-Modus
winpop
2003 Dienstprogramm für die Verwaltung des POP3Dienstes
wlbs
2003 Veraltet, wurde durch das Kommando 'nlb' ersetzt
Gibt Informationen über den angemeldeten Benutzer aus
Windows 2003 Support Tools
wmic
XP
wscript
2000 Windows-Version des WSH-Ausführungsprogramms
xcopy
Konsolenprogramm zur Abfrage von WMI-Daten
2000 Kopiert Dateien und Verzeichnisse
17.2 Windows 2003 Support Tools Die folgende Liste enthält die Programme, die mit den Support Tools für den 2003 Server installiert werden. Sie finden die Installationsdatei auf der CD von Windows 2003 im Verzeichnis support. Kommando
Bedeutung
Acldiag.exe
Diagnose von Access Control Lists
Addiag.exe
Diagnose der installierten Software
Adsiedit.msc
Editor und Viewer fürs Active-Verzeichnis
Apmstat.exe
Advanced Power Management-Status
Bindiff.exe
Vergleicht Dateien oder Verzeichnisse auf binärer Ebene
Bitsadmin.exe
BITS-Verwaltung auf Kommandozeilenebene
Browstat.exe
Browser Status
Cabarc.exe
Cabinet Tool
Clonepr
Clone Principal
Connstat.cmd
FRS Connection Status Report
Dcdiag.exe
Domain Controller Diagnostic Tool
Depends.exe
Dependency Walker
Devcon.exe
Device Console Utility
Dfsutil.exe
Distributed File System Utility
Dhcploc.exe
DHCP Server Locator Utility
Diruse.exe
Verzeichnis Disk Usage
DiskProbe
Dskprobe.exe
Dmdiag.exe
Disk Manager Diagnostics
Dnscmd.exe
Verwaltung und Diagnose des DNS-Serverdienstes
Dnslint.exe
DNS Lint
Dsacls.exe
Verzeichnis Services ACL Editor
Dsastat.exe
Verzeichnis Services Utility
DskProbe.exe
Disk Probe
Efsinfo.exe
Encrypting File System Information
Exctrlst.exe
Extensible Performance Counter List
Tabelle 17.1: Die Kommandos der Support Tools für Windows 2003
253
17 Referenz
254
Kommando
Bedeutung
Filever.exe
File Version
Ftonline.exe
Fault Tolerant Disk Mounter
Getsid.exe
Get Security ID
Gflags.exe
Global Flags Editor
Health_chk.cmd
FRS Health Check
Httpcfg.exe
HTTP Configuration Utility
Iologsum.cmd
FRS Inbound and Outbound Logs Summary Report Tool
Iasparse.exe
IAS Parse Tool
Ksetup.exe
Kerberos Setup
Ktpass.exe
Kerberos Keytab Setup
Ldp.exe
LDP Tool
Memsnap.exe
Memory Profiling Tool
Movetree.exe
Move Users
Msicuu.exe
Windows Installer Cleanup Utility
Msizap.exe
Windows Installer Zapper
Netcap.exe
Network Monitor Capture Utility
Netdiag.exe
Network Connectivity Tester
Netdom.exe
Windows Domain Manager
Nltest.exe
NLTest
Ntfrsutl.exe
NTFRS Utility
Poolmon.exe
Memory Pool Monitor
Portqry.exe
Port Query
Pviewer.exe
Process Viewer
Remote.exe
Remote Command Line
Repadmin.exe
Replication Diagnostics Tool
Replmon.exe
Active Verzeichnis Replication Monitor
Rsdiag.exe
Remote Storage Diagnostic Utility
Rsdir.exe
Remote Storage File Analysis Utility
Search.vbs
Active-Verzeichnis Search Tool
Sdcheck.exe
Security Descriptor Check Utility
Setspn.exe
Manipulate Service Principal Names for Accounts
SIDWalk.msc
Security Administration Tools
Spcheck.exe
Service Pack Check
Topchk.cmd
DFS and SYSVOL Replication Topology Analysis Tool
Windiff.exe
WinDiff File und Verzeichnis Comparison
Xcacls.exe
Extended Change Access Control Lists
Windows 2003 Resource Kit
17.3 Windows 2003 Resource Kit Die folgende Tabelle listet die Kommandos des Resource Kits auf. Nicht alle Befehle in dieser Liste sind kommandozeilenorientiert. Aus Gründen der Vollständigkeit sind aber auch die GUI-Anwendungen enthalten. Kommando
Bedeutung
Adlb.exe
Active-Verzeichnis Load Balancing Tool
Admx.msi
ADM Parser für Policy Templates
Atmarp.exe
ATM ARP Server Information Tool
Atmlane.exe
ATM LAN Emulation Client Information
Autoexnt.exe
AutoExNT Service
Cdburn.exe
Brennt ISO-Images auf CD
Checkrepl.vbs
Testet die Replikation für einen DC
Chklnks.exe
Testet Verknüpfungen und entfernt tote Links
Chknic.exe
Check der Netzwerkkarte für NLB
Cleanspl.exe
Löscht Jobs, Drucker, Treiber für den Spooler eines Rechners
Clearmem.exe
Speicherallokations-Tools
Clusdiag.msi
Cluster-Diagnose-Tools
Clusterrecovery.exe
Cluster Recovery Utility
Cmdhere.inf
Installiert einen Shell-Aufruf im Explorer (s. Kapitel zur Shell-Konfiguration)
Cmgetcer.dll
Connection Manager Certificate Deployment Tool
Compress.exe
Komprimiert Dateien, die mit Expand wieder entpackt werden können
Confdisk.exe
Cluster Disk Recovery Tool
Consume.exe
Memory Consumers Tool
Creatfil.exe
Erzeugt eine Datei der angegebenen Größe
Csccmd.exe
Client-Side Caching Command-Line Options
Custreasonedit.exe
Manage custom shutdown reasons
Delprof.exe
Löschen von Benutzerprofilen
Dh.exe
Anzeige des Heaps
Diskraid.exe
RAID-Konfigurationstool
Tabelle 17.2: Die Tools des Windows 2003 Server Resource Kit
255
17 Referenz
Kommando
Bedeutung
Diskuse.exe
Plattenverbrauch pro Benutzer
Dnsdiag.exe
DNS Diagnose für den SMTP-Transport
Dumpfsmos.cmd
Anzeige der FSMO Roles (nutzt ntdsutil.exe)
256
Dvdburn.exe
Brennt ISO-Images auf DVD
Empty.exe
Gibt das Working Set eines Prozesses frei
Eventcombmt.exe
Sammelt Replikationsevents aus den Logs
Fcopy.exe
Komprimiert und kopiert Dateien per MSMQ
Frsflags.vbs
Verwaltet das Install Override Flag für den FRS
Getcm.exe
Connection Manager Profile Update
Gpmonitor.exe
Group Policy Monitor
Gpotool.exe
Group Policy Checks per Kommandozeile
Hlscan.exe
Zeigt Hard Links an
Ifilttst.exe
Testprogramm für Index Server IFilter
Ifmember.exe
Testet Gruppenmitgliedschaft
Inetesc.adm
Erweiterte Sicherheitskonfiguration für den IE
Iniman.exe
Bearbeiten von ini-Dateien
Instcm.exe
Installiert Connection Manager Profile
Instsrv.exe
Installiert exe-Programme als Service
Intfiltr.exe
Interrupt Affinity Tool
Kerbtray.exe
Zeigt Kerberosinfos im Systemtray an
Kernrate.exe
Kernel Profiling Tool
Klist.exe
Anzeige von Ticketinfos für die Konsole
Krt.exe
Certification Authority Key Recovery
Lbridge.cmd
Brücke für die Replikation zwischen NT und 200X
Linkd.exe
Erzeugt für ein NTFS-Verzeichnis einen Link
Linkspeed.exe
Testet die Geschwindigkeit einer Netzwerkverbindung
List.exe
Tool zur Anzeige von Textdateien (auch in hex)
Lockoutstatus.exe
Sammelt Informationen über gesperrte Accounts
Windows 2003 Resource Kit
Kommando
Bedeutung
Logtime.exe
Gibt Text und Zeitstempel in eine Datei aus
Lsreport.exe
Terminal Services Licensing Reporter
Lsview.exe
Terminal Services License Server Viewer
Mcast.exe
Multicast Packet Tool
Memmonitor.exe
Memory Monitor
Memtriage.exe
Resource Leak Triage Tool
Mibcc.exe
SNMP MIB Compiler
Moveuser.exe
Verschieben von Benutzern
Nlsinfo.exe
Ausgabe von Infos zu Ländereinstellungen
Now.exe
Gibt Datum und Zeit nach StdOut aus
Ntimer.exe
Gibt Ausführungszeiten für Programme an
Ntrights.exe
Privilegienverwaltung per Kommandozeile
Oh.exe
Zeit offene Handles an
Oleview.exe
OLE/COM Object Viewer
Pathman.exe
Unterstützt bei der Verwaltung des Befehlspfades
Permcopy.exe
Share Permissions Copy
Perms.exe
User File Permissions Tool
Pfmon.exe
Page Fault Monitor
Pkiview.msc
PKI Health Tool
Pmon.exe
Process Resource Monitor
Printdriverinfo.exe
Drivers Source
Prnadmin.dll
Printer Administration Objects
Qgrep.exe
Eine grep-Variante für Windows
Qtcp.exe
QoS Time Stamp
Queryad.vbs
Abfragen im Active-Verzeichnis durchführen
Rassrvmon.exe
RAS Server Monitor
Rcontrolad.exe
Active-Verzeichnis Remote Control AddOn
Regini.exe
Registry-Änderungen per Script
Regview.exe
Erlaubt das Ansehen von registry.polDateien
257
17 Referenz
258
Kommando
Bedeutung
Remapkey.exe
Remap Windows Keyboard Layout
Robocopy.exe
Robust File Copy Utility
Rpccfg.exe
RPC Configuration Tool
RPing
RPC Connectivity Verification Tool
Rqc.exe
Remote Access Quarantine Client
Rqs.exe
Remote Access Quarantine Agent
Setprinter.exe
Spooler Configuration Tool
Showacls.exe
Anzeige von Acces Control Lists
Showperf.exe
Performance Data Block Dump Utility
Showpriv.exe
Show Privilege
Sleep.exe
Batch File Wait
Sonar.exe
FRS Status Viewer
Splinfo.exe
Print Spooler Information
Srvany.exe
Applications as Services Utility
Srvcheck.exe
Server Share Check
Srvinfo.exe
Informationen über ein Remote-System
Srvmgr.exe
Server Manager
Ssdformat.exe
System State Data Formatter
Subinacl.exe
Manipulation von Berechtigungslisten
Tail.exe
Zeigt das Ende einer Textdatei an
Tcmon.exe
Traffic Control Monitor
Timeit.exe
Stoppuhr für Prozesse
Timezone.exe
Daylight Saving Time Update Utility
Tsctst.exe
Terminal Server Client License Dump Tool
Tsscalling.exe
Terminal Services Scalability Planning Tools
Uddicatschemeeditor.exe
UDDI Services Categorization Scheme Editor
Uddiconfig.exe
UDDI Services Command-line Configuration Utility
Uddidataexport.exe
UDDI Data Export Wizard
Usrmgr.exe
User Manager for Domains
Vadump.exe
Virtual Address Dump
Vfi.exe
Visual File Information
Volperf.exe
Shadow Copy Performance Counters
Informationen zu einzelnen Befehlen
Kommando
Bedeutung
Volrest.exe
Shadow Copies for Shared Folders Restore Tool
Vrfydsk.exe
Verify Disk
Winexit.scr
Windows Exit Screen Saver
Winhttpcertcfg.exe
WinHTTP Certificate Configuration Tool
Winhttptracecfg.exe
WinHTTP Tracing Facility Configuration Tool
Winpolicies.exe
Policy Spy
Wins.dll
WINS Replication Network Monitor Parser
Wlbs_*.dll
Windows Load Balancing Server Network Monitor Parsers
17.4 Informationen zu einzelnen Befehlen Die nachfolgenden Anmerkungen zu einzelnen Kommandos der Shell sind eine Art Sammlung aus den Teilnehmerfragen während meiner Seminare. An dieser Stelle finden Sie einige Kommandos, die nicht so bekannt sind, aber auch unbekanntere Optionen oder Einsatzmöglichkeiten einzelner Shell-Kommandos. Dieser Abschnitt soll also keine komplette Syntaxreferenz sein (dafür gibt es die OnlineHilfe von Windows), sondern soll Ihnen nur die eine oder andere Möglichkeit zeigen, die Ihnen vielleicht Arbeit erspart.
17.4.1
Dateiverwaltung
diskpart Dies ist der lang erwartete Ersatz für fdisk gewesen. Als freie Ergänzung zu den Resource Kit Tools war diskpart ab Windows 2000 verfügbar und gehört seit XP zum Standardumfang der Shell. diskpart kann interaktiv (wie ftp oder nslookup) benutzt werden oder mit Hilfe von Scripts. Script bedeutet hierbei allerdings keine richtige Scriptsprache, sondern nur eine Textdatei mit einer Liste von Befehlen. Der Aufruf geschieht entweder ohne Parameter oder mit /s , wobei den Dateinamen der Scriptdatei darstellt. Ein Grundkonzept bei der Bedienung von diskpart ist das des focus. Den focus erhält ein Objekt (Platte, Partition oder Datenträger) durch eine explizite Anwahl per select. Damit Sie die Kennung erfahren, wird üblicherweise vorher per list eine Auswahl angezeigt.
259
17 Referenz
Hier ein Beispiel für die Auswahl einer Partition (Eingaben sind fett markiert): Listing 17.1: Eine Beispielsitzung mit diskpart
DISKPART> list disk Disk ### -------* Disk 0
Status ---------Online
Size ------4095 MB
Free ------8033 KB
Dyn ---
Gpt ---
DISKPART> select disk 0 Disk 0 is now the selected disk. DISKPART> list partition Partition ### ------------Partition 1
Type ---------------Primary
Size ------4087 MB
Offset ------32 KB
DISKPART> select partition 1 Partition 1 is now the selected partition. DISKPART> detail partition Partition 1 Type : 07 Hidden: No Active: Yes Volume ### Ltr Label Fs Type Size Status Info ---------- --- ----------- ----- ---------- ------ --------- -------* Volume 1 C NTFS Partition 4087 MB Healthy System DISKPART>
Der große Vorteil von diskpart liegt darin, dass durch die Möglichkeit der Erstellung von Scriptdateien mit Befehlen eine Automatisierung leicht möglich ist. Das Programm benutzt unter anderem auch sinnvolle Voreinstellungen. Eine neu erzeugte Partition bekommt automatisch den Focus, so dass diese nicht extra ausgewählt werden muss. Wird keine Größe für eine primäre Partition angegeben, wird der verfügbare freie Platz gewählt und so weiter.
260
Informationen zu einzelnen Befehlen
Sollten Sie diskpart mehrfach hintereinander aufrufen (beispielsweise mit mehreren Scripts), benötigt das Kommando ca. 15 Sekunden für das Beenden und zum neuen Start. Wird diese Zeit nicht eingehalten, kann es vorkommen, dass ein diskpart-Script fehlschlägt. Benutzen Sie dazu z.B. die Kommandos choice oder timeout. expand Das Kommando expand ist immer noch brauchbar. expand dient der Extraktion von Dateien aus einer cab-Datei oder dem Dekomprimieren einer Datei aus gepackten Installationsdateien. EXPAND EXPAND EXPAND EXPAND
[-r] Source Destination -r Source [Destination] -D Source.cab [-F:Files] Source.cab -F:Files Destination
Die Option -r erlaubt das Umbenennen von Dateien beim Auspacken. Die Angabe source für die Quelle kann auch Wildcards enthalten, allerdings muss dann als destination ein Verzeichnis angegeben werden, wenn mehrere Dateien entpackt werden. fsutil Das Kommando fsutil ist eine Art Schweizer Offiziersmesser für die Arbeit an den Einstellungen zum NTFS-Dateisystem. Als Administrator werden Sie es oft zum Erzeugen von hard links einsetzen (s. Kap. 5.3). Daneben können Sie aber auch Informationen zu NTFSDatenträgern abrufen. In vielen Fällen sind diese Daten aber mittlerweile über WMI-Provider und die WMI Konsole wmic zugänglich. md (mkdir) md (oder mkdir) kann auch Pfadstrukturen anlegen, die mehr als eine Ebene umfassen. Angenommen, unterhalb von c:\tmp möchten Sie ein Verzeichnis daten und darunter eins namens 2004, dann briefe anlegen. Dazu reicht das Kommando md c:\tmp\daten\2004\briefe, die noch nicht vorhandenen Zwischenschritte oberhalb von briefe wer-
den ab Windows 2000 automatisch erzeugt, falls die Befehlserweiterungen aktiviert sind. mountvol Damit können Bereitstellungspunkte (mount points) über die Kommandozeile verwaltet werden. Seit Windows 2000 können Datenträger nicht nur über Laufwerksbuchstaben, sondern auch über Bereitstellungspunkte angebunden werden. Damit ist nicht nur die Beschränkung auf 26 Laufwerksbuchstaben kein Problem mehr, sondern Windows nähert sich damit dem Ziel eines single-rooted-Datei-
261
17 Referenz
systems, wie das auch bei Unix möglich ist. Das einzige Laufwerk ist dann das Systemlaufwerk (normalerweise C:). Benötigen Sie irgendwo noch Platz, erzeugen Sie in einem Ordner unterhalb von C: ein leeres Verzeichnis und benutzen dieses als Bereitstellungspunkt (mount point). Die allgemeine Syntax lautet: MOUNTVOL [Laufwerk:]Pfad Datenträgername MOUNTVOL [Laufwerk:]Pfad /D MOUNTVOL [Laufwerk:]Pfad /L
Hier die möglichen Optionen: Tabelle 17.3: Optionen für mountvol
Pfad
Gibt das (bereits vorhandene) NTFS-Verzeichnis an, auf dem der Bereitstellungspunkt eingerichtet werden soll.
Datenträgername
Gibt den Namen des bereitzustellenden Datenträgers an.
/D
Löscht den Bereitstellungspunkt vom angegebenen Verzeichnis.
/L
Zeigt den Namen des bereitgestellten Datenträgers für das angegebene Verzeichnis an.
/P
Entfernt den Mountpoint vom angegebenen Verzeichnis, beendet die Bereitstellung und macht den Datenträger nicht mehr mountbar.
/R
Entfernt Bereitstellungspunkte und Registry-Einträge für nicht mehr im System vorhandene Datenträger.
/N
Deaktiviert das automatische Bereitstellen.
/E
Aktiviert das automatische Bereitstellen.
Um beispielsweise eine Partition, die über keinen Laufwerksbuchstaben verfügt, unter dem Ordner c:\mnt\datadisk verfügbar zu machen, gehen Sie wie folgt vor (das Verzeichnis sei bereits vorhanden und leer): 왘 Auflisten der Datenträgernamen mit mountvol [/L] 왘 Anhängen an den Bereitstellungspunkt c:\mnt\datadisk durch
die Eingabe des Kommandos mountvol c:\mnt\datadisk \\?\ Volume{f00c4687-c0e0-11d5-8779c-405e37435631}\, wobei der verwendete Datenträgername den der Partition darstellt. Mit der Angabe mountvol c:\mnt\datadisk /D kann diese Bereitstellung wieder gelöscht werden (unmount). Sie sind durchaus in der Lage, einen Datenträger über mehr als einen Pfad oder einen Laufwerksbuchstaben anzubinden. Ob dies allerdings Sinn macht, sei dahingestellt.
262
Informationen zu einzelnen Befehlen
move Verschiebt Dateien bzw. benennt diese beim Verschieben um. Was vielleicht nicht auf Anhieb klar ist: move kann auch benutzt werden, um eine Datei ins gleiche Verzeichnis zu verschieben, nur mit einem anderen Namen (also ein Umbenennen durchzuführen), und entspricht damit in etwa mv unter Unix. rd (rmdir) Löscht Verzeichnisse. Geben Sie hinter rd den Pfad des Ordners an. Im Normalfall kann ein Ordner nur dann gelöscht werden, wenn er leer ist und auch keine Unterordner mehr enthält. Sobald Sie aber die Option /s benutzen, wird die gesamte Struktur inklusive aller Dateien und Unterordner gelöscht. Falls Sie jemals deltree vermisst haben, hier haben Sie es wieder. Noch gefährlicher ist die Option /q, die jede Nachfrage unterdrückt. Sollten Sie jemals keine Lust mehr haben, reicht ein rd c:\ /s /q, und dies war das Letzte, was Sie von Ihrem Windows gesehen haben … ren (rename) Benennt Dateien um. Sie können für den neuen Namen keinen Pfad angeben, dafür muss das Kommando move benutzt werden. Im Gegensatz dazu kann move allerdings als Umbenennungskommando benutzt werden. replace Eine kaum beachtete, aber sehr nützliche Option von replace ist /A. Damit werden Dateien, die im Zielverzeichnis noch nicht enthalten sind, aus dem Quellverzeichnis ergänzt. Bevor Sie also lange Scripts schreiben, um eine manuelle Synchronisation durchzuführen, sehen Sie sich auch die anderen Optionen von replace an. sfc Dies ist der System File Checker von Windows. Seit dem Schutz wichtiger Betriebssystemdateien ab Windows 2000 dient dieses Kommando dem Scan auf Veränderung und einer eventuellen Reparatur. Die Ausführung kann mit folgenden Optionen erfolgen: /SCANNOW
Durchsucht sofort alle geschützten Systemdateien
/SCANONCE
Durchsucht alle geschützten Systemdateien einmal beim nächsten Systemstart
/SCANBOOT
Durchsucht alle geschützten Systemdateien bei jedem Systemstart
263
17 Referenz
/REVERT
Setzt die Einstellungen auf den Standard zurück
/PURGECACHE
Löscht den Filecache und startet sofort einen Scan
/CACHESIZE=x
Setzt die Cachegröße der Systemdateien auf x MB
Der Filecache im Ordner %systemroot%\system32\dllcache muss lesbar sein. Ist dieser defekt oder kann nicht mehr gelesen werden, starten Sie einfach einen Scan, und der Cache wird wieder aufgebaut. Wird während eines Scans eine veränderte Systemdatei gefunden, wird diese mit den Originalversionen überschrieben und so der Originalzustand des Systems wiederhergestellt. takeown takeown ist so etwas wie der globale Dietrich für Administratoren.
Wohl jeder kennt das Problem: Ein besonders sicherheitsbewusster Anwender hat als Berechtigung für eine Datei allen außer sich selbst den Zugriff entzogen. Jetzt wird diese Datei oder der ganze Ordner benötigt. takeown erlaubt es Ihnen, den Zugriff auf der Kommandozeile wieder zu aktivieren. Auch hier ist wieder die Möglichkeit einer remote-Verwendung gegeben. Interessant ist vor allem die Verwendung von Optionen zum Zurücksetzen ganzer Ordnerstrukturen. TAKEOWN /F [/A] [/R [/D <prompt>]]
Hier die Optionen zu takeown: /S <system>
Name des Remote-Systems
/U [<domain>\] <user>
Benutzername, unter dessen Kontext das Kommando ausgeführt werden soll
/P <password>
Passwort für den Benutzer. Wird abgefragt, wenn nicht angegeben
/F
Datei- oder Verzeichnismaske. Als Wildcard ist "*" zugelassen. Die Form share\datei ist ebenfalls gültig.
/A
Die Gruppe der Administratoren bekommt den Dateibesitz anstelle des angemeldeten Benutzers
/R
Läuft durch das angegebene Verzeichnis und alle Unterverzeichnisse
/D <prompt>
Die Standardantwort, falls der angemeldete Benutzer nicht das Recht zum Auflisten des Ordnerinhaltes besitzt. Dies ist bei der Verwendung der Option / R der Fall. Mögliche Werte sind "Y", um den Besitz zu übernehmen, oder "N", um den Ordner/die Datei zu überspringen.
Wird die Option /A nicht angegeben, wird der derzeit angemeldete Benutzer der Besitzer der Datei(en).
264
Informationen zu einzelnen Befehlen
Beispiele: TAKEOWN /F \\system\share\lostfile /A TAKEOWN /F %windir%\*.txt
17.4.2
Netzwerk
hostname Zu hostname nur ein Hinweis an alle Umsteiger: Das Setzen des Hostnamens ist nicht möglich, es kann nur der Name abgefragt werden. net Das Kommando net enthält eine Reihe von Subkommandos, die in der Tabelle unten mit ihren Funktionen aufgelistet sind. net accounts
Verwaltung der Benutzerdatenbankeinstellungen
net computer
Verwaltung von Computerkonten
net config server
Konfiguration des Serverdienstes
net config workstation
Konfiguration des Arbeitsstationsdienstes
net continue
Setzt einen Dienst fort
net file
Schließt eine freigegebene Datei
net group
Verwaltung von Gruppenkonten
net help
Hilfstexte zu den einzelnen Kommandos
net helpmsg
Hilfstexte zu einer NET-Fehlermeldung
net localgroup
Verwaltung von lokalen Gruppenkonten
net name
Verwaltet Namen in der NetBIOS-Namenstabelle
net pause
Hält einen Dienst an
net print
Informationen zu den Druckerwarteschlangen
net send
Sendet Texte zu einem entfernten Benutzer
net session
Zeigt Sitzungsinformationen an und beendet Sitzungen
net share
Verwaltet die Freigaben des Computers
net start
Startet einen Dienst
net statistics
Gibt Statistiken für den Server bzw. den Arbeitsstationsdienst aus
net stop
Beendet einen Dienst
net time
Verwaltet die Zeit im Netzwerk (ausgeben und setzen)
net use
Verwaltet die verbundenen Netzwerklaufwerke
net user
Verwaltung von Benutzerkonten
net view
Zeigt Computer und freigegebene Ressourcen an
Tabelle 17.4: Die Subkommandos von net
265
17 Referenz
Noch ein Tipp zum Thema net use: Falls Sie alle bestehenden Netzlaufwerke ohne Rückfrage trennen möchten, verwenden Sie einfach net use * /d /y. netsh netsh ist ein sehr mächtiges Kommando, mit dem interaktiv Netzwerkeinstellungen verändert werden können. Auch netsh kann per Eingabeumleitung gesteuert werden, so dass Änderungen an den Netzwerkparametern per Shell kein Problem darstellen. Mit Hilfe des Kommandos quit kann netsh wieder verlassen werden. Tabelle 17.5: Die obersten Subkommandos von netsh
netsh AAAA
Internet Authentication Service context
netsh DHCP
DHCP context
netsh diag commands
Diagnosekommandos
netsh Interface IP
IPv4 context
netsh Interface IPv6
IPv6 context
netsh Interface Portproxy Portproxy context netsh IPSec
IPSEC context
netsh Network Bridge
Bridging context
netsh ras
RAS context
netsh Routing
Routing context
netsh RPC
RPC context
netsh WINS
WINS context
nslookup nslookup dient normalerweise der Diagnose der Namensauflösung.
Mit etwas Kreativität können Sie sich damit aber auch eine Menge Arbeit sparen. Ein Kollege war mit der Migration der Domäne eines Automobilzulieferers nach Windows 2003 beschäftigt und fragte bei mir an, ob ich ihm nicht ein WSH-Script oder ein Programm schreiben könne. Er wollte per ADSI testen, wann ein (für das Upgrade vorgesehener) Domain-Controller aus dem Verzeichnis herausrepliziert wäre. Etwas Überlegung erbrachte dann die Erkenntnis, dass dieses Programm bereits existiert: nslookup! Wenn ein Domain-Controller nicht mehr im AD ist, sind auch die Service-Records nicht mehr per DNS verfügbar. Also muss nur der Query-Typ auf SRV-Records umgestellt werden, und wenn nslookup für den gewählten Namensserver nichts mehr für den gesuchten Host findet, ist die Replikation durch. Für eine Diskussion der einzelnen Subkommandos von nslookup sehen Sie in der Online-Hilfe nach. Eine sehr ausführliche Darstel-
266
Informationen zu einzelnen Befehlen
lung von nslookup finden Sie in DNS and BIND von Albitz und Liu (erschienen bei O'Reilly and Associates).
17.4.3
ActiveDirectory
dcgpofix Falls Sie sich verkonfiguriert haben, kann dieses Kommando evtl. weiterhelfen. Damit werden die Standard-GPOs einer Domain wieder neu erzeugt. dcgpofix besitzt nur zwei optionale Parameter: /target: {Domain | DC | BOTH}
Die Angabe von Domain erzeugt nur das Default-GPO der Domain, die Angabe von DC erzeugt nur das Domain-Controller-GPO, während die Angabe von both beide GP-Objekte erzeugt. /ignoreschema
Ignoriert die Schemaversion. Falls diese Option nicht angegeben wird, läuft das Kommando nur unter der Windows-Version, mit der dieses Tool ausgeliefert wurde. gpupdate Dieses Kommando dient der Aktualisierung (refresh) von Einstellungen in Gruppenrichtlinien. Beim Aufruf können Sie folgende Optionen mit angeben: /target: computer | user
Per Default werden sowohl die Benutzer- als auch die Computereinstellungen aktualisiert. Mit dieser Option können Sie die Aktualisierung einschränken
/force
Wendet alle Einstellungen neu an. Per Default werden nur die geänderten Einstellungen beim Aktualisieren angewendet.
/wait:<sekunden>
Wartet die angegebene Zahl von Sekunden auf die Abarbeitung der Aktualisierung. 0 wartet nicht, –1 wartet bis zum Ende der Aktualisierung. Wenn der eingestellte Timeout abgelaufen ist, erscheint wieder die Systemmeldung bzw. wird das Shell Script weiter abgearbeitet, aber die Aktualisierung der GPO-Einstellungen geht im Hintergrund weiter.
/logoff
Erzwingt eine Abmeldung, wenn die Aktualisierung beendet ist.
/boot
Startet das System nach der Anwendung der Aktualisierung neu
Tabelle 17.6: Optionen für gpupdate
267
17 Referenz
17.4.4
Systemverwaltung
bootcfg Das Kommando bootcfg dient der Verwaltung der Datei boot.ini im Stammverzeichnis der Systempartition. Sie können natürlich auch die Datei mit einem beliebigen Texteditor direkt bearbeiten, aber für den automatisierten Einsatz ist die Benutzung von bootcfg sinnvoller. Das Kommando bootcfg existiert auch in der Wiederherstellungskonsole von Windows (XP und 2003). Dort gibt es eine zusätzliche Option mit dem Namen /rebuild, mit der auf einer Platte alle Installationen von Windows wieder mit den passenden Parametern in ihrer boot.ini versorgt werden. Falls Ihr Windows nach Experimenten in dieser Datei den Dienst verweigert, können Sie so die Standardwerte wiederherstellen. chcp Dieses Kommando arbeitet etwas seltsam, wenn Sie die Darstellung der Shell mit den Rasterfonts (z.B. 10x18) konfiguriert haben. Hier werden bei einem Wechsel der Codepage die Zeichen nicht korrekt angezeigt, da die Rasterfonts nur für die OEM-Codepage vorhanden sind. Falls Sie sich also wundern, warum die Shell partout keine Umlaute ausgibt, obwohl Sie diese im Notepad wunderbar sehen, kann dies daran liegen, dass Sie keinen TrueType-Font für die Konsole eingestellt haben. cipher Der Befehl cipher dient der Verwaltung der Verschlüsselung einer Datei mit EFS. Im Gegensatz zum Explorer und den anderen GUITools können Sie hier auch Dateien in Verzeichnisbäumen bearbeiten. cipher kann sowohl verschlüsseln als auch entschlüsseln. Sollten Sie lieber ein gesondertes Kommando für die Entschlüsselung vorziehen, können Sie sich leicht ein Makro definieren, dass cipher mit den entsprechenden Parametern aufruft. pushd pushd verfügt über eine nette Zusatzfunktion beim Arbeiten mit Netzwerk-Shares. Wird mit Hilfe von pushd zu einem Netzwerk-Share
gewechselt, verbindet das Kommando den Netzwerkpfad mit einem temporären Laufwerksbuchstaben, so dass Sie sich ein net use … sparen. Diese temporären Laufwerke werden von Z: aus abwärts belegt.
17.4.5
Monitoring/Prozessverwaltung
sc Das Kommando sc dient der Kommunikation mit dem Dienstkontrollprogramm (service control manager) und mit einzelnen Diensten.
268
Informationen zu einzelnen Befehlen
Im Gegensatz zu net können Sie hier viel mehr machen, als nur einen Dienst starten oder stoppen. Die allgemeine Syntax sieht wie folgt aus: sc []
Die Tabelle unten gibt die möglichen Kommandos zur Steuerung der Dienste an. Kommando
Beschreibung
query
Fragt den Zustand eines Dienstes ab. Ohne die Angabe eines Dienstes werden alle Dienste aufgelistet.
queryex
Fragt den erweiterten Zustand für einen Dienst ab. Ohne die Angabe eines Dienstes werden alle Dienste aufgelistet.
start
Startet einen Dienst.
pause
Hält einen Dienst an.
interrogate
Sendet ein INTERROGATE Steuersignal an einen Dienst.
continue
Setzt die Ausführung eines Dienstes fort.
stop
Sendet ein Stopp-Signal an einen Dienst.
config
Ändert dauerhaft die Konfiguration eines Dienstes.
description
Ändert die Beschreibung eines Dienstes.
failure
Ändert die Aktionen, die beim Fehlschlagen eines Dienstes ausgeführt werden sollen.
qc
Fragt die Konfigurationsinformationen für einen Dienst ab.
qdescription
Fragt die Beschreibung für einen Dienst ab.
qfailure
Fragt die Fehleraktionen für einen Dienst ab.
delete
Löscht einen Dienst (Austragen aus der Registry!).
create
Erzeugt einen Diensteintrag in der Registry.
control
Sendet eine Steueranweisung an einen Dienst.
sdshow
Zeigt den Security Descriptor eines Dienstes an.
sdset
Setzt den Security Descriptor eines Dienstes.
GetDisplayName
Liefert den Anzeigenamen für einen Dienst.
GetKeyName
Liefert den Schlüsselnamen für einen Dienst.
EnumDepend
Listet die Abhängigkeiten eines Dienstes auf.
Lock
Sperrt die Dienstdatenbank, benötigt keinen Dienstnamen als Parameter.
Boot
Stellt ein, ob der letzte Boot als so genannte Last Known Good-Konfiguration benutzt werden soll.
Tabelle 17.7: Kommandos für die Verwaltung des SCM
269
17 Referenz
Damit ist es nun ein Leichtes, für einen Dienst den Anzeigenamen bzw. der kurzen Schlüsselnamen zu erfahren. Bei net start bekommen Sie immer nur die Anzeigenamen aufgelistet, wie ein Auszug der Ausgabe zeigt: These Windows services are started: Application Management COM+ Event System Distributed File System DNS Client DNS Server : :
Musste vorher in der Registry (meist per WSH-Script) gesucht werden, reicht jetzt ein Kommando: C:\tmp>sc getkeyname "dns server" [SC] GetServiceKeyName SUCCESS Name = DNS C:\tmp>
Die meisten Kommandos von sc dienen der Fehlersuche, sind aber manchmal sehr nützlich. Wenn Sie beispielsweise verhindern wollen, dass ein gestoppter Dienst noch einmal starten, weil Sie die Binärdatei löschen oder ersetzen möchten, können Sie mit dem Kommando sc lock die Dienstdatenbank sperren. Sobald Sie ein „(u)“ eingeben, wird diese wieder freigegeben. typeperf Dieses Kommando erlaubt die Ausgabe der Performance-Daten über die Konsole bzw. in eine Logdatei, ohne erst eine grafische Anwendung starten zu müssen. Sie sammeln die zu überwachenden Zähler in einer Textdatei, jeweils ein Zähler pro Zeile, und starten dann typeperf. Das Format muss dabei folgendem Muster entsprechen: "\\\()\"
Um beispielsweise die verfügbaren Bytes des Arbeitsspeichers auf dem Server orion mitzuschreiben, lautet die Angabe \\orion\Memory\Available bytes
Die Benutzerzeit auf dem Server mail für alle CPUs wird wie folgt definiert: "\\mail\Processor(_Total)\% User Time"
Diese Datei wird dann über die Option -cf an das Kommando typeperf übergeben. Weitere Optionen gibt die folgende Tabelle an.
270
Informationen zu einzelnen Befehlen
-f
Ausgabeformat, Standard ist CSV.
-cf
Die Datei mit den definierten Zählern
-si
Intervall für neue Werte, Standard ist eine Sekunde.
-o
Pfad zur Ausgabedatei oder SQL-Verbindung. Wird nichts angegeben, gehen die Daten nach StdOut.
-q [object]
Listet alle installierten Zählerobjekte ohne Instanzen auf. Kann durch die Angabe eines Objekts auf die Zähler für dieses Objekt beschränkt werden.
-qx [object]
Listet alle installierten Zählerobjekte mit den Instanzen auf. Kann durch die Angabe eines Objekts auf die Zähler für dieses Objekt beschränkt werden.
-sc <samples>
Anzahl der zu sammelnden Datenwerte. Standard ist das Sammeln von Daten, bis der Benutzer das Programm mit Strg-C abbricht.
-config
Datei mit den Konfigurationsoptionen.
-s
Server, der überwacht wird, wenn im Pfad für die Zähler keine Angabe erfolgt ist. Dies erlaubt den schnellen Wechsel des zu überwachenden Systems.
-y
Alle Fragen mit „Ja“ beantworten, keine Rückfrage.
Tabelle 17.8: Die Optionen für typeperf
Mit diesem Kommando haben Sie auch eine schnelle Möglichkeit der Überprüfung, welche Zähler überhaupt für ein Objekt installiert sind. C:\tmp>typeperf -q Processor \Processor(*)\% Processor Time \Processor(*)\% User Time \Processor(*)\% Privileged Time \Processor(*)\Interrupts/sec \Processor(*)\% DPC Time \Processor(*)\% Interrupt Time \Processor(*)\DPCs Queued/sec \Processor(*)\DPC Rate \Processor(*)\% Idle Time \Processor(*)\% C1 Time \Processor(*)\% C2 Time \Processor(*)\% C3 Time \Processor(*)\C1 Transitions/sec \Processor(*)\C2 Transitions/sec \Processor(*)\C3 Transitions/sec The command completed successfully. C:\tmp>
271
17 Referenz
relog Erlaubt die Konvertierung von bestehenden Counter Logs sogar im Windows NT4-Format. Sie können dabei filtern, die Start- und Endzeit bestimmen und das Format wechseln, inklusive des Schreibens in eine SQL-Datenbank. Syntax: relog Tabelle 17.9: Optionen für die Konvertierung von Logdaten mit relog.
272
-a
Hängt an einer bestehenden Binärdatei an
-c <path [path ...]>
Zähler, die gefiltert werden sollen
-cf
Gibt eine Datei an, welche die zu filternden Zähler enthält, standardmäßig werden alle Zähler bearbeitet.
-f
Ausgabeformat
-t
Nur jeden n-ten Wert in die Ausgabedatei übernehmen. Der Standard ist die Übernahme aller Werte
-o
Ausgabedatei oder SQL-Verbindung in der Form SQL:!
-b
Startzeit für den ersten zu übernehmenden Satz
-e
Endzeit für den letzten zu übernehmenden Satz
-config
Datei mit den Optionen, spart Tipparbeit
-q
Auflisten aller Zähler in der Eingabedatei
-y
Alle Fragen mit „Ja“ beantworten.
18
Ausblick
Wie geht es weiter? Nehmen Sie die hier besprochenen Techniken als Ausgangsbasis für eigene Ideen. Viele Kommandos, die hier aus Platzgründen nicht detailliert besprochen werden konnten, bieten weiteres Potenzial für Produktivitätssteigerungen. So lässt sich über die Befehle dnscmd,dhcpcmd und andere Netzwerkkommandos zusammen mit wmic die TCP/IP-Verwaltung Ihres Servers komplett über die Kommandozeile abwickeln. Die prn*-Kommandos der Shell ersparen seit Windows 2003 viele Aufrufe von rundll32 und so weiter. Dieses Buch sollte Sie auf den Geschmack bringen und einen fundierten Einstieg in die Möglichkeiten der Shell unter Windows 200x bieten. Jetzt ist Ihre Fantasie gefragt … Wie lange werden wir noch mit der Shell von Windows arbeiten? Am Horizont beginnt sich langsam das nächste Windows mit dem Codenamen Longhorn abzuzeichnen. Unter den vielen Neuerungen ist auch eine neue Shell für die Verwaltung von Windows über die Kommandozeile. Dieser erste neue Ansatz seit der Shell von MS-DOS trägt den Namen Microsoft Shell (msh). Unter dem Codenamen Monad soll dieser Ansatz die drei Bereiche WSH, die Shell cmd.exe und WMI-Scripting in einer neuen Oberfläche vereinen. Bis diese neue Shell allerdings auf dem Markt ist und dann weite Verbreitung findet, wird es noch dauern. Meine persönliche Schätzung für die großflächige Ablösung von cmd.exe liegt bei etwa 2008. Bis dahin bleibt nur, aus den vorhandenen Möglichkeiten das Optimum herauszuholen. Ich hoffe, dieses Buch hat dazu beigetragen.
273
A A.1
Anhang
Die Aufgaben vom Anfang
Wie versprochen hier die Lösungen für alle Aufgaben aus der Einleitung des Buches. 왘 Kopieren Sie alle .log- und .rpt-Dateien aus dem Stammverzeich-
nis der Rechner von 192.168.1.1 bis 192.168.1.20 in das Verzeichnis logs des Laufwerks C: Ihrer Maschine. for /L %f in (1,1,20) do copy \\192.168.1.%f\c$\ *.log;*.rpt c:\logs\*.* 왘 Finden Sie alle exe-Dateien in system32, die eine gleichnamige
DLL besitzen. for %f in (C:\WINDOWS\system32\*.exe) do @if exist %~df%~pf%~nf.dll echo %f 왘 Welche Dateitypen hat der Internet Explorer auf Ihrem System für
sich registriert? ftype | find /i "iexplore.exe" 왘 Benennen Sie alle Dateien im Ordner c:\fotos so um, dass diese
Dateien aufsteigend nummerisch umbenannt werden. Benutzen Sie das Shell Script zum Umbenennen aller Dateien in einem Verzeichnis aus dem Abschnitt 16.3.6. 왘 Welche Dateien in Ihrem Verzeichnis source wurden im letzten
Monat geändert? Wie groß sind diese Dateien alle zusammen? Hier ist der Code für die Batchdatei (deutsches Datumsformat): @echo off set fsize=0 set mon=%date:~3,2% set /a mon=mon-1 if %mon% LSS 10 set mon=0%mon% c: cd \source for %%f in (*.*) do call :proc "%%f" "%%~tf" echo Total size: %fsize% byte(s). goto :eof :proc
275
A Anhang set fdate=%~2 set fdate=%fdate:~3,2% if not %mon% == %fdate% goto :eof for %%g in (%1) do set /a fsize="fsize+%%~zg"
Für dieses letzte Shell Script sind einige Informationen sinnvoll, die Sie nach der Lektüre des Buches sicher bereits selbst gefunden haben. 왘 Zuerst wird aus der Variablen %date% der aktuelle Monat extra-
hiert und anschließend um eins erniedrigt. Für den späteren Vergleich muss bei den Werten unter 10 wieder die führende Null ergänzt werden. 왘 Jetzt wird als aktuelles Verzeichnis das Verzeichnis source einge-
stellt. Dies wird hier nur deshalb nicht in der for-Schleife gemacht, damit die Zeilen nicht zu lang werden. 왘 In einer for-Schleife werden nun alle Dateien durchlaufen und
der Name der Datei sowie die Datumsangaben per call an eine Sprungmarke übergeben. 왘 Bei dieser Sprungmarke wird aus dem zweiten Parameter (der
Datumsangabe) der Monat extrahiert (für ein deutsches Datum in der Form tt.mm.jjjj) und mit dem gesuchten Monat verglichen. 왘 Falls die beiden Werte nicht übereinstimmen, ist die Bearbeitung
beendet. Andernfalls wird die Variable fsize um den Wert der Dateigröße erhöht. 왘 Nach der for-Schleife wird die Gesamtgröße aller geänderten
Dateien noch ausgegeben. Fertig!
A.2
Literatur
Dies sind die Angaben zu den im Text erwähnten Büchern. Jedes dieser Bücher sollte auf jeden Fall in Ihrem Regal stehen. [1] Jeffrey E. F. Friedl, „Reguläre Ausdrücke“, O’Reilly, ISBN 3-89721349-4 Die Bibel zum Thema reguläre Ausdrücke. Zwar mit dem Schwerpunkt auf Unix-Tools, aber für Administratoren jedes Systems die beste Referenz und Anleitung. [2] Andrew Hunt, David Thomas, „The Pragmatic Programmer“, Addison-Wesley, ISBN 0-20161622-X Das ist bereits ein Klassiker. So viel Erfahrung und Hinweise zu professionellem Arbeiten findet man selten so kompakt, lesbar und praxisorientiert. Lassen Sie sich nicht vom Titel in die Irre leiten: Wer auch nur eine Zeile Shell Scripts oder WSH-Scripts schreibt, wird dieses Buch mit Gewinn lesen. Mein Rat an Vorgesetzte: kaufen, auf dem Schreibtisch liegen lassen. Diesen Vorgang
276
Literatur
wiederholen, bis jeder Mitarbeiter seine Kopie geklaut hat, und dann noch eines für sich selbst kaufen. Es lohnt sich! [3] David Solomon, Mark Russinovich, „Inside Windows 2000“, Microsoft Press, ISBN 3-86063630-8 Die beste technische Beschreibung der „inner workings“ von Windows und den Kernkomponenten des Betriebssystems. Dies ist die offizielle Architekturbeschreibung. Schwere Kost, aber hier finden Sie auch als Admin Details, die sonst nirgends stehen. [4] Holger Schwichtenberg u.a., „Windows Scripting lernen“, Addison-Wesley, ISBN 3-8273-2019-4 Falls Ihnen die Shell doch nicht reicht, Sie aber bisher keine Zeit hatten, das Programmieren zu lernen, bietet Ihnen dieses Buch einen leichten Einstieg in die Welt der WSH-Programmierung. [5] Holger Schwichtenberg, „Windows Scripting“, Addison-Wesley, ISBN 3-8273-1843-2 Wenn jemand in einer Newsgroup schreibt, „steht im Schwichtenberg“, meint er dieses Buch. Mittlerweile in der dritten Auflage die vollständigste Referenz zum Thema Script Hosts, die es gibt. Achtung: Das ist eine Referenz für erfahrene WSH-Leute, keine Einführung! Hier finden Sie für alle Scripting Hosts von Windows eine vollständiger Beschreibung der verwendbaren Objektmodelle und jede Menge technischer Details. Komplexe Script-Programmierung ohne dieses Buch macht meiner Meinung nach nicht viel Sinn. [6] Neal Stephenson, „Die Diktatur des schönen Scheins“, Goldmann Verlag, ISBN 3-44215177-5 Ein Essay, das mit dem Untertitel „Wie grafische Oberflächen die Computernutzer entmündigen“ auf knapp 180 Seiten eine umfassende Darstellung der Ideen hinter GUI und Kommandozeile liefert. Stephenson behandelt nicht nur die aktuellen Systeme Windows, Mac und Linux, sondern liefert auch sehr interessante Gedanken zum kulturellen Hintergrund der Bedienung von Computern. Das Buch ist in den Staaten ein Klassiker. Falls Sie Zeit haben, lesen Sie auch einen der Romane von Neal Stephenson (mein Favorit ist „Cryptonomicon“). [7] G. Pascal Zachary, „Der Krieg der Codes – wie Microsoft ein neues Betriebssystem entwickelt“, Hoffmann & Campe, ISBN 3-45511038-X Besorgen Sie sich dieses Buch, wenn Sie wissen wollen, wie Windows NT ursprünglich entstand und warum manche Sachen auch bei Windows 2003 so sind, wie sie sind. Das Original trägt den Titel „Showstopper“ und ist vielleicht noch gebraucht erhältlich. Dies ist die Geschichte hinter der aktuellen Windows-Plattform, die mehr als die Technik schildert. Streckenweise liest sich das Buch wie der Bericht des zuständigen Therapeuten …
277
A Anhang
278
Stichwortverzeichnis Symbols !variable! 72 %0 120 %variable% 71 & Operator 89 && Operator 89 ( _ ) 90 < Operator 45 > Operator 43 | Operator 46 || Operator 90
A Ablaufsteuerung 93, 123 Active Directory 199 AGGREGATE 174 Aliases 164 Alternate Data Streams 53 auflisten 58 löschen 58 und Shortcuts 59 Anzeigeoptionen 34 APPEND 174 assoc 78 Aufbau von Shell Scripts 117 Ausführbare Dateien 77 Ausführbarkeit 77 Ausführen 119 Ausgabegestaltung 147 Ausgabeumleitung 43 AUTHLEVEL 174
B Backquoting 107 Batch Files Bezeichnung 22 Batch Files siehe Shell Scripts Batch siehe Shell Scripts Batches 117 Bearbeitungsoptionen 34 Bedingte Befehlsauführung 93 beenden von Shell Scripts 127 Befehle 245 Befehlsauführung 93 Befehlserweiterungen Start 23 Befehlsgruppierung 90 Befehlsspeicher 34 Befehlsverknüpfung 89 Benutzer deaktivieren 211
Benutzer anlegen 204 Benutzerinteraktion 137 BinChk 235 bootcfg 268 Bulk Rename 196
C call 127, 129 Call-Logging 133 chcp 268 choice 137 cipher 268 clip 49 cmd.exe 21 Shell 21 Code und Daten 134 Color 39 command.com 30 CSVDE 201 Cursorgröße 34
D Dateiendezeichen 52 Dateihandles 43 Dateiprüfung 94 Dateischleifen 97 Dateiverwaltung 190 Datenstrom 55 Datenübergabe 46 dcgpofix 267 Delete 193 delims 104 Design 145 Ausgabegestaltung 147 Online-Hilfe 146 Parameter 146 Sicherheitsabfragen 146 Dienste 268 diskpart 259 DispChg 236 doskey 111 dsadd 221 dsget 218 dsmod 215 dsmove 220 dsquery 212 dsrm 222 Duplikate entfernen 198
E echo 138 Eingabeaufforderung 24
279
Stichwortverzeichnis Eingabeumleitung 45 endlocal 75 Environment 63 EOF-Zeichen 52 eol 104 errorlevel 75 Erweiterte Variablenexpansion 73 Escape character 27 expand 261 Explorer 36 externe Kommandos 25
F FAILFAST 174 Farben 36 Filter 43 find 47 findstr 159, 161 for 96 Dateimasken 98 Dateioptionen 104 Grundlagen 96 Lesen aus Dateien 103 rekursive Dateisuche 102 Spalten transformieren 108 Variablenersetzung 99 Wertelisten 97 Zählschleifen 103 fsutil 61, 261 ftype 78
G getmac 230 gettype 142 GetWord 190 GNU-Tools 158 gpupdate 267 Gruppen 225 Gruppenmitglieder 225
H Handles 43 hard links 61 help 28 Help and Support Center 28 here documents 134 Hilfe 27 wmic 164 HKEY_CURRENT_USER 38 HKEY_LOCAL_MACHINE 38 hostname 265
I
IMPLEVEL 175 Insert 192 INTERACTIVE 175 Interaktion 137 Internet Explorer 139
K kill 88 Kombiscripte 148 Kombiscripts 135 Kommando abbrechen 25 externes 25 internes 25 Kommandoausführung 77 Kommandoprozessor 21 Kommandos ausführen 24 Kommandotypen 25 Kommandozeile 24 Kommentare 118 Kommunikation 131 Konfiguration 31
L Laufzeitkonfiguration 39 Layout 36 LDAP-Suchen 215 LDAP-Suchfilter 200 LDIFDE 205 Passwörter ändern 224 Leere Dateien 45 Links 61 Literatur 276 LOCALE 175 Locale 143
M Mac-Adresse 229 Makros 111 /exename 114 definieren, ändern, löschen 112 Parameter 113 speichern und laden 115 Makro-Viren 60 md 261 Mehrfachkommandos 89 MessageBox 140 MocWall 238 Modularisierung 148 more 49, 51 mountvol 261 move 263
if defined 94 errorlevel 95 exist 94 Operatoren 95
280
N NAMESPACE 175 net 265 netsh 266
Stichwortverzeichnis netstat 232 Netzwerkadresse 228 NODE 175 nslookup 266 NTFS 53
O Online-Hilfe 28 Optionen 26 OUTPUT 175
P Parameter bei Makros 113 bei Shell Scripts 119 Parameterchecks 119 Parameterprüfung 122 Parsing von Zeilen 106 pathext 77 pause 142 ping 142 Pipelining 46 Portliste 232 PRIVILEGES 175 Prompt 40 Prozesse 82 Prozessinformationen 82 Prozessverwaltung 82 pushd 268
R rd 263 RECORD 176 Redirection 43 Referenz 245 Registry 37, 131 AutoRun 38 CompletionChar 38 Console Settings 39 DefaultColor 39 DelayedExpansion 38 EnableExtensions 38 PathCompletionChar 39 Shell-Konfiguration 37 WSH 184 regular expressions 158 Reguläre Ausdrücke 158 relog 272 ren 263 replace 263 Resource Kit 157, 255 Reverse 195 ROLE 176 runas 81 RunDLL32 151 Druckerverwaltung 154 Grenzen 156
S sc 268 Schleifen 97, 123 Variablenersetzung 99 Verzeichnisse 102 Schriftart 35 Selbstaufruf 127 Selbstmodifikation 132 Services 268 Services for Unix 157 set 65, 68, 137 set /a 69 set /p 70 setlocal 75 setx 66 sfc 263 Shell 21, 181 Historie 26 Kommandoliste 245 Konfiguration 31 Start 23 und WSH 181, 184 verlassen 25 Shell Scripts 117 Bezeichnung 22 Datenaustausch 131 Design 145 Selbstaufruf 127 selbstmodifizierende 132 Synchronisation 130 Shell scripts beenden 127 Shell-Fenster 34 Optionen 34 Titel ändern 41 Shell-Fensters 24 shift 121 skip 104 Sonderzeichen 27 sort 48 Sprache 143 start 79, 81 Startparameter 32 Startverzeichnis 36 StdErr 43 StdIn 43 StdOut 43 Stringmanipulation 73 Subroutinen 125 Support Tools 157, 253 Synchronisation 130 Syntax allgmeine 26 Systeminformationen 142
T takeown 264 taskkill 88
281
Stichwortverzeichnis tasklist 82, 85 Tastenkombinationen 31 Textdateien nummerieren 197 timeout 142 Title 41 tlist 82 tokens 104 Tools zum Buch 158 TRACE 176 type 51 typeperf 270
U Umgebung 63 Umgebungstypen 63 Umgebungsvariablen 63 anlegen 65 auflisten 71 global ändern 66 löschen 68 vordefinierte 64 Umleitung 43 beim WSH 46 uniq 198 Unterroutinen 125 usebackq 104 USER 176
W waitfor 131 Warten 142 where 170 which 189 Win32-Port 158 Windows Script Host 181 Windows-Versionen 17 WMI 163 WMIC 163 Ausgabeformate 177 Beispiele 178 Erste Schritte 167 get 171 list 171 Methoden 173 Schalter 173 Systemverwaltung 178 where-Klausel 170 zyklische Abfragen 172 wmic 143 Aliases 164 WMI-Methoden 173 WSH 181 Installationschecks 182 und die Shell 184
X V Variablen 63 löschen 68 Variablenexpansion 72–73 Verknüpfungen 59 Verzeichnis 28 feststellen 30 wechseln 28 Verzögerte Variablenexpansion 72 Verzweigungen 123
282
XEcho 240
Z Zählschleifen 103 Ziel-Betriebssystem 148 Zielgruppe 15 Zyklische Abfragen 172
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