Umformatiert

This commit is contained in:
rschaten
2004-12-10 14:38:03 +00:00
parent 15af99f29e
commit 464f0bcf77
6 changed files with 417 additions and 333 deletions

View File

@ -13,34 +13,40 @@ 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{listing}[2]{1} \begin{lstlisting}
#!/bin/sh #!/bin/sh
until who | grep "^root " until who | grep "^root "
do sleep 30 do sleep 30
done done
echo Big Brother is watching you! echo Big Brother is watching you!
\end{listing} \end{lstlisting}
\normalsize
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. 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
\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 meldet, sobald sich ein Benutzer abgemeldet hat. Dazu ersetzen wir nur die \texttt{until}- Schleife durch eine entsprechende \texttt{while}-Schleife: 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:
\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{listing}[2]{1} \begin{lstlisting}
#!/bin/sh #!/bin/sh
while who | grep "^root " while who | grep "^root "
do 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{listing} \end{lstlisting}
\normalsize
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. 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.
@ -49,8 +55,7 @@ Die Schleife wird n
\texttt{cat datei.txt | while read i} \texttt{cat datei.txt | while read i}
\footnotesize \begin{lstlisting}
\begin{listing}[2]{1}
#!/bin/sh #!/bin/sh
count=0 count=0
cat /etc/passwd | while read i; do cat /etc/passwd | while read i; do
@ -61,8 +66,7 @@ cat /etc/passwd | while read i; do
fi fi
done done
echo Es sind $count Benutzer mit einer ID kleiner 100 eingetragen echo Es sind $count Benutzer mit einer ID kleiner 100 eingetragen
\end{listing} \end{lstlisting}
\normalsize
TODO!!! Daten aus Subshell hochreichen TODO!!! Daten aus Subshell hochreichen
@ -76,19 +80,16 @@ Das Skript mu
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. 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.
\begin{flushright}
Zun<EFBFBD>chst wird festgelegt, da<64> dieses Skript in der Bourne-Shell ausgef<65>hrt 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}
\footnotesize \begin{lstlisting}
\begin{listing}[2]{1}
#!/bin/sh #!/bin/sh
\end{listing}
\normalsize \end{lstlisting}
\begin{flushright}
Dann folgen Kommentare\index{Kommentar}, die den Sinn des Skriptes erl<72>utern (\ref{kommentare}). Dann folgen Kommentare\index{Kommentar}, die den Sinn des Skriptes erl<72>utern (\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
# #
@ -100,119 +101,109 @@ 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}
\normalsize \end{lstlisting}
\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{listingcont} \begin{lstlisting}[firstnumber=last]
# Source function library. # Source function library.
. /etc/rc.d/init.d/functions . /etc/rc.d/init.d/functions
\end{listingcont}
\normalsize \end{lstlisting}
\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{listingcont} \begin{lstlisting}[firstnumber=last]
# 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}
\normalsize \end{lstlisting}
\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}
\footnotesize \begin{lstlisting}[firstnumber=last]
\begin{listingcont}
daemon httpd daemon httpd
echo echo
\end{listingcont}
\normalsize \end{lstlisting}
\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{listingcont} \begin{lstlisting}[firstnumber=last]
touch /var/lock/subsys/httpd touch /var/lock/subsys/httpd
;; ;;
stop) stop)
echo -n "Shutting down http: " echo -n "Shutting down http: "
\end{listingcont}
\normalsize \end{lstlisting}
\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}
\footnotesize \begin{lstlisting}[firstnumber=last]
\begin{listingcont}
killproc httpd killproc httpd
echo echo
\end{listingcont}
\normalsize \end{lstlisting}
\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}
\footnotesize \begin{lstlisting}[firstnumber=last]
\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}
\normalsize \end{lstlisting}
\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}
\footnotesize \begin{lstlisting}[firstnumber=last]
\begin{listingcont}
status httpd status httpd
;; ;;
restart) restart)
\end{listingcont}
\normalsize \end{lstlisting}
\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{listingcont} \begin{lstlisting}[firstnumber=last]
$0 stop $0 stop
$0 start $0 start
;; ;;
reload) reload)
echo -n "Reloading httpd: " echo -n "Reloading httpd: "
\end{listingcont}
\normalsize \end{lstlisting}
\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{listingcont} \begin{lstlisting}[firstnumber=last]
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}
\normalsize \end{lstlisting}
\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{listingcont} \begin{lstlisting}[firstnumber=last]
exit 1 exit 1
esac esac
exit 0 exit 0
\end{listingcont}
\normalsize \end{lstlisting}
\section{Parameter<EFBFBD>bergabe in der Praxis}\label{beisp_parameter}\index{Parameter} \section{Parameter<EFBFBD>bergabe in der Praxis}\label{beisp_parameter}\index{Parameter}
@ -221,21 +212,19 @@ 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{listing}[2]{1} \begin{lstlisting}
#!/bin/sh #!/bin/sh
set -- `getopt "ab:" "$@"` || { set -- `getopt "ab:" "$@"` || {
\end{listing}
\normalsize \end{lstlisting}
\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{listingcont} \begin{lstlisting}[firstnumber=last]
echo "Anwendung: `basename $0` [-a] [-b Name] Dateien" 1>&2 echo "Anwendung: `basename $0` [-a] [-b Name] Dateien" 1>&2
exit 1 exit 1
} }
@ -243,41 +232,38 @@ echo "Momentan steht in der Kommandozeile folgendes: $*"
aflag=0 name=NONE aflag=0 name=NONE
while : while :
do do
\end{listingcont}
\normalsize \end{lstlisting}
\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{listingcont} \begin{lstlisting}[firstnumber=last]
case "$1" in case "$1" in
-a) aflag=1 ;; -a) aflag=1 ;;
-b) shift; name="$1" ;; -b) shift; name="$1" ;;
--) break ;; --) break ;;
\end{listingcont}
\normalsize \end{lstlisting}
\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{listingcont} \begin{lstlisting}[firstnumber=last]
esac esac
shift shift
done done
shift shift
\end{listingcont}
\normalsize \end{lstlisting}
\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{listingcont} \begin{lstlisting}[firstnumber=last]
echo "aflag=$aflag / Name = $name / Die Dateien sind $*" echo "aflag=$aflag / Name = $name / Die Dateien sind $*"
\end{listingcont}
\normalsize \end{lstlisting}
\section{Fallensteller: Auf Traps \section{Fallensteller: Auf Traps
@ -293,50 +279,45 @@ Wie l
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. 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.
\footnotesize
\index{!==\texttt{!=}} \index{!==\texttt{!=}}
\begin{listing}[2]{1} \begin{lstlisting}
#!/bin/sh #!/bin/sh
stat=1 stat=1
temp=/tmp/zeige$$ temp=/tmp/zeige$$
\end{listing}
\normalsize \end{lstlisting}
\begin{flushright}
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. 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.
\end{flushright}
\footnotesize
\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{listingcont} \begin{lstlisting}[firstnumber=last]
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}
\normalsize \end{lstlisting}
\begin{flushright}
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. 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.
\end{flushright}
\footnotesize
\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{listingcont} \begin{lstlisting}[firstnumber=last]
case $# in case $# in
1) zcat "$1" > $temp 1) zcat "$1" > $temp
pg $temp pg $temp
stat=0 stat=0
;; ;;
\end{listingcont}
\normalsize \end{lstlisting}
\begin{flushright}
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. 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.
\end{flushright}
\footnotesize
\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{listingcont} \begin{lstlisting}[firstnumber=last]
*) echo "Anwendung: `basename $0` Dateiname" 1>&2 *) echo "Anwendung: `basename $0` Dateiname" 1>&2
esac esac
\end{listingcont}
\normalsize \end{lstlisting}
\begin{flushright}
Wenn \texttt{case} eine andere Parameterzahl feststellt, wird eine Meldung mit der Aufrufsyntax auf die Standard-Fehlerausgabe geschrieben. Wenn \texttt{case} eine andere Parameterzahl feststellt, wird eine Meldung mit der Aufrufsyntax auf die Standard-Fehlerausgabe geschrieben.
\end{flushright}
\index{trap=\texttt{trap}|)}\index{Signal|)} \index{trap=\texttt{trap}|)}\index{Signal|)}
@ -358,27 +339,25 @@ Zwecke noch etwas `bereinigt' werden.
Wie das aussieht, wenn es fertig ist, sieht man im folgenden Skript: Wie das aussieht, wenn es fertig ist, sieht man im folgenden Skript:
\footnotesize
\index{!==\texttt{!=}} \index{!==\texttt{!=}}
\begin{listing}[2]{1} \begin{lstlisting}
#!/bin/sh #!/bin/sh
for i in `find $1 -type f -name "*.[mM][pP]3"`; do for i in `find $1 -type f -name "*.[mM][pP]3"`; do
\end{listing}
\normalsize \end{lstlisting}
\begin{flushright}
Hier beginnt eine Schleife, die <20>ber alle Ausgaben des \texttt{find}-Kommandos Hier beginnt eine Schleife, die <20>ber alle Ausgaben des \texttt{find}-Kommandos
iteriert. Dabei sucht \texttt{find} nach allen normalen Dateien (\texttt{-type 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 f}), die die Extension .mp3 tragen (\texttt{-name \dq*.[mM][pP]3\dq} -- wir
ignorieren Gro<72>- / Kleinschreibung). ignorieren Gro<72>- / Kleinschreibung).
\end{flushright}
\footnotesize
\index{find=\texttt{find}} \index{find=\texttt{find}}
\begin{listingcont} \begin{lstlisting}[firstnumber=last]
echo `tr -dc "[:alpha:]" < /dev/urandom | \ echo `tr -dc "[:alpha:]" < /dev/urandom | \
dd count=8 bs=1 2> /dev/null`$i dd count=8 bs=1 2> /dev/null`$i
\end{listingcont}
\normalsize \end{lstlisting}
\begin{flushright}
Hier ist der `magische Teil'. Mit dem \texttt{echo} wird die Ausgabe einer Pipe 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 ausgegeben, gefolgt von dem aktuellen Dateinamen. Diese Pipe enth<74>lt ein
\texttt{tr}, der alle ungewollten Zeichen (alles, was kein Textzeichen ist) aus \texttt{tr}, der alle ungewollten Zeichen (alles, was kein Textzeichen ist) aus
@ -391,14 +370,13 @@ Kommando \texttt{dd} mit den angegebenen Parametern. Damit die Erfolgsmeldung
von \texttt{dd} nicht die Ausgabe verunstaltet, lenken wir sie nach von \texttt{dd} nicht die Ausgabe verunstaltet, lenken wir sie nach
\texttt{/dev/null} um. \texttt{/dev/null} um.
\index{tr=\texttt{tr}}\index{dd=\texttt{dd}} \index{tr=\texttt{tr}}\index{dd=\texttt{dd}}
\end{flushright}
\footnotesize
\index{find=\texttt{find}} \index{find=\texttt{find}}
\begin{listingcont} \begin{lstlisting}[firstnumber=last]
done | sort | cut -b 9- | while read i; do done | sort | cut -b 9- | while read i; do
\end{listingcont}
\normalsize \end{lstlisting}
\begin{flushright}
Das Ergebnis der obigen Schleife ist also die Liste der Dateinamen, denen Das Ergebnis der obigen Schleife ist also die Liste der Dateinamen, denen
jeweils acht zuf<75>llige Zeichen vorangestellt wurden. Die Reihenfolge entspricht jeweils acht zuf<75>llige Zeichen vorangestellt wurden. Die Reihenfolge entspricht
allerdings immer noch der Ausgabe von \texttt{find}, wird also nach jedem allerdings immer noch der Ausgabe von \texttt{find}, wird also nach jedem
@ -414,15 +392,15 @@ Diese lesen wir jetzt zeilenweise mittels \texttt{read} ein. In der
\texttt{while}-Schleife k<>nnen wir alle erforderlichen Sachen mit dem \texttt{while}-Schleife k<>nnen wir alle erforderlichen Sachen mit dem
Dateinamen anstellen. Hier wird er nur mittels \texttt{echo} ausgegeben. 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{sort=\texttt{sort}}\index{cut=\texttt{cut}} \index{read=\texttt{read}}\index{while=\texttt{while}}
\end{flushright}
\footnotesize
\index{find=\texttt{find}} \index{find=\texttt{find}}
\begin{listingcont} \begin{lstlisting}[firstnumber=last]
echo "Jetzt wird $i gespielt" echo "Jetzt wird $i gespielt"
mpg123 "$i" mpg123 "$i"
done done
\end{listingcont}
\normalsize \end{lstlisting}
\index{Zufallszahlen|)} \index{Zufallszahlen|)}
@ -437,8 +415,7 @@ das Problem, da
Proze<EFBFBD> l<>uft oder nicht. Im Normalfall wird er zuerst folgendes ausprobieren, Proze<EFBFBD> l<>uft oder nicht. Im Normalfall wird er zuerst folgendes ausprobieren,
was aber oft (nicht immer) in die Hose gehen wird: was aber oft (nicht immer) in die Hose gehen wird:
\texttt{ps aux | grep }\textit{prozessname}\texttt{ \&\& echo \dq}\textit{l<EFBFBD>uft \lstinline/ps aux | grep prozessname && echo "l<>uft schon"/
schon}\texttt{\dq}
Der Grund daf<61>r ist, da<64> unter Umst<73>nden in der Ausgabe von \texttt{ps} auch 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 das \texttt{grep}-Kommando samt Parameter (\textit{prozessname}) aufgelistet
@ -447,8 +424,7 @@ wird. So findet das \texttt{grep}-Kom\-man\-do sich quasi selbst.
Abhilfe schafft entweder \texttt{pgrep} (\ref{pgrep}) oder das folgende Abhilfe schafft entweder \texttt{pgrep} (\ref{pgrep}) oder das folgende
Konstrukt: Konstrukt:
\texttt{ps aux | grep \dq}\textit{[p]rozessname}\texttt{\dq~\&\& echo \lstinline/ps aux | grep "[p]rozessname" && echo "l<>uft schon"/
\dq}\textit{l<EFBFBD>uft schon}\texttt{\dq}
Das p ist jetzt als eine Zeichenmenge (regul<EFBFBD>rer Ausdruck) angegeben worden. 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 Jetzt sucht \texttt{grep} also nach dem String \textit{prozessname}, in der
@ -466,7 +442,7 @@ folgendes Szenario: Es gibt ein Verzeichnis mit vielen Unterverzeichnissen,
denen eine Zeile mit dem Inhalt `strict' vorkommt. Man k<>nnte jetzt denen eine Zeile mit dem Inhalt `strict' vorkommt. Man k<>nnte jetzt
folgendes versuchen: folgendes versuchen:
\texttt{grep -r strict *} \lstinline|grep -r strict *|
Das f<>hrt allerdings dazu, da<64> alle Dateien durchsucht werden, nicht nur die 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 Perl-Skripte. Diese tragen nach unserer Konvention\footnote{Perl-Skripte m<>ssen
@ -474,14 +450,14 @@ keine spezielle Extension haben, es sei aber um des Beispiels Willen mal
angenommen.} die Extension `.pl'. Wir starten also eine rekursive Suche <20>ber angenommen.} die Extension `.pl'. Wir starten also eine rekursive Suche <20>ber
alle Dateien, die dem Muster entsprechen: alle Dateien, die dem Muster entsprechen:
\texttt{grep -r strict *.pl} \lstinline|grep -r strict *.pl|
Das f<>hrt wieder nicht zu dem gew<65>nschten Ergebnis. Da die Unterverzeichnisse Das f<>hrt wieder nicht zu dem gew<65>nschten Ergebnis. Da die Unterverzeichnisse
nicht die Extension `*.pl' tragen, werden sie nicht ber<65>cksichtigt. F<>r die nicht die Extension `*.pl' tragen, werden sie nicht ber<65>cksichtigt. F<>r die
Suche in Unterverzeichnissen ziehen wir \texttt{find} (Siehe Abschnitt Suche in Unterverzeichnissen ziehen wir \texttt{find} (Siehe Abschnitt
\ref{find}) heran: \ref{find}) heran:
\texttt{find . -name \textbackslash*.pl -exec grep \{\} \textbackslash;} \lstinline|find . -name \*.pl -exec grep strict {} \;|
Dieser Befehl gibt uns zwar die gefundenen Zeilen aus, nicht aber die Namen der 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 Dateien. Es sieht f<>r \texttt{grep} so aus als ob nur eine Datei durchsucht
@ -490,7 +466,7 @@ Parameter \texttt{-l}, allerdings w
angezeigt. Eine Ausgabe mit beiden Informationen erhalten wir mit dem folgenden angezeigt. Eine Ausgabe mit beiden Informationen erhalten wir mit dem folgenden
Konstrukt: Konstrukt:
\texttt{find . -name \textbackslash*.pl -exec grep strict /dev/null \{\} \textbackslash;} \lstinline|find . -name \*.pl -exec grep strict /dev/null {} \;|
Hier durchsucht \texttt{grep} nicht nur die gefundenen Dateien, sondern bei Hier durchsucht \texttt{grep} nicht nur die gefundenen Dateien, sondern bei
jedem Aufruf auch \texttt{/dev/null}, also den digitalen M<>lleimer der per jedem Aufruf auch \texttt{/dev/null}, also den digitalen M<>lleimer der per

