1 Commits

Author SHA1 Message Date
f2b7d3468d Die ursprüngliche Version 2001-07-02 12:52:18 +00:00
77 changed files with 703 additions and 4164 deletions

View File

@ -134,10 +134,6 @@ ifndef DVIVIEWER
DVIVIEWER=xdvi DVIVIEWER=xdvi
endif endif
ifndef PDFVIEWER
PDFVIEWER=acroread
endif
ifndef LATEX2HTML ifndef LATEX2HTML
LATEX2HTML=latex2html LATEX2HTML=latex2html
endif endif
@ -275,21 +271,6 @@ TEXFILES=$(wildcard *.tex)
touch $*.ind; \ touch $*.ind; \
fi fi
pdflatex:
# Below the 'true' is included to prevent unnecessarily many errors.
@if [ -n "${LATEXTARGET}" ]; then \
$(MAKE) ${LATEXTARGET}.pdf; \
true; \
else \
if [ `ls *.tex | wc -l` = "1" ]; then \
$(MAKE) `basename \`ls *.tex\` .tex`.pdf; \
true; \
else \
$(MAKE) `echo $$PWD|tr '/' '\n'|tail -1`.pdf; \
true; \
fi; \
fi
latex: latex:
# Below the 'true' is included to prevent unnecessarily many errors. # Below the 'true' is included to prevent unnecessarily many errors.
@if [ -n "${LATEXTARGET}" ]; then \ @if [ -n "${LATEXTARGET}" ]; then \
@ -305,12 +286,27 @@ latex:
fi; \ fi; \
fi fi
pdflatex:
# Below the 'true' is included to prevent unnecessarily many errors.
@if [ -n "${LATEXTARGET}" ]; then \
$(MAKE) ${LATEXTARGET}.pdf; \
true; \
else \
if [ `ls *.tex | wc -l` = "1" ]; then \
$(MAKE) `basename \`ls *.tex\` .tex`.pdf; \
true; \
else \
$(MAKE) `echo $$PWD|tr '/' '\n'|tail -1`.pdf; \
true; \
fi; \
fi
latexfigures: latexfigures:
@for i in $(FIGUREOBJS); do \ @for i in $(FIGUREOBJS); do \
$(MAKE) $$i; \ $(MAKE) $$i; \
done done
viewdvi: view:
# Below the 'true' is included to prevent unnecessarily many errors. # Below the 'true' is included to prevent unnecessarily many errors.
@if [ -n "${LATEXTARGET}" ]; then \ @if [ -n "${LATEXTARGET}" ]; then \
$(MAKE) ${LATEXTARGET}.dvi && \ $(MAKE) ${LATEXTARGET}.dvi && \
@ -328,24 +324,6 @@ viewdvi:
fi; \ fi; \
fi fi
view:
# Below the 'true' is included to prevent unnecessarily many errors.
@if [ -n "${LATEXTARGET}" ]; then \
$(MAKE) ${LATEXTARGET}.pdf && \
$(PDFVIEWER) ${LATEXTARGET}.pdf; \
true; \
else \
if [ `ls *.tex | wc -l` = "1" ]; then \
$(MAKE) `basename \`ls *.tex\` .tex`.pdf && \
$(PDFVIEWER) `basename \`ls *.tex\` .tex`.pdf; \
true; \
else \
$(MAKE) `echo $$PWD|tr '/' '\n'|tail -1`.pdf && \
$(PDFVIEWER) `echo $$PWD|tr '/' '\n'|tail -1`.pdf; \
true; \
fi; \
fi
%.ps: %.dvi %.ps: %.dvi
$(DVIPS) -o $@ $< $(DVIPS) -o $@ $<

View File

