• Keine Ergebnisse gefunden

Shell-Skript - Aufbau Shell-Skript Inhalt Shell-Programmierung

N/A
N/A
Protected

Academic year: 2021

Aktie "Shell-Skript - Aufbau Shell-Skript Inhalt Shell-Programmierung"

Copied!
10
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

Foliensatz 7

Shell-Programmierung

Inhalt

• Aufbau Shell-Skript

• Tests

• Eingabe- und Ausgabebefehle

• Verzweigungen

• Schleifen

• Funktionen

• Hilfreiche (Bash-)Befehle

Shell-Skript

• Ein Shell-Skript ist einen Textdatei, die von der Shell interpretiert wird. Um ein möglichst portables Shell-Skript zu schreiben, darf man nur die POSIX-konforme Syntax und die POSIX-konformen Befehle verwenden.

Da aber die Bash die Standardshell der meisten Linux-Distributionen und /bin/sh zumeist ein Link auf /bin/bash ist, ist es in den meisten Fällen okay, auch spezielle Bash-Befehle zu verwenden.

• Alles, was man auf der Kommandozeile eingeben kann, kann man auch in einem Skript verwenden.

Umgekehrt gilt das gleiche.

Daher ist es möglich, zuerst direkt auf der Kommandozeile Befehle zu kombinieren und auszuprobieren und später daraus ein Skript zu machen.

Eine gute Dokumentation, die kurz und bündig ist, aber viele Beispiele umfasst, ist der Advanced Bash- Scripting Guide.

Shell-Skript - Aufbau

• In einem Shell-Skript werden meist überwiegend Shell-Befehle benutzt. Zu den Shell-Befehlen gehören unter anderem:

• Variablenzuweisungen

• Tests (test, [ ... ], [[ ... ]])

• Verzweigungen (if, case)

• Schleifen (for, while, until)

• Ein- und Ausgabebefehle (read, echo, printf)

• Funktionen (function)

• Darüber hinaus können natürlich auch alle anderen Programme wie head, tail, cut, … verwendet werden.

(2)