View File

@ -57,8 +57,7 @@ z
Folgendes Skript funktioniert nicht: Folgendes Skript funktioniert nicht:
\footnotesize \begin{lstlisting}
\begin{listing}[2]{1}
#!/bin/sh #!/bin/sh
count=0 count=0
cat /etc/passwd | while read i; do cat /etc/passwd | while read i; do
@ -69,8 +68,7 @@ cat /etc/passwd | while read i; do
fi fi
done done
echo Es sind $count Benutzer mit einer ID kleiner 100 eingetragen echo Es sind $count Benutzer mit einer ID kleiner 100 eingetragen
\end{listing} \end{lstlisting}
\normalsize
Was ist passiert? Was ist passiert?
@ -91,8 +89,7 @@ praktisch nur lokal zur Verf
Neben der Methode in \ref{daten_hochreichen} bietet sich hier eine viel Neben der Methode in \ref{daten_hochreichen} bietet sich hier eine viel
einfachere L<>sung an: einfachere L<>sung an:
\footnotesize \begin{lstlisting}
\begin{listing}[2]{1}
#!/bin/sh #!/bin/sh
count=0 count=0
while read i; do while read i; do
@ -103,8 +100,7 @@ while read i; do
fi fi
done < /etc/passwd done < /etc/passwd
echo Es sind $count Benutzer mit einer ID kleiner 100 eingetragen echo Es sind $count Benutzer mit einer ID kleiner 100 eingetragen
\end{listing} \end{lstlisting}
\normalsize
Hier befindet sich die Schleife nicht in einer Pipe, daher wird sie auch nicht 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 in einer Subshell ausgef<65>hrt. Man kann auf das \texttt{cat}-Kommando verzichten
@ -124,7 +120,7 @@ enthalten.
Der erste Versuch an der Stelle wird etwas in der Form Der erste Versuch an der Stelle wird etwas in der Form
\texttt{grep }\textit{wichtig datei.txt}\texttt{ > }\textit{datei.txt} \lstinline|grep wichtig datei.txt > datei.txt|
sein. Das kann funktionieren, es kann aber auch in die sprichw<68>rtliche Hose 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 gehen. Das Problem an der Stelle ist, da<64> die Datei an der Stelle gleichzeitig
@ -136,15 +132,13 @@ 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 gerade angelegten Deskriptor gelesen werden, w<>hrend eine neue Datei unter
dem alten Namen angelegt wird: dem alten Namen angelegt wird:
\footnotesize \begin{lstlisting}
\begin{listing}[2]{1}
#!/bin/sh #!/bin/sh
FILE=datei.txt FILE=datei.txt
exec 3< "$FILE" exec 3< "$FILE"
rm "$FILE" rm "$FILE"
grep "wichtig" <&3 > "$FILE" grep "wichtig" <&3 > "$FILE"
\end{listing} \end{lstlisting}
\normalsize
Allerdings sollte man bei dieser Methode beachten, da<64> man im Falle eines 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. Fehlers die Quelldaten verliert, da die Datei ja bereits gel<65>scht wurde.

View File

