\texttt{\$ (date; who; pwd) > logfile}\index{!>=\texttt{!>}}& F<>hrt die Befehle in einer Subshell\index{Subshell} aus und lenkt alle Ausgaben um \tabularnewline\STRUT
\texttt{\$\{ date; who; pwd; \} > logfile}\index{!>=\texttt{!>}}& Lenkt alle Ausgaben um \tabularnewline\STRUT
\texttt{\$ time \{ date; who; pwd; \}}\index{time=\texttt{time}}& Summiert die Laufzeit der drei Kommandos\tabularnewline\STRUT
\texttt{\$ sort }\textsl{Datei}\texttt{ | lp}& Sortiert die \textsl{Datei} und druckt sie\index{sort=\texttt{sort}}\tabularnewline\STRUT
\texttt{\$ vi `grep -l ifdef *.c`}\index{*=\texttt{*}}\index{grep=\texttt{grep}}& Editiert die mittels grep gefundenen Dateien \tabularnewline\STRUT
\texttt{\$ grep }\textsl{XX Datei}\texttt{\&\& lp }\textsl{Datei}\index{grep=\texttt{grep}}& Druckt die \textsl{Datei}, wenn sie \textsl{XX} enth<74>lt\index{AND}\tabularnewline\STRUT
\texttt{\$!}& Proze<7A>nummer des letzten Hintergrundprozesses \tabularnewline\STRUT
\texttt{\$ERRNO}& Fehlernummer des letzten fehlgeschlagenen Systemaufrufs \tabularnewline\STRUT
\texttt{\$IFS}& Feldseparator, wird beispielsweise beim Lesen mittels \texttt{read} benutzt \tabularnewline\STRUT
\texttt{\$PATH}& Pfad, in dem nach ausf<73>hrbaren Kommandos gesucht wird. Mehrere Eintr<74>ge werden durch Doppelpunkte getrennt angegeben \tabularnewline\STRUT
\texttt{\$PATH}& Pfad, in dem nach ausf<73>hrbaren Kommandos gesucht wird\footnote{Mit dem Kommando \texttt{type}\index{type=\texttt{type}} findet man heraus, welches Executable tats<74>chlich verwendet wird.}. Mehrere Eintr<74>ge werden durch Doppelpunkte getrennt angegeben \tabularnewline\STRUT
\texttt{\$PWD}& Aktuelles Verzeichnis (wird durch \texttt{cd} gesetzt\footnote{Durch das Kommando \texttt{cd} wird das aktuelle Verzeichnis gewechselt, siehe Abschnitt \ref{cd}.}) \tabularnewline\STRUT
\texttt{\$OLDPWD}& Vorheriges Verzeichnis (wird durch \texttt{cd} gesetzt)
Wie schon erw<72>hnt, kann ein Shell-Skript beinahe alles, was eine `richtige'
Programmiersprache auch kann. Bei der Entwicklung sollte man nur bedenken, da<64>
gerade die Ausf<EFBFBD>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<72>gung ziehen.
gerade die Aus\-f<EFBFBD>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<72>gung ziehen.
In der Shell stehen viele Mechanismen zur Verf<72>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<EFBFBD>tzliches}
\section{HowTo}
Zun<EFBFBD>chst soll die Frage gekl<6B>rt werden, wie man <20>berhaupt ein ausf<73>hrbares Shell-Skript schreibt. Dabei wird vorausgesetzt, da<64> 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<EFBFBD>chst soll die Frage gekl<6B>rt werden, wie man <20>berhaupt ein ausf<73>hrbares
Shell-Skript schreibt. Dabei wird vorausgesetzt, da<64> dem Benutzer der Umgang
Bei der Erstellung oder Bearbeitung von Shell-Skripten mu<6D> darauf geachtet
werden, da<64> sich keine CR/LF-Zeilenumbr<62>che einschleichen, wie dies leicht bei
der Benutzung von MS-DOS bzw. Windows-Systemen zur Bearbeitung von Skripten
<EFBFBD>ber das Netzwerk passieren kann.
\subsection{HowTo}
Zun<EFBFBD>chst mu<6D> 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<EFBFBD>chst mu<6D> mit Hilfe des Editors eine Textdatei angelegt werden, in die der
`Quelltext' geschrieben wird. Dabei mu<6D> darauf geachtet werden, da<64> sich keine
CR/LF-Zei\-len\-um\-br<EFBFBD>\-che einschleichen, wie dies leicht bei der Benutzung
von MS-DOS bzw. Windows-Systemen zur Bearbeitung von Skripten <EFBFBD>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<6E>ngerfehler. Mehr zu dem
\texttt{test}-Kommando unter \ref{bedingungen}.} mu<6D> die sie ausf<73>hrbar gemacht
werden. Das geht mit dem Unix-Kommando
\texttt{chmod}\index{chmod=\texttt{chmod}}. Rechte k<>nnen unter Unix getrennt
f<EFBFBD>r den Benutzer (user, \texttt{u}), die Gruppe (group, \texttt{g}) oder andere
(others, \texttt{o}) vergeben werden. Au<41>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<73>hrung
(execution, \texttt{x}) vergeben. Damit die Datei f<>r einen Benutzer wirklich
ausf<EFBFBD>hrbar ist, mu<6D> er das Lese- und das
Ausf<EFBFBD>hrungsrecht\index{Aus<EFBFBD>hrungsrecht} haben. Um die Rechte zu setzen, mu<6D> 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<73>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<EFBFBD>hrungsrechte.
\texttt{chmod}\index{chmod=\texttt{chmod}} und wird in Abschnitt \ref{chmod}
ausf<EFBFBD>hrlich beschrieben. An dieser Stelle reicht uns ein Aufruf in der Form
\texttt{chmod 755 dateiname}, um das Skript f<>r alle Benutzer ausf<73>hrbar zu
machen.
Um ein Shell-Skript ausf<73>hren zu k<>nnen braucht es aus der Sicht des
ausf<EFBFBD>hrenden Benutzers mindestens die Rechte zum Lesen (r) und Ausf<73>hren (x).
Dann kann das Skript gestartet werden. Da sich aus Sicherheitsgr<67>nden auf den meisten Systemen das aktuelle Verzeichnis nicht im Pfad des Benutzers befindet, mu<6D> 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<75>hren.
Dann kann das Skript gestartet werden. Da sich aus Sicherheitsgr<67>nden auf den
meisten Systemen das aktuelle Verzeichnis nicht im Pfad des Benutzers befindet,
mu<EFBFBD> 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<75>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
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<72>gung stehen. Eine ausf<73>hrlichere Beschreibung der Eintr<74>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<EFBFBD>\-gung stehen. Eine ausf<73>hrlichere Beschreibung der Eintr<74>ge findet sich
auf Seite \pageref{beschreibung_der_muster}. \nopagebreak
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<7A>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<7A>-ID (PID) haben. Erzeugt ein
Programm mehrere Prozesse, sind die zu einer Proze<7A>gruppe zusammengefa<66>t. Jeder
laufende Proze<7A>\footnote{Es gibt eine Ausnahme: der Init-Proze<7A>, der immer die
PID 1 hat, hat keine Eltern. Er stammt direkt vom Kernel ab.} verf<72>gt <20>ber
genau eine Parent-Proze<7A>-ID (PPID). Das ist die ID des Prozesses, der den
jeweiligen Proze<7A> erzeugt hat. Man spricht in diesem Zusammenhang tats<74>chlich
von Eltern- bzw. Kind-Prozessen.
Diese Zusammenh<6E>nge lassen sich sehr sch<63>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, <20>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<73>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<EFBFBD> kann die Umgebung des Parent-Prozesses nicht ver<65>ndern. Das geschieht
nicht zuletzt aus Sicherheitsgr<67>nden so.
Will man die <20>nderungen eines Skriptes <20>bernehmen~--~beispielsweise wenn ein
Skript die Benutzerumgebung konfigurieren soll (.bashrc, .profile und
Konsorten)~--~mu<6D> 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<6D> man diesen Umstand im Hinterkopf behalten, wenn mit
Pipelines\index{Pipe} (siehe Abschnitt \ref{befehlsformen}) gearbeitet wird.
Dabei werden auch Kommandos in Subshells ausgef<65>hrt, was dann dazu f<>hrt da<64>
Variablen belegt werden die dann nach Ausf<73>hrung der Pipeline pl<70>tzlich wieder
leer sind. Die Abschnitte \ref{subshellschleifen} und \ref{daten_hochreichen}
widmen sich diesem mitunter recht <20>rgerlichen Thema.
\index{Prozess|)}\index{Subshell|)}
\section{Programmablaufkontrolle}
Bei der Shell-Programmierung verf<72>gt man <20>ber <20>hnliche Konstrukte wie bei anderen Programmiersprachen, um den Ablauf des Programms zu steuern. Dazu geh<65>ren Funktionsaufrufe, Schleifen, Fallunterscheidungen und dergleichen.\nopagebreak
Nat<EFBFBD>rlich stellt sich die Frage, in welchen Situationen ein Shell-Skript der
richtige Weg ist, und wann man vielleicht doch besser zu einer interpretierten
oder compilierten Sprache greift.
\section{Wof<EFBFBD>r?}
Die Shell ist der perfekte Baukasten f<>r das Unix-Paradigma `small is
beautiful'. Die mitgelieferten Unix-Standardkommandos sind einfach gehalten,
erledigen aber auf effiziente Weise die Arbeit f<>r die sie programmiert wurden.
@ -23,3 +29,19 @@ Befehlen ausf
Beispiel eine Audio-CD kopieren soll, sollte das Brennprogramm nur dann
aufrufen, wenn der Einlesevorgang erfolgreich abgeschlossen wurde.
\section{Wof<EFBFBD>r nicht?}
Ein Shell-Skript besteht aus einer Abfolge von System-Tool-Aufrufen. Das hei<65>t,
f<EFBFBD>r jeden Schritt in einem Skript wird ein neuer Proze<7A> gestartet. Das kostet
eine Menge Systemzeit, die Skripte laufen also vergleichsweise langsam. F<>r
komplexe, zeitkritische oder langwierige Aufgaben sollte man also besser zu
Perl, Python oder in Extremf<6D>llen zu C / C++ greifen.
Shell-Skripte k<>nnen als imperativ angesehen werden, f<>r viele Aufgaben ist
aber ein objektorientierter Ansatz wesentlich geeigneter. Auch hier ist also
der Griff zu einer anderen Sprache angeraten.
Es gibt zwar ein paar Tools\footnote{Zum Beispiel dialog im Textmodus, oder
xmessage unter X.}, mit denen auch Shell-Skripte eine grafische oder
textorientierte Benutzeroberfl<66>che (GUI) bekommen k<>nnen, aber das ist trotzdem
nicht das nat<61>rliche Terrain der Shell-Programmierung.
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.