Umformatiert
This commit is contained in:
310
beispiele.tex
310
beispiele.tex
@@ -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 überprüft, ob der Admin angemeldet ist. Wir erreichen das mit dem folgenden Code:
|
||||
|
||||
\footnotesize
|
||||
\index{\^=\texttt{\^}}\index{Anführungszeichen}\index{Pipe}\index{grep=\texttt{grep}}\index{sleep=\texttt{sleep}}\index{who=\texttt{who}}
|
||||
\begin{listing}[2]{1}
|
||||
\begin{lstlisting}
|
||||
#!/bin/sh
|
||||
until who | grep "^root "
|
||||
do sleep 30
|
||||
done
|
||||
echo Big Brother is watching you!
|
||||
\end{listing}
|
||||
\normalsize
|
||||
\end{lstlisting}
|
||||
|
||||
Das Skript führt also so lange das Kommando aus, bis die Ausfü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äftigt ist, wird im Schleifenkörper ein \texttt{sleep 30}\index{sleep=\texttt{sleep}} ausgeführt, um den Prozeß 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ü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äftigt ist, wird im Schleifenkörper ein
|
||||
\lstinline|sleep 30|\index{sleep=\texttt{sleep}} ausgeführt, um den Prozeß 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}
|
||||
|
||||
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ührungszeichen}\index{grep=\texttt{grep}}\index{Pipe}\index{sleep=\texttt{sleep}}\index{who=\texttt{who}}
|
||||
\begin{listing}[2]{1}
|
||||
\begin{lstlisting}
|
||||
#!/bin/sh
|
||||
while who | grep "^root "
|
||||
do sleep 30
|
||||
done
|
||||
echo Die Katze ist aus dem Haus, Zeit, daß die Mäuse tanzen!
|
||||
\end{listing}
|
||||
\normalsize
|
||||
\end{lstlisting}
|
||||
|
||||
Die Schleife wird nämlich dann so lange ausgeführt, bis \texttt{grep}\index{grep=\texttt{grep}} einen Fehler (bzw. eine erfolglose Suche) zurückmeldet.
|
||||
|
||||
@@ -49,8 +55,7 @@ Die Schleife wird n
|
||||
|
||||
\texttt{cat datei.txt | while read i}
|
||||
|
||||
\footnotesize
|
||||
\begin{listing}[2]{1}
|
||||
\begin{lstlisting}
|
||||
#!/bin/sh
|
||||
count=0
|
||||
cat /etc/passwd | while read i; do
|
||||
@@ -61,8 +66,7 @@ cat /etc/passwd | while read i; do
|
||||
fi
|
||||
done
|
||||
echo Es sind $count Benutzer mit einer ID kleiner 100 eingetragen
|
||||
\end{listing}
|
||||
\normalsize
|
||||
\end{lstlisting}
|
||||
|
||||
TODO!!! Daten aus Subshell hochreichen
|
||||
|
||||
@@ -76,19 +80,16 @@ Das Skript mu
|
||||
|
||||
Das Ergebnis der Ausfü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ächst wird festgelegt, daß dieses Skript in der Bourne-Shell ausgeführt werden soll (\ref{auswahl_der_shell}).
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
\begin{listing}[2]{1}
|
||||
|
||||
\begin{lstlisting}
|
||||
#!/bin/sh
|
||||
\end{listing}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
Dann folgen Kommentare\index{Kommentar}, die den Sinn des Skriptes erläutern (\ref{kommentare}).
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
\begin{listingcont}
|
||||
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
#
|
||||
# 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/httpd.conf
|
||||
# config: /etc/httpd/conf/srm.conf
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
Jetzt wird die Datei mit den Funktionen\index{Funktion} eingebunden (\ref{source}).
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
|
||||
\index{source=\texttt{source}}
|
||||
\begin{listingcont}
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
# Source function library.
|
||||
. /etc/rc.d/init.d/functions
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
Hier werden die Aufrufparameter ausgewertet (\ref{case}).
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
|
||||
\index{\$n=\texttt{\$}$n$}\index{Anführungszeichen}\index{case=\texttt{case}}
|
||||
\begin{listingcont}
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
# See how we were called.
|
||||
case "$1" in
|
||||
start)
|
||||
echo -n "Starting httpd: "
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
Nachdem eine Meldung über den auszuführenden Vorgang ausgegeben wurde, wird die Funktion \texttt{daemon} aus der Funktionsbibliothek ausgeführt. Diese Funktion startet das Programm, dessen Name hier als Parameter\index{Parameter} übergeben wird. Dann gibt sie eine Meldung über den Erfolg aus.
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
\begin{listingcont}
|
||||
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
daemon httpd
|
||||
echo
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
Jetzt wird ein Lock-File\footnote{Ein Lock-File signalisiert anderen Prozessen, daß ein bestimmter Prozeß bereits gestartet ist. So kann ein zweiter Aufruf verhindert werden.} angelegt.
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
|
||||
\index{Anführungszeichen}\index{touch=\texttt{touch}}
|
||||
\begin{listingcont}
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
touch /var/lock/subsys/httpd
|
||||
;;
|
||||
stop)
|
||||
echo -n "Shutting down http: "
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
Hier passiert im Prinzip das gleiche wie oben, nur daß mit der Funktion \texttt{killproc} der Daemon angehalten wird.
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
\begin{listingcont}
|
||||
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
killproc httpd
|
||||
echo
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
Danach werden Lock-File und PID-File\footnote{In einem sogenannten PID-File hinterlegen einige Prozesse ihre Prozeß-ID, um anderen Programmen den Zugriff zu erleichtern (z. B. um den Prozeß anzuhalten etc).} gelöscht.
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
\begin{listingcont}
|
||||
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
rm -f /var/lock/subsys/httpd
|
||||
rm -f /var/run/httpd.pid
|
||||
;;
|
||||
status)
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
Die Funktion \texttt{status} stellt fest, ob der entsprechende Daemon bereits läuft, und gibt das Ergebnis aus.
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
\begin{listingcont}
|
||||
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
status httpd
|
||||
;;
|
||||
restart)
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
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ührungszeichen}
|
||||
\begin{listingcont}
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
$0 stop
|
||||
$0 start
|
||||
;;
|
||||
reload)
|
||||
echo -n "Reloading httpd: "
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
Hier sendet die \texttt{killproc}-Funktion dem Daemon ein Signal\index{Signal} das ihm sagt, daß er seine Konfiguration neu einlesen soll.
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
|
||||
\index{\$n=\texttt{\$}$n$}\index{Anführungszeichen}
|
||||
\begin{listingcont}
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
killproc httpd -HUP
|
||||
echo
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {start|stop|restart|reload|status}"
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
Bei aufruf mit einem beliebigen anderen Parameter\index{Parameter} wird eine Kurzhilfe ausgegeben. Dann wird dafür gesorgt, daß das Skript mit dem Exit-Code 1 beendet wird. So kann festgestellt werden, ob das Skript ordnungsgemäß beendet wurde (\ref{exit}).
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
|
||||
\index{exit=\texttt{exit}}
|
||||
\begin{listingcont}
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
exit 1
|
||||
esac
|
||||
|
||||
exit 0
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
|
||||
\section{Parameterü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ß ein zusätzlicher Wert mitgegeben werden. Alle anderen Parameter\index{Parameter} werden als Dateinamen interpretiert.
|
||||
|
||||
\footnotesize
|
||||
\index{\$@=\texttt{\$@}}\index{Anführungszeichen}\index{Backticks}\index{!|!|=\texttt{!|!|}}\index{getopt=\texttt{getopt}}\index{OR}\index{set=\texttt{set}}
|
||||
\begin{listing}[2]{1}
|
||||
\begin{lstlisting}
|
||||
#!/bin/sh
|
||||
set -- `getopt "ab:" "$@"` || {
|
||||
\end{listing}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
Das \texttt{set}\index{set=\texttt{set}}-Kommando belegt den Inhalt der vordefinierten Variablen (\ref{vordefinierte_variablen}) neu, so daß es aussieht, als ob dem Skript die Rückgabewerte von \texttt{getopt}\index{getopt=\texttt{getopt}} übergeben wurden. Man muß die beiden Minuszeichen angeben, da sie dafür sorgen, daß die Aufrufparameter an \texttt{getopt}\index{getopt=\texttt{getopt}} und nicht an die Shell selbst übergeben werden. Die originalen Parameter\index{Parameter} werden von \texttt{getopt}\index{getopt=\texttt{getopt}} untersucht und modifiziert zurückgegeben: \texttt{a} und \texttt{b} werden als Parameter\index{Parameter} Markiert, \texttt{b} sogar mit der Möglichkeit einer zusätzlichen Angabe.
|
||||
|
||||
Wenn dieses Kommando fehlschlägt ist das ein Zeichen dafür, daß falsche Parameter\index{Parameter} ü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ührungszeichen}\index{Backticks}\index{basename=\texttt{basename}}
|
||||
\begin{listingcont}
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
echo "Anwendung: `basename $0` [-a] [-b Name] Dateien" 1>&2
|
||||
exit 1
|
||||
}
|
||||
@@ -243,41 +232,38 @@ echo "Momentan steht in der Kommandozeile folgendes: $*"
|
||||
aflag=0 name=NONE
|
||||
while :
|
||||
do
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
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ührungszeichen}\index{case=\texttt{case}}\index{shift=\texttt{shift}}
|
||||
\begin{listingcont}
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
case "$1" in
|
||||
-a) aflag=1 ;;
|
||||
-b) shift; name="$1" ;;
|
||||
--) break ;;
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
Wenn ein \texttt{-{}-} erscheint, ist das ein Hinweis darauf, daß 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}}
|
||||
\begin{listingcont}
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
esac
|
||||
shift
|
||||
done
|
||||
shift
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
Am Ende werden die Feststellungen ausgegeben.
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
|
||||
\index{\$*=\texttt{\$*}}\index{Anführungszeichen}
|
||||
\begin{listingcont}
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
echo "aflag=$aflag / Name = $name / Die Dateien sind $*"
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
|
||||
\section{Fallensteller: Auf Traps
|
||||
@@ -293,50 +279,45 @@ Wie l
|
||||
|
||||
Das Skript soll eine komprimierte Textdatei mittels \texttt{zcat} in ein temporäres File entpacken, dieses mit \texttt{pg} seitenweise anzeigen und nachher wieder löschen.
|
||||
|
||||
\footnotesize
|
||||
\index{!==\texttt{!=}}
|
||||
\begin{listing}[2]{1}
|
||||
\begin{lstlisting}
|
||||
#!/bin/sh
|
||||
stat=1
|
||||
temp=/tmp/zeige$$
|
||||
\end{listing}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
Zunä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ückliefern soll. Die Variable \texttt{temp} enthält den Namen für eine temporäre Datei. Dieser setzt sich zusammen aus \texttt{/tmp/zeige} und der Prozeßnummer des laufenden Skripts. So soll sichergestellt werden, daß noch keine Datei mit diesem Namen existiert.
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
|
||||
\index{Ticks}\index{!>\&=\texttt{!>\&}}\index{\$n=\texttt{\$}$n$}\index{Ticks}\index{Anführungszeichen}\index{Backticks}\index{basename=\texttt{basename}}
|
||||
\begin{listingcont}
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
trap 'rm -f $temp; exit $stat' 0
|
||||
trap 'echo "`basename $0`: Ooops..." 1>&2' 1 2 15
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
Hier werden die Traps definiert. Bei Signal 0 wird die temporäre Datei gelöscht und der Wert aus der Variable \texttt{stat} als Exit-Code zurü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ßt, er wird bei jedem unnormalen Ende ausgeführt. Er gibt eine entsprechende Meldung auf die Standard-Fehlerausgabe (\ref{datenstrom}) aus. Danach wird das Skript beendet, und der erste Trap wird ausgeführt.
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
|
||||
\index{\$\#=\texttt{\$\#}}\index{!==\texttt{!=}}\index{!>=\texttt{!>}}\index{\$n=\texttt{\$}$n$}\index{Anführungszeichen}\index{case=\texttt{case}}
|
||||
\begin{listingcont}
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
case $# in
|
||||
1) zcat "$1" > $temp
|
||||
pg $temp
|
||||
stat=0
|
||||
;;
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
Jetzt kommt die eigentliche Funktionalität des Skriptes: Das \texttt{case}-Kommando (\ref{case}) testet die Anzahl der übergebenen Parameter\index{Parameter}. Wenn genau ein Parameter\index{Parameter} übergeben wurde, entpackt \texttt{zcat} die Datei, die im ersten Parameter\index{Parameter} angegeben wurde, in die temporä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ückgegeben wird.
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
|
||||
\index{!>\&=\texttt{!>\&}}\index{\$n=\texttt{\$}$n$}\index{Anführungszeichen}\index{Backticks}\index{basename=\texttt{basename}}
|
||||
\begin{listingcont}
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
*) echo "Anwendung: `basename $0` Dateiname" 1>&2
|
||||
esac
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
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|)}
|
||||
|
||||
|
||||
@@ -358,27 +339,25 @@ Zwecke noch etwas `bereinigt' werden.
|
||||
|
||||
Wie das aussieht, wenn es fertig ist, sieht man im folgenden Skript:
|
||||
|
||||
\footnotesize
|
||||
\index{!==\texttt{!=}}
|
||||
\begin{listing}[2]{1}
|
||||
\begin{lstlisting}
|
||||
#!/bin/sh
|
||||
for i in `find $1 -type f -name "*.[mM][pP]3"`; do
|
||||
\end{listing}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
Hier beginnt eine Schleife, die über alle Ausgaben des \texttt{find}-Kommandos
|
||||
iteriert. Dabei sucht \texttt{find} nach allen normalen Dateien (\texttt{-type
|
||||
f}), die die Extension .mp3 tragen (\texttt{-name \dq*.[mM][pP]3\dq} -- wir
|
||||
ignorieren Groß- / Kleinschreibung).
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
|
||||
\index{find=\texttt{find}}
|
||||
\begin{listingcont}
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
echo `tr -dc "[:alpha:]" < /dev/urandom | \
|
||||
dd count=8 bs=1 2> /dev/null`$i
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
Hier ist der `magische Teil'. Mit dem \texttt{echo} wird die Ausgabe einer Pipe
|
||||
ausgegeben, gefolgt von dem aktuellen Dateinamen. Diese Pipe enthält ein
|
||||
\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
|
||||
\texttt{/dev/null} um.
|
||||
\index{tr=\texttt{tr}}\index{dd=\texttt{dd}}
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
|
||||
\index{find=\texttt{find}}
|
||||
\begin{listingcont}
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
done | sort | cut -b 9- | while read i; do
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
Das Ergebnis der obigen Schleife ist also die Liste der Dateinamen, denen
|
||||
jeweils acht zufällige Zeichen vorangestellt wurden. Die Reihenfolge entspricht
|
||||
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
|
||||
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}}
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
|
||||
\index{find=\texttt{find}}
|
||||
\begin{listingcont}
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
echo "Jetzt wird $i gespielt"
|
||||
mpg123 "$i"
|
||||
done
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
\index{Zufallszahlen|)}
|
||||
|
||||
|
||||
@@ -437,8 +415,7 @@ das Problem, da
|
||||
Prozeß läuft oder nicht. Im Normalfall wird er zuerst folgendes ausprobieren,
|
||||
was aber oft (nicht immer) in die Hose gehen wird:
|
||||
|
||||
\texttt{ps aux | grep }\textit{prozessname}\texttt{ \&\& echo \dq}\textit{läuft
|
||||
schon}\texttt{\dq}
|
||||
\lstinline/ps aux | grep prozessname && echo "läuft schon"/
|
||||
|
||||
Der Grund dafür ist, daß unter Umständen in der Ausgabe von \texttt{ps} auch
|
||||
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
|
||||
Konstrukt:
|
||||
|
||||
\texttt{ps aux | grep \dq}\textit{[p]rozessname}\texttt{\dq~\&\& echo
|
||||
\dq}\textit{läuft schon}\texttt{\dq}
|
||||
\lstinline/ps aux | grep "[p]rozessname" && echo "läuft schon"/
|
||||
|
||||
Das p ist jetzt als eine Zeichenmenge (regulärer Ausdruck) angegeben worden.
|
||||
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
|
||||
folgendes versuchen:
|
||||
|
||||
\texttt{grep -r strict *}
|
||||
\lstinline|grep -r strict *|
|
||||
|
||||
Das führt allerdings dazu, daß alle Dateien durchsucht werden, nicht nur die
|
||||
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 über
|
||||
alle Dateien, die dem Muster entsprechen:
|
||||
|
||||
\texttt{grep -r strict *.pl}
|
||||
\lstinline|grep -r strict *.pl|
|
||||
|
||||
Das führt wieder nicht zu dem gewünschten Ergebnis. Da die Unterverzeichnisse
|
||||
nicht die Extension `*.pl' tragen, werden sie nicht berücksichtigt. Für die
|
||||
Suche in Unterverzeichnissen ziehen wir \texttt{find} (Siehe Abschnitt
|
||||
\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
|
||||
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
|
||||
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
|
||||
jedem Aufruf auch \texttt{/dev/null}, also den digitalen Mülleimer der per
|
||||
|
||||
Reference in New Issue
Block a user