@ -45,6 +45,17 @@
\usepackage{fancybox} % K<>stchen f<>r Tastendarstellung \usepackage{fancybox} % K<>stchen f<>r Tastendarstellung
\usepackage{moreverb} % F<>r Listings \usepackage{moreverb} % F<>r Listings
\usepackage{listings} % F<>r Listings
\lstset{
extendedchars=true,
backgroundcolor=\color[gray]{0.95},
basicstyle=\ttfamily\scriptsize,
numbers=left,
numberstyle=\tiny,
stepnumber=2,
numbersep=5pt
}
% F<>r PDF % F<>r PDF
\usepackage[ \usepackage[

View File

@ -10,10 +10,10 @@
\texttt{-c} & Anzahl der Vorkommnisse vor die Zeilen schreiben \tabularnewline\STRUT \texttt{-c} & Anzahl der Vorkommnisse vor die Zeilen schreiben \tabularnewline\STRUT
\texttt{-d} & Nur doppelte Zeilen ausgeben, jede nur einmal \tabularnewline\STRUT \texttt{-d} & Nur doppelte Zeilen ausgeben, jede nur einmal \tabularnewline\STRUT
\texttt{-D} & Alle doppelten Zeilen ausgeben \tabularnewline\STRUT \texttt{-D} & GNU-Erweiterung: Alle doppelten Zeilen ausgeben \tabularnewline\STRUT
\texttt{-f }\textsl{n} & Die ersten \textsl{n} Felder ignorieren \tabularnewline\STRUT \texttt{-f }\textsl{n} & Die ersten \textsl{n} Felder ignorieren \tabularnewline\STRUT
\texttt{-i} & Gro<72>- / Kleinschreibung ignorieren \tabularnewline\STRUT \texttt{-i} & GNU-Erweiterung: Gro<72>- / Kleinschreibung ignorieren \tabularnewline\STRUT
\texttt{-s }\textsl{n} & Die ersten \textsl{n} Zeichen 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{-u} & Nur einfach vorkommende Zeilen ausgeben \tabularnewline\STRUT
\texttt{-w }\textsl{n} & Nur die ersten \textsl{n} Zeichen betrachten \texttt{-w }\textsl{n} & GNU-Erweiterung: Nur die ersten \textsl{n} Zeichen betrachten
\end{longtable} \end{longtable}

View File

@ -1,5 +1,6 @@
% $Id$ % $Id$
\chapter{Werkzeugkasten}\label{werkzeugkasten} \chapter{Werkzeugkasten}\label{werkzeugkasten}
Durch die gezeigten Steuerungsm<73>glichkeiten stehen dem Shell-Pro\-grammie\-rer Durch die gezeigten Steuerungsm<73>glichkeiten stehen dem Shell-Pro\-grammie\-rer
M<EFBFBD>g\-lich\-kei\-ten offen, fast alle g<>ngigen Algorithmen zu implementieren. Es M<EFBFBD>g\-lich\-kei\-ten offen, fast alle g<>ngigen Algorithmen zu implementieren. Es
ist tats<74>chlich in der Shell m<>glich, Sortier- oder Suchfunktionen zu ist tats<74>chlich in der Shell m<>glich, Sortier- oder Suchfunktionen zu
@ -43,6 +44,14 @@ typische Aufgaben beschrieben. Diese enthalten `Links' zu den in Frage
kommenden Werkzeugen. Danach gibt es eine alphabetische Aufz<66>hlung der kommenden Werkzeugen. Danach gibt es eine alphabetische Aufz<66>hlung der
wichtigsten Kommandos. wichtigsten Kommandos.
Das GNU-Projekt\marginpar{GNU!} hat vielen Kommandos n<>tzliche Parameter
zugef<EFBFBD>gt, einige der hier beschriebenen Tools stehen ausschlie<69>lich auf
GNU-Systemen zur Verf<72>gung. Da diese Optionen nicht auf allen Unix-Systemen zur
Verf<EFBFBD>gung stehen, werden die betroffenen Stellen wie dieser Absatz am Rand mit
`GNU!' markiert. Wenn diese Kommandos und Optionen benutzt werden mu<6D> also das
Zielsystem ber<65>cksichtigt werden, im Zweifelsfall sollten die Skripte
ausf<EFBFBD>hrlich getestet werden.
\section{N<EFBFBD>gel...}\label{naegel} \section{N<EFBFBD>gel...}\label{naegel}
\subsection{Ein- und Ausgabe}\label{ein_und_ausgabe} \subsection{Ein- und Ausgabe}\label{ein_und_ausgabe}
@ -66,6 +75,7 @@ Dateien auf der Festplatte.
\item \texttt{echo} (\ref{echo}): Daten ausgeben \item \texttt{echo} (\ref{echo}): Daten ausgeben
\item \texttt{grep} (\ref{grep}): In Dateien suchen \item \texttt{grep} (\ref{grep}): In Dateien suchen
\item \texttt{head} (\ref{head}): Dateianfang ausgeben \item \texttt{head} (\ref{head}): Dateianfang ausgeben
\item \texttt{logger} (\ref{logger}): Text ins System-Log schreiben
\item \texttt{printf} (\ref{printf}): Formatierte Datenausgabe \item \texttt{printf} (\ref{printf}): Formatierte Datenausgabe
\item \texttt{read} (\ref{read}): Zeilen einlesen \item \texttt{read} (\ref{read}): Zeilen einlesen
\item \texttt{tail} (\ref{tail}): Dateiende ausgeben \item \texttt{tail} (\ref{tail}): Dateiende ausgeben
@ -215,8 +225,7 @@ Eine weitere Gemeinsamkeit ist die Art der Ein- und Ausgabe. Wenn eine
Eingabedatei angegeben wird, wird diese verarbeitet. Ansonsten wird die Eingabedatei angegeben wird, wird diese verarbeitet. Ansonsten wird die
Standard-Eingabe gelesen. Ausgaben erfolgen immer auf der Standard-Ausgabe. Standard-Eingabe gelesen. Ausgaben erfolgen immer auf der Standard-Ausgabe.
\footnotesize \begin{lstlisting}
\begin{listing}[2]{1}
# Aufruf als Filter: # Aufruf als Filter:
kommando1 | awk '{ print $1; print $2 }' | kommando2 kommando1 | awk '{ print $1; print $2 }' | kommando2
@ -233,15 +242,14 @@ awk '
# Alternativ k<>nnen die Kommandos auch in eine eigene Datei gespeichert und # Alternativ k<>nnen die Kommandos auch in eine eigene Datei gespeichert und
# <20>ber den Parameter -f eingebunden werden: # <20>ber den Parameter -f eingebunden werden:
awk -f script.awk datei.txt awk -f script.awk datei.txt
\end{listing} \end{lstlisting}
\normalsize
Neben dem Parameter \texttt{-f} zum Einlesen der Programmdatei gibt es noch den Neben dem Parameter \texttt{-f} zum Einlesen der Programmdatei gibt es noch den
Parameter \texttt{-F} mit dem der Feld-Trenner angegeben werden kann. Die Parameter \texttt{-F} mit dem der Feld-Trenner angegeben werden kann. Die
folgende Zeile gibt beispielsweise alle Benutzernamen und deren User-IDs aus folgende Zeile gibt beispielsweise alle Benutzernamen und deren User-IDs aus
der Doppelpunktseparierten Datei \texttt{/etc/passwd} aus: der Doppelpunktseparierten Datei \texttt{/etc/passwd} aus:
\texttt{awk -F: '\{ print \$1\dq hat ID \dq\$3 \}' /etc/passwd} \lstinline|awk -F: '{ print $1" hat ID "$3 }' /etc/passwd|
\subsubsection{Muster und Prozeduren} \subsubsection{Muster und Prozeduren}
@ -291,8 +299,7 @@ mit den TeX-Dateien weiter unten.
Hier ein paar Einfache Beispiele f<>r Blocks aus Mustern und Prozeduren: Hier ein paar Einfache Beispiele f<>r Blocks aus Mustern und Prozeduren:
\footnotesize \begin{lstlisting}
\begin{listing}[2]{1}
# Das erste Feld jeder Zeile ausgeben: # Das erste Feld jeder Zeile ausgeben:
{ print $1 } { print $1 }
@ -335,8 +342,7 @@ END { summe /= 1024; print "Die Gr
# ausgeben, verarbeitet die Ausgabe von 'df': # ausgeben, verarbeitet die Ausgabe von 'df':
BEGIN { OFS="|" } BEGIN { OFS="|" }
/^\/dev\// { print $1,$5 } /^\/dev\// { print $1,$5 }
\end{listing} \end{lstlisting}
\normalsize
\index{awk=\texttt{awk}|)} \index{awk=\texttt{awk}|)}
@ -377,17 +383,17 @@ an vielen, teilweise sehr unterschiedlich gelagerten Aufgaben wertvolle
Dienste. Dienste.
Durch Umlenklung der Ausgabe k<>nnen Dateien erzeugt und erweitert werden. So Durch Umlenklung der Ausgabe k<>nnen Dateien erzeugt und erweitert werden. So
k<EFBFBD>nnen mehrere Dateien per \texttt{cat datei1.txt datei2.txt > datei.txt} k<EFBFBD>nnen mehrere Dateien per \lstinline|cat datei1.txt datei2.txt > datei.txt|
verkettet werden. verkettet werden.
Au<EFBFBD>erdem kann man mit einem Aufruf in der Art \texttt{cat datei.txt | kommando} Au<EFBFBD>erdem kann man mit einem Aufruf in der Art
Daten an ein Programm <20>bergeben, das nur von der Standardeingabe lesen kann \lstinline|cat datei.txt | kommando| Daten an ein Programm <20>bergeben, das nur
(Filter). von der Standardeingabe lesen kann (Filter).
\texttt{cat} verf<72>gt <20>ber eine Reihe von Parametern, um die Ausgabe zu GNU-\texttt{cat}\marginpar{GNU!} verf<72>gt <20>ber eine Reihe von Parametern, um die
formatieren, so k<>nnen mit \texttt{-n} bzw. \texttt{-b} die Zeilen numeriert Ausgabe zu formatieren, so k<>nnen mit \texttt{-n} bzw. \texttt{-b} die Zeilen
werden, oder mit \texttt{-s} mehrere Zeilen zu einer einzigen zusammengefa<66>t numeriert werden, oder mit \texttt{-s} mehrere Zeilen zu einer einzigen
werden. zusammengefa<EFBFBD>t werden.
\index{cat=\texttt{cat}|)} \index{cat=\texttt{cat}|)}
@ -458,8 +464,9 @@ Zur Verdeutlichung ein paar Beispiele, wo es m
\LTXtable{\textwidth}{tab_kommandos_chmod_beispiele.tex} \LTXtable{\textwidth}{tab_kommandos_chmod_beispiele.tex}
Am wichtigsten sind also die Aufrufe \texttt{chmod 644 datei} und \texttt{chmod Am wichtigsten sind also die Aufrufe \lstinline|chmod 644 datei| und
755 datei}, je nachdem ob die Datei ausf<73>hrbar sein soll oder nicht. \lstinline|chmod 755 datei|, je nachdem ob die Datei ausf<73>hrbar sein soll oder
nicht.
\index{chmod=\texttt{chmod}|)} \index{chmod=\texttt{chmod}|)}
@ -482,9 +489,9 @@ Will man lediglich die Gruppen-ID
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{chpasswd}\index{chpasswd=\texttt{chpasswd}|(textbf} \subsection{chpasswd}\index{chpasswd=\texttt{chpasswd}|(textbf}\marginpar{GNU!}
Mit diesem Kommando bietet sich dem Administrator des Systems die Mit diesem GNU-Kommando bietet sich dem Administrator des Systems die
M<EFBFBD>g\-lich\-keit, scriptgesteuert die Pa<50>w<EFBFBD>rter f<>r neue Benutzer zu vergeben. M<EFBFBD>g\-lich\-keit, scriptgesteuert die Pa<50>w<EFBFBD>rter f<>r neue Benutzer zu vergeben.
Manuell <20>ndert man ein Pa<50>wort mit dem Kommando Manuell <20>ndert man ein Pa<50>wort mit dem Kommando
\texttt{passwd}\index{passwd=\texttt{passwd}}, allerdings l<>scht (flusht) \texttt{passwd}\index{passwd=\texttt{passwd}}, allerdings l<>scht (flusht)
@ -511,7 +518,23 @@ diese Datei nicht allgemein lesbar ist.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{cmp}\label{cmp}\index{cmp=\texttt{cmp}|(textbf} \subsection{cmp}\label{cmp}\index{cmp=\texttt{cmp}|(textbf}
TODO!!! cmp GNU? Mit \texttt{cmp} werden zwei Dateien verglichen. Wenn die beiden Dateien
identisch sind gibt es keine Ausgabe, ansonsten wird die Position des ersten
Unterschiedes ausgegeben.
Einer der beiden anzugebenden Dateinamen kann auch durch \texttt{-} ersetzt
werden, dann wird die Standard-Eingabe mit der anderen angegebenen Datei
verglichen.
Mit dem Parameter \texttt{-l} werden alle abweichenden Bytes aufgelistet,
jeweils mit der Position (dezimal) und den beiden Bytes (oktal).
Durch \texttt{-s} l<><6C>t sich die Ausgabe von Unterschieden unterdr<64>cken, der
Exit-Status gibt weiterhin das Ergebnis an.
In der GNU-Version\marginpar{GNU!} gibt es auch Parameter, mit denen Bereiche
der Datei vom Vergleich ausgeschlossen werden k<>nnen (\texttt{-i}), oder mit
denen nur die ersten n Bytes der Dateien verglichen werden (\texttt{-n}).
\index{cmp=\texttt{cmp}|)} \index{cmp=\texttt{cmp}|)}
@ -552,7 +575,15 @@ Dateien in Spalten zusammengef
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{diff}\label{diff}\index{diff=\texttt{diff}|(textbf} \subsection{diff}\label{diff}\index{diff=\texttt{diff}|(textbf}
TODO!!! diff Mit \texttt{diff} werden zwei Dateien verglichen, und die <20>nderungen auf der
Standardausgabe aufgelistet, die n<>tig sind um die erste an die zweite Datei
anzupassen.
Mit dem Parameter \texttt{-r} k<>nnen auch ganze Verzeichnisse rekursiv
verglichen werden.
Die ausgegebenen Listen k<>nnen mit dem \texttt{patch}-Kommando auf Dateien
angewandt werden um sie auf den ge<67>nderten Stand zu bringen.
\index{diff=\texttt{diff}|)} \index{diff=\texttt{diff}|)}
@ -602,7 +633,7 @@ Variablen zu bilden.
Eine wichtige Anwendung f<>r dieses Kommando ist der Fall, wenn eigentlich ein Eine wichtige Anwendung f<>r dieses Kommando ist der Fall, wenn eigentlich ein
Array\index{Array} gebraucht w<>rde. Der Inhalt eines Array-Elements kann Array\index{Array} gebraucht w<>rde. Der Inhalt eines Array-Elements kann
beispielsweise mittels \texttt{eval echo \textbackslash\$arr\$index} ausgegeben beispielsweise mittels \lstinline|eval echo \$arr$index| ausgegeben
werden, dabei ist \texttt{arr} der Name des Arrays und \texttt{index} der Name werden, dabei ist \texttt{arr} der Name des Arrays und \texttt{index} der Name
der Variablen, die den Index des auszugebenden Elementes enth<74>lt. der Variablen, die den Index des auszugebenden Elementes enth<74>lt.
@ -625,7 +656,7 @@ wichtigsten Operatoren lauten wie folgt:
Bei einigen Sonderzeichen ist deren Bedeutung in der Shell zu ber<65>cksichtigen, Bei einigen Sonderzeichen ist deren Bedeutung in der Shell zu ber<65>cksichtigen,
sie sind also durch Anf<6E>hrungszeichen oder Backslashes zu quoten: sie sind also durch Anf<6E>hrungszeichen oder Backslashes zu quoten:
\texttt{i=`expr \$i \textbackslash{}* 3`}. \lstinline|i=`expr $i \* 3`|.
Eine andere M<>glichkeit f<>r einfache Rechnungen besteht in der sogenannten Eine andere M<>glichkeit f<>r einfache Rechnungen besteht in der sogenannten
Arith\-me\-tik-Ex\-pan\-sion (Siehe \ref{arithmetikexpansion}). Arith\-me\-tik-Ex\-pan\-sion (Siehe \ref{arithmetikexpansion}).
@ -666,8 +697,7 @@ Vorkommen gr
Da die reine Beschreibung der Parameter manchmal etwas verwirrend ist, folgen Da die reine Beschreibung der Parameter manchmal etwas verwirrend ist, folgen
hier ein paar praktische Beispiele: hier ein paar praktische Beispiele:
\footnotesize \begin{lstlisting}
\begin{listing}[2]{1}
# Suche alle Eintr<74>ge in bzw. unter dem aktuellen Verzeichnis: # Suche alle Eintr<74>ge in bzw. unter dem aktuellen Verzeichnis:
find . find .
# Suche alle normalen Dateien mit der Endung txt unter /home: # Suche alle normalen Dateien mit der Endung txt unter /home:
@ -680,8 +710,7 @@ find ~ -size +10000000c -exec ls -l {} \;
# Suche alle Eintr<74>ge im Homeverzeichnis, die innerhalb der letzten zwei Tage # Suche alle Eintr<74>ge im Homeverzeichnis, die innerhalb der letzten zwei Tage
# ge<67>ndert wurden: # ge<67>ndert wurden:
find ~ -mtime -2 find ~ -mtime -2
\end{listing} \end{lstlisting}
\normalsize
Wenn mittels \texttt{-exec} weitere Kommandos gestartet werden, sollte beachtet Wenn mittels \texttt{-exec} weitere Kommandos gestartet werden, sollte beachtet
werden da<64> mindestens ein Proze<7A> pro Fundstelle gestartet wird. Das kostet sehr werden da<64> mindestens ein Proze<7A> pro Fundstelle gestartet wird. Das kostet sehr
@ -755,8 +784,7 @@ Daneben stehen noch eine Reihe weiterer Signale zur Verf
Es gibt verschiedene Wege, das Signal abzusetzen. Welchen man w<>hlt ist Es gibt verschiedene Wege, das Signal abzusetzen. Welchen man w<>hlt ist
Geschmackssache. Hier ein paar Beispiele: Geschmackssache. Hier ein paar Beispiele:
\footnotesize \begin{lstlisting}
\begin{listing}[2]{1}
# Die folgenden Befehle sind gleichwertig. Alle senden ein HUP an Proze<7A>-ID 42: # Die folgenden Befehle sind gleichwertig. Alle senden ein HUP an Proze<7A>-ID 42:
kill -1 42 kill -1 42
kill -HUP 42 kill -HUP 42
@ -770,8 +798,7 @@ kill -9 -1
# SIGTERM an mehrere Prozesse senden: # SIGTERM an mehrere Prozesse senden:
kill 123 456 789 kill 123 456 789
\end{listing} \end{lstlisting}
\normalsize
Siehe auch: Das Beispiel `Fallensteller' in Abschnitt \ref{traps} zeigt, wie Siehe auch: Das Beispiel `Fallensteller' in Abschnitt \ref{traps} zeigt, wie
ein Skript auf Signale reagieren kann. ein Skript auf Signale reagieren kann.
@ -780,12 +807,12 @@ ein Skript auf Signale reagieren kann.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{killall}\label{killall}\index{killall=\texttt{killall}|(textbf} \subsection{killall}\label{killall}\index{killall=\texttt{killall}|(textbf}\marginpar{GNU!}
Im Abschnitt <20>ber \texttt{kill} (\ref{kill}) wird beschrieben, wie man ein Im Abschnitt <20>ber \texttt{kill} (\ref{kill}) wird beschrieben, wie man ein
Signal an einen Proze<7A> schickt, dessen ID bekannt ist. Kennt man die ID nicht, Signal an einen Proze<7A> schickt, dessen ID bekannt ist. Kennt man die ID nicht,
oder will man das Signal an mehrere Prozesse schicken, kann dieses Kommando oder will man das Signal an mehrere Prozesse schicken, kann dieses Kommando auf
eine gro<72>e Hilfe darstellen. GNU-Systemen eine gro<72>e Hilfe darstellen.
Mit dem Parameter \texttt{-i} wird vor jedem Signal interaktiv gefragt, ob es Mit dem Parameter \texttt{-i} wird vor jedem Signal interaktiv gefragt, ob es
geschickt werden soll. Mit \texttt{-v} wird angegeben, ob die Signale geschickt werden soll. Mit \texttt{-v} wird angegeben, ob die Signale
@ -803,6 +830,22 @@ zur Verf
\index{killall=\texttt{killall}|)} \index{killall=\texttt{killall}|)}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{logger}\label{logger}\index{logger=\texttt{logger}|(textbf}
Mit \texttt{logger} werden Nachrichten an die Log-Mechanismen des Systems
geschickt. So k<>nnen auch unbeobachtet laufende Skripte <20>ber ihr tun
informieren.
Der zu loggende Text wird einfach als Parameter <20>bergeben.
Die GNU-Version\marginpar{GNU!} verf<72>gt <20>ber einige Parameter, unter anderem
kann die Nachricht mit \texttt{-s} parallel zum System-Log auch auf der
Standard-Fehlerausgabe ausgegeben werden.
\index{logger=\texttt{logger}|)}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{ls}\label{ls}\index{ls=\texttt{ls}|(textbf} \subsection{ls}\label{ls}\index{ls=\texttt{ls}|(textbf}
@ -812,7 +855,7 @@ oder angegebenen Verzeichnis auf, das Kommando hat aber auch sehr viele
Parameter mit denen sich die Ausgabe anpassen l<><6C>t. Hier sind die wichtigsten, Parameter mit denen sich die Ausgabe anpassen l<><6C>t. Hier sind die wichtigsten,
eine vollst<73>ndige Auflistung bietet wie immer die Man-Page: eine vollst<73>ndige Auflistung bietet wie immer die Man-Page:
\LTXtable{\textwidth}{tab_kommandos_ls_parameter.tex} \marginpar{GNU!}\LTXtable{\textwidth}{tab_kommandos_ls_parameter.tex}
Besonders informativ gibt sich der Parameter \texttt{-l}, da damit auch die Besonders informativ gibt sich der Parameter \texttt{-l}, da damit auch die
Eigent<EFBFBD>mer und die Berechtigungen der Dateien angezeigt werden. Die Ausgabe hat Eigent<EFBFBD>mer und die Berechtigungen der Dateien angezeigt werden. Die Ausgabe hat
@ -893,7 +936,7 @@ gedreht.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{pgrep}\label{pgrep}\index{pgrep=\texttt{pgrep}|(textbf} \subsection{pgrep}\label{pgrep}\index{pgrep=\texttt{pgrep}|(textbf}\marginpar{GNU!}
Eine h<>ufig wiederkehrende Aufgabe ist es, zu sehen ob ein bestimmter Proze<7A> Eine h<>ufig wiederkehrende Aufgabe ist es, zu sehen ob ein bestimmter Proze<7A>
existiert oder nicht. Falls das Kommando \texttt{pgrep} zur Verf<72>gung steht, existiert oder nicht. Falls das Kommando \texttt{pgrep} zur Verf<72>gung steht,
@ -901,7 +944,7 @@ kannn man auf das Konstrukt mit \texttt{ps} und \texttt{grep} verzichten. Der
folgende Aufruf liefert alle Proze<7A>-IDs, deren Name httpd enth<74>lt, inclusive folgende Aufruf liefert alle Proze<7A>-IDs, deren Name httpd enth<74>lt, inclusive
des vollen Kommandos: des vollen Kommandos:
\texttt{pgrep -lf httpd} \lstinline|pgrep -lf httpd|
<EFBFBD>ber weitere Parameter l<><6C>t sich genauer spezifizieren, wonach gesucht werden <EFBFBD>ber weitere Parameter l<><6C>t sich genauer spezifizieren, wonach gesucht werden
soll, hier die wichtigsten: soll, hier die wichtigsten:
@ -912,7 +955,7 @@ Die Ausgabe enth
sich als Parameter f<>r andere Programme benutzen. Das folgende Beispiel liefert sich als Parameter f<>r andere Programme benutzen. Das folgende Beispiel liefert
detaillierte Informationen <20>ber alle xterm-Prozesse: detaillierte Informationen <20>ber alle xterm-Prozesse:
\texttt{ps -fp \$(pgrep -d, -x xterm)} \lstinline|ps -fp $(pgrep -d, -x xterm)|
Siehe auch: Abschnitt \ref{beispiele_suchen_prozesse}. Siehe auch: Abschnitt \ref{beispiele_suchen_prozesse}.
@ -920,7 +963,7 @@ Siehe auch: Abschnitt \ref{beispiele_suchen_prozesse}.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{pkill}\label{pkill}\index{pkill=\texttt{pkill}|(textbf} \subsection{pkill}\label{pkill}\index{pkill=\texttt{pkill}|(textbf}\marginpar{GNU!}
Dieses Kommando ist eng verwandt mit \texttt{pgrep} (Siehe Abschnitt Dieses Kommando ist eng verwandt mit \texttt{pgrep} (Siehe Abschnitt
\ref{pgrep}), es versteht im Wesentlichen die gleichen Parameter. Allerdings \ref{pgrep}), es versteht im Wesentlichen die gleichen Parameter. Allerdings
@ -934,7 +977,7 @@ diese Funktion wird im Abschnitt zu \texttt{kill} (\ref{kill}) n
beschrieben. Das folgende Kommando veranla<6C>t beispielsweise den Syslog-Daemon, beschrieben. Das folgende Kommando veranla<6C>t beispielsweise den Syslog-Daemon,
seine Konfiguration neu einzulesen: seine Konfiguration neu einzulesen:
\texttt{pkill -HUP syslogd} \lstinline|pkill -HUP syslogd|
Das Kommando \texttt{killall} (Abschnitt \ref{killall}) bietet eine <20>hnliche Das Kommando \texttt{killall} (Abschnitt \ref{killall}) bietet eine <20>hnliche
Funktionalit<EFBFBD>t, allerdings fehlen ihm einige Parameter. Trotzdem sollte im Funktionalit<EFBFBD>t, allerdings fehlen ihm einige Parameter. Trotzdem sollte im
@ -954,7 +997,7 @@ Dabei enth
bestimmten Regeln durch die Daten ersetzt werden. bestimmten Regeln durch die Daten ersetzt werden.
Der Format-String folgt im Wesentlichen den gleichen Regeln wie in der Der Format-String folgt im Wesentlichen den gleichen Regeln wie in der
C-Version. N<>heres dazu erf<72>hrt man mit \texttt{man 3 printf}. C-Version. N<>heres dazu erf<72>hrt man mit \lstinline|man 3 printf|.
Hier die wichtigsten Parameter f<>r den Format-String: Hier die wichtigsten Parameter f<>r den Format-String:
@ -965,15 +1008,13 @@ Daten. Im folgenden Beispiel werden alle Benutzernamen, deren
Home-Verzeichnisse und Default-Shells aus der Datei \texttt{/etc/passwd} Home-Verzeichnisse und Default-Shells aus der Datei \texttt{/etc/passwd}
extrahiert und <20>bersichtlich ausgegeben: extrahiert und <20>bersichtlich ausgegeben:
\footnotesize \begin{lstlisting}
\begin{listing}[2]{1}
#!/bin/sh #!/bin/sh
IFS=: IFS=:
while read user pass uid gid name home shell; do while read user pass uid gid name home shell; do
printf "%-15s %-25s %s\n" $user $home $shell printf "%-15s %-25s %s\n" $user $home $shell
done < /etc/passwd done < /etc/passwd
\end{listing} \end{lstlisting}
\normalsize
Zur Erinnerung: Die vordefinierte Variable Zur Erinnerung: Die vordefinierte Variable
\texttt{\$IFS}\index{\$IFS=\texttt{\$IFS}} ist der Feld-Separator, die \texttt{\$IFS}\index{\$IFS=\texttt{\$IFS}} ist der Feld-Separator, die
@ -1001,12 +1042,12 @@ In Skripten m
aktiv ist, ob also zum Beispiel ein bestimmter Serverdienst l<>uft. Dazu macht aktiv ist, ob also zum Beispiel ein bestimmter Serverdienst l<>uft. Dazu macht
man \texttt{ps} <20>ber Optionen gespr<70>chiger. man \texttt{ps} <20>ber Optionen gespr<70>chiger.
Das Kommando versteht in der GNU-Version zwei unterschiedliche Arten von Das Kommando versteht in der GNU-Version\marginpar{GNU!} zwei unterschiedliche
Optionen. Den sogenannten Unix- bzw. Posix-Stil und den BSD-Stil. Zus<75>tzlich Arten von Optionen. Den sogenannten Unix- bzw. Posix-Stil und den BSD-Stil.
gibt es noch ausf<73>hrliche Parameter, aber die sollen hier nicht beschrieben Zus<EFBFBD>tzlich gibt es noch ausf<73>hrliche Parameter, aber die sollen hier nicht
werden. Die jeweiligen Formen stehen nicht auf allen Systemen zur Verf<72>gung, beschrieben werden. Die jeweiligen Formen stehen nicht auf allen Systemen zur
wenn ein Skript beispielsweise auch unter Solaris benutzt werden soll ist man Verf<EFBFBD>gung, wenn ein Skript beispielsweise auch unter Solaris benutzt werden
gezwungen, die Unix-Parametrisierung zu benutzen. soll ist man gezwungen, die Unix-Parametrisierung zu benutzen.
Unix-Parameter zeichnen sich durch die <20>bliche Angabe mit Bindestrich aus. Unix-Parameter zeichnen sich durch die <20>bliche Angabe mit Bindestrich aus.
BSD-Pa\-ra\-me\-ter werden ohne Bindestrich angegeben, was neben den meisten BSD-Pa\-ra\-me\-ter werden ohne Bindestrich angegeben, was neben den meisten
@ -1016,8 +1057,7 @@ Es gibt sehr viele verschiedene Parameter, die beste Informationsquelle ist wie
immer die Man-Page bzw. ein entsprechendes Buch. Hier werden nur ein paar immer die Man-Page bzw. ein entsprechendes Buch. Hier werden nur ein paar
typische Aufrufbeispiele gezeigt, deren Ausgabe sich jeder selber ansehen kann: typische Aufrufbeispiele gezeigt, deren Ausgabe sich jeder selber ansehen kann:
\footnotesize \begin{lstlisting}
\begin{listing}[2]{1}
# Alle Prozesse auflisten, Unix-Syntax: # Alle Prozesse auflisten, Unix-Syntax:
ps -e ps -e
ps -ef ps -ef
@ -1041,8 +1081,7 @@ ps -C syslogd -o pid=
# Nur den Namen des Prozesses mit der ID 42 ausgeben: # Nur den Namen des Prozesses mit der ID 42 ausgeben:
ps -p 42 -o comm= ps -p 42 -o comm=
\end{listing} \end{lstlisting}
\normalsize
F<EFBFBD>r die Suche nach Prozessen bestimmten Namens steht auf manchen Systemen auch F<EFBFBD>r die Suche nach Prozessen bestimmten Namens steht auf manchen Systemen auch
das Kommando \texttt{pgrep} (Abschnitt \ref{pgrep}) zur Verf<72>gung. das Kommando \texttt{pgrep} (Abschnitt \ref{pgrep}) zur Verf<72>gung.
@ -1070,36 +1109,38 @@ alle Zeichen, die in der vordefinierten Variable
Wenn keine Variablennamen angegeben werden, wird die Eingabe in der Variable Wenn keine Variablennamen angegeben werden, wird die Eingabe in der Variable
\texttt{REPLY} abgelegt. \texttt{REPLY} abgelegt.
Normalerweise wird eine Eingabezeile mit einem Newline abgeschlossen. Mit dem
Parameter \texttt{-d} ist es m<>glich, ein anderes Zeilenendezeichen anzugeben.
Beispielsweise liest \texttt{read -d \dq~\dq~var} alle Zeichen bis zum ersten
Leerzeichen in die Variable \texttt{var} ein.
Wenn nur eine bestimmte Zahl von Zeichen gelesen werden soll, kann diese durch
den Parameter \texttt{-n} angegeben werden. Der Befehl \texttt{read -n 5 var}
liest die ersten f<>nf Zeichen in die Variable \texttt{var} ein. Demzufolge kann
ein Skript durch ein \texttt{read -n 1} dazu gebracht werden, auf einen
einzelnen Tastendruck~--~nicht zwingend ein Return~--~zu warten.
Mit dem Parameter \texttt{-p} kann man einen Prompt, also eine
Eingabeaufforderung ausgeben lassen. \texttt{read -p \dq{}Gib was ein:\dq~var}
schreibt also erst den Text \textit{Gib was ein:} auf das Terminal, bevor die
Eingaben in die Variable \texttt{var} <20>bernommen werden. Dieser Prompt wird nur
an einem interaktiven Terminal ausgegeben, also nicht in einem Skript das seine
Eingaben aus einer Datei oder aus einem Stream erh<72>lt.
Sonderzeichen k<>nnen w<>hrend der Eingabe normalerweise mittels eines Backslash Sonderzeichen k<>nnen w<>hrend der Eingabe normalerweise mittels eines Backslash
vor der Interpretation gesch<63>tzt werden. Ein Backslash vor einem Newline vor der Interpretation gesch<63>tzt werden. Ein Backslash vor einem Newline
bewirkt also eine mehrzeilige Eingabe. Dieses Verhalten kann mit dem Parameter bewirkt also eine mehrzeilige Eingabe. Dieses Verhalten kann mit dem Parameter
\texttt{-r} abgeschaltet werden. \texttt{-r} abgeschaltet werden.
Normalerweise wird eine Eingabezeile mit einem Newline abgeschlossen. Mit dem
Parameter \texttt{-d}\marginpar{GNU!} ist es m<>glich, ein anderes
Zeilenendezeichen anzugeben. Beispielsweise liest
\lstinline|read -d " " var| alle Zeichen bis zum ersten Leerzeichen in die
Variable \texttt{var} ein.
Wenn nur eine bestimmte Zahl von Zeichen gelesen werden soll, kann diese durch
den Parameter \texttt{-n}\marginpar{GNU!} angegeben werden. Der Befehl
\lstinline|read -n 5 var| liest die ersten f<>nf Zeichen in die Variable
\texttt{var} ein. Demzufolge kann ein Skript durch ein \lstinline|read -n 1|
dazu gebracht werden, auf einen einzelnen Tastendruck~--~nicht zwingend ein
Return~--~zu warten.
Mit dem Parameter \texttt{-p}\marginpar{GNU!} kann man einen Prompt, also eine
Eingabeaufforderung ausgeben lassen. \lstinline|read -p "Gib was ein:" var|
schreibt also erst den Text \textit{Gib was ein:} auf das Terminal, bevor die
Eingaben in die Variable \texttt{var} <20>bernommen werden. Dieser Prompt wird nur
an einem interaktiven Terminal ausgegeben, also nicht in einem Skript das seine
Eingaben aus einer Datei oder aus einem Stream erh<72>lt.
Wenn die Eingabe von einem Terminal kommt und nicht auf dem Bildschirm Wenn die Eingabe von einem Terminal kommt und nicht auf dem Bildschirm
erscheinen soll, zum Beispiel bei Pa<50>wortabfragen, kann die Ausgabe mit dem erscheinen soll, zum Beispiel bei Pa<50>wortabfragen, kann die Ausgabe mit dem
Parameter \texttt{-s} (Silent) unterdr<64>ckt werden. Parameter \texttt{-s}\marginpar{GNU!} (Silent) unterdr<64>ckt werden.
Mit \texttt{-t} kann ein Time-Out definiert werden, nach dessen Ablauf das Mit \texttt{-t}\marginpar{GNU!} kann ein Time-Out definiert werden, nach dessen
Kommando mit einem Fehler abbricht. Dieser Parameter ist nur bei interaktiver Ablauf das Kommando mit einem Fehler abbricht. Dieser Parameter ist nur bei
Eingabe oder beim Lesen aus einer Pipe aktiv. interaktiver Eingabe oder beim Lesen aus einer Pipe aktiv.
Der R<>ckgabewert des \texttt{read}-Kommandos ist 0, es sei denn es trat ein Der R<>ckgabewert des \texttt{read}-Kommandos ist 0, es sei denn es trat ein
Timeout oder ein EOF auf. Timeout oder ein EOF auf.
@ -1119,8 +1160,8 @@ Verzeichnisse k
Gegensatz zu \texttt{rmdir} werden dann auch s<>mtliche enthaltenen Dateien und Gegensatz zu \texttt{rmdir} werden dann auch s<>mtliche enthaltenen Dateien und
Unterverzeichnisse gel<65>scht. Unterverzeichnisse gel<65>scht.
Die GNU-Version von \texttt{rm} unterst<73>tzt zus<75>tzlich den Parameter Die GNU-Version\marginpar{GNU!} von \texttt{rm} unterst<73>tzt zus<75>tzlich den
\texttt{-v}, mit dem jeder L<>schvorgang ausgegeben wird. Parameter \texttt{-v}, mit dem jeder L<>schvorgang ausgegeben wird.
\index{rm=\texttt{rm}|)} \index{rm=\texttt{rm}|)}
@ -1142,7 +1183,7 @@ nicht-leere Verzeichnisse k
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{script}\label{script}\index{script=\texttt{script}|(textbf} \subsection{script}\label{script}\index{script=\texttt{script}|(textbf}\marginpar{GNU!}
Dieses Kommando eignet sich vorz<72>glich f<>r das Debuggen fertiger Skripte. Man Dieses Kommando eignet sich vorz<72>glich f<>r das Debuggen fertiger Skripte. Man
ruft es in Verbindung mit einem Dateinamen auf. Dieser Aufruf startet eine neue ruft es in Verbindung mit einem Dateinamen auf. Dieser Aufruf startet eine neue
@ -1176,8 +1217,7 @@ nur die g
\subsubsection{Aufruf} \subsubsection{Aufruf}
\footnotesize \begin{lstlisting}
\begin{listing}[2]{1}
# Aufruf als Stream-Editor: # Aufruf als Stream-Editor:
kommando1 | sed 's/alt/neu/' | kommando2 kommando1 | sed 's/alt/neu/' | kommando2
@ -1200,13 +1240,12 @@ s/alt/neu/
# Alternativ k<>nnen die Kommandos auch in eine eigene Datei gespeichert und # Alternativ k<>nnen die Kommandos auch in eine eigene Datei gespeichert und
# <20>ber den Parameter -f eingebunden werden: # <20>ber den Parameter -f eingebunden werden:
sed -f script.sed datei.txt sed -f script.sed datei.txt
\end{listing} \end{lstlisting}
\normalsize
Neben den oben erw<72>hnten Parametern kann \texttt{sed} auch mit \texttt{-n} Neben den oben erw<72>hnten Parametern kann \texttt{sed} auch mit \texttt{-n}
ruhig gestellt werden. Damit werden die Zeilen nur dann ausgegeben, wenn das ruhig gestellt werden. Damit werden die Zeilen nur dann ausgegeben, wenn das
mittels `p' explizit gefordert wird. Die GNU-Version stellt noch ein paar mittels `p' explizit gefordert wird. Die GNU-Version\marginpar{GNU!} stellt
Parameter zur Verf<72>gung, die Man-Page verr<72>t n<>heres. noch ein paar Parameter zur Verf<72>gung, die Man-Page verr<72>t n<>heres.
\subsubsection{Addressierung} \subsubsection{Addressierung}
@ -1278,8 +1317,7 @@ gehen soll werden hier keine komplexen Sachen vorgestellt, sondern nur ein paar
Einzeiler. Nichtsdestotrotz k<>nnen es auch diese unscheinbaren Aufrufe in sich Einzeiler. Nichtsdestotrotz k<>nnen es auch diese unscheinbaren Aufrufe in sich
haben. haben.
\footnotesize \begin{lstlisting}
\begin{listing}[2]{1}
### SUCHEN UND ERSETZEN ### SUCHEN UND ERSETZEN
# Im kompletten Text 'rot' durch 'blau' ersetzen: # Im kompletten Text 'rot' durch 'blau' ersetzen:
@ -1355,25 +1393,24 @@ sed '/./!d' # Methode 2
# Alle Leerzeilen am Dateianfang l<>schen: # Alle Leerzeilen am Dateianfang l<>schen:
sed '/./,$!d' sed '/./,$!d'
\end{listing} \end{lstlisting}
\normalsize
\index{sed=\texttt{sed}|)} \index{sed=\texttt{sed}|)}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{seq}\label{seq}\index{seq=\texttt{seq}|(textbf} \subsection{seq}\label{seq}\index{seq=\texttt{seq}|(textbf}\marginpar{GNU!}
Oft wird eine auf- oder absteigende Sequenz aufeinanderfolgender Zahlen Oft wird eine auf- oder absteigende Sequenz aufeinanderfolgender Zahlen
ben<EFBFBD>tigt, beispielsweise um eine Schleife 100 mal zu durchlaufen. Es ist nicht ben<EFBFBD>tigt, beispielsweise um eine Schleife 100 mal zu durchlaufen. Es ist nicht
sehr performant bei jedem Schleifendurchlauf hochzuz<75>hlen und dann die sehr performant bei jedem Schleifendurchlauf hochzuz<75>hlen und dann die
entstandene Zahl mit dem Limit zu vergleichen. Daher nimmt man an der Stelle entstandene Zahl mit dem Limit zu vergleichen. Daher nimmt man an der Stelle
\texttt{seq} zur Hilfe. \texttt{seq} zur Hilfe, wenn es zur Verf<72>gung steht.
Die zu z<>hlenden Werte werden durch drei unterschiedliche Arten der Die zu z<>hlenden Werte werden durch drei unterschiedliche Arten der
Parametrisierung definiert: Ein Aufruf in der Form \texttt{seq 10} gibt die Parametrisierung definiert: Ein Aufruf in der Form \lstinline|seq 10| gibt die
Zahlen von 1 bis 10 aus. Mit \texttt{seq 10 20} wird von 10 bis 20 gez<65>hlt, und Zahlen von 1 bis 10 aus. Mit \lstinline|seq 10 20| wird von 10 bis 20 gez<65>hlt,
\texttt{seq 20 -2 10} z<>hlt in zweierschritten r<>ckw<6B>rts von 20 nach 10. und \lstinline|seq 20 -2 10| z<>hlt in zweierschritten r<>ckw<6B>rts von 20 nach 10.
Per default kommen die Werte zeilenweise, mit dem Parameter \texttt{-s} kann Per default kommen die Werte zeilenweise, mit dem Parameter \texttt{-s} kann
aber auch ein anderes Trennzeichen definiert werden. Will man etwas numerieren aber auch ein anderes Trennzeichen definiert werden. Will man etwas numerieren
@ -1390,13 +1427,13 @@ mit f
Das Kommando \texttt{sleep} veranla<6C>t die Shell, f<>r eine angegebene Zeit zu Das Kommando \texttt{sleep} veranla<6C>t die Shell, f<>r eine angegebene Zeit zu
warten. Die Zeit wird dabei in Sekunden angegeben. warten. Die Zeit wird dabei in Sekunden angegeben.
In der GNU-Variante von \texttt{sleep} kann die Einheit der angegebenen In der GNU-Variante\marginpar{GNU!} von \texttt{sleep} kann die Einheit der
Zeitspanne durch Suffixe definiert werden: \texttt{sleep 10s} schl<68>ft zehn angegebenen Zeitspanne durch Suffixe definiert werden: \lstinline|sleep 10s|
Sekunden, \texttt{sleep 10m} zehn Minuten. Genauso werden Stunden (h) und Tage schl<EFBFBD>ft zehn Sekunden, \lstinline|sleep 10m| zehn Minuten. Genauso werden
(d) definiert. Stunden (h) und Tage (d) definiert.
Au<EFBFBD>erdem kann die GNU-Variante auch mit nicht-Integer Zeiten arbeiten: Au<EFBFBD>erdem kann die GNU-Variante auch mit nicht-Integer Zeiten arbeiten:
\texttt{sleep 0.5} schl<68>ft eine halbe Sekunde. \lstinline|sleep 0.5| schl<68>ft eine halbe Sekunde.
\index{sleep=\texttt{sleep}|)} \index{sleep=\texttt{sleep}|)}
@ -1447,6 +1484,9 @@ Parameter \texttt{-n} steuern.
Mit dem Parameter \texttt{-f} (follow) gibt \texttt{tail} neue Zeilen aus, Mit dem Parameter \texttt{-f} (follow) gibt \texttt{tail} neue Zeilen aus,
sobald sie an die Datei angeh<65>ngt werden. sobald sie an die Datei angeh<65>ngt werden.
Die GNU-Version\marginpar{GNU!} kann auch das Ende mehrere Dateien ausgeben
bzw. verfolgen, wenn mehrere Namen angegeben werden.
\index{tail=\texttt{tail}|)} \index{tail=\texttt{tail}|)}
@ -1517,8 +1557,7 @@ in der Man-Page.
Die folgenden Beispiele verdeutlichen die Anwendung: Die folgenden Beispiele verdeutlichen die Anwendung:
\footnotesize \begin{lstlisting}
\begin{listing}[2]{1}
text="Dies ist ein Testtext" text="Dies ist ein Testtext"
# kleine Umlaute durch grosse ersetzen: # kleine Umlaute durch grosse ersetzen:
@ -1544,8 +1583,7 @@ echo "$text" | tr -s "a-zA-Z"
# doppelte Buchstaben l<>schen, mit Zeichenklasse: # doppelte Buchstaben l<>schen, mit Zeichenklasse:
echo "$text" | tr -s "[:alpha:]" echo "$text" | tr -s "[:alpha:]"
# -> Dies ist ein Testext # -> Dies ist ein Testext
\end{listing} \end{lstlisting}
\normalsize
\index{tr=\texttt{tr}|)} \index{tr=\texttt{tr}|)}
@ -1564,7 +1602,7 @@ mehrere Bedingungen die zum Ausf
Kommando gibt zm Beispiel eine Fehlermeldung aus wenn sein Skript ein Signal 1 Kommando gibt zm Beispiel eine Fehlermeldung aus wenn sein Skript ein Signal 1
(HUP), 2 (INT) oder 15 (TERM) erh<72>lt: (HUP), 2 (INT) oder 15 (TERM) erh<72>lt:
\texttt{trap 'echo \dq`basename \$0`: Ooops...\dq 1>\&2' 1 2 15} \lstinline|trap 'echo "`basename $0`: Ooops..." 1>&2' 1 2 15|
Die Zeile ist dem Beispiel aus Abschnitt \ref{traps} entnommen, dort findet Die Zeile ist dem Beispiel aus Abschnitt \ref{traps} entnommen, dort findet
sich auch nochmal eine ausf<73>hrliche Erkl<6B>rung. sich auch nochmal eine ausf<73>hrliche Erkl<6B>rung.
@ -1601,13 +1639,14 @@ Weitaus h
Zeilen z<>hlen lassen. Weiterhin kann man Bytes (\texttt{-c}) oder Zeichen Zeilen z<>hlen lassen. Weiterhin kann man Bytes (\texttt{-c}) oder Zeichen
(\texttt{-m}) z<>hlen lassen. (\texttt{-m}) z<>hlen lassen.
Der Parameter \texttt{-L} gibt die L<>nge der l<>ngsten enthaltenen Zeile aus. Der Parameter \texttt{-L} gibt in der GNU-Version \marginpar{GNU!} die L<>nge
der l<>ngsten enthaltenen Zeile aus.
\index{wc=\texttt{wc}|)} \index{wc=\texttt{wc}|)}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{which}\label{which}\index{which=\texttt{which}|(textbf} \subsection{which}\label{which}\index{which=\texttt{which}|(textbf}\marginpar{GNU!}
Sucht im Pfad (vordefinierte Variable Sucht im Pfad (vordefinierte Variable
\texttt{\$PATH}\index{\$PATH=\texttt{\$PATH}}, siehe Abschnitt \texttt{\$PATH}\index{\$PATH=\texttt{\$PATH}}, siehe Abschnitt
@ -1633,8 +1672,8 @@ mit deren aktueller Konsole und der Anmeldezeit aus.
Bisweilen kommt man in die Verlegenheit, versehentlich zu lange Einzeiler Bisweilen kommt man in die Verlegenheit, versehentlich zu lange Einzeiler
geschrieben zu haben. Neben den F<>llen, in denen der Tipp-Eifer <20>berhand geschrieben zu haben. Neben den F<>llen, in denen der Tipp-Eifer <20>berhand
genommen hat handelt es sich in aller Regel um Zeilen in der Art `\texttt{grep genommen hat handelt es sich in aller Regel um Zeilen in der Art
'text' \$(find / -name \textbackslash*.txt)}'. Dieses Kommando sucht alle \lstinline|grep 'text' $(find / -name \*.txt)|. Dieses Kommando sucht alle
Dateien mit der Endung txt, die im System vorhanden sind. Diese werden `in die Dateien mit der Endung txt, die im System vorhanden sind. Diese werden `in die
Kommandozeile eingebaut'. Wenn sehr viele Dateien gefunden werden, wird die Kommandozeile eingebaut'. Wenn sehr viele Dateien gefunden werden, wird die
Zeile zu lang f<>r die Shell\footnote{Die maximale L<>nge der Kommandozeile Zeile zu lang f<>r die Shell\footnote{Die maximale L<>nge der Kommandozeile
@ -1642,23 +1681,23 @@ unterscheidet sich von System zu System}.
Ein weiterer und in der Praxis mindestens ebenso sinnvoller Einsatzzweck ist Ein weiterer und in der Praxis mindestens ebenso sinnvoller Einsatzzweck ist
das Vermeiden von Schleifen. Das obige Problem lie<69>e sich auch mit einer Zeile das Vermeiden von Schleifen. Das obige Problem lie<69>e sich auch mit einer Zeile
in der Form `\texttt{find / -name \textbackslash*.txt -exec grep 'text' \{\} in der Form \lstinline|find / -name \*.txt -exec grep 'text' {} \;| l<>sen.
\textbackslash;}'. Allerdings h<>tte das den Nachteil, da<64> f<>r jede gefundene Allerdings h<>tte das den Nachteil, da<64> f<>r jede gefundene Datei ein neuer
Datei ein neuer \texttt{grep} gestartet werden mu<6D>. Das kostet Resourcen. \texttt{grep} gestartet werden mu<6D>. Das kostet Resourcen.
Beide Probleme werden durch eine Zeile in der Form `\texttt{find / -name Beide Probleme werden durch eine Zeile in der Form
\textbackslash*.txt | xargs grep 'text'}' umgangen. Dabei liest \texttt{xargs} \lstinline+find / -name \*.txt | xargs grep 'text'+ umgangen. Dabei liest
aus der Standardeingabe die Parameter, die dann an den \texttt{grep}-Aufruf \texttt{xargs} aus der Standardeingabe die Parameter, die dann an den
angeh<EFBFBD>ngt werden. Sollten zu viele Dateien gefunden werden, wird \texttt{grep} \texttt{grep}-Aufruf angeh<EFBFBD>ngt werden. Sollten zu viele Dateien gefunden
mehrfach aufgerufen, allerdings im Gegensatz zum obigen Beispiel nicht einmal werden, wird \texttt{grep} mehrfach aufgerufen, allerdings im Gegensatz zum
pro Fundstelle. obigen Beispiel nicht einmal pro Fundstelle.
Neben einigen anderen Parametern informiert die Manpage <EFBFBD>ber die Option Neben einigen anderen Parametern informiert die Manpage der
\texttt{-r}. Damit kann vermieden werden, da<64> \texttt{xargs} das Kommando GNU-Version\marginpar{GNU!} <20>ber die Option \texttt{-r}. Damit kann vermieden
startet wenn keine Eingabe vorhanden ist. Bezogen auf das angegebene Beispiel werden, da<64> \texttt{xargs} das Kommando startet wenn keine Eingabe vorhanden
w<EFBFBD>rde \texttt{grep} ohne Dateinamen gestartet, wenn \texttt{find} nichts ist. Bezogen auf das angegebene Beispiel w<EFBFBD>rde \texttt{grep} ohne Dateinamen
findet. Es w<>rde auf Input von der Standardeingabe warten, der aber gestartet, wenn \texttt{find} nichts findet. Es w<>rde auf Input von der
wahrscheinlich nicht kommt. Das Skript w<>rde h<>ngen, wenn der Parameter Standardeingabe warten, der aber wahrscheinlich nicht kommt. Das Skript w<>rde
\texttt{-r} nicht angewandt w<>rde. h<EFBFBD>ngen, wenn der Parameter \texttt{-r} nicht angewandt w<>rde.
\index{xargs=\texttt{xargs}|)} \index{xargs=\texttt{xargs}|)}

View File

@ -38,21 +38,71 @@ zugleich einer der verwirrendsten Anf
werden. Das geht mit dem Unix-Kommando werden. Das geht mit dem Unix-Kommando
\texttt{chmod}\index{chmod=\texttt{chmod}} und wird in Abschnitt \ref{chmod} \texttt{chmod}\index{chmod=\texttt{chmod}} und wird in Abschnitt \ref{chmod}
ausf<EFBFBD>hrlich beschrieben. An dieser Stelle reicht uns ein Aufruf in der Form ausf<EFBFBD>hrlich beschrieben. An dieser Stelle reicht uns ein Aufruf in der Form
\texttt{chmod 755 dateiname}, um das Skript f<>r alle Benutzer ausf<73>hrbar zu \lstinline/chmod 755 name/, um das Skript f<>r alle Benutzer ausf<73>hrbar zu
machen. machen.
Dann kann das Skript gestartet werden. Da sich aus Sicherheitsgr<67>nden auf den Dann kann das Skript gestartet werden. Da sich aus Sicherheitsgr<67>nden auf den
meisten Systemen das aktuelle Verzeichnis nicht im Pfad des Benutzers befindet, meisten Systemen das aktuelle Verzeichnis nicht im Pfad des Benutzers befindet,
mu<EFBFBD> man der Shell noch mitteilen, wo sie zu suchen hat: Mit \texttt{./name} mu<EFBFBD> man der Shell noch mitteilen, wo sie zu suchen hat: Mit \lstinline|./name|
wird versucht, im aktuellen Verzeichnis (\texttt{./}) ein Programm namens wird versucht, im aktuellen Verzeichnis (\lstinline|./|) ein Programm namens
\texttt{name} auszuf<75>hren. \lstinline|name| auszuf<75>hren.
Auf den meisten Systemen befindet sich im Pfad ein Verweis auf das Verzeichnis Auf den meisten Systemen befindet sich im Pfad ein Verweis auf das Verzeichnis
\texttt{bin} unterhalb des Home-Verzeichnisses eines Benutzers. Das bedeutet \texttt{bin} unterhalb des Home-Verzeichnisses eines Benutzers. Das bedeutet
da<EFBFBD> man Skripte die immer wieder benutzt werden sollen dort ablegen kann, so da<EFBFBD> man Skripte die immer wieder benutzt werden sollen dort ablegen kann, so
da<EFBFBD> sie auch ohne eine Pfadangabe gefunden werden. Wie der Pfad genau aussieht da<EFBFBD> sie auch ohne eine Pfadangabe gefunden werden. Wie der Pfad genau aussieht
kann man an der Shell durch Eingabe von \texttt{echo kann man an der Shell durch Eingabe von \lstinline/echo $PATH/\index{\$PATH=\texttt{\$PATH}} herausfinden.
\$PATH}\index{\$PATH=\texttt{\$PATH}} herausfinden.
\section{Fehlersuche}
Es gibt f<>r Shell-Skripte keine wirklichen Debugger, aber trotzdem verf<72>gt man
<EFBFBD>ber einige bew<65>hrte Methoden zum Aufsp<73>ren von Fehlern:
\begin{itemize}
\item Debug-Ausgaben: Das wohl einfachste Mittel um herauszufinden was im
Skript vor sich geht sind wohl regelm<6C><6D>ige Debug-Ausgaben. Dazu f<>gt man
einfach an `strategisch wichtigen' Punkten im Skript \texttt{echo}-Zeilen ein,
die Auskunft <20>ber den Status geben.
\item Syntax-Check: Wenn man das Skript in der Form
\lstinline|sh -n ./skriptname| aufruft, wird es nicht wirklich ausgef<65>hrt.
Lediglich die Syntax der Kommandos wird gepr<70>ft. Diese Methode findet nat<61>rlich
keine logischen Fehler, und selbst wenn dieser Aufruf ohne Probleme durchl<68>uft
kann sich zur Laufzeit noch ein anderer Fehler einschleichen.
\item \texttt{set -x}: Wenn in einem Skript der Aufruf \lstinline|set -x|
abgesetzt wird, gibt die Shell jede Zeile nach der Expandierung aber vor der
Ausf<EFBFBD>hrung aus. Dadurch ist klar ersichtlich wann welche Kommandos mit welchen
Parametern ausgef<65>hrt werden. Um den Effekt wieder aufzuheben benutzt man
\lstinline|set +x|. Man kann die Option auch auf das komplette Skript anwenden
ohne sie in das Skript einbauen zu m<>ssen. Dazu startet man das Skript nicht
einfach durch \lstinline|./skriptname| sondern durch
\lstinline|sh -x ./skriptname|.
\item \texttt{set -v}: Dies funktioniert genau wie \lstinline|set -x|, auch der
Aufruf <20>ber \lstinline|sh -v ./skriptname| funktioniert. Diese Option gibt jede
Zeile vor der Ausf<73>hrung aus, allerdings im Gegensatz zu \texttt{-x} nicht in
der expandierten sondern in der vollen Form.
\item System-Log: F<>r das direkte Debuggen ist dieser Weg weniger geeignet,
aber gerade in unbeobachtet laufenden Skripten sollte man unerwartete Zust<73>nde
oder besondere Ereignisse im System-Log festhalten. Dies geschieht mit dem
Kommando \texttt{logger}, das in Abschnitt \ref{logger} beschrieben wird.
\item \texttt{script}: Mit dem Kommando \texttt{script} kann eine Sitzung an
der Shell vollst<73>ndig protokolliert werden, inclusive aller Ein- und Ausgaben.
Das umfa<66>t sogar Dr<44>cke auf die Pfeiltasten oder auf Backspace. So kann auch
eine l<>ngere Sitzung mit vielen Ein- und Ausgaben nach dem Testlauf in aller
Ruhe analysiert werden. Das Kommando wird in Abschnitt \ref{script}
beschrieben.
TODO: Debuggen
%http://localhost/~rschaten/doku/abs-guide/debugging.html#FTN.AEN14050
%-> trapping signals
\end{itemize}
\section{R<EFBFBD>ckgabewerte}\label{exitcode}\index{R<EFBFBD>ckgabewert|(textbf}\index{Exit-Code|see{R<EFBFBD>ckgabewert}}\index{Exit-Status|see{R<EFBFBD>ckgabewert}} \section{R<EFBFBD>ckgabewerte}\label{exitcode}\index{R<EFBFBD>ckgabewert|(textbf}\index{Exit-Code|see{R<EFBFBD>ckgabewert}}\index{Exit-Status|see{R<EFBFBD>ckgabewert}}
@ -84,7 +134,7 @@ verschiedenen Wert. Das wird im folgenden Beispiel deutlich:
Normalerweise wird man den Exit-Code nicht in dieser Form abfragen. Sinnvoller Normalerweise wird man den Exit-Code nicht in dieser Form abfragen. Sinnvoller
ist folgendes Beispiel, in dem eine Datei erst gedruckt wird, und dann~--~falls ist folgendes Beispiel, in dem eine Datei erst gedruckt wird, und dann~--~falls
der Ausdruck erfolgreich war ~--~el<EFBFBD>scht wird: der Ausdruck erfolgreich war~--~gel<EFBFBD>scht wird:
\LTXtable{\textwidth}{tab_beisp_exitcode_lpr.tex} \LTXtable{\textwidth}{tab_beisp_exitcode_lpr.tex}
@ -341,7 +391,7 @@ erzeugen.
\section{Arithmetik-Expansion\label{arithmetikexpansion}\index{Arithmetik-Expansion|(textbf}} \section{Arithmetik-Expansion\label{arithmetikexpansion}\index{Arithmetik-Expansion|(textbf}}
Auch hier werden Klammern expandiert. Allerdings gleich doppelte Klammern. Mit Auch hier werden Klammern expandiert. Allerdings gleich doppelte Klammern. Mit
einem Konstrukt in der Form \texttt{i=\$((\$i + 1))} k<>nnen einfache einem Konstrukt in der Form \lstinline|i=$(($i + 1))| k<>nnen einfache
Berechnungen angestellt werden. Berechnungen angestellt werden.
Dabei wird der Ausdruck in den Klammern bewertet als ob er in doppelten Dabei wird der Ausdruck in den Klammern bewertet als ob er in doppelten
@ -366,9 +416,9 @@ genau eine Parent-Proze
jeweiligen Proze<7A> erzeugt hat. Man spricht in diesem Zusammenhang tats<74>chlich jeweiligen Proze<7A> erzeugt hat. Man spricht in diesem Zusammenhang tats<74>chlich
von Eltern- bzw. Kind-Prozessen. von Eltern- bzw. Kind-Prozessen.
Diese Zusammenh<6E>nge lassen sich sehr sch<63>n durch die Ausgabe des Kommandos Diese Zusammenh<6E>nge lassen sich sehr sch<63>n durch die Ausgabe eines Kommandos
\texttt{pstree} oder \texttt{ps -efH} darstellen, letzteres zeigt auch gleich wie \texttt{pstree} oder \lstinline|ps -efH| darstellen, letzteres zeigt auch
die PIDs und die PPIDs an. gleich die PIDs und die PPIDs an.
Wenn in einer Shell ein Kommando gestartet wird, ist es ein Kind dieser Shell. Wenn in einer Shell ein Kommando gestartet wird, ist es ein Kind dieser Shell.
Wird ein Skript gestartet, <20>ffnet es sich seine eigene Shell (siehe Wird ein Skript gestartet, <20>ffnet es sich seine eigene Shell (siehe
@ -424,15 +474,15 @@ In der ersten Zeile eines Shell-Skriptes sollte definiert werden, mit welchem
Programm das Skript ausgef<65>hrt werden soll. Das System <20>ffnet dann eine Programm das Skript ausgef<65>hrt werden soll. Das System <20>ffnet dann eine
Subshell\index{Subshell} und f<>hrt das restliche Skript in dieser aus. Subshell\index{Subshell} und f<>hrt das restliche Skript in dieser aus.
Die Angabe erfolgt <20>ber eine Zeile in der Form \verb\#!/bin/sh\, wobei unter Die Angabe erfolgt <20>ber eine Zeile in der Form \lstinline|#!/bin/sh|, wobei
\verb\/bin/sh\ die entsprechende Shell (in diesem Fall die Bourne-Shell) liegt. unter \lstinline|/bin/sh| die entsprechende Shell (in diesem Fall die
Dieser Eintrag wirkt nur dann, wenn er in der ersten Zeile und der ersten Bourne-Shell) liegt. Dieser Eintrag wirkt nur dann, wenn er in der ersten Zeile
Spalte des Skripts steht. und der ersten Spalte des Skripts steht.
Dieser Mechanismus ist bei der Bourne-Shell nicht vorhanden, er wurde mit den Dieser Mechanismus ist bei der Bourne-Shell nicht vorhanden, er wurde mit den
moderneren Shells eingef<65>hrt um eben durch die Angabe von \verb\#!/bin/sh\ die moderneren Shells eingef<65>hrt um eben durch die Angabe von \lstinline|#!/bin/sh|
Bourne-Shell f<>r die Ausf<73>hrung von Shell-Skripten benutzen zu k<>nnen. In der die Bourne-Shell f<>r die Ausf<73>hrung von Shell-Skripten benutzen zu k<>nnen. In
Bourne-Shell wirkt das f<>hrende \verb\#\ als Kommentarzeichen. der Bourne-Shell wirkt das f<>hrende \verb\#\ als Kommentarzeichen.
\index{Shell>Auswahl der\ldots|)} \index{Shell>Auswahl der\ldots|)}
@ -450,24 +500,38 @@ Dieser Befehl tut nichts, au
Ein Shell-Skript kann in keiner Weise Einflu<6C> auf die umgebende Shell nehmen. Das hei<65>t, da<64> es beispielsweise nicht m<>glich ist, in einem Skript Variablen zu setzen, die dann in der aufrufenden Shell zur Verf<72>gung stehen. Genauso wenig ist es m<>glich, da<64> ein Skript den Pfad <20>ndert, in dem man sich befindet. Der Grund f<>r dieses Verhalten ist die Systemsicherheit. Man will verhindern, da<64> ein Skript unbemerkt <20>nderungen an der Benutzerumgebung vornimmt. Ein Shell-Skript kann in keiner Weise Einflu<6C> auf die umgebende Shell nehmen. Das hei<65>t, da<64> es beispielsweise nicht m<>glich ist, in einem Skript Variablen zu setzen, die dann in der aufrufenden Shell zur Verf<72>gung stehen. Genauso wenig ist es m<>glich, da<64> ein Skript den Pfad <20>ndert, in dem man sich befindet. Der Grund f<>r dieses Verhalten ist die Systemsicherheit. Man will verhindern, da<64> ein Skript unbemerkt <20>nderungen an der Benutzerumgebung vornimmt.
Wenn es aber doch gew<65>nscht wird, da<64> ein Skript die Umgebung des Benutzers <20>ndern kann, dann mu<6D> es mit dem Source-Kommando aufgerufen werden. Das wird in der Form \verb\source skriptname\ bzw. \verb\. skriptname\ angegeben. Er bewirkt <20>hnliches wie ein \verb\#include\ in der Programmiersprache C. Wenn es aber doch gew<65>nscht wird, da<64> ein Skript die Umgebung des Benutzers
<EFBFBD>ndern kann, dann mu<6D> es mit dem Source-Kommando aufgerufen werden. Das wird in
der Form \lstinline|source skriptname| bzw. \lstinline|. skriptname| angegeben.
Er bewirkt <20>hnliches wie ein \verb\#include\ in der Programmiersprache C.
Die `gesourcte' Datei wird eingelesen und ausgef<65>hrt, als ob ihr Inhalt an der Stelle des Befehls stehen w<>rde. Diese Methode wird zum Beispiel beim Login in den Konfigurationsdateien des Benutzers (z. B. \verb\.profile\, \verb\.bashrc\) oder w<>hrend des Bootvorgangs in den Init-Skripten benutzt, um immer wieder ben<65>tigte Funktionen (Starten eines Dienstes, Statusmeldungen auf dem Bildschirm etc.) in einer zentralen Datei pflegen zu k<>nnen (siehe Beispiel unter~\ref{init-skript}). Die `gesourcte' Datei wird eingelesen und ausgef<65>hrt, als ob ihr Inhalt an der
Stelle des Befehls stehen w<>rde. Diese Methode wird zum Beispiel beim Login in
den Konfigurationsdateien des Benutzers (z. B. \verb\.profile\, \verb\.bashrc\)
oder w<>hrend des Bootvorgangs in den Init-Skripten benutzt, um immer wieder
ben<EFBFBD>tigte Funktionen (Starten eines Dienstes, Statusmeldungen auf dem
Bildschirm etc.) in einer zentralen Datei pflegen zu k<>nnen (siehe Beispiel
unter~\ref{init-skript}).
\index{source=\texttt{source}|)} \index{source=\texttt{source}|)}
\subsection{Funktionen}\label{funktionen}\index{Funktion|(textbf} \subsection{Funktionen}\label{funktionen}\index{Funktion|(textbf}
Es ist in der Shell auch m<>glich, <20>hnlich wie in einer `richtigen' Programmiersprache Funktionen zu deklarieren und zu benutzen. Da die Bourne-Shell (\verb\sh\) nicht <20>ber Aliase\index{Aliase} verf<72>gt, k<>nnen einfache Funktionen als Ersatz dienen. Es ist in der Shell auch m<>glich, <20>hnlich wie in einer `richtigen'
Programmiersprache Funktionen zu deklarieren und zu benutzen. Da die
Bourne-Shell (\texttt{sh}) nicht <20>ber Aliase\index{Aliase} verf<72>gt, k<>nnen
einfache Funktionen als Ersatz dienen.
Der R<>ckgabewert einer Funktion ist gleich dem R<>ckgabewert des letzten in der Der R<>ckgabewert einer Funktion ist gleich dem R<>ckgabewert des letzten in der
Funktion aufgerufenen Kommandos, es sei denn man gibt mittels Funktion aufgerufenen Kommandos, es sei denn man gibt mittels
\verb\return\ (Siehe \ref{return}) explizit einen anderen Wert zur<75>ck. \texttt{return} (Siehe \ref{return}) explizit einen anderen Wert zur<75>ck.
\medskip\emph{Beispiel:} Die Funktion gibt die Anzahl der Dateien im aktuellen \medskip\emph{Beispiel:} Die Funktion gibt die Anzahl der Dateien im aktuellen
Verzeichnis aus. Aufgerufen wird diese Funktion wie ein Befehl, also einfach Verzeichnis aus. Aufgerufen wird diese Funktion wie ein Befehl, also einfach
durch die Eingabe von \verb\count\.\nopagebreak durch die Eingabe von \texttt{count}.
\LTXtable{\textwidth}{tab_beisp_funktionen.tex} \LTXtable{\textwidth}{tab_beisp_funktionen.tex}
\index{Funktion|)} \index{Funktion|)}