Shell-Scripts automatisieren Routinearbeiten

Effiziente und Administration und Pflege von Systemen mit Scripts

Immer wiederkehrende Routinearbeiten lassen sich in den meisten Betriebssystemen automatisieren. In den Betriebssystemen der UNIX-Familie (UNIX, SINIX, AIX, ULTRIX, LINUX usw.) ist diese Automatisierung sehr weit entwickelt, es steht in Form von sogenannten Shell-Scripts eine umfassende Programmiersprache zur Verfügung. Diese Programmiersprache verfügt über eine stattliche Anzahl von Befehlen und im Gegensatz zu Batch-Programmen sogar über mehrzeilige Kontroll-Strukturen wie IF/THEN/ELSE oder SWITCH.

Alle Befehle in einem Shell-Script werden wie bei einer Batch- oder Stapeldatei während der Ausführung von einer Shell interpretiert. Sehr verbreitet ist in diesem Zusammenhang die C-Shell (CSH) welche eine Ur-Version des Kommando-Interpreters von UNIX-Systemen darstellt.

Ein Shell-Script ist eine einfache Text-Datei mit einer logischen Abfolge von Befehlen aus dem Betriebssystem. Um ein Shell-Script zu erstellen, brauchen man also zumindest Kenntnisse über den Befehlsumfang des Betriebssystems.

Bearbeitung von Shell-Scripts
Weiterhin ist es von Vorteil einen leistungsfähigen Editor zur Verfügung zu haben. Wer mit einm Vi-Editor von UNIX nicht gerne arbeitet kann auch Shell-Scripts in einem Text-Editor unter Windows bearbeiten und sie beispielsweise per FTP auf den Server übertragen. Bei dieser Variante für ungeübte UNIX-Freaks wird natürlich vorausgesetzt dass sie überhaupt im Windows-Umfeld arbeiten und das UNIX-Terminal beispielsweise via eine Telnet-Sitzung betreiben.







Einfaches Beispiel als Basis

Um nun ein erstes Shell-Script zu erstellen starten wir also einen Editor (Vi) und schreiben die Befehle für einen einfachen Ablauf in einer logischen Reihenfolge auf. Als einfaches Beispiel wollen wir eine Ausgabe der Anzahl angemeldeter Benutzer auf dem Bildschirm anzeigen:

#Kommentar für C-Shell
#UCOUNT - Anzahl der angemeldeten Benutzer ausgeben
echo "Es sind "`who | wc -l`" Benutzer angemeldet."

Zu beachten ist der Kommentar in den ersten beiden Zeilen, soll die C-Shell das Script ausführen, so ist mindestens ein Kommentar am Anfang des Scripts notwendig. Dies kann selbstverständlich auch direkt ein «sinnvoller» Kommentar sein wie beispielsweise der Programm-Name und Autor.

In der Kommandozeile wird der Befehl von links nach rechts ausgeführt. 
  • Die erste Anweisung (echo) initiiert eine Text-Ausgabe durch die C-Shell direkt auf dem aktuellen Terminal. Der ausgegebene Text wird dabei in "Anführungszeichen" eingeschlossen
  • Innerhalb des Textes erfolgt eine Unterbrechung durch den WHO-Befehl der anzeigt, welche Benutzer angemeldet sind
  • Die Ausgabe von who wird durch ein Piping an wc (word count) weitergeleitet, die Option -l bedeutet, dass die Zeilen (lines) gezählt werden sollen
  • Die Textausgabe wird wiederum mit Anführungszeichen fortgesetzt und auch so abgeschlossen
Eine (nicht immer) kurze Anleitung zur Syntax (Verwendungs- / Verarbeitungs-Regeln) der einzelnen Befehle findet man in den Handbuch-Seiten (MAN-Pages) in UNIX.

Die Befehlsausgabe bzw. Interpretation der Befehl wird im Terminal-Fenster wie folgt dargestellt:

/usr/users/lenzs% who
lenzs ttyp0 Jan 10 22:39 (pop-zh-5-dialup-)

/usr/users/lenzs% echo 'Es sind 'who | wc -l ' Benutzer angemeldet.'
Es sind 1 Benutzer angemeldet.
/usr/users/lenzs% _

Der erste Abschnitt ist ein Kontroll-Eingabe von who, in der nur die einzige aktive Sitzung von des Benutzers «lenzs» angezeigt wird. Die Ausgabe des Script wird im zweiten Abschnitt dargestellt.

Benutzereingaben interpretieren

Im folgenden Beispiel sollen vom Benutzer die Eingabe eines Suchbegriffs entgegengenommen und das Wort anschliessend innerhalb von Textdateien im DIC-Verzeichnis des ULTRIX-Rechners (Übungsgerät an der TBZ-Technikerschule, das wir mit Ehrfurcht bedient haben) gesucht werden.