@ -1,4 +1,3 @@
% $Id$
\chapter{Beispiele} \chapter{Beispiele}
@ -13,132 +12,67 @@ Angenommen, bei der Benutzung eines Rechners tritt ein Problem auf, bei dem nur
Einfacher geht es, wenn wir uns ein kurzes Skript schreiben, das alle 30 Sekunden automatisch <20>berpr<70>ft, ob der Admin angemeldet ist. Wir erreichen das mit dem folgenden Code: Einfacher geht es, wenn wir uns ein kurzes Skript schreiben, das alle 30 Sekunden automatisch <20>berpr<70>ft, ob der Admin angemeldet ist. Wir erreichen das mit dem folgenden Code:
\footnotesize
\index{\^=\texttt{\^}}\index{Anf<EFBFBD>hrungszeichen}\index{Pipe}\index{grep=\texttt{grep}}\index{sleep=\texttt{sleep}}\index{who=\texttt{who}} \index{\^=\texttt{\^}}\index{Anf<EFBFBD>hrungszeichen}\index{Pipe}\index{grep=\texttt{grep}}\index{sleep=\texttt{sleep}}\index{who=\texttt{who}}
\begin{lstlisting} \begin{listing}[2]{1}
#!/bin/sh #!/bin/sh
until who | grep "^root "; do until who | grep "^root "
sleep 30 do sleep 30
done done
echo "Big Brother is watching you!" echo Big Brother is watching you!
\end{lstlisting} \end{listing}
\normalsize
Das Skript f<>hrt also so lange das Kommando aus, bis die Ausf<73>hrung erfolgreich Das Skript f<>hrt also so lange das Kommando aus, bis die Ausf<73>hrung erfolgreich war. Dabei wird die Ausgabe von \texttt{who}\index{who=\texttt{who}} mit einer Pipe (\ref{datenstrom}) in das \texttt{grep}\index{grep=\texttt{grep}}-Kommando umgeleitet. Dieses sucht darin nach einem Auftreten von `\texttt{root~}' am Zeilenanfang. Der R<>ckgabewert von \texttt{grep}\index{grep=\texttt{grep}} ist 0 wenn das Muster\index{Mustererkennung} gefunden wird, 1 wenn es nicht gefunden wird und 2 wenn ein Fehler auftrat. Damit der Rechner nicht die ganze Zeit mit dieser Schleife besch<63>ftigt ist, wird im Schleifenk<6E>rper ein \texttt{sleep 30}\index{sleep=\texttt{sleep}} ausgef<65>hrt, um den Proze<7A> f<>r 30 Sekunden schlafen zu schicken. Sobald der Admin sich eingeloggt hat, wird eine entsprechende Meldung ausgegeben.
war. Dabei wird die Ausgabe von \texttt{who}\index{who=\texttt{who}} mit einer
Pipe (\ref{datenstrom}) in das \texttt{grep}\index{grep=\texttt{grep}}-Kommando
umgeleitet. Dieses sucht darin nach einem Auftreten von `\texttt{root~}' am
Zeilenanfang. Der R<>ckgabewert von \texttt{grep}\index{grep=\texttt{grep}} ist
0 wenn das Muster\index{Mustererkennung} gefunden wird, 1 wenn es nicht
gefunden wird und 2 wenn ein Fehler auftrat. Damit der Rechner nicht die ganze
Zeit mit dieser Schleife besch<63>ftigt ist, wird im Schleifenk<6E>rper ein
\lstinline|sleep 30|\index{sleep=\texttt{sleep}} ausgef<65>hrt, um den Proze<7A> f<>r
30 Sekunden schlafen zu schicken. Sobald der Admin sich eingeloggt hat, wird
eine entsprechende Meldung ausgegeben.
\subsection{Schleife, bis ein Kommando erfolglos war} \subsection{Schleife, bis ein Kommando erfolglos war}
Analog zum vorhergehenden Beispiel kann man auch ein Skript schreiben, das Analog zum vorhergehenden Beispiel kann man auch ein Skript schreiben, das meldet, sobald sich ein Benutzer abgemeldet hat. Dazu ersetzen wir nur die \texttt{until}- Schleife durch eine entsprechende \texttt{while}-Schleife:
meldet, sobald sich ein Benutzer abgemeldet hat. Dazu ersetzen wir nur die
\texttt{until}- Schleife durch eine entsprechende \texttt{while}-Schleife:
\footnotesize
\index{\^=\texttt{\^}}\index{Anf<EFBFBD>hrungszeichen}\index{grep=\texttt{grep}}\index{Pipe}\index{sleep=\texttt{sleep}}\index{who=\texttt{who}} \index{\^=\texttt{\^}}\index{Anf<EFBFBD>hrungszeichen}\index{grep=\texttt{grep}}\index{Pipe}\index{sleep=\texttt{sleep}}\index{who=\texttt{who}}
\begin{lstlisting} \begin{listing}[2]{1}
#!/bin/sh #!/bin/sh
while who | grep "^root "; do while who | grep "^root "
sleep 30 do sleep 30
done done
echo "Die Katze ist aus dem Haus, Zeit, da<64> die M<>use tanzen!" echo Die Katze ist aus dem Haus, Zeit, da<64> die M<>use tanzen!
\end{lstlisting} \end{listing}
\normalsize
Die Schleife wird n<>mlich dann so lange ausgef<65>hrt, bis Die Schleife wird n<>mlich dann so lange ausgef<65>hrt, bis \texttt{grep}\index{grep=\texttt{grep}} einen Fehler (bzw. eine erfolglose Suche) zur<75>ckmeldet.
\texttt{grep}\index{grep=\texttt{grep}} einen Fehler (bzw. eine erfolglose
Suche) zur<75>ckmeldet.
\section{Subshell-Schleifen vermeiden}\label{subshellschleifen} \section{Eine Datei zeilenweise bearbeiten}
Wir wollen ein Skript schreiben, das die \texttt{/etc/passwd} liest und dabei \texttt{cat datei.txt | while read i}
z<EFBFBD>hlt, wie viele Benutzer eine UID kleiner als 100 haben.
Folgendes Skript funktioniert nicht: TODO!!!
\begin{lstlisting}
#!/bin/sh
count=0
cat /etc/passwd | while read i; do
uid=`echo $i | cut -f 3 -d:`
if [ $uid -lt 100 ]; then
count=`expr $count + 1`
echo $count
fi
done
echo Es sind $count Benutzer mit einer ID kleiner 100 eingetragen
\end{lstlisting}
Was ist passiert?
Dieses Skript besteht im Wesentlichen aus einer Pipe. Wir haben ein
\texttt{cat}-Kom\-man\-do, das den Inhalt der \texttt{/etc/passwd} durch eben
diese Pipe an eine Schleife <20>bergibt. Das \texttt{read}-Kommando in der
Schleife liest die einzelnen Zeilen aus, dann folgt ein Bi<42>chen Auswertung.
Es ist zu beobachten, da<64> bei der Ausgabe in Zeile 7 die Variable
\texttt{\$count} korrekte Werte enth<74>lt. Um so unverst<73>ndlicher ist es, da<64> sie
nach der Vollendung der Schleife wieder den Wert 0 enth<74>lt.
Das liegt daran, da<64> diese Schleife als Teil einer Pipe in einer Subshell
ausgef<EFBFBD>hrt wird. Die Variable \texttt{\$count} steht damit in der Schleife
praktisch nur lokal zur Verf<72>gung, sie wird nicht an das umgebende Skript
`hochgereicht'.
Neben der Methode in \ref{daten_hochreichen} bietet sich hier eine viel
einfachere L<>sung an:
\begin{lstlisting}
#!/bin/sh
count=0
while read i; do
uid=`echo $i | cut -f 3 -d:`
if [ $uid -lt 100 ]; then
count=`expr $count + 1`
echo $count
fi
done < /etc/passwd
echo Es sind $count Benutzer mit einer ID kleiner 100 eingetragen
\end{lstlisting}
Hier befindet sich die Schleife nicht in einer Pipe, daher wird sie auch nicht
in einer Subshell ausgef<65>hrt. Man kann auf das \texttt{cat}-Kommando verzichten
und den Inhalt der Datei durch die Umlenkung in Zeile 9 direkt auf die
Standardeingabe der Schleife (und somit auf das \texttt{read}-Kommando) legen.
Achtung! while ist eine Subshell - Daten m<>ssen hochgereicht werden.
\section{Ein typisches Init-Skript}\label{init-skript}\index{Init-Skript} \section{Ein typisches Init-Skript}\label{init-skript}\index{Init-Skript}
Dieses Skript dient dazu, den Apache HTTP-Server zu starten. Es wird w<>hrend Dieses Skript dient dazu, den Apache HTTP-Server zu starten. Es wird w<>hrend des Bootvorgangs gestartet, wenn der dazugeh<65>rige Runlevel initialisiert wird.
des Bootvorgangs gestartet, wenn der dazugeh<65>rige Runlevel initialisiert wird.
Das Skript mu<6D> mit einem Parameter\index{Parameter} aufgerufen werden. M<>glich Das Skript mu<6D> mit einem Parameter\index{Parameter} aufgerufen werden. M<>glich sind hier \textsl{start}, \textsl{stop}, \textsl{status}, \textsl{restart} und \textsl{reload}. Wenn falsche Parameter\index{Parameter} <20>bergeben wurden, wird eine entsprechende Meldung angezeigt.
sind hier \textsl{start}, \textsl{stop}, \textsl{status}, \textsl{restart} und
\textsl{reload}. Wenn falsche Parameter\index{Parameter} <20>bergeben wurden, wird
eine entsprechende Meldung angezeigt.
Das Ergebnis der Ausf<73>hrung wird mit Funktionen\index{Funktion} dargestellt, Das Ergebnis der Ausf<73>hrung wird mit Funktionen\index{Funktion} dargestellt, die aus der Datei \texttt{/etc/rc.d/init.d/functions} stammen. Ebenfalls in dieser Datei sind Funktionen, die einen Dienst starten oder stoppen.
die aus der Datei \lstinline|functions| stammen. Ebenfalls in dieser Datei sind
Funktionen, die einen Dienst starten oder stoppen.
Zun<EFBFBD>chst wird festgelegt, da<64> dieses Skript in der Bourne-Shell ausgef<65>hrt \begin{flushright}
werden soll (\ref{auswahl_der_shell}). Zun<EFBFBD>chst wird festgelegt, da<64> dieses Skript in der Bourne-Shell ausgef<65>hrt werden soll (\ref{auswahl_der_shell}).
\end{flushright}
\begin{lstlisting} \footnotesize
\begin{listing}[2]{1}
#!/bin/sh #!/bin/sh
\end{listing}
\end{lstlisting} \normalsize
\begin{flushright}
Dann folgen Kommentare\index{Kommentar}, die den Sinn des Skriptes erl<72>utern Dann folgen Kommentare\index{Kommentar}, die den Sinn des Skriptes erl<72>utern (\ref{kommentare}).
(\ref{kommentare}). \end{flushright}
\footnotesize
\begin{lstlisting}[firstnumber=last] \begin{listingcont}
# #
# Startup script for the Apache Web Server # Startup script for the Apache Web Server
# #
@ -150,109 +84,119 @@ Dann folgen Kommentare\index{Kommentar}, die den Sinn des Skriptes erl
# config: /etc/httpd/conf/access.conf # config: /etc/httpd/conf/access.conf
# config: /etc/httpd/conf/httpd.conf # config: /etc/httpd/conf/httpd.conf
# config: /etc/httpd/conf/srm.conf # config: /etc/httpd/conf/srm.conf
\end{listingcont}
\end{lstlisting} \normalsize
\begin{flushright}
Jetzt wird die Datei mit den Funktionen\index{Funktion} eingebunden (\ref{source}). Jetzt wird die Datei mit den Funktionen\index{Funktion} eingebunden (\ref{source}).
\end{flushright}
\footnotesize
\index{source=\texttt{source}} \index{source=\texttt{source}}
\begin{lstlisting}[firstnumber=last] \begin{listingcont}
# Source function library. # Source function library.
. /etc/rc.d/init.d/functions . /etc/rc.d/init.d/functions
\end{listingcont}
\end{lstlisting} \normalsize
\begin{flushright}
Hier werden die Aufrufparameter ausgewertet (\ref{case}). Hier werden die Aufrufparameter ausgewertet (\ref{case}).
\end{flushright}
\footnotesize
\index{\$n=\texttt{\$}$n$}\index{Anf<EFBFBD>hrungszeichen}\index{case=\texttt{case}} \index{\$n=\texttt{\$}$n$}\index{Anf<EFBFBD>hrungszeichen}\index{case=\texttt{case}}
\begin{lstlisting}[firstnumber=last] \begin{listingcont}
# See how we were called. # See how we were called.
case "$1" in case "$1" in
start) start)
echo -n "Starting httpd: " echo -n "Starting httpd: "
\end{listingcont}
\end{lstlisting} \normalsize
\begin{flushright}
Nachdem eine Meldung <20>ber den auszuf<75>hrenden Vorgang ausgegeben wurde, wird die Funktion \texttt{daemon} aus der Funktionsbibliothek ausgef<65>hrt. Diese Funktion startet das Programm, dessen Name hier als Parameter\index{Parameter} <20>bergeben wird. Dann gibt sie eine Meldung <20>ber den Erfolg aus. Nachdem eine Meldung <20>ber den auszuf<75>hrenden Vorgang ausgegeben wurde, wird die Funktion \texttt{daemon} aus der Funktionsbibliothek ausgef<65>hrt. Diese Funktion startet das Programm, dessen Name hier als Parameter\index{Parameter} <20>bergeben wird. Dann gibt sie eine Meldung <20>ber den Erfolg aus.
\end{flushright}
\begin{lstlisting}[firstnumber=last] \footnotesize
\begin{listingcont}
daemon httpd daemon httpd
echo echo
\end{listingcont}
\end{lstlisting} \normalsize
\begin{flushright}
Jetzt wird ein Lock-File\footnote{Ein Lock-File signalisiert anderen Prozessen, da<64> ein bestimmter Proze<7A> bereits gestartet ist. So kann ein zweiter Aufruf verhindert werden.} angelegt. Jetzt wird ein Lock-File\footnote{Ein Lock-File signalisiert anderen Prozessen, da<64> ein bestimmter Proze<7A> bereits gestartet ist. So kann ein zweiter Aufruf verhindert werden.} angelegt.
\end{flushright}
\footnotesize
\index{Anf<EFBFBD>hrungszeichen}\index{touch=\texttt{touch}} \index{Anf<EFBFBD>hrungszeichen}\index{touch=\texttt{touch}}
\begin{lstlisting}[firstnumber=last] \begin{listingcont}
touch /var/lock/subsys/httpd touch /var/lock/subsys/httpd
;; ;;
stop) stop)
echo -n "Shutting down http: " echo -n "Shutting down http: "
\end{listingcont}
\end{lstlisting} \normalsize
\begin{flushright}
Hier passiert im Prinzip das gleiche wie oben, nur da<64> mit der Funktion \texttt{killproc} der Daemon angehalten wird. Hier passiert im Prinzip das gleiche wie oben, nur da<64> mit der Funktion \texttt{killproc} der Daemon angehalten wird.
\end{flushright}
\begin{lstlisting}[firstnumber=last] \footnotesize
\begin{listingcont}
killproc httpd killproc httpd
echo echo
\end{listingcont}
\end{lstlisting} \normalsize
\begin{flushright}
Danach werden Lock-File und PID-File\footnote{In einem sogenannten PID-File hinterlegen einige Prozesse ihre Proze<7A>-ID, um anderen Programmen den Zugriff zu erleichtern (z. B. um den Proze<7A> anzuhalten etc).} gel<65>scht. Danach werden Lock-File und PID-File\footnote{In einem sogenannten PID-File hinterlegen einige Prozesse ihre Proze<7A>-ID, um anderen Programmen den Zugriff zu erleichtern (z. B. um den Proze<7A> anzuhalten etc).} gel<65>scht.
\end{flushright}
\begin{lstlisting}[firstnumber=last] \footnotesize
\begin{listingcont}
rm -f /var/lock/subsys/httpd rm -f /var/lock/subsys/httpd
rm -f /var/run/httpd.pid rm -f /var/run/httpd.pid
;; ;;
status) status)
\end{listingcont}
\end{lstlisting} \normalsize
\begin{flushright}
Die Funktion \texttt{status} stellt fest, ob der entsprechende Daemon bereits l<>uft, und gibt das Ergebnis aus. Die Funktion \texttt{status} stellt fest, ob der entsprechende Daemon bereits l<>uft, und gibt das Ergebnis aus.
\end{flushright}
\begin{lstlisting}[firstnumber=last] \footnotesize
\begin{listingcont}
status httpd status httpd
;; ;;
restart) restart)
\end{listingcont}
\end{lstlisting} \normalsize
\begin{flushright}
Bei Aufruf mit dem Parameter\index{Parameter} \textsl{restart} ruft sich das Skript zwei mal selbst auf (in \texttt{\$0} steht der Aufrufname des laufenden Programms). Einmal, um den Daemon zu stoppen, dann, um ihn wieder zu starten. Bei Aufruf mit dem Parameter\index{Parameter} \textsl{restart} ruft sich das Skript zwei mal selbst auf (in \texttt{\$0} steht der Aufrufname des laufenden Programms). Einmal, um den Daemon zu stoppen, dann, um ihn wieder zu starten.
\end{flushright}
\footnotesize
\index{\$n=\texttt{\$}$n$}\index{Anf<EFBFBD>hrungszeichen} \index{\$n=\texttt{\$}$n$}\index{Anf<EFBFBD>hrungszeichen}
\begin{lstlisting}[firstnumber=last] \begin{listingcont}
$0 stop $0 stop
$0 start $0 start
;; ;;
reload) reload)
echo -n "Reloading httpd: " echo -n "Reloading httpd: "
\end{listingcont}
\end{lstlisting} \normalsize
\begin{flushright}
Hier sendet die \texttt{killproc}-Funktion dem Daemon ein Signal\index{Signal} das ihm sagt, da<64> er seine Konfiguration neu einlesen soll. Hier sendet die \texttt{killproc}-Funktion dem Daemon ein Signal\index{Signal} das ihm sagt, da<64> er seine Konfiguration neu einlesen soll.
\end{flushright}
\footnotesize
\index{\$n=\texttt{\$}$n$}\index{Anf<EFBFBD>hrungszeichen} \index{\$n=\texttt{\$}$n$}\index{Anf<EFBFBD>hrungszeichen}
\begin{lstlisting}[firstnumber=last] \begin{listingcont}
killproc httpd -HUP killproc httpd -HUP
echo echo
;; ;;
*) *)
echo "Usage: $0 {start|stop|restart|reload|status}" echo "Usage: $0 {start|stop|restart|reload|status}"
\end{listingcont}
\end{lstlisting} \normalsize
\begin{flushright}
Bei aufruf mit einem beliebigen anderen Parameter\index{Parameter} wird eine Kurzhilfe ausgegeben. Dann wird daf<61>r gesorgt, da<64> das Skript mit dem Exit-Code 1 beendet wird. So kann festgestellt werden, ob das Skript ordnungsgem<65><6D> beendet wurde (\ref{exit}). Bei aufruf mit einem beliebigen anderen Parameter\index{Parameter} wird eine Kurzhilfe ausgegeben. Dann wird daf<61>r gesorgt, da<64> das Skript mit dem Exit-Code 1 beendet wird. So kann festgestellt werden, ob das Skript ordnungsgem<65><6D> beendet wurde (\ref{exit}).
\end{flushright}
\footnotesize
\index{exit=\texttt{exit}} \index{exit=\texttt{exit}}
\begin{lstlisting}[firstnumber=last] \begin{listingcont}
exit 1 exit 1
esac esac
exit 0 exit 0
\end{listingcont}
\end{lstlisting} \normalsize
\section{Parameter<EFBFBD>bergabe in der Praxis}\label{beisp_parameter}\index{Parameter} \section{Parameter<EFBFBD>bergabe in der Praxis}\label{beisp_parameter}\index{Parameter}
@ -261,19 +205,21 @@ Es kommt in der Praxis sehr oft vor, da
Das soll an folgendem Skript verdeutlicht werden. Das Skript kennt die Optionen \texttt{-a} und \texttt{-b}. Letzterer Option mu<6D> ein zus<75>tzlicher Wert mitgegeben werden. Alle anderen Parameter\index{Parameter} werden als Dateinamen interpretiert. Das soll an folgendem Skript verdeutlicht werden. Das Skript kennt die Optionen \texttt{-a} und \texttt{-b}. Letzterer Option mu<6D> ein zus<75>tzlicher Wert mitgegeben werden. Alle anderen Parameter\index{Parameter} werden als Dateinamen interpretiert.
\footnotesize
\index{\$@=\texttt{\$@}}\index{Anf<EFBFBD>hrungszeichen}\index{Backticks}\index{!|!|=\texttt{!|!|}}\index{getopt=\texttt{getopt}}\index{OR}\index{set=\texttt{set}} \index{\$@=\texttt{\$@}}\index{Anf<EFBFBD>hrungszeichen}\index{Backticks}\index{!|!|=\texttt{!|!|}}\index{getopt=\texttt{getopt}}\index{OR}\index{set=\texttt{set}}
\begin{lstlisting} \begin{listing}[2]{1}
#!/bin/sh #!/bin/sh
set -- `getopt "ab:" "$@"` || { set -- `getopt "ab:" "$@"` || {
\end{listing}
\end{lstlisting} \normalsize
\begin{flushright}
Das \texttt{set}\index{set=\texttt{set}}-Kommando belegt den Inhalt der vordefinierten Variablen (\ref{vordefinierte_variablen}) neu, so da<64> es aussieht, als ob dem Skript die R<>ckgabewerte von \texttt{getopt}\index{getopt=\texttt{getopt}} <20>bergeben wurden. Man mu<6D> die beiden Minuszeichen angeben, da sie daf<61>r sorgen, da<64> die Aufrufparameter an \texttt{getopt}\index{getopt=\texttt{getopt}} und nicht an die Shell selbst <20>bergeben werden. Die originalen Parameter\index{Parameter} werden von \texttt{getopt}\index{getopt=\texttt{getopt}} untersucht und modifiziert zur<75>ckgegeben: \texttt{a} und \texttt{b} werden als Parameter\index{Parameter} Markiert, \texttt{b} sogar mit der M<>glichkeit einer zus<75>tzlichen Angabe. Das \texttt{set}\index{set=\texttt{set}}-Kommando belegt den Inhalt der vordefinierten Variablen (\ref{vordefinierte_variablen}) neu, so da<64> es aussieht, als ob dem Skript die R<>ckgabewerte von \texttt{getopt}\index{getopt=\texttt{getopt}} <20>bergeben wurden. Man mu<6D> die beiden Minuszeichen angeben, da sie daf<61>r sorgen, da<64> die Aufrufparameter an \texttt{getopt}\index{getopt=\texttt{getopt}} und nicht an die Shell selbst <20>bergeben werden. Die originalen Parameter\index{Parameter} werden von \texttt{getopt}\index{getopt=\texttt{getopt}} untersucht und modifiziert zur<75>ckgegeben: \texttt{a} und \texttt{b} werden als Parameter\index{Parameter} Markiert, \texttt{b} sogar mit der M<>glichkeit einer zus<75>tzlichen Angabe.
Wenn dieses Kommando fehlschl<68>gt ist das ein Zeichen daf<61>r, da<64> falsche Parameter\index{Parameter} <20>bergeben wurden. Also wird nach einer entsprechenden Meldung das Programm mit Exit-Code 1 verlassen. Wenn dieses Kommando fehlschl<68>gt ist das ein Zeichen daf<61>r, da<64> falsche Parameter\index{Parameter} <20>bergeben wurden. Also wird nach einer entsprechenden Meldung das Programm mit Exit-Code 1 verlassen.
\end{flushright}
\footnotesize
\index{\$n=\texttt{\$}$n$}\index{Null-Befehl}\index{!>\&=\texttt{!>\&}}\index{!==\texttt{!=}}\index{Anf<EFBFBD>hrungszeichen}\index{Backticks}\index{basename=\texttt{basename}} \index{\$n=\texttt{\$}$n$}\index{Null-Befehl}\index{!>\&=\texttt{!>\&}}\index{!==\texttt{!=}}\index{Anf<EFBFBD>hrungszeichen}\index{Backticks}\index{basename=\texttt{basename}}
\begin{lstlisting}[firstnumber=last] \begin{listingcont}
echo "Anwendung: `basename $0` [-a] [-b Name] Dateien" 1>&2 echo "Anwendung: `basename $0` [-a] [-b Name] Dateien" 1>&2
exit 1 exit 1
} }
@ -281,284 +227,98 @@ echo "Momentan steht in der Kommandozeile folgendes: $*"
aflag=0 name=NONE aflag=0 name=NONE
while : while :
do do
\end{listingcont}
\end{lstlisting} \normalsize
\begin{flushright}
In einer Endlosschleife\index{Endlosschleife}, die man mit Hilfe des Null-Befehls (\texttt{:}, \ref{null-befehl}) baut, werden die `neuen' Parameter\index{Parameter} der Reihe nach untersucht. Wenn ein \texttt{-a} vorkommt, wird die Variable \texttt{aflag} gesetzt. Bei einem \texttt{-b} werden per \texttt{shift}\index{shift=\texttt{shift}} alle Parameter\index{Parameter} nach Links verschoben, dann wird der Inhalt des n<>chsten Parameters\index{Parameter} in der Variablen \texttt{name} gesichert. In einer Endlosschleife\index{Endlosschleife}, die man mit Hilfe des Null-Befehls (\texttt{:}, \ref{null-befehl}) baut, werden die `neuen' Parameter\index{Parameter} der Reihe nach untersucht. Wenn ein \texttt{-a} vorkommt, wird die Variable \texttt{aflag} gesetzt. Bei einem \texttt{-b} werden per \texttt{shift}\index{shift=\texttt{shift}} alle Parameter\index{Parameter} nach Links verschoben, dann wird der Inhalt des n<>chsten Parameters\index{Parameter} in der Variablen \texttt{name} gesichert.
\end{flushright}
\footnotesize
\index{!==\texttt{!=}}\index{\$n=\texttt{\$}$n$}\index{Anf<EFBFBD>hrungszeichen}\index{case=\texttt{case}}\index{shift=\texttt{shift}} \index{!==\texttt{!=}}\index{\$n=\texttt{\$}$n$}\index{Anf<EFBFBD>hrungszeichen}\index{case=\texttt{case}}\index{shift=\texttt{shift}}
\begin{lstlisting}[firstnumber=last] \begin{listingcont}
case "$1" in case "$1" in
-a) aflag=1 ;; -a) aflag=1 ;;
-b) shift; name="$1" ;; -b) shift; name="$1" ;;
--) break ;; --) break ;;
\end{listingcont}
\end{lstlisting} \normalsize
\begin{flushright}
Wenn ein \texttt{-{}-} erscheint, ist das ein Hinweis darauf, da<64> die Liste der Parameter\index{Parameter} abgearbeitet ist. Dann wird per \texttt{break}\index{break=\texttt{break}} (\ref{break}) die Endlosschleife unterbrochen. Die Aufrufparameter enthalten jetzt nur noch die eventuell angegebenen Dateinamen, die jetzt von dem Restlichen Skript wie gewohnt weiterverarbeitet werden k<>nnen. Wenn ein \texttt{-{}-} erscheint, ist das ein Hinweis darauf, da<64> die Liste der Parameter\index{Parameter} abgearbeitet ist. Dann wird per \texttt{break}\index{break=\texttt{break}} (\ref{break}) die Endlosschleife unterbrochen. Die Aufrufparameter enthalten jetzt nur noch die eventuell angegebenen Dateinamen, die jetzt von dem Restlichen Skript wie gewohnt weiterverarbeitet werden k<>nnen.
\end{flushright}
\footnotesize
\index{shift=\texttt{shift}} \index{shift=\texttt{shift}}
\begin{lstlisting}[firstnumber=last] \begin{listingcont}
esac esac
shift shift
done done
shift shift
\end{listingcont}
\end{lstlisting} \normalsize
\begin{flushright}
Am Ende werden die Feststellungen ausgegeben. Am Ende werden die Feststellungen ausgegeben.
\end{flushright}
\footnotesize
\index{\$*=\texttt{\$*}}\index{Anf<EFBFBD>hrungszeichen} \index{\$*=\texttt{\$*}}\index{Anf<EFBFBD>hrungszeichen}
\begin{lstlisting}[firstnumber=last] \begin{listingcont}
echo "aflag=$aflag / Name = $name / Die Dateien sind $*" echo "aflag=$aflag / Name = $name / Die Dateien sind $*"
\end{listingcont}
\end{lstlisting} \normalsize
\section{Fallensteller: Auf Traps reagieren}\label{traps}\index{trap=\texttt{trap}|(}\index{Signal|(} \section{Fallensteller: Auf Traps
reagieren}\label{traps}\index{trap=\texttt{trap}|(}\index{Signal|(}
Ein laufendes Shell-Skript kann durch Druck auf die Interrupt-Taste Ein laufendes Shell-Skript kann durch Druck auf die Interrupt-Taste (normalerweise \Ovalbox{CTRL}-\Ovalbox{C}) unterbrochen werden. Durch Druck auf diese Taste wird ein Signal an den entsprechenden Proze<7A> gesandt, das ihn bittet sich zu beenden. Dieses Signal hei<65>t SIGINT (f<>r SIGnal INTerrupt) und tr<74>gt die Nummer 2. Das kann ein kleines Problem darstellen, wenn das Skript sich tempor<6F>re Dateien angelegt hat, da diese nach der Ausf<73>hrung nur noch unn<6E>tig Platz verbrauchen und eigentlich gel<65>scht werden sollten. Man kann sich sicher auch noch wichtigere F<>lle vorstellen, in denen ein Skript bestimmte Aufgaben auf jeden Fall erledigen mu<6D>, bevor es sich beendet.
(\Ovalbox{CTRL}+\Ovalbox{C}) unterbrochen werden. Durch Druck auf
diese Taste wird ein Signal an den entsprechenden Proze<7A> gesandt, das ihn
bittet sich zu beenden. Dieses Signal hei<65>t SIGINT (f<>r SIGnal INTerrupt) und
tr<EFBFBD>gt die Nummer 2. Das kann ein kleines Problem darstellen, wenn das Skript
sich tempor<6F>re Dateien angelegt hat, da diese nach der Ausf<73>hrung nur noch
unn<EFBFBD>tig Platz verbrauchen und eigentlich gel<65>scht werden sollten. Man kann
sich sicher auch noch wichtigere F<>lle vorstellen, in denen ein Skript
bestimmte Aufgaben auf jeden Fall erledigen mu<6D>, bevor es sich beendet.
Es gibt eine Reihe weiterer Signale, auf die ein Skript reagieren kann. Alle Es gibt eine Reihe weiterer Signale, auf die ein Skript reagieren kann. Alle sind in der Man-Page von \texttt{signal} beschrieben. Hier die wichtigsten:\nopagebreak
sind in der Man-Page von \texttt{signal} beschrieben. Hier die
wichtigsten:\nopagebreak
\LTXtable{\textwidth}{tab_signale.tex} \LTXtable{\textwidth}{tab_signale.tex}
Wie l<>st man jetzt dieses Problem? Gl<47>cklicherweise verf<72>gt die Shell <20>ber das Wie l<>st man jetzt dieses Problem? Gl<47>cklicherweise verf<72>gt die Shell <20>ber das \texttt{trap}-Kommando, mit dessen Hilfe man auf diese Signale reagieren kann. Die Anwendung soll in folgendem Skript beispielhaft dargestellt werden.
\texttt{trap}-Kommando, mit dessen Hilfe man auf diese Signale reagieren kann.
Die Anwendung soll in folgendem Skript beispielhaft dargestellt werden.
Das Skript soll eine komprimierte Textdatei mittels \texttt{zcat} in ein Das Skript soll eine komprimierte Textdatei mittels \texttt{zcat} in ein tempor<6F>res File entpacken, dieses mit \texttt{pg} seitenweise anzeigen und nachher wieder l<>schen.
tempor<EFBFBD>res File entpacken, dieses mit \texttt{pg} seitenweise anzeigen und
nachher wieder l<>schen.
\footnotesize
\index{!==\texttt{!=}} \index{!==\texttt{!=}}
\begin{lstlisting} \begin{listing}[2]{1}
#!/bin/sh #!/bin/sh
stat=1 stat=1
temp=/tmp/zeige$$ temp=/tmp/zeige$$
\end{listing}
\end{lstlisting} \normalsize
\begin{flushright}
Zun<EFBFBD>chst werden zwei Variablen belegt, die im weiteren Verlauf benutzt werden Zun<EFBFBD>chst werden zwei Variablen belegt, die im weiteren Verlauf benutzt werden sollen. In \texttt{stat} wird der Wert abgelegt, den das Skript im Falle eines Abbruchs als Exit-Status zur<75>ckliefern soll. Die Variable \texttt{temp} enth<74>lt den Namen f<>r eine tempor<6F>re Datei. Dieser setzt sich zusammen aus \texttt{/tmp/zeige} und der Proze<7A>nummer des laufenden Skripts. So soll sichergestellt werden, da<64> noch keine Datei mit diesem Namen existiert.
sollen. In \texttt{stat} wird der Wert abgelegt, den das Skript im Falle eines \end{flushright}
Abbruchs als Exit-Status zur<75>ckliefern soll. Die Variable \texttt{temp} enth<74>lt \footnotesize
den Namen f<>r eine tempor<6F>re Datei. Dieser setzt sich zusammen aus
\texttt{/tmp/zeige} und der Proze<7A>nummer des laufenden Skripts. So soll
sichergestellt werden, da<64> noch keine Datei mit diesem Namen existiert.
\index{Ticks}\index{!>\&=\texttt{!>\&}}\index{\$n=\texttt{\$}$n$}\index{Ticks}\index{Anf<EFBFBD>hrungszeichen}\index{Backticks}\index{basename=\texttt{basename}} \index{Ticks}\index{!>\&=\texttt{!>\&}}\index{\$n=\texttt{\$}$n$}\index{Ticks}\index{Anf<EFBFBD>hrungszeichen}\index{Backticks}\index{basename=\texttt{basename}}
\begin{lstlisting}[firstnumber=last] \begin{listingcont}
trap 'rm -f $temp; exit $stat' 0 trap 'rm -f $temp; exit $stat' 0
trap 'echo "`basename $0`: Ooops..." 1>&2' 1 2 15 trap 'echo "`basename $0`: Ooops..." 1>&2' 1 2 15
\end{listingcont}
\end{lstlisting} \normalsize
\begin{flushright}
Hier werden die Traps definiert. Bei Signal 0 wird die tempor<6F>re Datei gel<65>scht Hier werden die Traps definiert. Bei Signal 0 wird die tempor<6F>re Datei gel<65>scht und der Wert aus der Variable \texttt{stat} als Exit-Code zur<75>ckgegeben. Dabei wird dem \texttt{rm}-Kommando der Parameter\index{Parameter} \texttt{-f} mitgegeben, damit keine Fehlermeldung ausgegeben wird, falls die Datei (noch) nicht existiert. Dieser Fall tritt bei jedem Beenden des Skriptes auf, also sowohl bei einem normalen Ende, als auch beim Exit-Kommando, bei einem Interrupt oder bei einem Kill\index{kill=\texttt{kill}}. Der zweite Trap reagiert auf die Signale 1, 2 und 15. Das hei<65>t, er wird bei jedem unnormalen Ende ausgef<65>hrt. Er gibt eine entsprechende Meldung auf die Standard-Fehlerausgabe (\ref{datenstrom}) aus. Danach wird das Skript beendet, und der erste Trap wird ausgef<65>hrt.
und der Wert aus der Variable \texttt{stat} als Exit-Code zur<75>ckgegeben. Dabei \end{flushright}
wird dem \texttt{rm}-Kommando der Parameter\index{Parameter} \texttt{-f} \footnotesize
mitgegeben, damit keine Fehlermeldung ausgegeben wird, falls die Datei (noch)
nicht existiert. Dieser Fall tritt bei jedem Beenden des Skriptes auf, also
sowohl bei einem normalen Ende, als auch beim Exit-Kommando, bei einem
Interrupt oder bei einem Kill\index{kill=\texttt{kill}}. Der zweite Trap
reagiert auf die Signale 1, 2 und 15. Das hei<65>t, er wird bei jedem unnormalen
Ende ausgef<65>hrt. Er gibt eine entsprechende Meldung auf die
Standard-Fehlerausgabe (\ref{datenstrom}) aus. Danach wird das Skript beendet,
und der erste Trap wird ausgef<65>hrt.
\index{\$\#=\texttt{\$\#}}\index{!==\texttt{!=}}\index{!>=\texttt{!>}}\index{\$n=\texttt{\$}$n$}\index{Anf<EFBFBD>hrungszeichen}\index{case=\texttt{case}} \index{\$\#=\texttt{\$\#}}\index{!==\texttt{!=}}\index{!>=\texttt{!>}}\index{\$n=\texttt{\$}$n$}\index{Anf<EFBFBD>hrungszeichen}\index{case=\texttt{case}}
\begin{lstlisting}[firstnumber=last] \begin{listingcont}
case $# in case $# in
1) zcat "$1" > $temp 1) zcat "$1" > $temp
pg $temp pg $temp
stat=0 stat=0
;; ;;
\end{listingcont}
\end{lstlisting} \normalsize
\begin{flushright}
Jetzt kommt die eigentliche Funktionalit<69>t des Skriptes: Das Jetzt kommt die eigentliche Funktionalit<69>t des Skriptes: Das \texttt{case}-Kommando (\ref{case}) testet die Anzahl der <20>bergebenen Parameter\index{Parameter}. Wenn genau ein Parameter\index{Parameter} <20>bergeben wurde, entpackt \texttt{zcat} die Datei, die im ersten Parameter\index{Parameter} angegeben wurde, in die tempor<6F>re Datei. Dann folgt die Seitenweise Ausgabe mittels \texttt{pg}. Nach Beendigung der Ausgabe wird der Status in der Variablen auf 0 gesetzt, damit beim Skriptende der korrekte Exit-Code zur<75>ckgegeben wird.
\texttt{case}-Kommando (\ref{case}) testet die Anzahl der <20>bergebenen \end{flushright}
Parameter\index{Parameter}. Wenn genau ein Parameter\index{Parameter} <20>bergeben \footnotesize
wurde, entpackt \texttt{zcat} die Datei, die im ersten
Parameter\index{Parameter} angegeben wurde, in die tempor<6F>re Datei. Dann folgt
die Seitenweise Ausgabe mittels \texttt{pg}. Nach Beendigung der Ausgabe wird
der Status in der Variablen auf 0 gesetzt, damit beim Skriptende der korrekte
Exit-Code zur<75>ckgegeben wird.
\index{!>\&=\texttt{!>\&}}\index{\$n=\texttt{\$}$n$}\index{Anf<EFBFBD>hrungszeichen}\index{Backticks}\index{basename=\texttt{basename}} \index{!>\&=\texttt{!>\&}}\index{\$n=\texttt{\$}$n$}\index{Anf<EFBFBD>hrungszeichen}\index{Backticks}\index{basename=\texttt{basename}}
\begin{lstlisting}[firstnumber=last] \begin{listingcont}
*) echo "Anwendung: `basename $0` Dateiname" 1>&2 *) echo "Anwendung: `basename $0` Dateiname" 1>&2
esac esac
\end{listingcont}
\end{lstlisting} \normalsize
\begin{flushright}
Wenn \texttt{case} eine andere Parameterzahl feststellt, wird eine Meldung mit Wenn \texttt{case} eine andere Parameterzahl feststellt, wird eine Meldung mit der Aufrufsyntax auf die Standard-Fehlerausgabe geschrieben.
der Aufrufsyntax auf die Standard-Fehlerausgabe geschrieben. \end{flushright}
\index{trap=\texttt{trap}|)}\index{Signal|)} \index{trap=\texttt{trap}|)}\index{Signal|)}
\section{Chaoten: Dateien in zuf<75>llige Reihenfolge bringen}\label{chaoten}\index{Zufallszahlen|(}
Wir wollen uns einen MP3-Player programmieren, der Alle MP3-Dateien aus einem
bestimmten Verzeichnisbaum in zuf<75>lliger Reihenfolge abspielt. Damit dieses
Problem f<>r uns eine Herausforderung darstellt\footnote{Denn schlie<69>lich hat
mpg123 schon von Hause aus eine Random-Funktion.}, wollen wir vor dem Abspielen
der jeweiligen Datei etwas mit dem Dateinamen anstellen. Ob das eine einfache
Ausgabe per \texttt{echo} ist, oder ob der Name per Sprachsynthese oder auf
einem externen Display angezeigt werden soll ist an dieser Stelle egal.
Das Problem ist, da<64> wir in der Shell nur <20>ber Umwege an Zufallszahlen kommen
k<EFBFBD>nnen. Auf Systemen, in denen die Datei \texttt{/dev/urandom} existiert,
liefert uns der Kernel aber schon sehr zuf<75>llige Zeichenfolgen. Diese Folgen
k<EFBFBD>nnen alle Zeichen enthalten, daher m<>ssen sie vor der Benutzung f<>r unsere
Zwecke noch etwas `bereinigt' werden.
Wie das aussieht, wenn es fertig ist, sieht man im folgenden Skript:
\index{!==\texttt{!=}}
\begin{lstlisting}
#!/bin/sh
for i in `find $1 -type f -name "*.[mM][pP]3"`; do
\end{lstlisting}
Hier beginnt eine Schleife, die <20>ber alle Ausgaben des \texttt{find}-Kommandos
iteriert. Dabei sucht \texttt{find} nach allen normalen Dateien (\texttt{-type
f}), die die Extension .mp3 tragen (\texttt{-name \dq*.[mM][pP]3\dq} -- wir
ignorieren Gro<72>- / Kleinschreibung).
\index{find=\texttt{find}}
\begin{lstlisting}[firstnumber=last]
echo `tr -dc "[:alpha:]" < /dev/urandom | \
dd count=8 bs=1 2> /dev/null`$i
\end{lstlisting}
Hier ist der `magische Teil'. Mit dem \texttt{echo} wird die Ausgabe einer Pipe
ausgegeben, gefolgt von dem aktuellen Dateinamen. Diese Pipe enth<74>lt ein
\texttt{tr}, der alle ungewollten Zeichen (alles, was kein Textzeichen ist) aus
einem Datenstrom entfernt. Die Daten erh<72>lt \texttt{tr} durch die
\texttt{<}-Umleitung aus oben genannter Datei.
Diese Datei liefert `ohne Ende' Zeichen. Wir wollen aber nur acht Zeichen
haben, die wir unserem Dateinamen voranstellen k<>nnen. Dazu benutzen wir das
Kommando \texttt{dd} mit den angegebenen Parametern. Damit die Erfolgsmeldung
von \texttt{dd} nicht die Ausgabe verunstaltet, lenken wir sie nach
\texttt{/dev/null} um.
\index{tr=\texttt{tr}}\index{dd=\texttt{dd}}
\index{find=\texttt{find}}
\begin{lstlisting}[firstnumber=last]
done | sort | cut -b 9- | while read i; do
\end{lstlisting}
Das Ergebnis der obigen Schleife ist also die Liste der Dateinamen, denen
jeweils acht zuf<75>llige Zeichen vorangestellt wurden. Die Reihenfolge entspricht
allerdings immer noch der Ausgabe von \texttt{find}, wird also nach jedem
Durchlauf gleich sein.
Um das zu <20>ndern, pipen wir die Ausgabe der Schleife durch ein \texttt{sort}.
Da die ersten acht Zeichen jeder Zeile zuf<75>llig sind, erhalten wir so eine
zuf<EFBFBD>llige Reihenfolge der Zeilen. Jetzt m<>ssen wir nur noch durch ein
\texttt{cut} die zuf<75>lligen Zeichen abschneiden, und erhalten so die
urspr<EFBFBD>ngliche Liste von Dateien in einer zuf<75>lligen Reihenfolge.
Diese lesen wir jetzt zeilenweise mittels \texttt{read} ein. In der
\texttt{while}-Schleife k<>nnen wir alle erforderlichen Sachen mit dem
Dateinamen anstellen. Hier wird er nur mittels \texttt{echo} ausgegeben.
\index{sort=\texttt{sort}}\index{cut=\texttt{cut}} \index{read=\texttt{read}}\index{while=\texttt{while}}
\index{find=\texttt{find}}
\begin{lstlisting}[firstnumber=last]
echo "Jetzt wird $i gespielt"
mpg123 "$i"
done
\end{lstlisting}
\index{Zufallszahlen|)}
\section{Wer suchet, der findet}\label{beispiele_suchen}\index{grep=\texttt{grep}|(textbf}
\subsection{Prozesse suchen}\label{beispiele_suchen_prozesse}\index{ps=\texttt{ps}|(textbf}\index{pgrep=\texttt{pgrep}|(textbf}
Im Zusammenhang mit grep st<73><74>t fast jeder Shell-Skripter fr<66>her oder sp<73>ter auf
das Problem, da<64> er irgendwas davon abh<62>ngig machen will, ob ein bestimmter
Proze<EFBFBD> l<>uft oder nicht. Im Normalfall wird er zuerst folgendes ausprobieren,
was aber oft (nicht immer) in die Hose gehen wird:
\lstinline/ps aux | grep prozessname && echo "l<>uft schon"/
Der Grund daf<61>r ist, da<64> unter Umst<73>nden in der Ausgabe von \texttt{ps} auch
das \texttt{grep}-Kommando samt Parameter (\textit{prozessname}) aufgelistet
wird. So findet das \texttt{grep}-Kom\-man\-do sich quasi selbst.
Abhilfe schafft entweder \texttt{pgrep} (\ref{pgrep}) oder das folgende
Konstrukt:
\lstinline/ps aux | grep "[p]rozessname" && echo "l<>uft schon"/
Das p ist jetzt als eine Zeichenmenge (regul<EFBFBD>rer Ausdruck) angegeben worden.
Jetzt sucht \texttt{grep} also nach dem String \textit{prozessname}, in der
Ausgabe von \texttt{ps} erscheint das \texttt{grep}-Kommando allerdings mit
\textit{[p]rozessname} und wird somit ignoriert.
\index{ps=\texttt{ps}|)textbf}\index{pgrep=\texttt{pgrep}|)textbf}
\subsection{Dateiinhalte suchen}\label{beispiele_suchen_dateien}\index{find=\texttt{find}|(textbf}
Ein weiterer wertvoller Trick, diesmal im Zusammenhang mit \texttt{find}, ist
folgendes Szenario: Es gibt ein Verzeichnis mit vielen Unterverzeichnissen,
<EFBFBD>berall liegen Perl-Skripte und andere Dateien. Gesucht sind alle Dateien, in
denen eine Zeile mit dem Inhalt `strict' vorkommt. Man k<>nnte jetzt
folgendes versuchen:
\lstinline|grep -r strict *|
Das f<>hrt allerdings dazu, da<64> alle Dateien durchsucht werden, nicht nur die
Perl-Skripte. Diese tragen nach unserer Konvention\footnote{Perl-Skripte m<>ssen
keine spezielle Extension haben, es sei aber um des Beispiels Willen mal
angenommen.} die Extension `.pl'. Wir starten also eine rekursive Suche <20>ber
alle Dateien, die dem Muster entsprechen:
\lstinline|grep -r strict *.pl|
Und wieder f<>hrt es nicht zu dem gew<65>nschten Ergebnis. Da die
Unterverzeichnisse nicht die Extension `*.pl' tragen, werden sie nicht
ber<EFBFBD>cksichtigt. F<>r die Suche in Unterverzeichnissen ziehen wir \texttt{find}
(Siehe Abschnitt \ref{find}) heran:
\lstinline|find . -name \*.pl -exec grep strict {} \;|
Dieser Befehl gibt uns zwar die gefundenen Zeilen aus, nicht aber die Namen der
Dateien. Es sieht f<>r \texttt{grep} so aus als ob nur eine Datei durchsucht
w<EFBFBD>rde, da besteht keine Notwendigkeit den Namen anzugeben. Das ginge mit dem
Parameter \texttt{-l}, allerdings w<>rden uns dann nur noch die Dateinamen
angezeigt. Eine Ausgabe mit beiden Informationen erhalten wir mit dem folgenden
Konstrukt:
\lstinline|find . -name \*.pl -exec grep strict /dev/null {} \;|
Hier durchsucht \texttt{grep} nicht nur die gefundenen Dateien, sondern bei
jedem Aufruf auch \texttt{/dev/null}, also den digitalen M<>lleimer der per
Definition leer ist. Da es f<>r \texttt{grep} so aussieht als ob mehr als eine
Datei durchsucht w<>rden, wird bei jeder Fundstelle sowohl der Dateiname als
auch die gefundene Zeile ausgegeben.
\index{find=\texttt{find}|)textbf}
\index{grep=\texttt{grep}|)textbf}

