Was sind Shell-Skripte?

Shell-Skripte sind einfache Textdateien die eine Abfolge von Befehlen enthalten. Mit Shell-Skripten lassen sich einfache Programme schreiben um wiederkehrende Aufgaben effizient zu erledigen. Beispielsweise lassen sich so Backup-Prozeduren intelligent organisieren oder Aufgaben erledigen, die voneinander abhängen. Shell-Skripte werden mit Hilfe eines Editors (vi, emacs, kedit, gedit, kwrite, kate…) erstellt. Um diese Textdateien auszuführen zu können muss man sich nur noch mit ausführbar machen.

Erstellen eines Shellscripts

Man nehme einen Editor seiner Wahl und schreibe z.B. das:

#!/bin/sh  
# Das ist mein erstes Shellscript 

echo "Das ist der Inhalt vom aktuellen Verzeichnis:" 
ls 
echo "das wars schon ;)"

Das “#„ hat eine besondere Bedeutung bei Shellskripten. Es ist dafür da um Kommentare zu schreiben zu können. Alles was nach diesem Zeichen in der Zeile steht wird nicht interpretiert. Bei größeren Skripten ist es sehr nützlich sich ein paar Notizen zu machen um den Überblick nicht zu verlieren. Als nächstes kommt der echo Befehl, er ist dafür da um einfach einen Text beim Ablauf des Skriptes auszugeben. Danach kommt ein ls das den Inhalt des aktuellen Verzeichnisses ausgibt und darauf folgend noch mal ein echo. Hat man diesen Text geschrieben speichert man es z.B. mit dem Namen „shellskript“ ins Homeverzeichnis (nicht als „test“ speichern, der test-Befehl ist in der Bash ist schon belegt). Nun nehme man eine Shell um diese Textdatei aufführbar zu machen der Befehl chmod ist dafür zuständig.

grey@grey:~$ chmod 755 ./shellskript

Das „grey@grey:~$“ ist bei jedem unterschiedlich das ist der so genannte Prompt einer Shell in diesen Fall der Bash. Wenn das chmod geklappt hat dann kann man es gleich ein mal starten. Wenn nicht dann kann es vielleicht sein das die Textdatei nicht im aktuellen Verzeichnis liegt ;-) das “~“ im Prompt steht für das HomeVerzeichnis, das unter /home/BENUTZERNAME/ liegt.

grey@grey:~$ ./shellskript 
Das ist der Inhalt vom aktuellen Verzeichnis: 
Desktop  DIGI  Mail  MySach  nohup.out  test.sh 
das wars schon ;)

Geschafft? Herzlichen Glückwunsch das war Ihr erstes Shellskript :-D

Bestimmen des Interpreters

Skripte beginnen mit dem sog. „shebang“ und dem Interpreter in der ersten Zeile. Das teilt der Shell mit, dass diese Datei vom Interpreter /bin/sh aufgerufen werden soll.

#!/bin/sh

Variablen

Variablen sind dafür da um Dinge wie Wörter, Zahlen usw. zu speichern. Man erkennt sie meisten an einem „$“ Dollarzeichen davor. Variablen kann man durch ein einfaches “=“ Gleichheitszeichen einen Wert zuweisen. Es ist darauf zu achten dass keine Leerzeichen vorkommen.

grey@grey:~$ t=hallo     
grey@grey:~$ echo $t 
hallo 
grey@grey:~$ t=grey     
grey@grey:~$ echo $t 
grey  
grey@grey:~$

Beim Zuweisen eines Wertes einer Variable darf die Variable kein „$“ davor haben. Man kann die Ausgabe von Programmen einer Variable zuweisen. Das geht ganz einfach in dem man der Variable eine Variable zuweist, deren Wert das Ergebnis eines Befehls ist ;-). Mal ein paar Beispiele zur Verdeutlichung:

grey@grey:~$ t=$(echo hallo) 
grey@grey:~$ echo $t 
hallo 
grey@grey:~$ t=$(date) 
grey@grey:~$ echo $t 
Fr Apr 1 17:46:00 UTC 2005 
grey@grey:~$ t=$(ls) 
grey@grey:~$ echo $t 
Desktop  DIGI  Mail  MySach  nohup.out  test.sh 
grey@grey:~$

Was ist jetzt wenn ich ein Leerzeichen will? Dann kann man es einfach das machen:

grey@grey:~$ t="hallo du da?" 
grey@grey:~$ echo $t 
hallo du da? 
grey@grey:~$

und ein Dollarzeichen? Dafür hat die Shell ein Zeichen. Das direkt auf „\“ folgende Zeichen wird nicht interpretiert sogar Returnzeichen nicht! Beispiel:

