Viele Aenderungen
This commit is contained in:
@@ -2,27 +2,31 @@
|
||||
\chapter{Wie sieht ein Shell-Skript aus?}
|
||||
Wie schon erwähnt, kann ein Shell-Skript beinahe alles, was eine `richtige'
|
||||
Programmiersprache auch kann. Bei der Entwicklung sollte man nur bedenken, daß
|
||||
gerade die Ausführung von externen Kommandos~--~und das ist eine der
|
||||
Standard-Techniken bei der Shell-Programmierung~--~nur sehr langsam vonstatten
|
||||
geht. Für Anwendungen bei denen z. B. viele Rechnungen oder Stringbearbeitungen
|
||||
gemacht werden müssen, sollte man also ggf. die Benutzung einer anderen
|
||||
Sprache, beispielsweise Perl\index{Perl}, in Erwägung ziehen.
|
||||
gerade die Aus\-füh\-rung von externen Kommandos~--~und das ist eine der
|
||||
Standard-Techniken bei der Shell-Pro\-gram\-mie\-rung~--~nur sehr langsam
|
||||
vonstatten geht. Für Anwendungen bei denen z. B. viele Rechnungen oder
|
||||
Stringbearbeitungen gemacht werden müssen, sollte man also ggf. die Benutzung
|
||||
einer anderen Sprache, beispielsweise Perl\index{Perl}, in Erwägung ziehen.
|
||||
|
||||
In der Shell stehen viele Mechanismen zur Verfügung, die auch aus anderen Sprachen bekannt sind. Um den Umfang dieses Dokuments nicht zu sprengen, werden an dieser Stelle nur die wichtigsten vorgestellt.
|
||||
|
||||
|
||||
\section{Grundsätzliches}
|
||||
\section{HowTo}
|
||||
|
||||
Zunächst soll die Frage geklärt werden, wie man überhaupt ein ausführbares Shell-Skript schreibt. Dabei wird vorausgesetzt, daß dem Benutzer der Umgang mit mindestens einem Texteditor\index{Texteditor} (\texttt{vi}\index{vi=\texttt{vi}}, \texttt{emacs}\index{emacs=\texttt{emacs}} etc.) bekannt ist.
|
||||
Zunächst soll die Frage geklärt werden, wie man überhaupt ein ausführbares
|
||||
Shell-Skript schreibt. Dabei wird vorausgesetzt, daß dem Benutzer der Umgang
|
||||
mit mindestens einem Texteditor\index{Texteditor}
|
||||
(\texttt{vi}\index{vi=\texttt{vi}}, \texttt{emacs}\index{emacs=\texttt{emacs}}
|
||||
etc.) bekannt ist.
|
||||
|
||||
Bei der Erstellung oder Bearbeitung von Shell-Skripten muß darauf geachtet
|
||||
werden, daß sich keine CR/LF-Zeilenumbrüche einschleichen, wie dies leicht bei
|
||||
der Benutzung von MS-DOS bzw. Windows-Systemen zur Bearbeitung von Skripten
|
||||
über das Netzwerk passieren kann.
|
||||
|
||||
\subsection{HowTo}
|
||||
|
||||
Zunächst muß mit Hilfe des Editors eine Textdatei angelegt werden, in die der `Quelltext' geschrieben wird. Wie der aussieht, sollte man anhand der folgenden Abschnitte und der Beispiele im Anhang erkennen können. Beim Schreiben sollte man nicht mit den Kommentaren\index{Kommentar} geizen, da ein Shell-Skript auch schon mal sehr unleserlich werden kann.
|
||||
Zunächst muß mit Hilfe des Editors eine Textdatei angelegt werden, in die der
|
||||
`Quelltext' geschrieben wird. Dabei muß darauf geachtet werden, daß sich keine
|
||||
CR/LF-Zei\-len\-um\-brü\-che einschleichen, wie dies leicht bei der Benutzung
|
||||
von MS-DOS bzw. Windows-Systemen zur Bearbeitung von Skripten über das Netzwerk
|
||||
passieren kann. Wie der Quelltext aussieht, sollte man anhand der folgenden
|
||||
Abschnitte und der Beispiele im Anhang erkennen können. Beim Schreiben sollte
|
||||
man nicht mit den Kommentaren\index{Kommentar} geizen, da ein Shell-Skript auch
|
||||
schon mal sehr unleserlich werden kann.
|
||||
|
||||
Nach dem Abspeichern der Datei unter einem geeigneten Namen\footnote{Bitte
|
||||
\emph{nicht} den Namen \texttt{test}\index{test=\texttt{test}} verwenden. Es
|
||||
@@ -32,25 +36,16 @@ ausgef
|
||||
zugleich einer der verwirrendsten Anfängerfehler. Mehr zu dem
|
||||
\texttt{test}-Kommando unter \ref{bedingungen}.} muß die sie ausführbar gemacht
|
||||
werden. Das geht mit dem Unix-Kommando
|
||||
\texttt{chmod}\index{chmod=\texttt{chmod}}. Rechte können unter Unix getrennt
|
||||
für den Benutzer (user, \texttt{u}), die Gruppe (group, \texttt{g}) oder andere
|
||||
(others, \texttt{o}) vergeben werden. Außerdem kann man die Rechte für alle
|
||||
Gruppen zusammen (all, a) setzen. Man kann getrennt die Rechte für das lesen
|
||||
(read, \texttt{r}), das schreiben (write, \texttt{w}) und die Ausführung
|
||||
(execution, \texttt{x}) vergeben. Damit die Datei für einen Benutzer wirklich
|
||||
ausführbar ist, muß er das Lese- und das
|
||||
Ausführungsrecht\index{Ausührungsrecht} haben. Um die Rechte zu setzen, muß man
|
||||
\texttt{chmod} in Parametern mitgeben, worauf sich das Kommando bezieht, ob das
|
||||
Recht gesetzt (\texttt{+}) oder weggenommen (\texttt{-}) werden soll, und
|
||||
welche Rechte gemeint sind. Damit alle Benutzer das Skript ausführen dürfen,
|
||||
benutzt man das Kommando \texttt{chmod ugo+rx name} oder einfach \texttt{chmod
|
||||
+rx name}. Mit \texttt{chmod u+x name} hat nur der Besitzer der Datei
|
||||
Ausführungsrechte.
|
||||
\texttt{chmod}\index{chmod=\texttt{chmod}} und wird in Abschnitt \ref{chmod}
|
||||
ausführlich beschrieben. An dieser Stelle reicht uns ein Aufruf in der Form
|
||||
\texttt{chmod 755 dateiname}, um das Skript für alle Benutzer ausführbar zu
|
||||
machen.
|
||||
|
||||
Um ein Shell-Skript ausführen zu können braucht es aus der Sicht des
|
||||
ausführenden Benutzers mindestens die Rechte zum Lesen (r) und Ausführen (x).
|
||||
|
||||
Dann kann das Skript gestartet werden. Da sich aus Sicherheitsgründen auf den meisten Systemen das aktuelle Verzeichnis nicht im Pfad des Benutzers befindet, muß man der Shell noch mitteilen, wo sie zu suchen hat: Mit \texttt{./name} wird versucht, im aktuellen Verzeichnis (\texttt{./}) ein Programm namens \texttt{name} auszuführen.
|
||||
Dann kann das Skript gestartet werden. Da sich aus Sicherheitsgründen auf den
|
||||
meisten Systemen das aktuelle Verzeichnis nicht im Pfad des Benutzers befindet,
|
||||
muß man der Shell noch mitteilen, wo sie zu suchen hat: Mit \texttt{./name}
|
||||
wird versucht, im aktuellen Verzeichnis (\texttt{./}) ein Programm namens
|
||||
\texttt{name} auszuführen.
|
||||
|
||||
Auf den meisten Systemen befindet sich im Pfad ein Verweis auf das Verzeichnis
|
||||
\texttt{bin} unterhalb des Home-Verzeichnisses eines Benutzers. Das bedeutet
|
||||
@@ -60,7 +55,7 @@ kann man an der Shell durch Eingabe von \texttt{echo
|
||||
\$PATH}\index{\$PATH=\texttt{\$PATH}} herausfinden.
|
||||
|
||||
|
||||
\subsection{Rückgabewerte}\label{exitcode}\index{Rückgabewert|(textbf}\index{Exit-Code|see{Rückgabewert}}\index{Exit-Status|see{Rückgabewert}}
|
||||
\section{Rückgabewerte}\label{exitcode}\index{Rückgabewert|(textbf}\index{Exit-Code|see{Rückgabewert}}\index{Exit-Status|see{Rückgabewert}}
|
||||
|
||||
Wenn unter Unix ein Prozeß beendet wird, gibt er einen Rückgabewert (auch
|
||||
Exit-Code oder Exit-Status genannt) an seinen aufrufenden Prozeß zurück. So
|
||||
@@ -281,7 +276,9 @@ Ausdruck}}\index{Ausdruck|see{Regul
|
||||
wesentlich mehr Möglichkeiten als die relativ einfachen Wildcards für
|
||||
Dateinamen.
|
||||
|
||||
In der folgenden Tabelle wird gezeigt, in welchen Unix-Tools welche Zeichen zur Verfügung stehen. Eine ausführlichere Beschreibung der Einträge findet sich auf Seite \pageref{beschreibung_der_muster}. \nopagebreak
|
||||
In der folgenden Tabelle wird gezeigt, in welchen Unix-Tools welche Zeichen zur
|
||||
Ver\-fü\-gung stehen. Eine ausführlichere Beschreibung der Einträge findet sich
|
||||
auf Seite \pageref{beschreibung_der_muster}. \nopagebreak
|
||||
\LTXtable{\textwidth}{tab_mustererkennung_muster.tex}
|
||||
|
||||
Bei einigen Tools (\texttt{ex}, \texttt{sed} und \texttt{ed}) werden zwei Muster angegeben: Ein Suchmuster (links) und ein Ersatzmuster (rechts). Nur die folgenden Zeichen sind in einem Ersatzmuster gültig:\nopagebreak
|
||||
@@ -358,6 +355,54 @@ F
|
||||
\index{Arithmetik-Expansion|)}
|
||||
|
||||
|
||||
\section{Eltern und Kinder: Prozeßordnung\label{prozessordnung}\index{Prozess|(textbf}\index{PID|see{Prozess}}\index{Parent-Prozess|see{Prozess}}\index{PPID|see{Prozess}}\index{Subshell|(textbf}}
|
||||
|
||||
Jedes laufende Programm auf einem Unixoiden System besteht aus einem oder
|
||||
mehreren Prozessen, die jeweils eine eigene Prozeß-ID (PID) haben. Erzeugt ein
|
||||
Programm mehrere Prozesse, sind die zu einer Prozeßgruppe zusammengefaßt. Jeder
|
||||
laufende Prozeß\footnote{Es gibt eine Ausnahme: der Init-Prozeß, der immer die
|
||||
PID 1 hat, hat keine Eltern. Er stammt direkt vom Kernel ab.} verfügt über
|
||||
genau eine Parent-Prozeß-ID (PPID). Das ist die ID des Prozesses, der den
|
||||
jeweiligen Prozeß erzeugt hat. Man spricht in diesem Zusammenhang tatsächlich
|
||||
von Eltern- bzw. Kind-Prozessen.
|
||||
|
||||
Diese Zusammenhänge lassen sich sehr schön durch die Ausgabe des Kommandos
|
||||
\texttt{pstree} oder \texttt{ps -efH} darstellen, letzteres zeigt auch gleich
|
||||
die PIDs und die PPIDs an.
|
||||
|
||||
Wenn in einer Shell ein Kommando gestartet wird, ist es ein Kind dieser Shell.
|
||||
Wird ein Skript gestartet, öffnet es sich seine eigene Shell (siehe
|
||||
\ref{auswahl_der_shell}) und führt sich innerhalb dieser aus. Die Shell des
|
||||
Skriptes ist dabei ein Kind der interaktiven Shell, die einzelnen Kommandos des
|
||||
Skriptes sind Kinder der Skript-Shell.
|
||||
|
||||
Eine solche Shell-in-Shell-Umgebung wird `Subshell' genannt, dieser
|
||||
Mechanismus~--~und somit auch der Begriff~--~tauchen immer wieder auf.
|
||||
|
||||
Wichtig in diesem Zusammenhang ist das Verständnis für die Vererbung zwischen
|
||||
den beteiligten Prozessen. Wenn in einer Shell eine Variable definiert und
|
||||
exportiert wird, existiert diese auch für die Kind-Prozesse. Gleiches gilt
|
||||
beispielsweise für einen Verzeichnis-Wechsel. Umgekehrt gilt dies nicht: ein
|
||||
Prozeß kann die Umgebung des Parent-Prozesses nicht verändern. Das geschieht
|
||||
nicht zuletzt aus Sicherheitsgründen so.
|
||||
|
||||
Will man die Änderungen eines Skriptes übernehmen~--~beispielsweise wenn ein
|
||||
Skript die Benutzerumgebung konfigurieren soll (.bashrc, .profile und
|
||||
Konsorten)~--~muß das explizit angefordert werden. Dazu ruft man es mit einem
|
||||
vorangestellten \texttt{source}\index{source=\texttt{source}} bzw. in der
|
||||
Kurzform mit einem vorangestellten Punkt auf. Weiteres zu dem Thema findet sich
|
||||
im Abschnitt \ref{source}.
|
||||
|
||||
Besonders muß man diesen Umstand im Hinterkopf behalten, wenn mit
|
||||
Pipelines\index{Pipe} (siehe Abschnitt \ref{befehlsformen}) gearbeitet wird.
|
||||
Dabei werden auch Kommandos in Subshells ausgeführt, was dann dazu führt daß
|
||||
Variablen belegt werden die dann nach Ausführung der Pipeline plötzlich wieder
|
||||
leer sind. Die Abschnitte \ref{subshellschleifen} und \ref{daten_hochreichen}
|
||||
widmen sich diesem mitunter recht ärgerlichen Thema.
|
||||
|
||||
\index{Prozess|)}\index{Subshell|)}
|
||||
|
||||
|
||||
\section{Programmablaufkontrolle}
|
||||
|
||||
Bei der Shell-Programmierung verfügt man über ähnliche Konstrukte wie bei anderen Programmiersprachen, um den Ablauf des Programms zu steuern. Dazu gehören Funktionsaufrufe, Schleifen, Fallunterscheidungen und dergleichen.\nopagebreak
|
||||
|
||||
Reference in New Issue
Block a user