View File

@ -1,17 +1,10 @@
% $Id$ \chapter{Quellen}
\chapter{Quellen}\label{quellen}
\begin{itemize} \begin{itemize}
\item Bash Reference Manual (\href{http://www.gnu.org/software/bash/manual/bashref.html}{http://www.gnu.org/software/bash/manual/bashref.html}) \item Bash Reference Manual (\texttt{http://www.gnu.org/manual/bash-2.02/\\bashref.html})
\item Die Man-Page der Bash \item Unix In A Nutshell (\texttt{http://www.oreilly.com/catalog/unixnut3/})
\item Die deutschsprachige Shell-Newsgroup (\href{news://de.comp.os.unix.shell}{news://de.comp.os.unix.shell}) \item Unix Power Tools (\texttt{http://www.oreilly.com/catalog/upt2/})
\item Unix In A Nutshell (\href{http://www.oreilly.com/catalog/unixnut3/}{http://www.oreilly.com/catalog/unixnut3/}) \item Von DOS nach Linux HOWTO (\texttt{http://www.tu-harburg.de/\\\~{}semb2204/dlhp/HOWTO/DE-DOS-nach-Linux-HOWTO.html})
\item Unix Power Tools (\href{http://www.oreilly.com/catalog/upt2/}{http://www.oreilly.com/catalog/upt2/})
\item Von DOS nach Linux HOWTO (\href{http://www.linuxhaven.de/dlhp/HOWTO/DE-DOS-nach-Linux-HOWTO.html}{http://www.linuxhaven.de/dlhp/HOWTO/DE-DOS-nach-Linux-HOWTO.html})
\item Bash Guide for Beginners (\href{http://tldp.org/LDP/Bash-Beginners-Guide/}{http://tldp.org/LDP/Bash-Beginners-Guide/})
\item Advanced Bash-Scripting Guide (\href{http://tldp.org/LDP/abs/}{http://tldp.org/LDP/abs/})
\item The Open Group Base Specifications
\item Single Unix Specifications V2
\item ... und eine Menge Skripte, die ich im Laufe der Zeit gelesen habe (das \item ... und eine Menge Skripte, die ich im Laufe der Zeit gelesen habe (das
kann ich nur jedem empfehlen - es ist spannender als es sich anh<6E>rt...). kann ich nur jedem empfehlen - es ist spannender als es sich anh<6E>rt...).
\end{itemize} \end{itemize}

View File

@ -1,4 +1,3 @@
% $Id$
\chapter{Schmutzige Tricks :-)} \chapter{Schmutzige Tricks :-)}
Eigentlich sind diese Tricks gar nicht so schmutzig. Hier ist lediglich eine Eigentlich sind diese Tricks gar nicht so schmutzig. Hier ist lediglich eine
@ -24,411 +23,29 @@ haben.
\section{Die Tar-Br<42>cke} \section{Die Tar-Br<42>cke}
Eine sogenannte Tar-Br<42>cke benutzt man, wenn eine oder mehrere Dateien zwischen TODO!!!
Rechnern <20>bertragen werden sollen, aber kein Dienst wie SCP oder FTP zur
Verf<EFBFBD>gung steht. Au<41>erdem hat die Methode den Vorteil, da<64> Benutzerrechte und
andere Dateiattribute bei der <20>bertragung erhalten
bleiben\footnote{Vorausgesetzt nat<61>rlich, da<64> der Benutzer auf der entfernten
Seite <20>ber die n<>tigen Rechte verf<72>gt.}.
Der Trick besteht darin, auf einer Seite der Verbindung etwas mit \texttt{tar}
einzupacken, dies durch eine Pipe auf die andere Seite der Verbindung zu
bringen und dort wieder zu entpacken.
Wenn dem Kommando \texttt{tar} an Stelle eines Dateinamens ein Minus-Zeichen
als Archiv gegeben wird, benutzt es~--~je nach der gew<65>hlten Aktion~--~die
Standard-Ein- bzw. -Ausgabe. Diese kann an ein weiteres \texttt{tar} <20>bergeben
werden um wieder entpackt zu werden.
Ein Beispiel verdeutlicht diese Kopier-F<>higkeit:
\lstinline_tar cf - . | ( cd /tmp/backup; tar xf - )_
Hier wird zun<75>chst der Inhalt des aktuellen Verzeichnisses `verpackt'. Das
Resultat wird an die Standard-Ausgabe geschrieben. Auf der Empf<70>ngerseite der
Pipe wird eine Subshell ge<67>ffnet. Das ist notwendig, da das empfangende
\texttt{tar} in einem anderen Verzeichnis laufen soll. In der Subshell wird
zun<EFBFBD>chst das Verzeichnis gewechselt. Dann liest ein \texttt{tar} von der
Standard-Eingabe und entpackt alles was er findet. Sobald keine Eingaben mehr
kommen, beendet sich der Proze<7A> mitsamt der Subshell.
Am Ziel-Ort finden sich jetzt die gleichen Dateien wie am Quell-Ort.
Das lie<69>e sich lokal nat<61>rlich auch anders l<>sen. Man k<>nnte erst ein Archiv
erstellen, das dann an anderer Stelle wieder auspacken. Nachteil: Es mu<6D>
gen<EFBFBD>gend Platz f<>r das Archiv vorhanden sein. Denkbar w<>re auch ein in den Raum
gestelltes
\lstinline_cp -Rp * /tmp/backup_
Allerdings fehlen einem dabei mitunter n<>tzliche
\texttt{tar}-Optionen\footnote{Mit \texttt{-l} verl<72><6C>t \texttt{tar}
beispielsweise nicht das File-System. N<>tzlich wenn nur eine Partition
gesichert werden soll.}, und die oben erw<72>hnte Br<42>cke w<>re mit einem reinen
\texttt{cp} nicht m<>glich.
Eine Seite der Pipe kann n<>mlich auch ohne Probleme auf einem entfernten
Rechner `stattfinden'. Kommandos wie \texttt{ssh} oder \texttt{rsh} (letzteres
nur unter Vorsicht einsetzen!) schlagen die Br<42>cke zu einem anderen System,
dort wird entweder gepackt und versendet oder quasi die Subshell gestartet und
gelesen. Das sieht wie folgt aus:
\lstinline_ssh 192.168.2.1 tar clf - / | (cd /mnt/backup; tar xf - )_
Hier wird auf einem entfernten Rechner die Root-Partition verpackt, per SSH in
das lokale System geholt und lokal im Backup-Verzeichnis entpackt.
Der Weg in die andere Richtung ist ganz <20>hnlich:
\lstinline_tar cf - datei.txt | ssh 192.168.2.1 "(mkdir -p $PWD ;cd $PWD; tar xf -)"_
Hier wird die Datei verpackt und versendet. Eine Besonderheit gegen<65>ber dem
vorigen Beispiel besteht darin, da<64> das Zielverzeichnis bei Bedarf erstellt
wird, bevor die Datei dort entpackt wird. Zur Erkl<6B>rung: Die Variable
\texttt{\$PWD} wird, da sie nicht von Ticks `gesichert' wird, schon lokal durch
die Shell expandiert. An dieser Stelle erscheint also auf dem entfernten System
der Name des aktuellen Verzeichnisses auf dem lokalen System.
\section{Binaries inside} \section{Binaries inside}
Software wird meistens in Form von Paketen verteilt. Entweder handelt es sich TODO!!!
dabei um auf das Betriebssystem abgestimmte Installationspakete (rpm, deb, pkg
usw.), gepackte Archive (zip, tgz) oder Installationsprogramme. Unter
Unix-Systemen bietet sich f<>r letztere die Shell als Tr<54>gersystem an.
Shell-Skripte sind mit wenigen Einschr<68>nkungen plattformunabh<62>ngig, sie k<>nnen
also ohne vorherige Installations- oder Compilier-Arbeiten gestartet werden und
die Umgebung f<>r das zu installierende Programm testen und / oder vorbereiten.
Abgesehen davon k<>nnen Skripte mit den hier vorgestellten Techniken auch andere
Daten, z. B. Bilder oder T<>ne, enthalten.
Doch wie werden die~--~<7E>blicherweise bin<69>ren~--~Pakete auf das Zielsystem
gebracht?
Im Prinzip gibt es daf<61>r zwei unterschiedliche Verfahren:
\subsection{Bin<EFBFBD>re Here-Dokumente} \subsection{Bin<EFBFBD>re Here-Dokumente}
\index{Here-Dokument}
Eine M<>glichkeit ist es, die bin<69>re Datei in Form eines Here-Dokuments TODO!!!
mitzuliefern. Da es aber in der Natur einer bin<69>ren Datei liegt nicht-druckbare
Zeichen zu enthalten, kann die Datei mit Hilfe des Tools \texttt{uuencode}
vorbereitet werden. Das Tool codiert Eingabedateien so, da<64> sie nur noch
einfache Textzeichen enthalten.
Sehen wir uns das folgende einfache Beispiel an. Es ist etwas wild konstruiert
und nicht sehr sinnvoll, aber es zeigt das Prinzip.
\begin{lstlisting}
#!/bin/sh
echo "Das Bild wird ausgepackt..."
uudecode << 'EOF'
begin 644 icon.png
MB5!.1PT*&@H````-24A$4@```!8````6"`8```#$M&P[````"7!(67,```L3
M```+$P$`FIP8````!&=!34$``+&.?/M1DP```"!C2%)-``!Z)0``@(,``/G_
\end{lstlisting}
Nach einem Hinweis wird also das Here-Dokument als Eingabe f<>r das Tool
\texttt{uudecode} benutzt. Erstellt wurde das Dokument mit einer Zeile der
folgenden Form:
\lstinline|uuencode icon.png icon.png|
Wie man sieht ist der Name der Datei in dem Here-Dokument enthalten. Die Datei
wird entpackt und unter diesem gespeichert. In der `realen Welt' mu<6D> an der
Stelle auf jeden Fall sichergestellt werden, da<64> keine existierenden Dateien
versehentlich <20>berschrieben werden.
Um diesen Abschnitt nicht allzu lang werden zu lassen <20>berspringen wir einen
Teil der Datei.
\begin{lstlisting}[firstnumber=38]
M#-""F4%,@%4.GUZ``"(*`6VW6!S#\>C_?/;__Q<R_S]<P/F7AXDA'I\>@``B
K!>E;2S-,]5!A7`,,U'0@GQ6?8H```P`#@&?)O'P'L0````!)14Y$KD)@@@``
`
end
EOF
if [ $? -ne 0 ]; then
echo "Fehler beim Auspacken der Datei"
exit 1
fi
display icon.png
\end{lstlisting}
Nach dem Entpacken wird noch der Exit-Code von \texttt{uudecode} <20>berpr<70>ft und
im Fehlerfall eine Ausgabe gemacht. Im Erfolgsfall wird das Bild mittels
\texttt{display} angezeigt.
\subsection{Schwanz ab!} \subsection{Schwanz ab!}
Diese Variante basiert darauf, da<64> die bin<69>re Datei ohne weitere Codierung an TODO!!!
das Shell-Skript angeh<65>ngt wurde. Nachteil dieses Verfahrens ist, da<64> das
`abschneidende Kommando' nach jeder <20>nderung der L<>nge des Skriptes angepa<70>t
werden mu<6D>.
Dabei gibt es zwei Methoden, die angeh<65>ngte Datei wieder abzuschneiden. Die \section{Dateien, die es nicht gibt}
einfachere Methode funktioniert mit \texttt{tail}:
\lstinline|tail -n +227 $0 > icon.png| TODO!!!
Dieses Beispiel geht davon aus, da<64> das Skript selbst 227 Zeilen umfa<66>t. Die \subsection{Speichern in nicht existente Dateien}
bin<EFBFBD>re Datei wurde mit einem Kommando wie \lstinline|cat icon.png >> skript.sh|
an das Skript angeh<65>ngt.
F<EFBFBD>r die etwas kompliziertere Variante mu<6D> die L<>nge des eigentlichen TODO!!!
Skript-Teiles genau angepa<70>t werden. Wenn das Skript beispielsweise etwa 5,5kB
lang ist, m<>ssen genau passend viele Leerzeilen oder Kommentarzeichen angeh<65>ngt
werden, damit sich eine L<>nge von 6kB ergibt. Dann kann das Anh<6E>ngsel mit dem
Kommando \texttt{dd} in der folgenden Form abgeschnitten werden:
\lstinline|dd bs=1024 if=$0 of=icon.png skip=6| \subsection{Daten aus einer Subshell hochreichen}
Das Kommando kopiert Daten aus einer Eingabe- in eine Ausgabedatei. Im
einzelnen wird hier eine Blockgr<67><72>e (blocksize, bs) von 1024 Bytes festgelegt.
Dann werden Eingabe- und Ausgabedatei benannt, dabei wird als Eingabedatei
\texttt{\$0} und somit der Name des laufenden Skriptes benutzt. Schlie<69>lich
wird festgelegt, da<64> bei der Aktion die ersten sechs Block~--~also die ersten
sechs Kilobytes~--~<7E>bersprungen werden sollen.
Um es nochmal zu betonen: Diese beiden Methoden sind mit Vorsicht zu genie<69>en.
Bei der ersten f<>hrt jede zus<75>tzliche oder gel<65>schte Zeile zu einer kaputten
Ausgabedatei, bei der zweiten reichen schon einzelne Zeichen. In jedem Fall
sollte nach dem Auspacken noch einmal mittels \texttt{sum} oder \texttt{md5sum}
eine Checksumme gezogen und verglichen werden.
\section{Dateien, die es nicht gibt}\label{dateien_die_es_nicht_gibt}
Eine Eigenart der Behandlung von Dateien unter Unix besteht im Verhalten beim
L<EFBFBD>schen. Gel<65>scht wird n<>mlich zun<75>chst nur der Verzeichniseintrag. Der Inode,
also die Markierung im Dateisystem unter der die Datei gefunden werden kann,
besteht weiterhin. Er wird erst dann freigegeben, wenn er nicht mehr
referenziert wird. Physikalisch besteht die Datei also noch, sie wird lediglich
im Verzeichnis nicht mehr angezeigt.
Hat ein Proze<7A> die Datei noch in irgendeiner Form ge<67>ffnet, kann er weiter
darauf zugreifen. Erst wenn er die Datei schlie<69>t ist sie tats<74>chlich und
unwiederbringlich `weg'.
Dieser Effekt der `nicht existenten Dateien' l<><6C>t sich an verschiedenen Stellen
geschickt einsetzen.
\subsection{Daten aus einer Subshell hochreichen}\label{daten_hochreichen}
Ein immer wieder auftretendes und oft sehr verwirrendes Problem ist, da<64>
Variablen die in einer Subshell definiert wurden au<61>erhalb dieser nicht
sichtbar sind (siehe Abschnitt \ref{subshellschleifen}). Dies ist um so
<EFBFBD>rgerlicher, als da<64> Subshells auch bei vergleichsweise einfachen Pipelines
ge<EFBFBD>ffnet werden.
Ein Beispiel f<>r ein mi<6D>lingendes Skriptfragment w<>re das folgende:
\begin{lstlisting}
nCounter=0
cat datei.txt | while read VAR; do
nCounter=`expr $nCounter + 1`
done
echo "nCounter=$nCounter"
\end{lstlisting}
Die Variable nCounter wird mit 0 initialisiert. Dann wird eine Datei per Pipe
in eine \texttt{while}-Schleife geleitet. Innerhalb der Schleife wird f<>r jede
eingehende Zeile die Variable hochgez<65>hlt. Am Ende der Schleife enth<74>lt die
Variable tats<74>chlich den korrekten Wert, aber da die Pipe eine Subshell
ge<EFBFBD>ffnet hat ist der Wert nach Beendigung der Schleife nicht mehr sichtbar. Das
\texttt{echo}-Kommando gibt die Zahl 0 aus.
Es gibt mehrere Ans<6E>tze, diesem Problem zu begegnen. Am einfachsten w<>re es in
diesem Fall, dem Rat aus Abschnitt \ref{subshellschleifen} zu folgen und die
Subshell geschickt zu vermeiden. Doch das ist leider nicht immer m<>glich. Wie
geht man in solchen F<>llen vor?
Bei einfachen Zahlenwerten k<>nnte beispielsweise ein R<>ckgabewert helfen.
Komplexere Informationen k<>nnen in eine tempor<6F>re Datei geschrieben werden, die
danach geparst werden m<><6D>te. Wenn die Informationen in Zeilen der Form
\lstinline|VARIABLE="Wert"| gespeichert werden, kann die Datei einfach mittels
\texttt{source} (Abschnitt \ref{source}) oder einem Konstrukt der folgenden Art
gelesen werden:
\lstinline|eval `cat tempfile`|
Und genau mit dieser <20>berlegung kommen wir zu einem eleganten~--~wenn auch
nicht ganz einfachen~--~Trick.
Anstatt die Daten in eine tempor<6F>re Datei zu schreiben, wo sie wom<6F>glich durch
andere Prozesse ver<65>ndert oder ausgelesen werden k<>nnten, kann man sie auch in
`nicht existente' Dateien schreiben. Das folgende Beispiel demonstriert das
Verfahren:
\begin{lstlisting}
#!/bin/sh -x
TMPNAME="/tmp/`date '+%Y%m%d%H%M%S'`$$.txt"
exec 3> "$TMPNAME"
exec 4< "$TMPNAME"
rm -f "$TMPNAME"
\end{lstlisting}
Bis hierher wurde zun<75>chst eine tempor<6F>re Datei angelegt. Die Filehandles 3 und
4 wurden zum Schreiben bzw. Lesen mit dieser Datei verbunden. Daraufhin wurde
die Datei entfernt. Die Filehandles verweisen weiterhin auf die Datei, obwohl
sie im Dateisystem nicht mehr sichtbar ist.
Kommen wir zum n<>tzlichen Teil des Skriptes:
\begin{lstlisting}[firstnumber=6]
nCounter=0
cat datei.txt | ( while read VAR; do
while read VAR; do
nCounter=`expr $nCounter + 1`
done
echo "nCounter=$nCounter"
) >&3
\end{lstlisting}
Hier wurde wieder die Variable nCounter initialisiert und in der Subshell die
Zeilen gez<65>hlt wie im ersten Beispiel. Allerdings wurde explizit eine Subshell
um die Schleife gestartet. Dadurch steht die in der Schleife hochgez<65>hlte
Variable auch nach Beendigung der Schleife zur Verf<72>gung, allerdings immernoch
nur in der Subshell. Um das zu <20>ndern, wird in Zeile 11 der Wert ausgegeben.
Die Ausgaben der Subshell werden in den oben erstellen Deskriptor umgeleitet.
\begin{lstlisting}[firstnumber=13]
echo "(vor eval) nCounter=$nCounter"
eval `cat <&4`
echo "(nach eval) nCounter=$nCounter"
\end{lstlisting}
Das \texttt{echo}-Kommando in Zeile 13 beweist, da<64> der Wert von nCounter
tats<EFBFBD>chlich au<61>erhalb der Subshell nicht zur Verf<72>gung steht. Zun<75>chst.
In Zeile 14 wird dann die ebenfalls oben schon angesprochene
\texttt{eval}-Zeile benutzt, um die Informationen aus dem Filedeskriptor zu
lesen, die die Schleife dort hinterlassen hat.
Abschlie<EFBFBD>end zeigt die Zeile 15, da<64> der Transport tats<74>chlich funktioniert
hat, die Variable nCounter ist mit dem Wert aus der Subshell belegt.
\subsection{Dateien gleichzeitig lesen und schreiben}\label{lesen_und_schreiben}
Es kommt vor, da<64> man eine Datei bearbeiten m<>chte, die hinterher aber wieder
unter dem gleichen Namen zur Verf<72>gung stehen soll. Beispielsweise sollen alle
Zeilen aus einer Datei entfernt werden, die nicht das Wort \textit{wichtig}
enthalten.
Der erste Versuch an der Stelle wird etwas in der Form
\lstinline|grep wichtig datei.txt > datei.txt|
sein. Das kann funktionieren, es kann aber auch in die sprichw<68>rtliche Hose
gehen. Das Problem an der Stelle ist, da<64> die Datei an der Stelle gleichzeitig
zum Lesen und zum Schreiben ge<67>ffnet wird. Das Ergebnis ist undefiniert.
Eine Elegante L<>sung besteht darin, einen Filedeskriptor auf die Quelldatei zu
legen und diese dann zu l<>schen. Die Datei wird erst dann wirklich aus dem
Dateisystem entfernt, wenn kein Deskriptor mehr auf sie zeigt. Dann kann aus
dem gerade angelegten Deskriptor gelesen werden, w<>hrend eine neue Datei unter
dem alten Namen angelegt wird:
\begin{lstlisting}
#!/bin/sh
FILE=datei.txt
exec 3< "$FILE"
rm "$FILE"
grep "wichtig" <&3 > "$FILE"
\end{lstlisting}
Allerdings sollte man bei dieser Methode beachten, da<64> man im Falle eines
Fehlers die Quelldaten verliert, da die Datei ja bereits gel<65>scht wurde.
\section{Auf der Lauer: Wachhunde}\label{wachhunde}\index{Watchdog}
Es kommt vor, da<64> man einen Proze<7A> startet, bei dem man sich nicht sicher sein
kann da<64> er sich auch in absehbarer Zeit wieder beendet. Beispielsweise kann
der Timeout f<>r einen Netzwerkzugriff deutlich h<>her liegen als erw<72>nscht, und
wenn der `gegnerische' Dienst nicht antwortet bleibt einem nur zu warten.
Es sei denn, man legt einen geeigneten Wachhund\footnote{Der englische Begriff
`Watchdog' ist in diesem Zusammenhang wahrscheinlich gel<65>ufiger...} auf die
Lauer, der im Notfall rettend eingreift. In einem Shell-Skript k<>nnte das wie
folgt aussehen:
\begin{lstlisting}
#!/bin/sh
timeout=5
ping 192.168.0.254 &
cmdpid=$!
\end{lstlisting}
Bis hierher nichts aufregendes. Eine Variable wird mit dem Timeout belegt, also
mit der Anzahl an Sekunden nach denen der zu <20>berwachende Proze<7A> unterbrochen
werden soll. Dann wird der zu <20>berwachende Proze<7A> gestartet und mittels \& in
den Hintergrund geschickt. Die Proze<7A>-ID des Prozesses wird in der Variablen
cmdpid gesichert.
\begin{lstlisting}[firstnumber=5]
(sleep $timeout; kill -9 $cmdpid) &
watchdogpid=$!
\end{lstlisting}
In Zeile 5 findet sich der eigentliche Watchdog. Hier wird eine Subshell
gestartet, in der zun<75>chst der oben eingestellte Timeout abgewartet und dann
der zu <20>berwachende Proze<7A> get<65>tet wird. Diese Subshell wird ebenfalls mit \&
in den Hintergrund geschickt. Die ID der Subshell wird in der Variablen
watchdogpid gesichert.
\begin{lstlisting}[firstnumber=7]
wait $cmdpid
kill $watchdogpid > /dev/null 2>&1
exit 0
\end{lstlisting}
Dann wird durch ein \texttt{wait}\index{wait=\texttt{wait}} darauf gewartet,
da<EFBFBD> sich der <20>berwachte Proze<7A> beendet. Dabei w<>rde \texttt{wait} bis in alle
Ewigkeit warten, w<>re da nicht der Watchdog in der Subshell. Wenn dem die
Ausf<EFBFBD>hrung zu lange dauert, sorgt er daf<61>r da<64> der Proze<7A> beendet wird.
Kommt der <20>berwachte Proze<7A> aber rechtzeitig zur<75>ck, sorgt \texttt{kill} in
Zeile 8 daf<61>r da<64> der Wachhund `eingeschl<68>fert' wird.
Auf diese Weise ist sichergestellt, da<64> der \texttt{ping} auf keinen Fall
l<EFBFBD>nger als f<>nf Sekunden l<>uft.
\section{Unter Druck: Auf Tasten warten}\label{tastendruck}\index{Tastendruck}
Oft baut man in l<>ngere Ausgaben eine Art Warte-Prompt im Stile von `Bitte
Enter dr<64>cken um fortzufahren' ein. Gewartet wird dann mit Hilfe des
\texttt{read}-Kommandos\index{read=\texttt{read}}.
Will man nicht nur auf den Druck der Enter-Taste reagieren, sondern auf einen
beliebigen Tastendruck, eignet sich das folgende Konstrukt:
\begin{lstlisting}
stty raw -echo
inputchar=`dd if=/dev/tty bs=1 count=1 2> /dev/null`
stty sane
\end{lstlisting}
Zur Erkl<6B>rung: Mit dem Kommando \texttt{stty}\index{stty=\texttt{stty}} kann
ein Terminal konfiguriert werden. Dabei kann es sich sowohl um eine Leitung wie
die serielle Schnittstelle des Rechners handeln, als auch um das Terminal an
dem der Benutzer sitzt. Jedes Terminal hat eine Reihe von Eigenschaften.
Mittels \lstinline|stty raw -echo| wird das Terminal in einen passenden Modus
geschaltet. Das \texttt{-echo} sorgt daf<61>r, da<64> eingegebene Zeichen nicht in
der Konsole wiedergegeben werden.
Danach wird mit \texttt{dd}\index{dd=\texttt{dd}} genau ein Zeichen eingelesen.
Die Fehlerausgabe von \texttt{dd} wird dabei nach /dev/null umgeleitet, da
ansonsten auf der Konsole die Erfolgsmeldungen \textit{1+0 Datens<6E>tze ein, 1+0
Datens<EFBFBD>tze aus} erscheinen w<>rden. Das gelesene Zeichen wird in der Variablen
\texttt{\$inputchar} gesichert und steht somit zur Verf<72>gung.
Nach dem Einlesevorgang wird die Konsole schlie<69>lich mittels
\lstinline|stty sane| wieder in einen benutzbaren Zustand zur<75>ckversetzt.
TODO!!!

235
shell.tex
View File

@ -1,4 +1,3 @@
% $Id$
%============================================================================== %==============================================================================
% LaTeX-Schema-Datei schema.tex % LaTeX-Schema-Datei schema.tex
%============================================================================== %==============================================================================
@ -7,39 +6,51 @@
% Vorspann % Vorspann
%============================================================================== %==============================================================================
% Dokumentstil f<>r Buch \newif\ifpdf % Feststellen, ob wir PDF oder DVI
\documentclass[ % erzeugen
a4paper, % Seitenformat A4 \ifx\pdfoutput\undefined
12pt, % 12-Punkt-Schrift \pdffalse % Wir haben kein PDFLaTeX
BCOR.5cm, % 0,5cm Rand f<>r die Bindung \else
headsepline, % Trennlinie unter die Kopfzeile \pdftrue % Wir haben PDFLaTeX
pointlessnumbers, % Keine Punkte hinter den \fi
% Gliederungsnummern
halfparskip, % Abst<73>nde zwischen den Abs<62>tzen, statt
% Einr<6E>ckung der ersten Zeile
% draft, % Entwurfsmodus
final, % Release-Modus
twoside % Doppelseitig, f<>r Buch
]{scrbook}
\ifpdf % PDF-Einstellungen
\pdfoutput=1
\pdfcompresslevel=9
\pdfinfo{
/Author (Ronald Schaten)
/CreationDate (D:20000301170300) % (D:YYYYMMDDhhmmss)
% /ModDate (D:19980212201000) % ModDate is similar
/Title (Shell-Programmierung)
/Subject (Shell-Programmierung)
/Keywords (Shell)
}
\pdfcatalog{ % Catalog dictionary of PDF output.
/PageMode /UseOutlines
/URI (http://www.fi.muni.cz/)
}
\else % Nicht-PDF-Einstellungen
\fi
% Dokumentstil f<>r Buch
\documentclass[a4paper,12pt,draft,twoside]{book}
\usepackage{german} % deutsches Paket f<>r Umlaute \usepackage{german} % deutsches Paket f<>r Umlaute
%\usepackage{t1enc} % DC-Font mit 8 Bit verwenden
\usepackage[latin1]{inputenc} % Codepage latin1 \usepackage[latin1]{inputenc} % Codepage latin1
\usepackage{mathptmx} % Andere Schriften benutzen %\usepackage{graphicx} % Grafikpaket f<>r Bilder laden
\usepackage[scaled=.90]{helvet}
\usepackage{courier}
\usepackage{pifont} % f<>r dinglist (Icon neben Text)
%\usepackage[dvips]{graphicx} % Grafikpaket f<>r Bilder laden
%\usepackage{epstopdf} % .eps bei Bedarf nach .pdf wandeln
%\DeclareGraphicsRule{.tif}{bmp}{}{} % Grafikformate %\DeclareGraphicsRule{.tif}{bmp}{}{} % Grafikformate
\usepackage{tabularx} % f<>r Tabellen <20>ber die Seitenbreite
%\usepackage{tabularx} % f<>r Tabellen <20>ber die Seitenbreite \usepackage{longtable} % f<>r Tabellen <20>ber die Seitenbreite
%\usepackage{longtable} % f<>r Tabellen <20>ber die Seitenbreite \usepackage{supertabular} % f<>r Tabellen <20>ber die Seitenbreite
%\usepackage{supertabular} % f<>r Tabellen <20>ber die Seitenbreite
\usepackage{ltxtable} % f<>r Tabellen <20>ber die Seitenbreite \usepackage{ltxtable} % f<>r Tabellen <20>ber die Seitenbreite
\ifpdf % PDF-Einstellungen
\usepackage{thumbpdf}
\else % Nicht-PDF-Einstellungen
\fi
\usepackage{makeidx} % Index wird sp<73>ter eingef<65>gt \usepackage{makeidx} % Index wird sp<73>ter eingef<65>gt
\makeindex % durch \printindex \makeindex % durch \printindex
@ -47,39 +58,23 @@
\usepackage{fancybox} % K<>stchen f<>r Tastendarstellung \usepackage{fancybox} % K<>stchen f<>r Tastendarstellung
%\usepackage{moreverb} % F<EFBFBD>r Listings \usepackage{fancyhdr} % Kopf- und Fu<46>zeilen
\usepackage{listings} % F<>r Listings \pagestyle{fancy}
\lstset{ \renewcommand{\chaptermark}[1]{\markboth{#1}{}}
extendedchars=true, \renewcommand{\sectionmark}[1]{\markright{\thesection\ #1}}
backgroundcolor=\color[gray]{0.95}, \fancyhf{}
basicstyle=\ttfamily\footnotesize, \fancyhead[RE]{\bfseries\leftmark}
numbers=left, \fancyhead[LO]{\bfseries\rightmark}
numberstyle=\scriptsize, \fancyhead[RO,LE]{\bfseries\thepage}
stepnumber=2, \renewcommand{\headrulewidth}{0.5pt}
numbersep=5pt \addtolength{\headheight}{2.5pt}
\fancypagestyle{plain}{
\fancyhead{}
\renewcommand{\headrulewidth}{0pt}
\fancyfoot[C]{\bfseries\thepage}
} }
\usepackage{moreverb} % F<>r Listings
% F<>r PDF
\usepackage[
pdftitle = {Shell-Programmierung},
pdfsubject = {Programmierung~der~Unix-Shell},
pdfkeywords = {shell~programmierung},
pdfauthor = {Ronald~Schaten},
bookmarks,
bookmarksopen,
bookmarksopenlevel = 1,
bookmarksnumbered,
linktocpage,
colorlinks,
linkcolor = black,
urlcolor = black
]{hyperref}
%\pdfinfo{/CreationDate (D:20000301170300-01'00')} % (D:YYYYMMDDhhmmss)
%% /ModDate (D:19980212201000) % ModDate is similar
\newcommand{\STRUT}{\rule{0in}{3ex}} % Ein vertikaler Abstand f<>r Tabellen \newcommand{\STRUT}{\rule{0in}{3ex}} % Ein vertikaler Abstand f<>r Tabellen
@ -92,149 +87,56 @@
\begin{document} % hiermit mu<6D> jedes Dokument beginnen \begin{document} % hiermit mu<6D> jedes Dokument beginnen
% Syntax-Boxen (sybox) definieren: \vspace*{.75in} % Die Titelseite
\fboxsep 1.36mm
\definecolor{g1}{gray}{0.95}
\newsavebox{\syntaxbox}
\newenvironment{sybox}
{\begin{lrbox}{\syntaxbox}
\begin{minipage}{\textwidth}}
{\end{minipage}
\end{lrbox}
{\fcolorbox{g1}{g1}
{\parbox{\textwidth}{\usebox{\syntaxbox}\hfill\hbox{}}}}}
\vspace*{.6in} % Die Titelseite
\thispagestyle{empty} \thispagestyle{empty}
\begin{centering} \begin{centering}
\rule{5in}{.04in}\\ \vspace{.25in} \rule{5in}{.04in}\\ \vspace{.25in}
\Huge {\bf SHELL\\ \vspace{.4in} PROGRAMMIERUNG}\\ \vspace{.1in} \Huge {\bf SHELL\\ \vspace{.4in} PROGRAMMIERUNG}\\ \vspace{.1in}
\rule{5in}{.04in}\\ \vspace{.6in} \rule{5in}{.04in}\\ \vspace{.5in}
\large v2.0.1\\
\large \today\\ \vspace{.75in} \large \today\\ \vspace{.75in}
\large von\\ \vspace{.3in} \large von\\ \vspace{.3in}
\LARGE {\bf Ronald Schaten} \\ \vspace{.6in} \LARGE {\bf Ronald Schaten} \\ \vspace{.6in}
\large ronald@schatenseite.de\\ \large ronald@schatenseite.de\\
\large http://www.schatenseite.de/\\ \large http://www.schatenseite.de/\\
\end{centering} \end{centering}
\newpage \newpage
\thispagestyle{empty} % eine Leerseite \thispagestyle{empty} % eine Leerseite
\begin{quote}
\emph{The best way to become acquainted with a subject is to write a book about it.
\begin{flushright}(Benjamin Disraeli)\end{flushright}}
\end{quote}
~\vfill ~\vfill
\footnotesize \footnotesize
Die aktuellste Version dieses Dokumentes befindet sich auf Copyright \copyright{} 2001 Ronald Schaten (\texttt{ronald@schatenseite.de})\bigskip
\href{http://www.schatenseite.de/}{http://www.schatenseite.de/}.
Dieses Dokument ist entstanden, weil ich f<>r mich selbst eine kompakte Die aktuellste Version dieses Dokumentes befindet sich im World Wide Web auf meiner Homepage (\texttt{http://www.schatenseite.de/}).\bigskip
<EFBFBD>bersicht zu diesem Thema haben wollte. Ich beabsichtige nicht, damit in
irgendeiner Form Kommerz zu machen. Ich stelle es zur Verf<72>gung, in der
Hoffnung, da<64> andere Leute daraus vielleicht einen Nutzen ziehen k<>nnen.
\textbf{Aber ich <20>bernehme keine Garantie f<>r die Korrektheit der hier
dargestellten Dinge.}
Copyright \copyright{} 2000-2005 Ronald Schaten (ronald@schatenseite.de) Dieses Dokument ist entstanden, weil ich f<>r mich selbst eine kompakte <20>bersicht zu diesem Thema haben wollte. Ich beabsichtige nicht, damit in irgendeiner Form Kommerz zu machen. Ich stelle es frei zur Verf<72>gung, in der Hoffnung, da<64> andere Leute daraus vielleicht einen Nutzen ziehen k<>nnen. \textbf{Aber ich <20>bernehme keine Garantie f<>r die Korrektheit der hier dargestellten Dinge.} Mit der Formulierung \textsl{'daraus vielleicht einen Nutzen ziehen k<>nnen'} meine ich nicht, da<64> dieses Dokument~---~oder Teile daraus~---~verkauft werden darf. \textbf{Dieses Dokument darf nur kostenlos weitergegeben werden.}\bigskip
\textbf{Dieses Dokument steht unter der Creative Commons Lizenz.} Die Ich danke folgenden Personen, die mir bei der Durchsicht behilflich waren und durch ihre konstruktive Kritik zu Verbesserungen beigetragen haben (in chronologischer Reihenfolge ihres Eingreifens):
Weiterverbreitung ist unter gewissen Bedingungen (Namensnennung, keine
kommerzielle Nutzung und keine Bearbeitung) erlaubt und gew<65>nscht. Ich habe
diese Lizenz gew<65>hlt um sicherzustellen da<64> Verbesserungen am Inhalt des
Dokumentes bei mir ankommen, damit ich sie in die `Hauptversion' einflie<69>en
lassen kann.
Die Lizenzbedingungen stehen unter
\href{http://creativecommons.org/licenses/by-nc-nd/2.0/de/}{http://creativecommons.org/licenses/by-nc-nd/2.0/de/}.
% <!-- Creative Commons-Lizenzvertrag -->
% <a rel="license"
% href="http://creativecommons.org/licenses/by-nc-nd/2.0/de/"><img alt="Creative
% Commons-Lizenzvertrag" border="0"
% src="http://creativecommons.org/images/public/somerights20.gif" /></a><br />
% Diese Inhalt ist unter einer <a rel="license"
% href="http://creativecommons.org/licenses/by-nc-nd/2.0/de/">Creative
% Commons-Lizenz</a> lizenziert.
% <!-- /Creative Commons-Lizenzvertrag -->
%
%
% <!--
%
% <rdf:RDF xmlns="http://web.resource.org/cc/"
% xmlns:dc="http://purl.org/dc/elements/1.1/"
% xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
% <Work rdf:about="">
% <dc:title>Shell&amp;#45;Programmierung</dc:title>
% <dc:date>2005</dc:date>
% <dc:description>Einf<6E>hrung in die
% Shell&amp;#45;Programmierung</dc:description>
% <dc:creator><Agent>
% <dc:title>Ronald Schaten</dc:title>
% </Agent></dc:creator>
% <dc:rights><Agent>
% <dc:title>Ronald Schaten</dc:title>
% </Agent></dc:rights>
% <dc:type rdf:resource="http://purl.org/dc/dcmitype/Text" />
% <license rdf:resource="http://creativecommons.org/licenses/by-nc-nd/2.0/de/"
% />
% </Work>
%
% <License rdf:about="http://creativecommons.org/licenses/by-nc-nd/2.0/de/">
% <permits rdf:resource="http://web.resource.org/cc/Reproduction" />
% <permits rdf:resource="http://web.resource.org/cc/Distribution" />
% <requires rdf:resource="http://web.resource.org/cc/Notice" />
% <requires rdf:resource="http://web.resource.org/cc/Attribution" />
% <prohibits rdf:resource="http://web.resource.org/cc/CommercialUse" />
% </License>
%
% </rdf:RDF>
%
% -->
Ich danke folgenden Personen, die mir bei der Durchsicht behilflich waren und
durch ihre konstruktive Kritik zu Verbesserungen beigetragen haben (in
chronologischer Reihenfolge ihres Eingreifens):
\begin{list}{$\bullet$}{\itemsep=-0.5cm} \begin{list}{$\bullet$}{\itemsep=-0.5cm}
\item J<>rgen Ilse (ilse@asys-h.de)\\ \item J<>rgen Ilse (\texttt{ilse@asys-h.de})\\
\item Christian Perle (christian.perle@tu-clausthal.de)\\ \item Christian Perle (\texttt{christian.perle@tu-clausthal.de})\\
\item Andreas Metzler (ametzler@downhill.at.eu.org)\\ \item Andreas Metzler (\texttt{ametzler@downhill.at.eu.org})\\
\item Johannes Kolb (johannes.kolb@web.de)\\ \item Johannes Kolb (\texttt{johannes.kolb@web.de})\\
\item Falk Friedrich (falk@gmx.de)\\
\item Kai Th<54>ne (kai.thoene@gmx.de)\\
\end{list} \end{list}
Und ich bitte alle Leser, auf eventuelle Fehler zu achten und mich darauf Und ich bitte alle Leser, auf eventuelle Fehler zu achten und mich darauf aufmerksam zu machen. Auch abgesehen davon freue ich mich <20>ber jede R<>ckmeldung.
aufmerksam zu machen. Auch abgesehen davon freue ich mich <20>ber jede
R<EFBFBD>ckmeldung.
Dieses Dokument entstand unter Verwendung von Linux, vim und \LaTeX. Dank an
deren Entwickler.
\normalsize \normalsize
\newpage \newpage
\pagenumbering{roman} \pagenumbering{roman}
%\renewcommand{\headrulewidth}{0.5pt} \renewcommand{\headrulewidth}{0.5pt}
\setcounter{tocdepth}{3} \setcounter{tocdepth}{3}
\tableofcontents \tableofcontents
\newpage \newpage
\pagenumbering{arabic} \pagenumbering{arabic}
% Haupttextteil % Haupttextteil
\include{was_ist_die_shell} \include{was_ist_die_shell}
\include{wo_sind_unterschiede_zu_dos_batchdateien}
\include{wofuer_shell_programmierung} \include{wofuer_shell_programmierung}
\include{wie_sieht_ein_shell_skript_aus} \include{wie_sieht_ein_shell_skript_aus}
\include{werkzeugkasten} \include{nuetzliche_shell-kommandos}
\include{wo_sind_unterschiede_zu_dos_batchdateien}
\appendix \appendix
\include{beispiele} \include{beispiele}
\include{schmutzige_tricks} \include{schmutzige_tricks}
\include{quellen} \include{quellen}
\include{todo}
\printindex % Index einf<6E>gen \printindex % Index einf<6E>gen
@ -244,6 +146,11 @@ deren Entwickler.
\end{document} \end{document}
\ifpdf % PDF-Einstellungen
\bye
\else % Nicht-PDF-Einstellungen
\fi
%============================================================================== %==============================================================================
% Ende von schema.tex % Ende von schema.tex
%============================================================================== %==============================================================================

View File

@ -1,4 +1,3 @@
% $Id$
\begin{longtable}{|l|X|} \begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill % KILLED & LINE!!!! \kill
\hline \hline

View File

@ -1,4 +1,3 @@
% $Id$
\begin{longtable}{|l|X|} \begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill % KILLED & LINE!!!! \kill
\hline \hline

View File

@ -1,4 +1,3 @@
% $Id$
\begin{longtable}{|l|X|} \begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill % KILLED & LINE!!!! \kill
\hline \hline

View File

@ -1,4 +1,3 @@
% $Id$
\begin{longtable}{|l|X|} \begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill % KILLED & LINE!!!! \kill
\hline \hline

View File

@ -1,4 +1,3 @@
% $Id$
\begin{longtable}{|l|X|} \begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill % KILLED & LINE!!!! \kill
\hline \hline
@ -11,10 +10,9 @@
\textsl{Befehl}\texttt{ \&} & Ausf<73>hrung von \textsl{Befehl} im Hintergrund \tabularnewline\STRUT \textsl{Befehl}\texttt{ \&} & Ausf<73>hrung von \textsl{Befehl} im Hintergrund \tabularnewline\STRUT
\textsl{Befehl1}\texttt{ ; }\textsl{Befehl2} & Befehlsfolge, f<>hrt mehrere Befehle nacheinander aus \tabularnewline\STRUT \textsl{Befehl1}\texttt{ ; }\textsl{Befehl2} & Befehlsfolge, f<>hrt mehrere Befehle nacheinander aus \tabularnewline\STRUT
\texttt{(}\textsl{Befehl1}\texttt{ ; }\textsl{Befehl2}\texttt{)} & Subshell\index{Subshell}, behandelt \textsl{Befehl1} und \textsl{Befehl2} als Befehlsblock und f<>hrt sie in einer Subshell aus \tabularnewline\STRUT \texttt{(}\textsl{Befehl1}\texttt{ ; }\textsl{Befehl2}\texttt{)} & Subshell\index{Subshell}, behandelt \textsl{Befehl1} und \textsl{Befehl2} als Befehlsblock und f<>hrt sie in einer Subshell aus \tabularnewline\STRUT
\texttt{\{ }\textsl{Befehl1}\texttt{ ; }\textsl{Befehl2}\texttt{; \}} & Befehlsblock; alle Befehle werden in der momentanen Shell ausgef<65>hrt, aber die Ausgaben werden behandelt, als ob nur ein Befehl ausgef<65>hrt w<>rde \tabularnewline\STRUT \texttt{\{ }\textsl{Befehl1}\texttt{ ; }\textsl{Befehl2}\texttt{ \}} & Befehlsblock; alle Befehle werden in der momentanen Shell ausgef<65>hrt, aber die Ausgaben werden behandelt, als ob nur ein Befehl ausgef<65>hrt w<>rde \tabularnewline\STRUT
\textsl{Befehl1}\texttt{ | }\textsl{Befehl2} & Pipe\index{Pipe}, verwendet die Ausgabe von \textsl{Befehl1} als Eingabe f<>r \textsl{Befehl2} \tabularnewline\STRUT \textsl{Befehl1}\texttt{ | }\textsl{Befehl2} & Pipe\index{Pipe}, verwendet die Ausgabe von \textsl{Befehl1} als Eingabe f<>r \textsl{Befehl2} \tabularnewline\STRUT
\textsl{Befehl1}\texttt{ `}\textsl{Befehl2}\texttt{`} & Befehls-Substitution, verwendet die Ausgabe von \textsl{Befehl2} als Argumente\index{Parameter}\index{Argument|see{Parameter}} f<>r \textsl{Befehl1} \tabularnewline\STRUT \textsl{Befehl1}\texttt{ `}\textsl{Befehl2}\texttt{`} & Befehls-Substitution, verwendet die Ausgabe von \textsl{Befehl2} als Argumente\index{Parameter}\index{Argument|see{Parameter}} f<>r \textsl{Befehl1} \tabularnewline\STRUT
\textsl{Befehl1}\texttt{ \$(}\textsl{Befehl2}\texttt{)} & Befehls-Substitution, andere Schreibweise\tabularnewline\STRUT
\textsl{Befehl1}\texttt{ \&\& }\textsl{Befehl2} & AND\index{AND}, f<>hrt zuerst \textsl{Befehl1} und dann (wenn \textsl{Befehl1} erfolgreich war) \textsl{Befehl2} aus\footnote{Einen <20>hnlichen Mechanismus kennt man aus verschiedenen Programmiersprachen unter dem Begriff \textsl{Kurzschlu<EFBFBD>auswertung}\index{Kurzschlu<EFBFBD>auswertung} bzw. \textsl{lazy evaluation}\index{Lazy Evaluation|see{Kurzschlu<EFBFBD>auswertung}}.} \tabularnewline\STRUT \textsl{Befehl1}\texttt{ \&\& }\textsl{Befehl2} & AND\index{AND}, f<>hrt zuerst \textsl{Befehl1} und dann (wenn \textsl{Befehl1} erfolgreich war) \textsl{Befehl2} aus\footnote{Einen <20>hnlichen Mechanismus kennt man aus verschiedenen Programmiersprachen unter dem Begriff \textsl{Kurzschlu<EFBFBD>auswertung}\index{Kurzschlu<EFBFBD>auswertung} bzw. \textsl{lazy evaluation}\index{Lazy Evaluation|see{Kurzschlu<EFBFBD>auswertung}}.} \tabularnewline\STRUT
\textsl{Befehl1}\texttt{ || }\textsl{Befehl2} & OR\index{OR}, entweder \textsl{Befehl1} ausf<73>hren oder \textsl{Befehl2} (Wenn \textsl{Befehl1} nicht erfolgreich war) \textsl{Befehl1}\texttt{ || }\textsl{Befehl2} & OR\index{OR}, entweder \textsl{Befehl1} ausf<73>hren oder \textsl{Befehl2} (Wenn \textsl{Befehl1} nicht erfolgreich war)
\end{longtable} \end{longtable}

View File

@ -1,4 +1,3 @@
% $Id$
\begin{longtable}{|l|X|} \begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill % KILLED & LINE!!!! \kill
\hline \hline

View File

@ -1,4 +1,3 @@
% $Id$
\begin{longtable}{|l|X|} \begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill % KILLED & LINE!!!! \kill
\hline \hline
@ -11,8 +10,7 @@
\texttt{\$ nroff }\textsl{Datei}\texttt{ \&} & Formatiert die \textsl{Datei} im Hintergrund \tabularnewline\STRUT \texttt{\$ nroff }\textsl{Datei}\texttt{ \&} & Formatiert die \textsl{Datei} im Hintergrund \tabularnewline\STRUT
\texttt{\$ cd; ls} & Sequentieller Ablauf \tabularnewline\STRUT \texttt{\$ cd; ls} & Sequentieller Ablauf \tabularnewline\STRUT
\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{!>}} & 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{\$ \{ 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{\$ 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{\$ 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{\$ 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

View File

@ -1,4 +1,3 @@
% $Id$
\begin{longtable}{|X l|} \begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill % KILLED & LINE!!!! \kill
\hline \hline

View File

@ -1,4 +1,3 @@
% $Id$
\begin{longtable}{|l|X|} \begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill % KILLED & LINE!!!! \kill
\hline \hline

View File

@ -1,4 +1,3 @@
% $Id$
\begin{longtable}{|X l|} \begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill % KILLED & LINE!!!! \kill
\hline \hline

View File

@ -1,4 +1,3 @@
% $Id$
\begin{longtable}{|X l|} \begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill % KILLED & LINE!!!! \kill
\hline \hline

View File

@ -1,4 +1,3 @@
% $Id$
\begin{longtable}{|X l|} \begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill % KILLED & LINE!!!! \kill
\hline \hline

View File

@ -1,4 +1,3 @@
% $Id$
\begin{longtable}{|X l|} \begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill % KILLED & LINE!!!! \kill
\hline \hline

29
tab_beisp_for.tex Normal file
View File

@ -0,0 +1,29 @@
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\textsl{Seitenweises Formatieren der Dateien, die auf der Befehlszeile angegeben wurden, und speichern des jeweiligen Ergebnisses:}} \\
\multicolumn{2}{|X|}{\texttt{for file do}} \\
\multicolumn{2}{|X|}{\texttt{~pr \$file > \$file.tmp~~\# pr: Formatiert Textdateien}\index{!>=\texttt{!>}}} \\
\multicolumn{2}{|X|}{\texttt{done}} \\
\multicolumn{2}{|X|}{\STRUT\textsl{Durchsuche Kapitel zur Erstellung einer Wortliste (wie \texttt{fgrep -f}):}} \\
\multicolumn{2}{|X|}{\texttt{for item in `cat program\_list`~~\# cat: Datei ausgeben}\index{cat=\texttt{cat}}\index{Backticks}} \\
\multicolumn{2}{|X|}{\texttt{do}} \\
\multicolumn{2}{|X|}{\texttt{~echo \dq Pruefung der Kapitel auf\dq}\index{Anf<EFBFBD>hrungszeichen}} \\
\multicolumn{2}{|X|}{\texttt{~echo \dq Referenzen zum Programm \$item ...\dq}\index{Anf<EFBFBD>hrungszeichen}} \\
\multicolumn{2}{|X|}{\texttt{~grep -c \dq\$item.[co]\dq~chap*~~\# grep: nach Muster\index{Mustererkennung} suchen}\index{[abc]=\texttt{[}\textsl{abc}\texttt{]}}\index{Anf<EFBFBD>hrungszeichen}\index{grep=\texttt{grep}}} \\
\multicolumn{2}{|X|}{\texttt{done}} \\
\multicolumn{2}{|X|}{\STRUT\textsl{Ermittle einen Ein-Wort-Titel aus jeder Datei und verwende ihn als neuen Dateinamen:}} \\
\multicolumn{2}{|X|}{\texttt{for file do}} \\
\multicolumn{2}{|X|}{\texttt{~name=`sed -n 's/NAME: //p' \$file`}\index{!==\texttt{!=}}\index{Backticks}\index{Ticks}} \\
\multicolumn{2}{|X|}{\texttt{~~~~~~~~~~\# sed: Skriptsprache zur}\index{sed=\texttt{sed}}} \\
\multicolumn{2}{|X|}{\texttt{~~~~~~~~~~\# Textformatierung}} \\
\multicolumn{2}{|X|}{\texttt{~mv \$file \$name~~\# mv: Datei verschieben}} \\
\multicolumn{2}{|X|}{\texttt{~~~~~~~~~~~~~~~~~\# bzw. umbenennen}} \\
\multicolumn{2}{|X|}{\texttt{done}} \\
\end{longtable}

16
tab_beisp_funktionen.tex Normal file
View File

@ -0,0 +1,16 @@
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\texttt{count () \{}} \\
\multicolumn{2}{|X|}{\texttt{~ls -1 | wc -l~~\# ls: Liste aller Dateien im Verzeichnis}\index{Pipe}} \\
\multicolumn{2}{|X|}{\texttt{~~~~~~~~~~~~~~~~\#~~~~~Mit Parameter -1 einspaltig}} \\
\multicolumn{2}{|X|}{\texttt{~~~~~~~~~~~~~~~~\# wc: Word-Count, z<>hlt W<>rter}\index{wc=\texttt{wc}}} \\
\multicolumn{2}{|X|}{\texttt{~~~~~~~~~~~~~~~~\#~~~~~Mit Parameter -l Zeilen}} \\
\multicolumn{2}{|X|}{\texttt{\}}} \\
\end{longtable}

16
tab_beisp_if.tex Normal file
View File

@ -0,0 +1,16 @@
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\textsl{F<EFBFBD>ge eine 0 vor Zahlen kleiner 10 ein:}} \\
\multicolumn{2}{|X|}{\texttt{if [ \$counter -lt 10 ]; then}\index{;=\texttt{;}}} \\
\multicolumn{2}{|X|}{\texttt{~number=0\$counter; else number=\$counter; fi}\index{!==\texttt{!=}}} \\
\multicolumn{2}{|X|}{\STRUT\textsl{L<EFBFBD>sche ein Verzeichnis, wenn es existiert:}} \\
\multicolumn{2}{|X|}{\texttt{if [ -d \$dir ]; then}\index{!!=\texttt{!!}}\index{;=\texttt{;}}} \\
\multicolumn{2}{|X|}{\texttt{~rmdir \$dir; fi~~\# rmdir: Verzeichnis l<>schen}} \\
\end{longtable}

13
tab_beisp_metazeichen.tex Normal file
View File

@ -0,0 +1,13 @@
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\texttt{\$ ls neu*} & Listet alle Dateien, die mit `neu' anfangen \tabularnewline\STRUT
\texttt{\$ ls neu?} & Listet `neuX', `neu4', aber nicht `neu10' \tabularnewline\STRUT
\texttt{\$ ls [D-R]*} & Listet alle Dateien, die mit einem Gro<72>buchstaben\index{Gro<EFBFBD>buchstaben}\footnote{Nat<EFBFBD>rlich wird in Shell-Skripten --- wie <20>berall in der Unix-Welt --- zwischen Gro<72>- und Kleinschreibung unterschieden.} zwischen D und R anfangen
\end{longtable}

View File

@ -1,4 +1,3 @@
% $Id$
\begin{longtable}{|l|X|} \begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill % KILLED & LINE!!!! \kill
\hline \hline

View File

@ -1,4 +1,3 @@
% $Id$
\begin{longtable}{|l|X|} \begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill % KILLED & LINE!!!! \kill
\hline \hline

View File

@ -1,4 +1,3 @@
% $Id$
\begin{longtable}{|l|X|} \begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill % KILLED & LINE!!!! \kill
\hline \hline

View File

@ -1,4 +1,3 @@
% $Id$
\begin{longtable}{|l|X|} \begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill % KILLED & LINE!!!! \kill
\hline \hline

15
tab_beisp_nullbefehl.tex Normal file
View File

@ -0,0 +1,15 @@
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\texttt{if who | grep \$1 > /dev/null~~\# who: Liste der Benutzer}\index{Pipe}\index{\$n=\texttt{\$}$n$}\index{!>=\texttt{!>}}\index{who=\texttt{who}}} \\
\multicolumn{2}{|X|}{\texttt{~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\# grep: Suche nach Muster}} \\
\multicolumn{2}{|X|}{\texttt{then :~~~~~~~~~~~~~~~~~~~~~~~~\# tut nichts}} \\
\multicolumn{2}{|X|}{\texttt{~else echo \dq Benutzer \$1 ist nicht angemeldet\dq}\index{Anf<EFBFBD>hrungszeichen}} \\
\multicolumn{2}{|X|}{\texttt{fi}} \\
\end{longtable}

18
tab_beisp_quoting.tex Normal file
View File

@ -0,0 +1,18 @@
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\texttt{\$ echo 'Ticks \dq sch<63>tzen\dq~Anf<6E>hrungszeichen'}} \\
\multicolumn{2}{|X|}{\texttt{Ticks \dq sch<63>tzen\dq~Anf<6E>hrungszeichen}} \\
\multicolumn{2}{|X|}{\STRUT\texttt{\$ echo \dq Ist dies ein \textbackslash\dq Sonderfall\textbackslash\dq ?\dq}} \\
\multicolumn{2}{|X|}{\texttt{Ist dies ein \dq Sonderfall\dq ?}} \\
\multicolumn{2}{|X|}{\STRUT\texttt{\$ echo \dq Sie haben `ls | wc -l` Dateien in `pwd`\dq}\index{wc=\texttt{wc}}} \\
\multicolumn{2}{|X|}{\texttt{Sie haben 43 Dateien in /home/rschaten}} \\
\multicolumn{2}{|X|}{\STRUT\texttt{\$ echo \dq Der Wert von \textbackslash\$x ist \$x\dq}} \\
\multicolumn{2}{|X|}{\texttt{Der Wert von \$x ist 100}} \\
\end{longtable}

View File

@ -1,4 +1,3 @@
% $Id$
\begin{longtable}{|l|X|} \begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill % KILLED & LINE!!!! \kill
\hline \hline

17
tab_beisp_until.tex Normal file
View File

@ -0,0 +1,17 @@
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\textsl{Warten, bis sich der Administrator einloggt:}} \\
\multicolumn{2}{|X|}{\texttt{until who | grep \dq root\dq; do}\index{;=\texttt{;}}\index{Anf<EFBFBD>hrungszeichen}\index{who=\texttt{who}}} \\
\multicolumn{2}{|X|}{\texttt{~~~~~~~~~~\# who: Liste der Benutzer}} \\
\multicolumn{2}{|X|}{\texttt{~~~~~~~~~~\# grep: Suchen nach Muster}\index{Mustererkennung}} \\
\multicolumn{2}{|X|}{\texttt{~sleep 2~~\# sleep: warten}\index{sleep=\texttt{sleep}}} \\
\multicolumn{2}{|X|}{\texttt{done}} \\
\multicolumn{2}{|X|}{\texttt{echo \dq Der Meister ist anwesend\dq}\index{Anf<EFBFBD>hrungszeichen}} \\
\end{longtable}

View File

@ -1,4 +1,3 @@
% $Id$
\begin{longtable}{|l|X|} \begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill % KILLED & LINE!!!! \kill
\hline \hline
@ -11,7 +10,7 @@
\texttt{\$ \textsl{h}=\textsl{hoch} \textsl{r}=\textsl{runter} \textsl{l}=} & Weist den drei Variablen Werte zu, wobei \textsl{l} einen leeren Wert erh<72>lt. \tabularnewline\STRUT \texttt{\$ \textsl{h}=\textsl{hoch} \textsl{r}=\textsl{runter} \textsl{l}=} & Weist den drei Variablen Werte zu, wobei \textsl{l} einen leeren Wert erh<72>lt. \tabularnewline\STRUT
\texttt{\$ echo \$\{h\}sprung} & Gibt \textsl{hochsprung} aus. Die Klammern m<>ssen gesetzt werden, damit \textsl{h} als Variablenname erkannt werden kann. \tabularnewline\STRUT \texttt{\$ echo \$\{h\}sprung} & Gibt \textsl{hochsprung} aus. Die Klammern m<>ssen gesetzt werden, damit \textsl{h} als Variablenname erkannt werden kann. \tabularnewline\STRUT
\texttt{\$ echo \$\{h-\$r\}} & Gibt \textsl{hoch} aus, da die Variable \textsl{h} belegt ist. Ansonsten w<>rde der Wert von \textsl{r} ausgegeben. \tabularnewline\STRUT \texttt{\$ echo \$\{h-\$r\}} & Gibt \textsl{hoch} aus, da die Variable \textsl{h} belegt ist. Ansonsten w<>rde der Wert von \textsl{r} ausgegeben. \tabularnewline\STRUT
\texttt{\$ echo \$\{tmp-`date`\}} & Gibt das aktuelle Datum aus, wenn die Variable \textsl{tmp} nicht gesetzt ist. \tabularnewline\STRUT \texttt{\$ echo \$\{tmp-`date`\}} & Gibt das aktuelle Datum aus, wenn die Variable \textsl{tmp} nicht gesetzt ist.\footnote{Der Befehl \texttt{date} gibt das Datum zur<75>ck.} \tabularnewline\STRUT
\texttt{\$ echo \$\{l:=\$r\}} & Gibt \textsl{runter} aus, da die Variable \textsl{l} keinen Wert enth<74>lt. Gleichzeitig wird \textsl{l} der Wert von \textsl{r} zugewiesen. \tabularnewline\STRUT \texttt{\$ echo \$\{l:=\$r\}} & Gibt \textsl{runter} aus, da die Variable \textsl{l} keinen Wert enth<74>lt. Gleichzeitig wird \textsl{l} der Wert von \textsl{r} zugewiesen. \tabularnewline\STRUT
\texttt{\$ echo \$l} & Gibt \textsl{runter} aus, da \textsl{l} jetzt den gleichen Inhalt hat wie \textsl{r}. \texttt{\$ echo \$l} & Gibt \textsl{runter} aus, da \textsl{l} jetzt den gleichen Inhalt hat wie \textsl{r}.
\end{longtable} \end{longtable}

View File

@ -1,4 +1,3 @@
% $Id$
\begin{longtable}{|X l|} \begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill % KILLED & LINE!!!! \kill
\hline \hline

View File

@ -1,4 +1,3 @@
% $Id$
\begin{longtable}{|X l|} \begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill % KILLED & LINE!!!! \kill
\hline \hline

11
tab_break.tex Normal file
View File

@ -0,0 +1,11 @@
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\texttt{break }\textsl{[ n ]}} \\
\end{longtable}

15
tab_case.tex Normal file
View File

@ -0,0 +1,15 @@
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\texttt{case }\textsl{Wert}\texttt{ in}} \\
\multicolumn{2}{|X|}{\texttt{~}\textsl{Muster1}\texttt{) }\textsl{Befehle1}\texttt{;;}} \\
\multicolumn{2}{|X|}{\texttt{~}\textsl{Muster2}\texttt{) }\textsl{Befehle2}\texttt{;;}} \\
\multicolumn{2}{|X|}{\texttt{~\vdots}} \\
\multicolumn{2}{|X|}{\texttt{esac}} \\
\end{longtable}

11
tab_continue.tex Normal file
View File

@ -0,0 +1,11 @@
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\texttt{continue }\textsl{[ n ]}} \\
\end{longtable}

View File

@ -1,4 +1,3 @@
% $Id$
\begin{longtable}{|l|X|} \begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill % KILLED & LINE!!!! \kill
\hline \hline

View File

@ -1,4 +1,3 @@
% $Id$
\begin{longtable}{|l|X|} \begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill % KILLED & LINE!!!! \kill
\hline \hline

View File

@ -1,4 +1,3 @@
% $Id$
\begin{longtable}{|X|X|X|X|} \begin{longtable}{|X|X|X|X|}
% KILLED & LINE!!!! \kill % KILLED & LINE!!!! \kill
\hline \hline

View File

@ -1,4 +1,3 @@
% $Id$
\begin{longtable}{|l|X|} \begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill % KILLED & LINE!!!! \kill
\hline \hline

11
tab_exit.tex Normal file
View File

@ -0,0 +1,11 @@
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\texttt{exit }\textsl{[ n ]}} \\
\end{longtable}

14
tab_for.tex Normal file
View File

@ -0,0 +1,14 @@
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\texttt{for }\textsl{x [}\texttt{ in }\textsl{Liste ]}} \\
\multicolumn{2}{|X|}{\texttt{do}} \\
\multicolumn{2}{|X|}{\texttt{~}\textsl{Befehle}} \\
\multicolumn{2}{|X|}{\texttt{done}} \\
\end{longtable}

17
tab_if.tex Normal file
View File

@ -0,0 +1,17 @@
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\texttt{if }\textsl{Bedingung1}} \\
\multicolumn{2}{|X|}{\texttt{then }\textsl{Befehle1}} \\
\multicolumn{2}{|X|}{\textsl{[}\texttt{ elif }\textsl{Bedingung2}} \\
\multicolumn{2}{|X|}{\texttt{ then }\textsl{Befehle2 ]}} \\
\multicolumn{2}{|X|}{\texttt{ \vdots}} \\
\multicolumn{2}{|X|}{\textsl{[}\texttt{ else }\textsl{Befehle3 ]}} \\
\multicolumn{2}{|X|}{\texttt{fi}} \\
\end{longtable}

View File

@ -1,21 +0,0 @@
% $Id$
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\texttt{FILENAME} & Der Name der aktuellen Eingabedatei, oder `-' wenn von der Standard-Eingabe gelesen wird\tabularnewline\STRUT
\texttt{FS} & Field Separator, das Trennzeichen nach dem die Felder unterteilt werden \tabularnewline\STRUT
\texttt{OFS} & Feldtrennzeichen f<>r die Ausgabe \tabularnewline\STRUT
\texttt{RS} & Record Separator, das Trennzeichen nach dem Datens<6E>tze unterteilt werden \tabularnewline\STRUT
\texttt{ORS} & Datensatztrennzeichen f<>r die Ausgabe \tabularnewline\STRUT
\texttt{NF} & Anzahl der Felder im aktuellen Datensatz \tabularnewline\STRUT
\texttt{NR} & Laufende Nummer des aktuellen Datensatzes \tabularnewline\STRUT
\texttt{OFMT} & Ausgabeformat f<>r die Ausgabe von Zahlen und Strings, \tabularnewline\STRUT
\texttt{\$0} & Der komplette aktuelle Datensatz \tabularnewline\STRUT
\texttt{\$}\textsl{n} & Feld \textsl{n} des aktuellen Datensatzes
\end{longtable}

View File

@ -1,16 +0,0 @@
% $Id$
\begin{longtable}{|l|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
a-x & & Allen Benutzern werden die Ausf<73>hrungsrechte genommen \tabularnewline\STRUT
ug+rw & & Dem Besitzer und der Gruppe werden Lese- und Schreibrechte gegeben \tabularnewline\STRUT
u=rw,go-rwx & 600 & Nur der Besitzer kann die Datei lesen und schreiben \tabularnewline\STRUT
u=rw,go=r & 644 & Der Besitzer darf lesen und schreiben, alle anderen nur lesen \tabularnewline\STRUT
u=rwx,go=rx & 755 & Der Besitzer darf lesen, schreiben und ausf<73>hren, alle anderen nur lesen und ausf<73>hren
\end{longtable}

View File

@ -1,16 +0,0 @@
% $Id$
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\textsl{s=\dq{}Dies ist ein Test\dq{}} & ~ \tabularnewline\STRUT
\texttt{echo \dq{}\$s\dq{} | cut -c 2-6} & gibt `ies i' aus \tabularnewline\STRUT
\texttt{echo \dq{}\$s\dq{} | cut -d \dq{}~\dq{} -f 2} & gibt `ist' aus \tabularnewline\STRUT
\texttt{echo \dq{}\$s\dq{} | cut -d \dq{}~\dq{} -f 2-3} & gibt `ist ein' aus \tabularnewline\STRUT
\texttt{echo \dq{}\$s\dq{} | cut -d \dq{}~\dq{} -f 2-} & gibt `ist ein Test' aus
\end{longtable}

View File

@ -1,16 +0,0 @@
% $Id$
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\texttt{-n} & Unterdr<64>ckt den Zeilenumbruch am Ende der Ausgabe \tabularnewline\STRUT
\texttt{-e} & Aktiviert die Interpretation von Steuerzeichen. Diese
Steuerzeichen werden mit einem Backslash gequoted, der ganze String mu<6D> in
Ticks eingeschlossen werden. Beispielsweise gibt \texttt{echo -e
'hallo\textbackslash a'} das Wort hallo und einen Piepton aus.
\end{longtable}

View File

@ -1,19 +0,0 @@
% $Id$
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\texttt{foo=42} & Der Variablen namens `foo' wird der Wert `42' zugewiesen. \tabularnewline\STRUT
\texttt{a=foo} & Der Variablen namens `a' wird der Wert `foo' zugewiesen. \tabularnewline\STRUT
\texttt{b='\$'\$a} & Der Variablen `b' wird ein \$ und der Inhalt der Variablen namens `a' zugewiesen. \tabularnewline\STRUT
\texttt{echo \$b} & Der Inhalt der Variablen `b' wird ausgegeben. \tabularnewline\STRUT
\textsl{\$foo} & \tabularnewline\STRUT
\texttt{eval b='\$'\$a} & Zun<75>chst wird die Zeile nach dem \texttt{eval} expandiert, Variablen werden durch Inhalte ersetzt. Es entsteht also ein neuer Ausdruck: `b=\$foo'. Der wird dann von \texttt{eval} ausgef<65>hrt. \tabularnewline\STRUT
\texttt{echo \$b} & Der neue Inhalt der Variablen `b' wird ausgegeben. \tabularnewline\STRUT
\textsl{42} &
\end{longtable}

View File

@ -1,29 +0,0 @@
% $Id$
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\texttt{|} & logisches `oder' \tabularnewline\STRUT
\texttt{\&} & logisches `und' \tabularnewline\STRUT
\texttt{<} & kleiner als \tabularnewline\STRUT
\texttt{<=} & kleiner als oder gleich \tabularnewline\STRUT
\texttt{=} & gleich \tabularnewline\STRUT
\texttt{!=} & ungleich \tabularnewline\STRUT
\texttt{>=} & gr<67><72>er als oder gleich \tabularnewline\STRUT
\texttt{>} & gr<67><72>er als \tabularnewline\STRUT
\texttt{+} & Addition \tabularnewline\STRUT
\texttt{-} & Subtraktion \tabularnewline\STRUT
\texttt{*} & Multiplikation \tabularnewline\STRUT
\texttt{/} & Division \tabularnewline\STRUT
\texttt{\%} & Modulo (`Divisionsrest') \tabularnewline\STRUT
\texttt{:} & Pattern-Match mit regul<75>ren Ausdr<64>cken \tabularnewline\STRUT
\texttt{match} & Analog zu `:' \tabularnewline\STRUT
\texttt{substr} & Teil einer Zeichenkette zur<75>ckgeben \tabularnewline\STRUT
\texttt{index} & Position einer Zeichenkette in einer anderen finden \tabularnewline\STRUT
\texttt{length} & L<>nge einer Zeichenkette
\end{longtable}

View File

@ -1,31 +0,0 @@
% $Id$
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
Kriterien: & \tabularnewline\STRUT
\texttt{-name }\textsl{pattern} & Suchmuster f<>r den Dateinamen, auch mit Meta-Zeichen (Abschnitt \ref{metazeichen}) \tabularnewline\STRUT
\texttt{-perm [-]}\textsl{mode} & Sucht nach Dateien, deren Berechtigungen dem angegebenen Modus entsprechen. Die Notation erfolgt dabei analog zu \texttt{chmod} (Abschnitt \ref{chmod}), wahlweise in der Buchstaben- oder in der Zahlenform \tabularnewline\STRUT
\texttt{-type }\textsl{c} & Sucht nach Dateien des angegebenen Typs. Dabei kann f<>r \textsl{c} `b' (block device), `c' (character device), `d' (directory), `l' (symbolic link), `p' (pipe), `f' (regular file), oder `s' (socket) eingesetzt werden \tabularnewline\STRUT
\texttt{-user }\textsl{name} & Sucht nach Dateien, die dem angegebenen Benutzer geh<65>ren. Die Angabe kann als Name oder als UID erfolgen \tabularnewline\STRUT
\texttt{-group }\textsl{name} & Sucht nach Dateien, die der angegebenen Gruppe geh<65>ren. Die Angabe kann als Name oder als GID erfolgen \tabularnewline\STRUT
\texttt{-size }\textsl{n}\texttt{[c]} & Sucht nach Dateien, deren Gr<47><72>e \textsl{n} Blocks\footnote{Blocks geben die Dateigr<67><72>e in Bytes dividiert durch 512 und aufgerundet auf den n<>chsten Integer an. Das hat historische Gr<47>nde.} oder bei nachgestelltem \texttt{c} \textsl{n} Bytes ist \tabularnewline\STRUT
\texttt{-atime }\textsl{n} & Sucht nach Dateien, deren letzter Zugriff (access time) \texttt{n}*24 Stunden zur<75>ck liegt \tabularnewline\STRUT
\texttt{-ctime }\textsl{n} & Sucht nach Dateien, deren letzte Status<75>nderung (change time) \texttt{n}*24 Stunden zur<75>ck liegt \tabularnewline\STRUT
\texttt{-mtime }\textsl{n} & Sucht nach Dateien, deren letzte <20>nderung (modification time) \texttt{n}*24 Stunden zur<75>ck liegt \tabularnewline\STRUT
\texttt{-newer }\textsl{file} & Sucht nach Dateien, die j<>nger sind als \textsl{file} \tabularnewline\STRUT
Optionen: & \tabularnewline\STRUT
\texttt{-xdev} & Nur auf einem Filesystem suchen \tabularnewline\STRUT
\texttt{-depth } & Normalerweise wird eine Breitensuche durchgef<65>hrt, dieser Parameter schaltet auf Tiefensuche um \tabularnewline\STRUT
Aktionen: & \tabularnewline\STRUT
\texttt{-print} & Dies ist default, die gefundenen Dateinamen werden ausgegeben \tabularnewline\STRUT
\texttt{-exec }\textsl{kommando}\texttt{ \{\};} & F<>hrt das Kommando f<>r jede
Fundstelle aus, an Stelle der geschweiften Klammern wird der gefundene
Dateiname eingesetzt. Das abschlie<69>ende Semikolon mu<6D> wegen seiner
Sonderbedeutung in der Regel durch einen Backslash gequoted werden
\end{longtable}

View File

@ -1,20 +0,0 @@
% $Id$
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\texttt{-E} & Benutzt erweiterte regul<75>re Ausdr<64>cke \tabularnewline\STRUT
\texttt{-F} & Der Suchbegriff wird nicht als regul<75>rer Ausdruck, sondern als `fixed String' benutzt \tabularnewline\STRUT
\texttt{-c} & Gibt f<>r jede durchsuchte Datei die Anzahl der Fundstellen aus \tabularnewline\STRUT
\texttt{-f} & Liest die Suchbegriffe Zeile f<>r Zeile aus einer Textdatei \tabularnewline\STRUT
\texttt{-i} & Ignoriert die Unterscheidung zwischen Gro<72>- und Kleinschreibung \tabularnewline\STRUT
\texttt{-l} & Gibt nur die Dateinamen aus \tabularnewline\STRUT
\texttt{-n} & Gibt zus<75>tzlich die Zeilennummern der Fundstellen aus \tabularnewline\STRUT
\texttt{-q} & Gibt die Fundstellen nicht aus, am Exitcode ist zu erkennen ob etwas gefunden wurde \tabularnewline\STRUT
\texttt{-v} & Findet alle Zeilen, in denen das Suchmuster \emph{nicht} vorkommt
\end{longtable}

View File

@ -1,23 +0,0 @@
% $Id$
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\texttt{-1} & Formatiert die Ausgabe einspaltig \tabularnewline\STRUT
\texttt{-a} & Zeigt alle Dateien an, auch solche deren Name mit einem Punkt anf<6E>ngt \tabularnewline\STRUT
\texttt{-A} & \ding{43} Zeigt `fast alle' Dateien an, also auch alle deren Name mit einem Punkt anf<6E>ngt, allerdings nicht `.' und `..', die in jedem Verzeichnis vorkommen \tabularnewline\STRUT
\texttt{-d} & Verzeichnisse werden behandelt wie jede andere Datei auch, ein \texttt{ls -ld verzeichnis} gibt also die Eigenschaften des Verzeichnisses aus, nicht dessen Inhalt \tabularnewline\STRUT
\texttt{-h} & \ding{43} Gibt bei einer langen Ausgabe mittels \texttt{-l} die Gr<47><72>e der Datei `human readable' aus, also nicht zwingend in Bytes \tabularnewline\STRUT
\texttt{-l} & Lange Ausgabe, inklusiv der Dateiattribute \tabularnewline\STRUT
\texttt{-L} & \ding{43} `Dereferenziert' Links vor der Ausgabe. Es werden nicht die Eigenschaften des Links angezeigt, sondern die der verlinkten Datei \tabularnewline\STRUT
\texttt{-r} & Sortierreihenfolge umkehren \tabularnewline\STRUT
\texttt{-R} & Rekursiv in Verzeichnisse absteigen und deren Inhalte anzeigen \tabularnewline\STRUT
\texttt{-S} & \ding{43} Nach der Gr<47><72>e der Datei sortieren \tabularnewline\STRUT
\texttt{-t} & Nach der letzten <20>nderungszeit sortieren \tabularnewline\STRUT
\texttt{-X} & \ding{43} Nach der Extension (also dem Namensteil nach dem letzten Punkt) sortieren
\end{longtable}

View File

@ -1,15 +0,0 @@
% $Id$
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\texttt{-f} & Normalerweise wird nur nach Proze<7A>-Namen gesucht, mit diesem Parameter wird das volle Kommando (incl. Pfad und Parametern) betrachtet\tabularnewline\STRUT
\texttt{-l} & Nicht nur die Proze<7A>-ID, sondern das volle Kommando wird ausgegeben\tabularnewline\STRUT
\texttt{-v} & Findet alle Zeilen, in denen das Suchmuster \emph{nicht} vorkommt\tabularnewline\STRUT
\texttt{-x} & Sucht nach Kommandos, deren Name dem Muster \emph{exakt} entspricht
\end{longtable}

View File

@ -1,15 +0,0 @@
% $Id$
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\texttt{\%b} & Behandelt die Ausgabe von Backslash-Sequenzen. Die Sequenzen sind im Abschnitt <20>ber \texttt{echo} (\ref{echo}) beschrieben. \tabularnewline\STRUT
\texttt{\%s} & Gibt den n<>chsten Datenstring aus \tabularnewline\STRUT
\texttt{\%}\textsl{n}\texttt{\$s} & Gibt den \textsl{n}-ten Datenstring aus \tabularnewline\STRUT
\texttt{\%[-]}\textsl{m}\texttt{[.}\textsl{n}\texttt{]s} & Gibt den n<>chsten String aus, dazu wird ein Platz von \textsl{m} Zeichen reserviert. Optional k<>nnen nur die ersten \textsl{n} Zeichen ausgegeben oder mit \texttt{-} eine Rechtsb<73>ndige Formatierung festgelegt werden.
\end{longtable}

View File

@ -1,19 +0,0 @@
% $Id$
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\texttt{d} & Keine Adresse angegeben, alle Zeilen werden gel<65>scht \tabularnewline\STRUT
\texttt{23d} & Zeile 23 wird gel<65>scht \tabularnewline\STRUT
\texttt{\$d} & Die letzte Eingabezeile wird gel<65>scht \tabularnewline\STRUT
\texttt{/}\textsl{pattern}\texttt{/d} & Jede Zeile, die den regul<75>ren Ausdruck \textsl{pattern} enth<74>lt wird gel<65>scht \tabularnewline\STRUT
\texttt{23,42d} & Die Zeilen 23 bis einschlie<69>lich 42 werden gel<65>scht \tabularnewline\STRUT
\texttt{23,\$d} & Von Zeile 23 bis zum Ende wird gel<65>scht \tabularnewline\STRUT
\texttt{1,/\^\$/d} & Von der ersten bis zur ersten Leerzeile wird gel<65>scht \tabularnewline\STRUT
\texttt{23,42!d} & Alles au<61>er den Zeilen 23 bis 42 wird gel<65>scht
\end{longtable}

View File

@ -1,17 +0,0 @@
% $Id$
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
Editieren: & \tabularnewline\STRUT
\texttt{/}\textsl{adresse}\texttt{/d} & Zeilen l<>schen \tabularnewline\STRUT
\texttt{s/}\textsl{regexp1}\texttt{/}\textsl{regexp2}\texttt{/} & Substitution: Suchen und ersetzen \tabularnewline\STRUT
\texttt{y/}\textsl{menge1}\texttt{/}\textsl{menge2}\texttt{/} & Zeichen ersetzen \tabularnewline\STRUT
Zeileninformation: & \tabularnewline\STRUT
\texttt{/}\textsl{adresse}\texttt{/p} & Zeilen ausgeben
\end{longtable}

View File

@ -1,16 +0,0 @@
% $Id$
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\texttt{-k 3} & Sortiert nach dem dritten Feld \tabularnewline\STRUT
\texttt{-k 3.5} & Sortiert nach dem f<>nften Zeichen des dritten Feldes \tabularnewline\STRUT
\texttt{-k 3.5r} & Sortiert r<>ckw<6B>rts nach dem f<>nften Zeichen des dritten Feldes \tabularnewline\STRUT
\texttt{-k 3,5} & Beachtet bei der Sortierung nur das dritte bis f<>nfte Feld \tabularnewline\STRUT
\texttt{-k 3.5,3.8} & Beachtet die Zeichen f<>nf bis acht des dritten Feldes
\end{longtable}

View File

@ -1,20 +0,0 @@
% $Id$
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\texttt{-b} & Ignoriert f<>hrende Leerzeichen \tabularnewline\STRUT
\texttt{-c} & Pr<50>ft nur, ob die Eingabedaten bereits sortiert sind \tabularnewline\STRUT
\texttt{-f} & Gro<72>- / Kleinschreibung nicht beachten \tabularnewline\STRUT
\texttt{-i} & Nur `printable' Zeichen beachten \tabularnewline\STRUT
\texttt{-k} & Sortiert nicht nach der ersten, sondern nach der angegebenen Spalte (siehe unten) \tabularnewline\STRUT
\texttt{-n} & Numerische Sortierung \tabularnewline\STRUT
\texttt{-r} & Sortierreihenfolge umkehren \tabularnewline\STRUT
\texttt{-t} & Normalerweise f<>ngt ein Feld (siehe \texttt{-k}) beim <20>bergang von `blank' nach `non-blank' an, mit diesem Parameter k<>nnen ander Feld-Trenner definiert werden \tabularnewline\STRUT
\texttt{-u} & Gibt bei identischen Zeilen nur die erste Fundstelle aus (unique)
\end{longtable}

View File

@ -1,19 +0,0 @@
% $Id$
\begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\texttt{-c} & Anzahl der Vorkommnisse vor die Zeilen schreiben \tabularnewline\STRUT
\texttt{-d} & Nur doppelte Zeilen ausgeben, jede nur einmal \tabularnewline\STRUT
\texttt{-D} & \ding{43} Alle doppelten Zeilen ausgeben \tabularnewline\STRUT
\texttt{-f }\textsl{n} & Die ersten \textsl{n} Felder ignorieren \tabularnewline\STRUT
\texttt{-i} & \ding{43} Gro<72>- / Kleinschreibung ignorieren \tabularnewline\STRUT
\texttt{-s }\textsl{n} & Die ersten \textsl{n} Zeichen ignorieren \tabularnewline\STRUT
\texttt{-u} & Nur einfach vorkommende Zeilen ausgeben \tabularnewline\STRUT
\texttt{-w }\textsl{n} & \ding{43} Nur die ersten \textsl{n} Zeichen betrachten
\end{longtable}

View File

@ -1,4 +1,3 @@
% $Id$
\begin{longtable}{|l|X|} \begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill % KILLED & LINE!!!! \kill
\hline \hline

View File

@ -1,4 +1,3 @@
% $Id$
\begin{longtable}{|l|c|c|c|X|} \begin{longtable}{|l|c|c|c|X|}
% KILLED & LINE!!!! \kill % KILLED & LINE!!!! \kill
\hline \hline

View File

@ -1,4 +1,3 @@
% $Id$
\begin{longtable}{|l|X|} \begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill % KILLED & LINE!!!! \kill
\hline \hline

View File

@ -1,4 +1,3 @@
% $Id$
\begin{longtable}{|l|c|c|c|c|c|c|c|X|} \begin{longtable}{|l|c|c|c|c|c|c|c|X|}
% KILLED & LINE!!!! \kill % KILLED & LINE!!!! \kill
\hline \hline

View File

@ -1,4 +1,3 @@
% $Id$
\begin{longtable}{|l|X|} \begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill % KILLED & LINE!!!! \kill
\hline \hline

View File

@ -1,4 +1,3 @@
% $Id$
\begin{longtable}{|l|X|} \begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill % KILLED & LINE!!!! \kill
\hline \hline
@ -10,12 +9,11 @@
\texttt{;} & Befehls-Trennzeichen\index{Befehls>-Trennzeichen} \tabularnewline\STRUT \texttt{;} & Befehls-Trennzeichen\index{Befehls>-Trennzeichen} \tabularnewline\STRUT
\texttt{\&} & Hintergrund-Verarbeitung \tabularnewline\STRUT \texttt{\&} & Hintergrund-Verarbeitung \tabularnewline\STRUT
\texttt{( ) \{ \}} & Befehlsfolge\index{Befehls>-folge} \tabularnewline\STRUT \texttt{( )} & Befehlsfolge\index{Befehls>-folge} \tabularnewline\STRUT
\texttt{|} & Pipe \tabularnewline\STRUT \texttt{|} & Pipe \tabularnewline\STRUT
\texttt{< > >\&} & Umlenkungssymbole \tabularnewline\STRUT \texttt{< > >\&} & Umlenkungssymbole \tabularnewline\STRUT
\texttt{* ? [ ] \~{} + - @ !} & Meta-Zeichen\index{Meta-Zeichen} f<>r Dateinamen \tabularnewline\STRUT \texttt{* ? [ ] \~{} + - @ !} & Meta-Zeichen\index{Meta-Zeichen} f<>r Dateinamen \tabularnewline\STRUT
\texttt{` ` }(Backticks oder Single Backquotes\footnote{Man erh<72>lt sie <EFBFBD>blicherweise durch \Ovalbox{SHIFT} und die Taste neben dem Backspace.}) & Befehls-Substitution\index{Befehls>-Substitution} \tabularnewline\STRUT \texttt{` ` }(Backticks\footnote{Man erh<72>lt sie durch \Ovalbox{SHIFT} und die Taste neben dem Backspace.}) & Befehls-Substitution\index{Befehls>-Substitution} \tabularnewline\STRUT
\texttt{\$} & Variablen-Substitution\index{Variablen>-Substitution} \tabularnewline\STRUT \texttt{\$} & Variablen-Substitution\index{Variablen>-Substitution} \tabularnewline\STRUT
\texttt{\Ovalbox{NEWLINE} \Ovalbox{SPACE} \Ovalbox{TAB}} & \texttt{\Ovalbox{NEWLINE} \Ovalbox{SPACE} \Ovalbox{TAB}} & Wort-Trennzeichen\footnote{Die Wort-Trennzeichen sind in der Variable \texttt{\$IFS}\index{\$IFS=\texttt{\$IFS}} abgelegt. Man kann diese Variable auch <20>berschreiben, um elegant Strings zu zerlegen.}
Wort-Trennzeichen\footnote{Die Wort-Trennzeichen sind in der vordefinierten Variable \texttt{\$IFS} abgelegt. Siehe Abschnitt \ref{vordefinierte_variablen}.}
\end{longtable} \end{longtable}

View File

@ -1,4 +1,3 @@
% $Id$
\begin{longtable}{|l|X|} \begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill % KILLED & LINE!!!! \kill
\hline \hline
@ -8,18 +7,17 @@
\hline \hline
\endlastfoot \endlastfoot
\texttt{\dq~\dq} & (Anf<6E>hrungszeichen oder Double Quotes) Alles zwischen diesen \texttt{\dq~\dq} & (Anf<6E>hrungszeichen) Alles zwischen diesen Zeichen ist
Zeichen ist buchstabengetreu zu interpretieren. Ausnahmen sind folgende buchstabengetreu zu interpretieren. Ausnahmen sind folgende Zeichen, die ihre
Zeichen, die ihre spezielle Bedeutung beibehalten: \texttt{\$ ` \dq} spezielle Bedeutung beibehalten: \texttt{\$ ` \dq} \tabularnewline\STRUT
\texttt{' '} & (Ticks\footnote{Sie liegen auf der Tastatur <20>ber der Raute.})
Alls zwischen diesen Zeichen wird w<>rtlich genommen, mit Ausnahme eines
weiteren \texttt{'} oder eines Backslashes (\texttt{\textbackslash})
\tabularnewline\STRUT \tabularnewline\STRUT
\texttt{' '} & (Ticks oder (Single) Quotes\footnote{Sie liegen auf der Tastatur
<EFBFBD>ber der Raute.}) Alls zwischen diesen Zeichen wird w<>rtlich genommen, mit
Ausnahme eines weiteren \texttt{'} oder eines Backslashes
(\texttt{\textbackslash}) \tabularnewline\STRUT
\texttt{\textbackslash} & (Backslash\index{Backslash}) Das Zeichen nach einem \texttt{\textbackslash} & (Backslash\index{Backslash}) Das Zeichen nach einem
\textbackslash wird w<>rtlich genommen. Anwendung z.~B. innerhalb von \textbackslash wird w<>rtlich genommen. Anwendung z. B. innerhalb von
\texttt{\dq~\dq}, um \texttt{\dq}, \texttt{\$} und \texttt{`} zu entwerten. \texttt{\dq~\dq}, um \texttt{\dq}, \texttt{\$} und \texttt{`} zu entwerten.
H<EFBFBD>ufig verwendet zur Angabe von Leerzeichen (space) und Zeilenendezeichen, oder H<EFBFBD>ufig verwendet zur Angabe von Leerzeichen (space) und Zeilenendezeichen, oder
um ein \textbackslash -Zeichen selbst anzugeben. um ein \textbackslash -Zeichen selbst anzugeben.

View File

@ -1,4 +1,3 @@
% $Id$
\begin{longtable}{|l|l|X|} \begin{longtable}{|l|l|X|}
% KILLED & LINE!!!! \kill % KILLED & LINE!!!! \kill
\hline \hline
@ -12,6 +11,6 @@ Nummer & Name & Bedeutung \\
0 & Normal Exit & Wird durch das \texttt{exit}\index{exit=\texttt{exit}}-Kommando ausgel<65>st. \tabularnewline\STRUT 0 & Normal Exit & Wird durch das \texttt{exit}\index{exit=\texttt{exit}}-Kommando ausgel<65>st. \tabularnewline\STRUT
1 & SIGHUP & Wenn die Verbindung abbricht (z. B. wenn das Terminal geschlossen wird). \tabularnewline\STRUT 1 & SIGHUP & Wenn die Verbindung abbricht (z. B. wenn das Terminal geschlossen wird). \tabularnewline\STRUT
2 & SIGINT & Zeigt einen Interrupt an (\Ovalbox{CTRL}+\Ovalbox{C}). \tabularnewline\STRUT 2 & SIGINT & Zeigt einen Interrupt an (\Ovalbox{CTRL}-\Ovalbox{C}). \tabularnewline\STRUT
15 & SIGTERM & Wird vom \texttt{kill}\index{kill=\texttt{kill}}-Kommando gesendet. 15 & SIGTERM & Wird vom \texttt{kill}\index{kill=\texttt{kill}}-Kommando gesendet.
\end{longtable} \end{longtable}

14
tab_until.tex Normal file
View File

@ -0,0 +1,14 @@
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\texttt{until }\textsl{Bedingung}} \\
\multicolumn{2}{|X|}{\texttt{do}} \\
\multicolumn{2}{|X|}{\texttt{~}\textsl{Befehle}} \\
\multicolumn{2}{|X|}{\texttt{done}} \\
\end{longtable}

View File

@ -1,4 +1,3 @@
% $Id$
\begin{longtable}{|l|X|} \begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill % KILLED & LINE!!!! \kill
\hline \hline
@ -9,9 +8,9 @@
\endlastfoot \endlastfoot
\textsl{Variable}\texttt{=}\textsl{Wert} & Setzt die \textsl{Variable} auf den \textsl{Wert}. Dabei ist unbedingt darauf zu achten, da<64> zwischen dem Variablennamen und dem Gleichheitszeichen keine Leerzeichen stehen. \tabularnewline\STRUT \textsl{Variable}\texttt{=}\textsl{Wert} & Setzt die \textsl{Variable} auf den \textsl{Wert}. Dabei ist unbedingt darauf zu achten, da<64> zwischen dem Variablennamen und dem Gleichheitszeichen keine Leerzeichen stehen. \tabularnewline\STRUT
\texttt{\$\{}\textsl{Variable}\texttt{\}} & Nutzt den Wert von \textsl{Variable}. Die Klammern m<>ssen nur angegeben werden, wenn auf die \textsl{Variable} eine Zahl, ein Buchstabe oder ein Unterstrich folgen. \tabularnewline\STRUT \texttt{\$\{}\textsl{Variable}\texttt{\}} & Nutzt den Wert von \textsl{Variable}. Die Klammern m<>ssen nicht mit angegeben werden, wenn die \textsl{Variable} von Trennzeichen umgeben ist. \tabularnewline\STRUT
\texttt{\$\{}\textsl{Variable}\texttt{:-}\textsl{Wert}\texttt{\}} & Nutzt den Wert von \textsl{Variable}. Falls die \textsl{Variable} nicht gesetzt oder leer ist, wird \textsl{Wert} benutzt. \tabularnewline\STRUT \texttt{\$\{}\textsl{Variable}\texttt{:-}\textsl{Wert}\texttt{\}} & Nutzt den Wert von \textsl{Variable}. Falls die \textsl{Variable} nicht gesetzt ist, wird der \textsl{Wert} benutzt. \tabularnewline\STRUT
\texttt{\$\{}\textsl{Variable}\texttt{:=}\textsl{Wert}\texttt{\}} & Nutzt den Wert von \textsl{Variable}. Falls die \textsl{Variable} nicht gesetzt oder leer ist, wird \textsl{Wert} benutzt, und \textsl{Variable} erh<72>lt den \textsl{Wert}. \tabularnewline\STRUT \texttt{\$\{}\textsl{Variable}\texttt{:=}\textsl{Wert}\texttt{\}} & Nutzt den Wert von \textsl{Variable}. Falls die \textsl{Variable} nicht gesetzt ist, wird der \textsl{Wert} benutzt, und \textsl{Variable} erh<72>lt den \textsl{Wert}. \tabularnewline\STRUT
\texttt{\$\{}\textsl{Variable}\texttt{:?}\textsl{Wert}\texttt{\}} & Nutzt den Wert von \textsl{Variable}. Falls die \textsl{Variable} nicht gesetzt oder leer ist, wird der \textsl{Wert} ausgegeben und die Shell beendet. Wenn kein \textsl{Wert} angegeben wurde, wird der Text \texttt{parameter null or not set} ausgegeben. \tabularnewline\STRUT \texttt{\$\{}\textsl{Variable}\texttt{:?}\textsl{Wert}\texttt{\}} & Nutzt den Wert von \textsl{Variable}. Falls die \textsl{Variable} nicht gesetzt ist, wird der \textsl{Wert} ausgegeben und die Shell beendet. Wenn kein \textsl{Wert} angegeben wurde, wird der Text \texttt{parameter null or not set} ausgegeben. \tabularnewline\STRUT
\texttt{\$\{}\textsl{Variable}\texttt{:+}\textsl{Wert}\texttt{\}} & \textsl{Wert}, falls die \textsl{Variable} gesetzt und nicht leer ist, andernfalls nichts. \texttt{\$\{}\textsl{Variable}\texttt{:+}\textsl{Wert}\texttt{\}} & Nutzt den \textsl{Wert}, falls die \textsl{Variable} gesetzt ist, andernfalls nichts.
\end{longtable} \end{longtable}

View File

@ -1,4 +1,3 @@
% $Id$
\begin{longtable}{|l|X|} \begin{longtable}{|l|X|}
% KILLED & LINE!!!! \kill % KILLED & LINE!!!! \kill
\hline \hline
@ -16,8 +15,6 @@
\texttt{\$\$} & Proze<7A>nummer der aktiven Shell \tabularnewline\STRUT \texttt{\$\$} & Proze<7A>nummer der aktiven Shell \tabularnewline\STRUT
\texttt{\$!} & Proze<7A>nummer des letzten Hintergrundprozesses \tabularnewline\STRUT \texttt{\$!} & Proze<7A>nummer des letzten Hintergrundprozesses \tabularnewline\STRUT
\texttt{\$ERRNO} & Fehlernummer des letzten fehlgeschlagenen Systemaufrufs \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{\$PWD} & Aktuelles Verzeichnis (wird durch \texttt{cd} gesetzt\footnote{Durch das Kommando \texttt{cd} wird das aktuelle Verzeichnis gewechselt.}) \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) \texttt{\$OLDPWD} & Vorheriges Verzeichnis (wird durch \texttt{cd} gesetzt)
\end{longtable} \end{longtable}

14
tab_while.tex Normal file
View File

@ -0,0 +1,14 @@
\begin{longtable}{|X l|}
% KILLED & LINE!!!! \kill
\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\multicolumn{2}{|X|}{\texttt{while }\textsl{Bedingung}} \\
\multicolumn{2}{|X|}{\texttt{do}} \\
\multicolumn{2}{|X|}{\texttt{~}\textsl{Befehle}} \\
\multicolumn{2}{|X|}{\texttt{done}} \\
\end{longtable}

View File

@ -1,29 +0,0 @@
% $Id$
\chapter{Routenplanung - Die Zukunft dieses Dokuments}
Ich werde in dieser Version des Dokumentes nicht alles umgesetzt haben, was mir
sinnvoll erscheint. An dieser Stelle sammele ich Ideen f<>r eine n<>chste
Version. Kommentare dazu nehme ich jederzeit dankend entgegen.
\begin{itemize}
\item \textbf{GNU / Posix:} Bessere Abgrenzung der GNU-Erweiterungen
ge\-gen\-<EFBFBD>\-ber dem Posix-Standard, damit die Skripte portabel bleiben und
nicht nur auf Linux laufen.
\item \textbf{Performance:} Ein Kapitel mit Hinweisen, wie Skripte nicht
unn<EFBFBD>tig langsam werden.
\item \textbf{Interaktive Shell:} Exkurs zur interaktiven Benutzung der Bash.
Es gibt da eine Reihe hilfreicher Tastenkombinationen, die l<>ngst nicht jedem
bekannt sind.
\item \textbf{HTML-Version:} Ich w<>rde gerne eine HTML-Version zur Verf<72>gung
stellen, bin mir aber noch nicht sicher ob das aus den \LaTeX-Quellen geht. Mir
liegt dabei die Indizierung der Stichworte am Herzen, die sollte nicht
verloren gehen.
\item \textbf{Glossar:} Verzeichnis von Begriffen wie PID, Prompt, GID, UID,
Cron, usw.
\end{itemize}

View File

@ -1,126 +1,45 @@
% $Id$
\chapter{Was ist die Shell?}\index{Shell} \chapter{Was ist die Shell?}\index{Shell}
Die Shell ist ein Programm, mit dessen Hilfe das System die Benutzerbefehle Die Shell ist ein Programm, mit dessen Hilfe das System die Benutzerbefehle verstehen kann. Aus diesem Grund wird die Shell auch oft als Befehls- oder Kommandointerpreter bezeichnet.
verstehen kann. Aus diesem Grund wird die Shell auch oft als Befehls- oder
Kommandointerpreter bezeichnet.
\section{Sinn und Zweck} \section{Sinn und Zweck}
In einem klassischen Unix-System (ohne die grafische Oberfl<66>che X) greifen die In einem klassischen Unix-System (ohne die grafische Oberfl<66>che X) greifen die Benutzer <20>ber Terminals\index{Terminal} auf das System zu. Auf diesen Terminals k<>nnen nur Textzeichen dargestellt werden. Um dem Benutzer die Arbeit mit dem System effektiv m<>glich zu machen, gibt es die Shell. Die Shell wird dabei f<>r drei Hauptaufgaben benutzt:
Benutzer <20>ber Terminals\index{Terminal} auf das System zu. Auf diesen Terminals
k<EFBFBD>nnen nur Textzeichen dargestellt werden. Um dem Benutzer die Arbeit mit dem
System effektiv m<>glich zu machen, gibt es die Shell. Die Shell wird dabei f<>r
drei Hauptaufgaben benutzt:
\begin{itemize} \begin{itemize}
\item Interaktive Anwendung (Dialog) \item Interaktive Anwendung (Dialog)
\item Anwendungsspezifische Anpassung des Unix-Systemverhaltens (Belegen von Umgebungsvariablen) \item Anwendungsspezifische Anpassung des Unix-Systemverhaltens (Belegen von Umgebungsvariablen)
\item Programmierung (Shell-Skripting). Zu diesem Zweck stehen einige Mechanismen zur Verf<72>gung, die aus Hochsprachen bekannt sind (Variablen, Datenstr<74>me, Funktionen usw.). \item Programmierung (Shell-Skripting). Zu diesem Zweck stehen einige Mechanismen zur Verf<72>gung, die aus Hochsprachen bekannt sind (Variablen, Datenstr<74>me, Funktionen usw.).
\end{itemize} \end{itemize}
Urspr<EFBFBD>nglich handelte es sich dabei um ein relativ einfaches Programm, der Urspr<EFBFBD>nglich handelte es sich dabei um ein relativ einfaches Programm, der Bourne Shell (wird oft auch Standard-Shell genannt). Dies ist praktisch die "`Mutter aller Shells"'. Aus dieser entwickelten sich im Laufe der Zeit mehrere Varianten, die alle ihre eigenen Vor- und Nachteile mit sich bringen. Da es unter Unix kein Problem darstellt den Kommandointerpreter auszutauschen, stehen auf den meisten Systemen mehrere dieser Shells zur Verf<72>gung. Welche Variante ein Benutzer verwenden m<>chte ist reine Geschmackssache.
Bourne Shell (wird oft auch Standard-Shell genannt). Dies ist praktisch die
"`Mutter aller Shells"'. Aus dieser entwickelten sich im Laufe der Zeit mehrere
Varianten, die alle ihre eigenen Vor- und Nachteile mit sich bringen. Da es
unter Unix kein Problem darstellt den Kommandointerpreter auszutauschen, stehen
auf den meisten Systemen mehrere dieser Shells zur Verf<72>gung. Welche Variante
ein Benutzer verwenden m<>chte ist reine Geschmackssache.
\section{Die Qual der Wahl} \section{Die Qual der Wahl}
Um die Auswahl einer Shell zu erleichtern, werden hier die wichtigsten Um die Auswahl einer Shell zu erleichtern, werden hier die wichtigsten Varianten kurz vorgestellt. Sie sind aufgeteilt in Einfach- und Komfort-Shells. Die Komfort-Shells zeichnen sich durch komfortablere Funktionen zur interaktiven Bedienung aus, w<>hrend die Einfach-Versionen <20>blicherweise f<>r die Programmierung benutzt werden.
Varianten kurz vorgestellt. Sie sind aufgeteilt in Einfach- und Komfort-Shells.
Die Komfort-Shells zeichnen sich durch komfortablere Funktionen zur
interaktiven Bedienung aus, w<>hrend die Einfach-Versionen <20>blicherweise f<>r die
Programmierung benutzt werden.
\medskip\emph{Einfach-Shells:}\nopagebreak \medskip\emph{Einfach-Shells:}\nopagebreak
\begin{itemize} \begin{itemize}
\item Die \item Die Bourne-\index{Bourne-Shell|textbf}\index{Shell>Bourne-|see{Bourne-Shell}} oder Standard-Shell\index{Shell>Standard-|see{Bourne-Shell}}\index{Standard-Shell|see{Bourne-Shell}} (\texttt{sh}\index{sh=\texttt{sh}|see{Bourne-Shell}}) ist die kompakteste und einfachste Form. Sie bietet schon Mechanismen wie die Umlenkung der Ein- oder Ausgaben, Wildcards zur Abk<62>rzung von Dateinamen, Shell-Variablen und einen Satz interner Befehle zum Schreiben von Shell-Prozeduren. Neuere Versionen beherrschen auch das Job-Controlling\index{Job-Controlling}. F<>r die Entwicklung von Shell-Skripten sollte man sich auf diese Shell beschr<68>nken, da sie auf praktisch allen Systemen zur Verf<72>gung steht. So bleiben die Skripte portabel.
Bourne-\index{Bourne-Shell|textbf}\index{Shell>Bourne-|see{Bourne-Shell}} oder
Standard-Shell\index{Shell>Standard-|see{Bourne-Shell}}\index{Standard-Shell|see{Bourne-Shell}}
(\texttt{sh}\index{sh=\texttt{sh}|see{Bourne-Shell}}) ist die kompakteste und
einfachste Form. Sie bietet schon Mechanismen wie die Umlenkung der Ein- oder
Ausgaben, Wildcards zur Abk<62>rzung von Dateinamen, Shell-Variablen und einen
Satz interner Befehle zum Schreiben von Shell-Prozeduren. Neuere Versionen
beherrschen auch das Job-Controlling\index{Job-Controlling}.
F<EFBFBD>r die Entwicklung von Shell-Skripten sollte man sich auf diese Shell \item Die Korn-Shell\index{Korn-Shell|textbf}\index{Shell>Korn-|see{Korn-Shell}} (\texttt{ksh}\index{ksh=\texttt{ksh}|see{Korn-Shell}}), eine Weiterentwicklung der Bourne-Shell, erlaubt das editieren in der Befehlszeile. Au<41>erdem gibt es hier History\index{History}-Funktionen\footnote{History-Funktionen erm<72>glichen es dem Benutzer, einfach auf zur<75>ckliegende Befehle zur<75>ckgreifen zu k<>nnen.}, eine Ganzzahl-Arithmetik, verbesserte M<>glichkeiten zur Mustererkennung, Aliase\index{Aliase}\footnote{Ein Alias ist eine Abk<62>rzung f<>r einen Befehl. Beispielsweise kann man das H<>ufig benutzte \texttt{ls -la} einfach durch \texttt{la} ersetzen.} und das Job-Controlling\footnote{Unter Job-Controlling versteht man einen Mechanismus, mit dessen Hilfe der Benutzer die Ausf<73>hrung von Prozessen selektiv stoppen oder fortsetzen kann}\index{Job-Controlling}. Au<41>erdem bietet die Korn-Shell im Gegensatz zu fast allen anderen Shells die M<>glichkeit, Aliase und Shell-Funktionen an Subshells zu vererben.
beschr<EFBFBD>nken, da sie auf praktisch allen Systemen zur Verf<72>gung steht. So
bleiben die Skripte mit kleinen Einschr<68>nkungen\footnote{Die verschiedenen
Implementierungen weisen kleine Unterschiede, z. B. bei der Behandlung von \$@
oder den Parametern von \texttt{read} (-r) auf.} portabel.
\item Die \item Die C-Shell \index{C-Shell|textbf}\index{Shell>C-|see{C-Shell}} (\texttt{csh}\index{csh=\texttt{csh}|see{C-Shell}}) bietet <20>hnliche Annehmlichkeiten wie die Korn-Shell, lehnt sich aber in der Syntax sehr stark an die Programmiersprache C an. Sie sollte nach M<>glichkeit nicht zur Shell-Programmierung benutzt werden, da sie an vielen Stellen nicht so reagiert, wie man es erwarten sollte.
Korn-Shell\index{Korn-Shell|textbf}\index{Shell>Korn-|see{Korn-Shell}}
(\texttt{ksh}\index{ksh=\texttt{ksh}|see{Korn-Shell}}), eine Weiterentwicklung
der Bourne-Shell, erlaubt das Editieren in der Befehlszeile. Au<41>erdem gibt es
hier History\index{History}-Funktionen\footnote{History-Funktionen erm<72>glichen
es dem Benutzer, einfach auf zur<75>ckliegende Befehle zur<75>ckgreifen zu k<>nnen.},
eine Ganzzahl-Arithmetik, verbesserte M<>glichkeiten zur Mustererkennung,
Arrays, Aliase\index{Aliase}\footnote{Ein Alias ist eine Abk<62>rzung f<>r einen
Befehl. Beispielsweise kann man das H<>ufig benutzte \texttt{ls -la} einfach
durch \texttt{la} ersetzen.} und das Job-Controlling\footnote{Unter
Job-Controlling versteht man einen Mechanismus, mit dessen Hilfe der Benutzer
die Ausf<73>hrung von Prozessen selektiv stoppen oder fortsetzen
kann}\index{Job-Controlling}. Au<41>erdem bietet die Korn-Shell im Gegensatz zu
fast allen anderen Shells die M<>glichkeit, Aliase und Shell-Funktionen an
Subshells zu vererben.
Die Korn-Shell existiert in verschiedenen Implementierungen, sowohl kommerziell
(ksh88), kostenlos (ksh93) als auch frei (pdksh).
\item Die C-Shell \index{C-Shell|textbf}\index{Shell>C-|see{C-Shell}}
(\texttt{csh}\index{csh=\texttt{csh}|see{C-Shell}}) bietet <20>hnliche
Annehmlichkeiten wie die Korn-Shell, lehnt sich aber in der Syntax sehr stark
an die Programmiersprache C an. Sie sollte nach M<>glichkeit nicht zur
Shell-Programmierung benutzt werden, da sie an vielen Stellen nicht so
reagiert, wie man es erwarten sollte.
\end{itemize} \end{itemize}
\medskip\emph{Komfort-Shells:}\nopagebreak \medskip\emph{Komfort-Shells:}\nopagebreak
\begin{itemize} \begin{itemize}
\item Die \item Die Bourne-Again-Shell\index{Bourne-Again-Shell|textbf}\index{Shell>Bourne-Again-|see{Bourne-Again-Shell}}\index{Shell>Bash|see{Bourne-Again-Shell}} (\texttt{bash}\index{bash=\texttt{bash}|see{Bourne-Again-Shell}}) ist voll abw<62>rtskompatibel zur sh, bietet aber von allen Shells die komfortabelsten Funktionen f<>r das interaktive Arbeiten. Da die Bash ein GNU-Produkt ist, ist sie die Standard-Shell auf allen Linux-Systemen. Sie steht aber auch auf den meisten anderen Unixen zur Verf<72>gung.
Bourne-Again-Shell\index{Bourne-Again-Shell|textbf}\index{Shell>Bourne-Again-|see{Bourne-Again-Shell}}\index{Shell>Bash|see{Bourne-Again-Shell}} Die Bash unterst<73>tzt Auto-Completion\index{Auto-Completion|textbf}\footnote{Mit Auto-Completion ist das automatische Vervollst<73>ndigen von Dateinamen\index{Dateinamen} gemeint.}, History-Funktionen, Aliase\index{Aliase}, eine Ganzzahl-Arithmetik und indizierte Arrays\index{Array}.
(\texttt{bash}\index{bash=\texttt{bash}|see{Bourne-Again-Shell}}) ist voll
abw<EFBFBD>rtskompatibel zur sh, bietet aber von allen Shells die komfortabelsten
Funktionen f<>r das interaktive Arbeiten. Da die Bash ein GNU-Produkt ist, ist
sie die Standard-Shell auf allen Linux-Systemen. Sie steht aber auch auf den
meisten anderen Unixen zur Verf<72>gung. Die Bash unterst<73>tzt
Auto-Completion\index{Auto-Completion|textbf}\footnote{Mit Auto-Completion ist
das automatische Vervollst<73>ndigen von Dateinamen\index{Dateinamen} gemeint.},
History-Funktionen, Aliase\index{Aliase}, eine Ganzzahl-Arithmetik und
indizierte Arrays\index{Array}.
\item Die
TENEX-C-Shell\index{TENEX-C-Shell|textbf}\index{Shell>TENEX-C-|see{TENEX-C-Shell}}
(\texttt{tcsh}\index{tcsh=\texttt{tcsh}|see{TENEX-C-Shell}}) verh<72>lt sich zur
C-Shell wie die Bourne-Again-Shell zur Standard-Shell. Sie ist voll kompatibel,
bietet aber Kom\-fort-Funk\-tio\-nen wie Kom\-man\-do\-zei\-len-Edi\-tie\-rung,
programmierbare Auto-Completion\index{Auto-Completion},
Recht\-schreib\-hil\-fen und eine History.
\item Die Z-Shell\index{Z-Shell|textbf}\index{Shell>Z-|see{Z-Shell}} \item Die TENEX-C-Shell\index{TENEX-C-Shell|textbf}\index{Shell>TENEX-C-|see{TENEX-C-Shell}} (\texttt{tcsh}\index{tcsh=\texttt{tcsh}|see{TENEX-C-Shell}}) verh<72>lt sich zur C-Shell wie die Bourne-Again-Shell zur Standard-Shell. Sie ist voll kompatibel, bietet aber Komfort-Funktionen wie Kommandozeilen-Editierung, programmierbare Auto-Completion\index{Auto-Completion}, Rechtschreibhilfen und eine History.
(\texttt{zsh}\index{zsh=\texttt{zsh}|see{Z-Shell}}) <20>hnelt der Korn-Shell,
enth<EFBFBD>lt aber viele Erweiterungen. Die Z-Shell unterst<73>tzt \item Die Z-Shell\index{Z-Shell|textbf}\index{Shell>Z-|see{Z-Shell}} (\texttt{zsh}\index{zsh=\texttt{zsh}|see{Z-Shell}}) <20>hnelt der Korn-Shell, enth<74>lt aber viele Erweiterungen. Die Z-Shell unterst<73>tzt Kommandozeilen-Editing, programmierbares Auto-Completion\index{Auto-Completion}, Shell-Funktionen und eine History. Zudem ist eine Rechtschreibpr<70>fung eingebaut.
Kom\-mandozeilen-Editing, programmierbares \end{itemize}
Auto-Completion\index{Auto-Completion}, Shell-Funktionen und eine History.
Zudem ist eine Rechtschreibpr<70>fung eingebaut. \end{itemize}
\medskip\emph{Exoten:}\medskip\nopagebreak \medskip\emph{Exoten:}\medskip\nopagebreak
Desweiteren gibt es noch eine Reihe weiterer Shells, die aber nur selten Desweiteren gibt es noch eine Reihe weiterer Shells, die aber nur selten eingesetzt werden. Dazu geh<65>ren die \texttt{ash}\index{ash|textbf}\index{Shell>ash=\texttt{ash}|see{ash}} (Ein Bourne-Shell-Clone f<>r Rechner mit wenig Speicher.), \texttt{rc}\index{rc|textbf}\index{Shell>rc=\texttt{rc}|see{rc}} (Noch ein Bourne-Shell-Clone, urspr<70>nglich aus AT\&T Plan 9. Klein, schnell und mit eine C-<2D>hnlichen Syntax.), \texttt{esh}\index{esh|textbf}\index{Shell>esh=\texttt{esh}|see{esh}} (Klein und schnell, bietet eine Lisp-<2D>hnliche Sprache), \texttt{sash}\index{sash|textbf}\index{Shell>sash=\texttt{sash}|see{sash}} (System Administrator's Shell - eine statisch gelinkte Shell mit integrierten Standard-Kommandos.).
eingesetzt werden. Dazu geh<65>ren die
\texttt{ash}\index{ash|textbf}\index{Shell>ash=\texttt{ash}|see{ash}} (Ein
Bourne-Shell-Clone f<>r Rechner mit wenig Speicher.),
\texttt{rc}\index{rc|textbf}\index{Shell>rc=\texttt{rc}|see{rc}} (Noch ein
Bourne-Shell-Clone, urspr<70>nglich aus AT\&T Plan 9. Klein, schnell und mit eine
C-<2D>hnlichen Syntax.),
\texttt{esh}\index{esh|textbf}\index{Shell>esh=\texttt{esh}|see{esh}} (Klein
und schnell, bietet eine Lisp-<2D>hnliche Sprache),
\texttt{sash}\index{sash|textbf}\index{Shell>sash=\texttt{sash}|see{sash}}
(System Administrator's Shell - eine statisch gelinkte Shell mit integrierten
Stan\-dard-Kom\-man\-dos.).
Diese Liste ist bei weitem nicht vollst<73>ndig. Diese Liste ist bei weitem nicht vollst<73>ndig.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +1,11 @@
% $Id$
\chapter{Wo sind Unterschiede zu DOS-Batchdateien?}\index{DOS|(textbf}\index{Batchdateien|(textbf} \chapter{Wo sind Unterschiede zu DOS-Batchdateien?}\index{DOS|(textbf}\index{Batchdateien|(textbf}
Unter DOS werden Batchdateien oft dazu benutzt, lange Kommandos abzuk<75>rzen um Unter DOS werden Batchdateien oft dazu benutzt, lange Kommandos abzuk<75>rzen um
die Tipparbeit zu vermindern, oder um sich das Merken von vielen Parametern zu die Tipparbeit zu vermindern, oder um sich das Merken von vielen Parametern zu
ersparen. Diese Aufgabe <20>berl<72><6C>t man unter Unix am besten den ersparen. Diese Aufgabe <20>berl<72><6C>t man unter Unix am besten den
Shell-Aliasen\index{Aliase} oder Shell-Funktionen. Shell-Aliasen\index{Aliase} oder Shell-Funktionen.\bigskip
Shell-Skripte k<>nnen viel mehr als Batchdateien. Shell-Skripte k<>nnen viel mehr als Batchdateien.\bigskip
Wie der Name schon sagt, sind Batchdateien im Wesentlichen nur ein `Stapel' von Wie der Name schon sagt, sind Batchdateien im Wesentlichen nur ein `Stapel' von
Anweisungen, die nacheinander ausgef<65>hrt werden. Es stehen zwar auch einige Anweisungen, die nacheinander ausgef<65>hrt werden. Es stehen zwar auch einige
@ -24,8 +23,8 @@ DOS keine M
erste Kommando vollst<73>ndig ausgef<65>hrt, seine Ausgabe in eine tempor<6F>re Datei erste Kommando vollst<73>ndig ausgef<65>hrt, seine Ausgabe in eine tempor<6F>re Datei
geschrieben und danach als Eingabe f<>r das zweite Kommando benutzt. Da<44> so ein geschrieben und danach als Eingabe f<>r das zweite Kommando benutzt. Da<44> so ein
Verhalten unter Umst<73>nden schnell zu einer vollen Festplatte f<>hren kann, sieht Verhalten unter Umst<73>nden schnell zu einer vollen Festplatte f<>hren kann, sieht
man bei dem Beispiel in Abschnitt \ref{cdrdao}, in dem eine CD kopiert werden man bei dem Beispiel, in dem eine CD kopiert werden soll (Kapitel \ref{cdrdao},
soll. Seite \pageref{cdrdao}).
Shell-Skripte kann man dagegen eher mit einer `richtigen' Programmiersprache Shell-Skripte kann man dagegen eher mit einer `richtigen' Programmiersprache
vergleichen. Es stehen alle Konstrukte zur Verf<72>gung, die eine vergleichen. Es stehen alle Konstrukte zur Verf<72>gung, die eine

View File

@ -1,18 +1,5 @@
% $Id$
\chapter{Wof<EFBFBD>r Shell-Programmierung?} \chapter{Wof<EFBFBD>r Shell-Programmierung?}
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.
Mit der Shell, bzw. dem Shell-Skript, wird aus dem Heinzelm<6C>nnchen ein starker
Riese.
Shell-Skripte werden im Wesentlichen aus zwei Gr<47>nden geschrieben: Erstens, Shell-Skripte werden im Wesentlichen aus zwei Gr<47>nden geschrieben: Erstens,
weil man so st<73>ndig wiederkehrende Kommandos zusammenfassen kann, die man dann weil man so st<73>ndig wiederkehrende Kommandos zusammenfassen kann, die man dann
mit einem einfachen Aufruf starten kann, und zweitens, weil man so einfache mit einem einfachen Aufruf starten kann, und zweitens, weil man so einfache
@ -29,19 +16,3 @@ Befehlen ausf
Beispiel eine Audio-CD kopieren soll, sollte das Brennprogramm nur dann Beispiel eine Audio-CD kopieren soll, sollte das Brennprogramm nur dann
aufrufen, wenn der Einlesevorgang erfolgreich abgeschlossen wurde. 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.