grey@grey:~$ euro=100     
grey@grey:~$ t="Die Variable heißt \$euro" 
grey@grey:~$ echo $t 
Die Variable heißt $euro 
grey@grey:~$ echo \ 
> $t 
Die Variable heißt $euro 
grey@grey:~$ 

Jetzt wo der Mensch ja faul ist ;-) kann man auch so was machen:

grey@grey:~$ echo "Wie heißt dieses tolle Betriebssystem? $(uname)" 
Wie heißt dieses tolle Betriebssystem? Linux 
grey@grey:~$

Was kann man noch für Scherze mit dem Variablen treiben… Ach ja mit diesem Zeichen “'“ kann man etwas einklammern wenn man nicht will das es von der Shell interpretiert wird. z.B so:

grey@grey:~$ echo '$PATH ist eine Variable ;)' 
$PATH ist eine Variable ;) 
grey@grey:~$

Oder mit diesem Zeichen „`“ kann man statt $() verwenden. z.B so:

grey@grey:~$ echo "Es ist `date +%X` Uhr" 
Es ist 17:33:05 Uhr 
grey@grey:~$

So das waren mal die meisten Dinge die man von der Shell mit Variablen in Skripten machen kann. Jetzt noch ein paar Skriptbesonderheiten. Bei vielen Befehlen auf der Konsole gibt es auch Optionen oder auch Parameter genannt. Diese kann man bei Shellskripte auch verwenden. Die Parameter werden bei Aufruf eines Skriptes werden in den Variablen $1,$2,$3,$…. abgespeichert. Die Variable $0 einhält den Namen des Skriptes und die Variable $# die Anzahl der Parameter. Hier ein kleines Beispielskript (wie oben beschrieben abspeichern und Rechte vergeben)

#!/bin/sh  
# Dateiname: parameter.sh 

echo "Das Skript wurde mit $# Parametern aufgerufen" 
echo "Der erste Parameter ist: $1" 
echo "Der zweite Parameter ist: $2" 
echo "Der dritte Parameter ist: $3"
grey@grey:~$ parameter.sh  
Das Skript wurde mit 0 Parametern aufgerufen 
Der erste Parameter ist:  
Der zweite Parameter ist:  
Der dritte Parameter ist:  
grey@grey:~$ parameter.sh hallo das ist 
Das Skript wurde mit 3 Parametern aufgerufen 
Der erste Parameter ist: hallo 
Der zweite Parameter ist: das 
Der dritte Parameter ist: ist 
grey@grey:~$ parameter.sh "hallo das" ist 
Das Skript wurde mit 2 Parametern aufgerufen 
Der erste Parameter ist: hallo das 
Der zweite Parameter ist: ist 
Der dritte Parameter ist:  
grey@grey:~$ 

Das ist noch ein einfaches Skript es kann noch nicht drauf reagieren wenn weniger Parameter als drei kommen oder wenn mehr. Beim letzten ist eine Besonderheit durch das “ wird das Leerzeichen ignoriert und als ein Parameter zurückgegeben.

siehe auch uname, echo, ls, date

Steuern und Regeln eines Shellskripts

Um ein Shellskript flexibel zu gestalten braucht man Befehle die es einem ermöglichen ein Skript für mehr als eine Sache zu verwenden. Beim Aufruf des Skriptes können dann Optionen dazu dienen das Skript zu Steuern. Anders will man auch auf Fehlersituationen reagieren können oder um abzubrechen bei bestimmten Situationen. Wenn z.B. es ein Verzeichnis nicht vorhanden ist das aber im späteren Verlauf noch gebraucht wird, dann soll das Skript das so Regeln dass das Verzeichnis erstellt wird.

Bedingungen

Bedingungen braucht man dazu um festzustellen ob ein Zustand zutrifft oder nicht. Sie sind dazu dann um herauszufingen ob eine Zahl größer ist oder nicht, ob das kopieren erfolgreich war, ist eine Datei vorhanden?, … usw.

Unter Unix liefert jedes Programm einen solchen Wert. Also ob die Aufgabe erfolgreich abgeschossen wurde oder nicht. Ein sehr sehr oft verwendetes Programm ist test es hat viele Optionen für verschiedenste Tests. Aber wie gesagt man kann dazu fast jedes Programm verwenden. Um zu reagieren wenn ein test nicht erfolgreich bzw. erfolgreich war gibt es zwei Zeichen einmal

BEFEHL1 && BEFEHL2 Wenn BEFEHL1 erfolgreich war dann wird BEFEHL2 ausgeführt
BEFEHL1 || BEFEHL2 Wenn BEFEHL1 fehlschlägt dann wird BEFEHL2 ausgeführt

Zum Verdeutlichung mit diesem Zustand ein Beispiel mit touch. Ich möchte mit touch ein Datei nach “/“ erzeugen mit dem Namen „hallo“. Sollte touch irgendwelche Meldungen bringen dann werden sie mit “&>“ nach “/dev/null“ umgeleitet (/dev/null ist ein „Schwarzes Loch“ ;-) alles was man da hineinwirft ist weg.). Wenn touch fertig ist dann wird überprüft ob es vielleicht nicht erfolgreich war (“„||““), wenn das der Fall ist wird mit echo „Keine Schreibberechtigung“ ausgegeben.

grey@grey:~$ touch /hallo &> /dev/null || echo "Kein Schreibberechtigung" 
Keine Schreibberechtigung 
grey@grey:~$ 

Eigentlich ein blödes Beispiel aber es soll nur zeigen was möglich ist.

Eine Sache die ich gerne verwende ist das ich bei einen Fehler eine Funktion aufruft die das Skript mit einer Fehlermeldung beendet. Es schaut so in der Art aus:

#! /bin/sh 

fatal() { 
 echo $@ 
 exit -1 
} 

# zum Beispiel ein Verzeichnis ins Root-Verzeichnis erstellen  
# gibt bestimmt einen Fehler ;-) als User. 

mkdir /testerei || fatal "Kommte Verzeichnis /testerei nicht erstellen :-(. EXIT -1!" 

..in einen Skript das man oft braucht hat man einige Kontrollen eingebaut damit es bei möglichen Fehlern lieber vorher abbricht. Vielen Meldungen von Programmen die was nicht gefunden haben oder so kann man dadurch im vornherein vermeiden.

Unterschiedliche Behandlung

Man kann mit if eine Ergebnis einer Bedingungen unterschiedlich behandeln lassen. Man braucht so eine Funktion wenn man auf beide Fälle reagieren will. Ein Beispiel:

grey@grey:~$ if touch /hallo &> /dev/null ; then echo "Datei wurde erzeugt" ; else echo "Kein Schreibeberechtung" ; fi 
Kein Schreibeberechtung 
grey@grey:~$ if touch ~/hallo &> /dev/null ; then echo "Datei wurde erzeugt" ; else echo "Kein Schreibeberechtung" ; fi 
Datei wurde erzeugt 
grey@grey:~$

Die for Schleife

Mit for kann man eine Liste abarbeiten. Diese Liste kann aus Dateinamen oder einfach Wörtern bestehen. Diese Schleife wird oft verwendet um z.B. viele Dateien nacheinander zu Bearbeiten.

Die while Schleife

Mit while hat man eine Schleife in der man solang bleibt bis die Bedingung die nach while kommt nicht mehr stimmt. Mit der Schleife kann man z.B. Parameter abarbeiten oder mit sleep auf ein bestimmtes Ereignis warten usw.

Unterschiedliche Behandlung mit case

case ist ein Möglichkeit eine Variable auf mehrere möglichen Inhalten zu prüfen welche zutreffend ist. Es wird oft zum erkennen von Optionen verwendet.

Funktionen

Funtionen sind dafür da um bestimmt Abläufe nicht immer und immer wieder in ein Skript schreiben zu müssen. Mehr dazu findet man unter ShellscriptFunktionen. Hier ein kleines Beispiel:

dateitest() 
{ 
 # Teste ob die Datei vorhanden ist. 
 if [ -f "$1" ] 
 then 
  echo "Datei gefunden" 
 else 
  echo "Datei nicht gefunden" 
 fi 
} 

dateitest Dateiname.odt 

Speicherorte

Damit die Shell Programme ausführen kann, muss sie diese Programme erst einmal finden. Dazu benutzt die Shell die Umgebungsvariable $PATH. Sie enthält eine Liste von Verzeichnissen siehe dazu das Beispiel:

grey@grey:~$ echo $PATH 
/home/grey/.dist/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/usr/local/sbin:/usr/local/bin:/usr/games:.

Die verschiedenen Pfade sind mit einem Doppelpunkt verbunden. Der letzte Eintrag ist ein besonderer, es ist nur ein Punkt. Er stellt das aktuelle Verzeichnis dar, in dem man sich befindet. Wenn Skripte häufig gebraucht werden, ist es sinnvoll es an einen dieser Orte zu verschieben oder den Pfad zum Skript aufzunehmen —> ~/bin anlegen und in $PATH aufnehmen.

Beispiele

Weblinks