• Um ein Skript ausführbar zu machen, muss das Executable-Bit auf die Datei gesetzt werden und in der ersten Zeile muss ein entsprechender Shebang stehen (für portable Skripte #!/bin/sh, sonst

#!/bin/bash). Oder man ruft das Skript direkt mit Hilfe der Bash auf, also bash skript.sh.

Shell-Skript - Stellungsparameter

• Einem Shell-Skript können beim Aufruf wie jedem anderen Befehl Argumente übergeben werden.

Die Shell stellt für das Arbeiten mit den Argumenten die Stellungsparameter sowie einige spezielle Parameter zur Verfügung.

• $1, $2, $3, … sind die Stellungsparameter. In $1 ist das erste Argument, in $2 das zweite Argument und so weiter. Man kann ihnen keinen Wert direkt zuordnen (nur über den Bash-Befehlset).

• Von den speziellen Parametern sind $*, $@ und $# für das Arbeiten mit den Stellungsparametern wichtig.

Shell-Skript - Spezielle Parameter

• Den sogenannten speziellen Parametern kann kein Wert zugewiesen werden und sie werden von Shell speziell behandelt:

• $*: Expandiert zu den Stellungsparametern. Werden doppelte Anführungszeichen benutzt ("$*"), so wird zu einem einzigen Wort expandiert. Die Werte der Stellungsparameter sind durch das erste Zeichen von $IFS (normalerweise das Leerzeichen) getrennt (also "$1 $2 $3 ...").

• $@: Expandiert zu den Stellungsparametern. Werden doppelte Anführungszeichen benutzt ("$@"), so expandiert jeder Parameter zu einem eigenen Wort (also "$1" "$2" "$3" ...).

• $#: Expandiert zur Anzahl der Stellungsparameter.

• $?: Expandiert zum Rückgabewert des letzten, im Vordergrund ausgeführten Befehls.

• $$: Expandiert zur PID der Shell (auch wenn in einer Subshell verwendet).

• $!: Expandiert zur PID des letzten, im Hintergrund gestarteten Befehls.

• $0: Expandiert zum Namen der Shell oder des Shell-Skripts.

Shell-Skript - Befehle für Stellungsparameter (set, shift)

set - Setzt oder löscht Shell-Optionen bzw. setzt Stellungsparameter.

» Wir gehen nicht näher auf die Shell-Optionen ein.

» Syntax: set -- Parameter1 Parameter2 ...

» $ set -- Param1 "Param 2"

$ echo $1 Param1

$ echo $2 Param 2

shift - Entfernt die ersten N Stellungsparameter und rückt die anderen nach.

» Falls kein Argument angegeben ist, wird als Anzahl N=1 benutzt.

» Das heißt, der Parameter $N+1 wird zu $1, $N+2 wird zu $2 und so weiter.

» Hat als Rückgabewert 0, wenn N nicht negativ und kleiner als $# ist.

(3)

» $ set -- Param1 "Param 2" "Param 3"

$ echo $1 Param1

$ shift 2

$ echo $1 Param 3

Shell-Skript - Beispiele

Hier ein Beispiel für ein einfaches Shell-Skript:

#!/bin/sh

#

# Wir werden jetzt einige Stellungsparameter und spezielle Parameter testen.

# Dazu dieses Skript mit mindestens drei Argumenten aufrufen.

echo Alle Parameter mit \$*: \""$*"\"

echo Alle Parameter mit \$@: \""$*"\"

echo Anzahl der Parameter: $#

echo $1 echo $2 echo $3 shift 3

echo Anzahl der Parameter: $#

echo $1 $2 $3

• In der ersten Zeile ist der Shebang. Dieser muss immer vorhanden sein!

• Danach folgen drei Zeilen mit Kommentaren (Shell-Kommentare beginnen mit dem Hash-Zeichen # und gehen dann bis zum Zeilenende).

• Anschließend sind die auszuführenden Befehle.

Tests - Befehle

• Die Bash besitzt drei verschiedene Möglichkeiten, um Tests auszuführen:

• test: Eingebauter Bash-Befehl, der es ermöglicht, Zeichenketten oder Zahlen miteinander zu vergleichen bzw. Dateien zu überprüfen. Üblicherweise gibt es auch einen eigenständigen Befehl (in Ubuntu /usr/bin/test).

• [ ... ]: Das ist nur eine andere Syntax für den test-Befehl. Man muss dabei die schließende Klammer immer zwingend angeben. Auch dafür gibt es einen eigenständigen Befehl (in Ubuntu /usr/bin/[).

• [[ ... ]]: Das ist eine Bash-Erweiterung der obigen Syntax, die die Verwendung angenehmer macht. Dieser Befehl ist eigentlich ein reserviertes Wort der Bash und wird daher von der Bash etwas anders verarbeitet als normale Befehle. Daher muss man Operatoren wie < und && nicht maskieren. Abgesehen davon können die gleichen Tests wie bei den obigen Varianten verwendet werden.

Bezüglich der Unterschiede der drei Möglichkeiten siehe auch BashFAQ/031.

• Verwendet wird wie üblich der Rückgabewert: 0 (wahr) bzw. 1 (falsch).

(4)

Tests 1

Hier eine Auflistung der wichtigsten Tests:

• Dateiexistenz und Dateitypen:

• -e Datei → Existiert die Datei?

• -d Datei → Existiert die Datei und ist sie ein Verzeichnis?

• -f Datei → Existiert die Datei und ist sie eine normale Datei?

• -L Datei → Existiert die Datei und ist sie ein symbolischer Link?

• -s Datei → Existiert die Datei und ist sie nicht leer?

• Zeichenketten:

• -z String → Wahr, falls die Länge der Zeichenkette 0 ist.

• -n String → Wahr, falls die Länge der Zeichenkette nicht 0 ist.

• String1 = String2 → Wahr, falls beide Zeichenketten gleich sind.

• String1 != String2 → Wahr, falls beide Zeichenketten nicht gleich sind.

• String1 < String2 → Wahr, falls String1 lexikographisch vor String2 kommt.

• String1 > String2 → Wahr, falls String1 lexikographisch nach String2 kommt.

Tests 2

• Arithmetische Operatoren:

Syntax: Argument1 OPERATOR Argument2

• -eq → Wahr, falls Argument1 gleich Argument2 ist.

• -ne → Wahr, falls Argument1 ungleich Argument2 ist.

• -lt → Wahr, falls Argument1 kleiner Argument2 ist.

• -le → Wahr, falls Argument1 kleiner gleich Argument2 ist.

• -gt → Wahr, falls Argument1 größer Argument2 ist.

• -ge → Wahr, falls Argument1 größer gleich Argument2 ist.

• Für einen Übersicht aller möglichen Tests siehe „CONDITIONAL EXPRESSIONS‘ in der Manpage der Bash oder help test.

• Nützlich für Tests sind auch folgende zwei Bash-Befehle:

• true → Hat als Rückgabewert immer 0 (wahr)

• false → Hat als Rückgabewert immer 1 (falsch)

Tests - Beispiele

• Überprüfen, ob eine Datei existiert und eine reguläre Datei ist:

$ [[ -f Datei ]] && echo ja || echo nein

• Vergleichen von Zeichenketten:

$ STR1=""

$ STR2="hallo"

$ STR3="HALLO"

(5)

$ [ $STR1 = "" ] && echo ja || echo nein -bash: [: =: unary operator expected nein

$ [ "$STR1" = "" ] && echo ja || echo nein ja

$ [[ "$STR1" = "" ]] && echo ja || echo nein ja

$ [[ $STR2 < $STR3 ]] && echo ja || echo nein ja

Ausgabebefehle (echo, printf)

echo - Gibt die Argumente aus.

» Optionen: -n → Keinen Zeilenumbruch ausgeben, -e → Auswertung von einigen maskierten Zeichen erlauben (z.B. \n – neue Zeile, \r – Wagenrücklauf, \t – Tabulator), -E → explizit die Auswertung von maskierten Zeichen unterdrücken.

» Der Rückgabewert ist immer 0 außer ein Schreibfehler tritt auf.

» $ echo a b c a b c

$ echo -e "a\tb"

a b

printf - Formatiert die Argumente basierend auf einem Format.

» Syntax: printf [-v Variable] Format [Argumente]

» Option -v Variable → die Ausgabe wird der Variablen zugewiesen und nicht auf der Standardausgabe ausgegeben

» Format ist eine Formatspezifikation gemäß man 1 printf.

» $ printf "%s %5.2f\n" Hallo 5.3236 Hallo 5.33

$ printf "%7.2f\n" 5.333 4.888    5.33

   4.89

Eingabebefehle (read)

read - Liest eine Zeile von der Standardeingabe und teilt sie in Felder.

» Syntax: read [Optionen] [Name ...]

» Optionen: -p Prompt → einen Eingabeprompt anzeigen (ohne Zeilenumbruch), -s → Eingabe vom Terminal nicht ausgeben (z.B. für Passworteingabe), -t Timeout → nach einer bestimmten Anzahl von Sekunden die Eingabe abbrechen.

» Die eingelesenen Felder werden den angegebenen Variablen zugewiesen, das letzte Feld bekommt alles, was übrig bleibt. Wird kein Variablenname angegeben, wird die Zeile in der Variablen REPLY gespeichert.

» $ echo "a b c" | read a b c

$ echo $a$b$c

$ echo "a b c" | (read a b c && echo $a$b$c) abc

$ read -p "Bitte um Eingabe: " -t 5 VAR && echo $VAR || echo Abbruch # keine Eingabe

Bitte um Eingabe: Abbruch

$ read -p "Bitte um Eingabe: " -t 5 VAR && echo $VAR || echo Abbruch Bitte um Eingabe: Hallo du

(6)

Hallo du

if Verzweigung

• if Liste; then Liste; [ elif Liste; then Liste; ] ... [ else Liste; ] fi

• Eine if-Verzweigung wird in „Wenn - dann“-Fällen verwendet, d.h. wenn man auf Grund eines Rückgabewerts den Programmablauf entweder in die eine oder in die andere Richtung lenken will.

• Eine Liste ist dabei eine Liste von Befehlen wie in „Arbeiten mit der Bash“ definiert. Die Listen bei if und elif entsprechen den Verzweigungsbedingungen.

• • Die if Liste wird ausgeführt und wenn der Rückgabewert 0 ist, wird die then Liste ausgeführt.

• Ansonsten wird jede (optionale) elif Liste der Reihe nach ausgeführt und wenn der Rückgabewert 0 ist, die zugehörige then Liste ausgeführt und der Befehl beendet.

• Falls das auch nicht der Fall ist und es eine else Liste gibt, wird diese ausgeführt.

• Der Rückgabewert ist der Rückgabewert des letzten ausgeführten Befehls oder 0, falls keine Bedingung wahr war.

if Verzweigung - Beispiel

• Hinweis: Eine Liste kann auch durch einen Zeilenumbruch abgeschlossen werden. Das erlaubt eine schönere Darstellung in einem Shell-Skript.

• Als Beispiel werden wir ein Skript schreiben, dass von Fahrenheit in Celsius umrechnet und umgekehrt.

Das Skript braucht zwei Argumente: Das erste Argument gibt die Skala für die Temperatur an (Fahrenheit oder Celsius) und das zweite Argument die Grad.

Folgende Schritte braucht man für die Berechnung von Celsius aus Fahrenheit:

1. Die Temperatur in Fahrenheit nehmen und davon 32 abziehen.

2. Das Ergebnis durch 1.8 dividieren.

3. Das Ergebnis ist die Temperatur in Celsius.

In Formeln zusammengefasst:

• °C = (°F - 32) * 5/9

• °F = °C * 9/5 + 32

case Verzweigung

• case Wort in [Muster [ | Muster ] ... ) Liste ;; ] ... esac

• Eine case-Verzweigung wird verwendet, wenn es für ein Wort mehrere mögliche Werte gibt und abhängig davon bestimmte Befehle ausgeführt werden sollen.

• • Das Wort und die Muster werden expandiert und es wird überprüft, ob das expandiert Wort auf ein expandiertes Muster nach den Regeln der Pfadexpansion (siehe „Arbeiten mit der Bash“) passt.

(7)

• Falls ein Muster passt, wird die entsprechende Liste ausgeführt und kein weiteres Muster wird überprüft (wenn ;; am Ende der Liste benutzt wird, es gibt auch noch andere Möglichkeiten, die wir hier nicht behandeln).

• Der Rückgabewert ist 0, wenn kein Muster gepasst hat oder sonst der Rückgabewert des letzten ausgeführten Befehls der Liste.

• Wir schreiben nun das vorhin erstelle Programm um und verwenden jetzt case anstatt von if.

for Schleife

• for Name [in Wörter ... ] ; do Liste ; done

for (( Ausdruck1 ; Ausdruck2 ; Ausdruck3 )) ; do Liste ; done

• Eine for-Schleife wird verwendet, um Befehle eine bestimmte Anzahl an Durchläufen auszuführen.

• • In der ersten Variante werden die Wörter expandiert. Dann wird die Variable Name der Reihe nach auf die einzelnen Worte gesetzt und jedes Mal die Liste an Befehlen ausgeführt.

Wenn die Expansion nichts ergibt, wird als Rückgabewert 0 zurückgegeben, ansonsten ist der Rückgabewert der des letzten ausgeführten Befehls.

• In der zweiten Variante wird zuerst Ausdruck1 arithmetische ausgewertet. Ausdruck2 wird solange ausgewertet, bis der Wert 0 herauskommt. Jedes Mal, wenn bei Ausdruck2 ein Wert ungleich 0 herauskommt (entspricht Rückgabewert 0), wird die Liste ausgeführt und Ausdruck3 arithmetisch ausgewertet.

• Der Rückgabewert ist der Rückgabewert des letzten Befehls in der Liste oder 1, falls einer der Ausdrücke ungültig sein sollte.

for Schleife - Beispiel

• Als Beispiel werden wir ein Skript schreiben, dass alle Benutzernamen und IDs der Benutzer, die in einer Datei definiert sind, auflistet.

Das Skript braucht als Argument die Datei, von der es die Daten lesen soll. Die Datei muss dabei dem Format der Datei /etc/passwd folgen.

while/until Schleife

• while Liste1; do Liste2; done until Liste1; do Liste2; done

• Die while-Schleife dient zur Ausführung von Befehlen, solange eine Bedingung wahr ist. Die until -Schleife dient zur Ausführung von Befehlen, bis eine Bedingung wahr ist.

• • Bei der while-Schleife werden die Befehle in Liste2 wiederholt ausgeführt, solange der letzte Befehl in Liste1 einen Rückgabewert von 0 hat.

• Bei der until-Schleife werden die Befehle in Liste2 solange ausgeführt, bis der letzte Befehl in Liste1 einen Rückgabewert von 0 hat.

• Der Rückgabewert ist in beiden Fällen der Rückgabewert des letzten ausgeführten Befehls der Liste2, oder 0, falls von Liste2 kein Befehl ausgeführt worden ist.

(8)

• Wir schreiben nun das vorhin erstelle Programm um und verwenden jetzt while anstatt von for.

Funktionen

• name () Verbundbefehl

function name [()] Verbundbefehl

• Eine Shell-Funktion erlaubt das Zuweisen eines Namens zu einem Verbundbefehl und dessen Aufruf über diesen Namen (wie einen einfachen Befehl).

Die Verwendung des reservierten Worts function ist optional; falls es nicht verwendet wird, muss das Klammernpaar angegeben werden.

• Ruft man eine Funktion auf, so werden innerhalb der Funktion die übergebenen Argumente den Stellungsparametern temporär zugewiesen.

• Der Rückgabewert einer Funktion, wenn sie ausgeführt wird, ist der Rückgabewert des letzten ausgeführten Befehls.

Funktionen - Beispiele

• Jeder Verbundbefehl ist möglich, normalerweise verwendet man { ... ; }, damit Änderungen an Variablen innerhalb der Funktion auch im Aufrufkontext wirksam sind.

$ A=5

$ testit () (A=7; echo Innerhalb: $A)

$ echo $A; testit; echo $A 5

Innerhalb: 7 5

$ testit () { A=7; echo Innerhalb: $A ;}

$ echo $A; testit; echo $A 5

Innerhalb: 7 7

• Das Verwenden von Stellungsparametern funktioniert wie üblich:

$ function add { echo Parameter: $@; echo $(($1 + $2)); }

$ add 4 6 Parameter: 4 6 10

Hilfreiche Befehle (alias, unalias, unset)

alias - Definiert Aliase oder zeigt sie an.

» Bash-interner Befehl.

» Wird benutzt, um oft eingegebenen Befehlen kürzere Namen zuzuordnen oder um Standardoptionen automatisch zu setzen.

» $ alias ls

alias ls='ls --color=auto'

$ alias z='ls -alF --color=auto' unalias - Entfernt Aliase.

» Bash-interner Befehl.

(9)

» $ unalias z

$ alias z

-bash: alias: z: not found

unset - Variablen und Funktionen löschen.

» Löscht die angegebenen Variablen oder Funktionen.

» $ VAR=5; echo $VAR 5

$ unset VAR; echo $VAR

Hilfreiche Befehle (source, export)

source - Führt Befehle von einer Datei in der aktuellen Shell aus.

» Syntax: source Dateiname [Argumente] oder . Dateiname [Argumente]

» Wird z.B. von Ubuntu für das Setzen von Standardwerten für Startskripte benutzt.

» $ echo "$ACTIVE_CONSOLES"

$ . /etc/default/console-setup

$ echo "$ACTIVE_CONSOLES"

/dev/tty[1-6]

export - Markiert Variablen für den automatischen Export an Subprozesse.

» Wenn eine Variable definiert wird, ist sie nur für die aktuelle Shell und Subshells sichtbar. Erst durch das Markieren mittels export stehen Variablen auch ausgeführten Befehlen zur Verfügung.

» Mit der Option -n kann man das Exportieren rückgängig machen.

» $ VAR=Wert ; bash -c 'echo $VAR'

$ export VAR ; bash -c 'echo $VAR' Wert

$ export -n VAR ; bash -c 'echo $VAR'

Hilfreiche Befehle (sleep, timeout)

sleep - Wartet für die angegebene Anzahl an Sekunden.

» Man kann auch Suffixe verwenden: s für Sekunden (default), m für Minuten, h für Stunden und d für Tage.

» Die verwendete Zahl kann auch Kommastellen beinhalten.

» $ date +"%S.%N"; sleep 0.05m; date +"%S.%N"

35.919635622 38.924289758

timeout - Bricht einen Befehl nach einer bestimmten Anzahl an Sekunden ab.

» Suffixe wie bei sleep möglich (Sekunden sind default).

» Optionen: -s Signal → legt das Signal fest (default TERM), das an den Befehl geschickt werden soll.

» Der Rückgabewert ist der Rückgabewert des Befehls, oder 124, falls der Befehl abgebrochen wurde.

» $ timeout 2 sleep 3

$ echo $?

124

(10)

Hilfreiche Befehle (exec, locate)

exec - Ersetzt die Shell durch einen Befehl.

» Wird öfters in Shell-Skripts verwendet, wenn das Skript am Ende einen Befehl ausführen soll, damit kein unnötiger Shell-Prozess existiert.

» $ exec vi

locate - Sucht Dateien über ihren Namen.

» Benutzt eine Datenbank, durchsucht also im Gegensatz zu find nicht das Dateisystem. Die Datenbank wird üblicherweise regelmäßig durch einen cron-Job aktualisiert.

» Es können Shell-Patterns oder reguläre Ausdrücke benutzt werden. Achtung: Falls kein Pattern benutzt wird, wird automatisch nach „Muster“ gesucht!

» Optionen: -b → Nur in Dateinamen suchen, nicht im ganzen Pfad

» $ locate -b '\passwd' /etc/passwd

/etc/cron.daily/passwd /etc/pam.d/passwd /usr/bin/passwd

/usr/share/bash-completion/completions/passwd /usr/share/doc/passwd

/usr/share/lintian/overrides/passwd

Copyright und Lizenz

• Copyright: Thomas Leitner thomas.leitner@univie.ac.at

• Basiert teilweise auf den Folien von Harald Schilly harald.schilly@univie.ac.at

• Lizenz: Creative Commons CC BY-NC-SA

„Namensnennung-Keine kommerzielle Nutzung-Weitergabe unter gleichen Bedingungen 3.0 Österreich.“ - http://creativecommons.org/licenses/by-nc-sa/3.0/at/

Referenzen

ÄHNLICHE DOKUMENTE

Aber da es unter DOS keine M¨oglichkeit gibt, zwei Kommandos parallel laufen zu lassen, wird das erste Kommando vollst¨andig ausgef¨uhrt, seine Ausgabe in eine tempor¨are

In this study, we followed a comparative approach with PST and/or LC producing strains of Alexandrium spp., to evaluate the time dependent e ff ects of exposure in blue mussels,

In this study, we followed a comparative approach with PST and/or LC producing strains of Alexandrium spp., to evaluate the time dependent e ff ects of exposure in blue mussels,

The genomes of several bivalve species contain multiple MIF-like genes, with Mytilidae showing, in particular, a remarkable radiation of the sequences pertaining to the D-

JESS beinhaltet eine Menge von eingebauten Funktionen, die Sie aufrufen können. Weitere Funktionen sind als Erweiterungen erhältlich. Deffunctions) oder in Java auch

Modifiziert (ohne explizite Option -i ) nicht die Datei sondern gibt auf stdout aus Ausgabe muss dann bei Bedarf in eine neue Datei umgeleitet werden. muss gequotet werden damit

f) H¨angen Sie den Inhalt der Datei indexBin an die Datei index an. Sortieren Sie die Datei index nach Pro- grammnamen, wobei Sie eine neue Datei index.sortiert erzeugen, die

In addition to this thermal smoothing of the PMMA shell, we generated a selection of shape anisotropic core-shell particles using a thermomechanical stretching procedure.. Because