#!/bin/csh
#Ein Dixionaer von Marc Kampus und Raphael Mueller

cd /usr/users/public/dic
echo -n 'Suchwort ? '
set Suchwort = $<
grep $Suchwort *

if ($status == 1) then
    echo 'Suchwort nicht gefunden'
endif

Zu beachten ist dabei die Syntax des ECHO-Befehls in Kombination mit dem SET-Befehl. Die Option -n verhindert einen Zeilenwechsel von ECHO, der SET-Befehl liest übernimmt die Eingabe des Benutzers in die Variable Suchwort.

Mit dem Kommando GREP wird in allen Dateien (*) nach dem Suchwort geforscht. Beachtlich ist auch die IF-Kontroll-Struktur am Ende, die es erlaubt über die STATUS-Variable den Erfolg des GREP-Kommandos zu überprüfen. STATUS ist vergleichbar mit dem ERRORLEVEL von Batch-Programmen

Parameter-Übernahme von der Kommandozeile

Viele komfortable UNIX-Kommando verfügen über einen Kommandozeilen-Parameter -h oder -? der eine Hilfe zur Verwendung anzeigt. Kommanozeilen-Parameter lassen sich auch in einem Shell-Script einlesen.

# -----------------------------------------------------------
# Script : BigBrother
# Shell : C-Shell (csh)
# Autor : Stefan Lenz 98b
# Datum : 09.11.20xx
# Funktion : Prueft, ob angegebene Benutzer angemeldet sind
# -----------------------------------------------------------

set version='1.0'
set autor='Stefan Lenz'

Zunächst wird geprüft, ob genügend Argumente übergeben wurden oder ob der Anwender eine Hilfe benötigt. Die Abfrage der Argumente erfolgt in gewohnter C-Manier über den Argument-Vektor argv[1], der auf das Array im Arbeitsspeicher zeigt in dem die Kommandozeilen-Argumente verfügbar sind.

# Syntax pruefen, sind genuegend Argumente vorhanden?
# Ist die Syntax nicht korrekt wird Hilfe angezeigt
if (($#argv < 1) || ($1argv == '-?')) then
   clear
   echo '--------------------------------------'
   echo $0' - Version ' $version
   echo $autor
   echo '--------------------------------------'
   echo ' '
   echo 'Fehler bei der Parameterangabe, es ist mindestens ein Benutzername'
   echo 'als Parameter notwendig.'
   echo ' '
   echo 'Beispiel: bigbrother meier lenzs'
   echo ' '
   echo 'Beschreibung: bigbrother prueft, ob die Benutzer meier und lenzs'
   echo 'sich angemeldet haben.'
   echo ' '
   exit
endif

Nun wird als Benutzereingabe ein Dateiname eingelesen, falls die Datei bereits existiert (von einer früheren Verarbeitung) wird sie gelöscht.

# Eingabe des Logfile-Dateinamens, wird in Variable filename gespeichert
echo -n 'Filename: '
set filename = $<
# Wenn die Datei existiert, wird sie geloescht

if (-e $filename) then
   rm $filename
endif

Der nächste Abschnitt im Shell-Script ist nun etwas komplexer:
  • LINES ist ein Index-Zähler vom Typ Integer
  • WHILE-Schleife arbeitet jedes Kommandozeilen-Argument ab
  • FOREACH-Schleife arbeitet alle Argumente in der Liste ab ($u ist eine Laufvariable)
  • WHO-Kommando wird ausgeführt und über einen GREP gefiltert nach einem Kommandozeilenargument
  • GREP-Textsuche in der allenfalls vom ersten GREP erstellten Datei wird im SILENT-Mode ausgeführt und zählt nur die Zeilen (C = COUNT)
  • Wenn der Mitarbeiter in WHO nicht aufgeführt wurde wird ein Eintrag in filename vorgenommen
  • Ganz zum Schluss wird ein Kontrollmeldung ausgegeben sowie der Inhalt der Log-Datei die von BIGBROTHER erstellt wurde

@ lines = 0
while ($lines < $#argv)
  foreach u ($*)

  if ({(who | grep -s $u)}) then
    grep -sc $u $filename >& /dev/null
    # $status = 2 -> Datei existiert nicht
    # $status = 1 -> GREP nicht erfolgreich
    # $status = 0 -> GREP war erfolgreich
    if (($status == 2) || ($status == 1)) then
       echo -n $u >> $filename ; date >> $filename
       @ lines = $lines + 1
    endif
endif
end

sleep 300
end

echo 'Es sind alle verlangten Mitarbeiter eingetroffen:'
more $filename

Dieses Beispiel-Script beinhaltet alle wesentlichen Aspekte eines Shell-Scripts, weitere Kontrollstrukturen wie SWITCH (entspricht einem SELECT CASE in Visual Basic) finden sie in den MAN-Pages des Betriebssystems.