Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
f2b7d3468d |
54
Makefile
54
Makefile
@ -134,10 +134,6 @@ ifndef DVIVIEWER
|
||||
DVIVIEWER=xdvi
|
||||
endif
|
||||
|
||||
ifndef PDFVIEWER
|
||||
PDFVIEWER=acroread
|
||||
endif
|
||||
|
||||
ifndef LATEX2HTML
|
||||
LATEX2HTML=latex2html
|
||||
endif
|
||||
@ -275,21 +271,6 @@ TEXFILES=$(wildcard *.tex)
|
||||
touch $*.ind; \
|
||||
fi
|
||||
|
||||
pdflatex:
|
||||
# Below the 'true' is included to prevent unnecessarily many errors.
|
||||
@if [ -n "${LATEXTARGET}" ]; then \
|
||||
$(MAKE) ${LATEXTARGET}.pdf; \
|
||||
true; \
|
||||
else \
|
||||
if [ `ls *.tex | wc -l` = "1" ]; then \
|
||||
$(MAKE) `basename \`ls *.tex\` .tex`.pdf; \
|
||||
true; \
|
||||
else \
|
||||
$(MAKE) `echo $$PWD|tr '/' '\n'|tail -1`.pdf; \
|
||||
true; \
|
||||
fi; \
|
||||
fi
|
||||
|
||||
latex:
|
||||
# Below the 'true' is included to prevent unnecessarily many errors.
|
||||
@if [ -n "${LATEXTARGET}" ]; then \
|
||||
@ -305,12 +286,27 @@ latex:
|
||||
fi; \
|
||||
fi
|
||||
|
||||
pdflatex:
|
||||
# Below the 'true' is included to prevent unnecessarily many errors.
|
||||
@if [ -n "${LATEXTARGET}" ]; then \
|
||||
$(MAKE) ${LATEXTARGET}.pdf; \
|
||||
true; \
|
||||
else \
|
||||
if [ `ls *.tex | wc -l` = "1" ]; then \
|
||||
$(MAKE) `basename \`ls *.tex\` .tex`.pdf; \
|
||||
true; \
|
||||
else \
|
||||
$(MAKE) `echo $$PWD|tr '/' '\n'|tail -1`.pdf; \
|
||||
true; \
|
||||
fi; \
|
||||
fi
|
||||
|
||||
latexfigures:
|
||||
@for i in $(FIGUREOBJS); do \
|
||||
$(MAKE) $$i; \
|
||||
done
|
||||
|
||||
viewdvi:
|
||||
view:
|
||||
# Below the 'true' is included to prevent unnecessarily many errors.
|
||||
@if [ -n "${LATEXTARGET}" ]; then \
|
||||
$(MAKE) ${LATEXTARGET}.dvi && \
|
||||
@ -328,24 +324,6 @@ viewdvi:
|
||||
fi; \
|
||||
fi
|
||||
|
||||
view:
|
||||
# Below the 'true' is included to prevent unnecessarily many errors.
|
||||
@if [ -n "${LATEXTARGET}" ]; then \
|
||||
$(MAKE) ${LATEXTARGET}.pdf && \
|
||||
$(PDFVIEWER) ${LATEXTARGET}.pdf; \
|
||||
true; \
|
||||
else \
|
||||
if [ `ls *.tex | wc -l` = "1" ]; then \
|
||||
$(MAKE) `basename \`ls *.tex\` .tex`.pdf && \
|
||||
$(PDFVIEWER) `basename \`ls *.tex\` .tex`.pdf; \
|
||||
true; \
|
||||
else \
|
||||
$(MAKE) `echo $$PWD|tr '/' '\n'|tail -1`.pdf && \
|
||||
$(PDFVIEWER) `echo $$PWD|tr '/' '\n'|tail -1`.pdf; \
|
||||
true; \
|
||||
fi; \
|
||||
fi
|
||||
|
||||
%.ps: %.dvi
|
||||
$(DVIPS) -o $@ $<
|
||||
|
||||
|
560
beispiele.tex
560
beispiele.tex
@ -1,4 +1,3 @@
|
||||
% $Id$
|
||||
\chapter{Beispiele}
|
||||
|
||||
|
||||
@ -13,132 +12,67 @@ Angenommen, bei der Benutzung eines Rechners tritt ein Problem auf, bei dem nur
|
||||
|
||||
Einfacher geht es, wenn wir uns ein kurzes Skript schreiben, das alle 30 Sekunden automatisch <20>berpr<70>ft, ob der Admin angemeldet ist. Wir erreichen das mit dem folgenden Code:
|
||||
|
||||
\footnotesize
|
||||
\index{\^=\texttt{\^}}\index{Anf<EFBFBD>hrungszeichen}\index{Pipe}\index{grep=\texttt{grep}}\index{sleep=\texttt{sleep}}\index{who=\texttt{who}}
|
||||
\begin{lstlisting}
|
||||
\begin{listing}[2]{1}
|
||||
#!/bin/sh
|
||||
until who | grep "^root "; do
|
||||
sleep 30
|
||||
until who | grep "^root "
|
||||
do sleep 30
|
||||
done
|
||||
echo "Big Brother is watching you!"
|
||||
\end{lstlisting}
|
||||
echo Big Brother is watching you!
|
||||
\end{listing}
|
||||
\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
|
||||
\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.
|
||||
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.
|
||||
|
||||
|
||||
\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}}
|
||||
\begin{lstlisting}
|
||||
\begin{listing}[2]{1}
|
||||
#!/bin/sh
|
||||
while who | grep "^root "; do
|
||||
sleep 30
|
||||
while who | grep "^root "
|
||||
do sleep 30
|
||||
done
|
||||
echo "Die Katze ist aus dem Haus, Zeit, da<64> die M<>use tanzen!"
|
||||
\end{lstlisting}
|
||||
echo Die Katze ist aus dem Haus, Zeit, da<64> die M<>use tanzen!
|
||||
\end{listing}
|
||||
\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.
|
||||
|
||||
|
||||
\section{Subshell-Schleifen vermeiden}\label{subshellschleifen}
|
||||
\section{Eine Datei zeilenweise bearbeiten}
|
||||
|
||||
Wir wollen ein Skript schreiben, das die \texttt{/etc/passwd} liest und dabei
|
||||
z<EFBFBD>hlt, wie viele Benutzer eine UID kleiner als 100 haben.
|
||||
\texttt{cat datei.txt | while read i}
|
||||
|
||||
Folgendes Skript funktioniert nicht:
|
||||
|
||||
\begin{lstlisting}
|
||||
#!/bin/sh
|
||||
count=0
|
||||
cat /etc/passwd | while read i; do
|
||||
uid=`echo $i | cut -f 3 -d:`
|
||||
if [ $uid -lt 100 ]; then
|
||||
count=`expr $count + 1`
|
||||
echo $count
|
||||
fi
|
||||
done
|
||||
echo Es sind $count Benutzer mit einer ID kleiner 100 eingetragen
|
||||
\end{lstlisting}
|
||||
|
||||
Was ist passiert?
|
||||
|
||||
Dieses Skript besteht im Wesentlichen aus einer Pipe. Wir haben ein
|
||||
\texttt{cat}-Kom\-man\-do, das den Inhalt der \texttt{/etc/passwd} durch eben
|
||||
diese Pipe an eine Schleife <20>bergibt. Das \texttt{read}-Kommando in der
|
||||
Schleife liest die einzelnen Zeilen aus, dann folgt ein Bi<42>chen Auswertung.
|
||||
|
||||
Es ist zu beobachten, da<64> bei der Ausgabe in Zeile 7 die Variable
|
||||
\texttt{\$count} korrekte Werte enth<74>lt. Um so unverst<73>ndlicher ist es, da<64> sie
|
||||
nach der Vollendung der Schleife wieder den Wert 0 enth<74>lt.
|
||||
|
||||
Das liegt daran, da<64> diese Schleife als Teil einer Pipe in einer Subshell
|
||||
ausgef<EFBFBD>hrt wird. Die Variable \texttt{\$count} steht damit in der Schleife
|
||||
praktisch nur lokal zur Verf<72>gung, sie wird nicht an das umgebende Skript
|
||||
`hochgereicht'.
|
||||
|
||||
Neben der Methode in \ref{daten_hochreichen} bietet sich hier eine viel
|
||||
einfachere L<>sung an:
|
||||
|
||||
\begin{lstlisting}
|
||||
#!/bin/sh
|
||||
count=0
|
||||
while read i; do
|
||||
uid=`echo $i | cut -f 3 -d:`
|
||||
if [ $uid -lt 100 ]; then
|
||||
count=`expr $count + 1`
|
||||
echo $count
|
||||
fi
|
||||
done < /etc/passwd
|
||||
echo Es sind $count Benutzer mit einer ID kleiner 100 eingetragen
|
||||
\end{lstlisting}
|
||||
|
||||
Hier befindet sich die Schleife nicht in einer Pipe, daher wird sie auch nicht
|
||||
in einer Subshell ausgef<65>hrt. Man kann auf das \texttt{cat}-Kommando verzichten
|
||||
und den Inhalt der Datei durch die Umlenkung in Zeile 9 direkt auf die
|
||||
Standardeingabe der Schleife (und somit auf das \texttt{read}-Kommando) legen.
|
||||
TODO!!!
|
||||
|
||||
Achtung! while ist eine Subshell - Daten m<>ssen hochgereicht werden.
|
||||
|
||||
\section{Ein typisches Init-Skript}\label{init-skript}\index{Init-Skript}
|
||||
|
||||
Dieses Skript dient dazu, den Apache HTTP-Server zu starten. Es wird w<>hrend
|
||||
des Bootvorgangs gestartet, wenn der dazugeh<65>rige Runlevel initialisiert wird.
|
||||
Dieses Skript dient dazu, den Apache HTTP-Server zu starten. Es wird w<>hrend des Bootvorgangs gestartet, wenn der dazugeh<65>rige Runlevel initialisiert wird.
|
||||
|
||||
Das Skript mu<6D> mit einem Parameter\index{Parameter} aufgerufen werden. M<>glich
|
||||
sind hier \textsl{start}, \textsl{stop}, \textsl{status}, \textsl{restart} und
|
||||
\textsl{reload}. Wenn falsche Parameter\index{Parameter} <20>bergeben wurden, wird
|
||||
eine entsprechende Meldung angezeigt.
|
||||
Das Skript mu<6D> mit einem Parameter\index{Parameter} aufgerufen werden. M<>glich sind hier \textsl{start}, \textsl{stop}, \textsl{status}, \textsl{restart} und \textsl{reload}. Wenn falsche Parameter\index{Parameter} <20>bergeben wurden, wird eine entsprechende Meldung angezeigt.
|
||||
|
||||
Das Ergebnis der Ausf<73>hrung wird mit Funktionen\index{Funktion} dargestellt,
|
||||
die aus der Datei \lstinline|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.
|
||||
|
||||
Zun<EFBFBD>chst wird festgelegt, da<64> dieses Skript in der Bourne-Shell ausgef<65>hrt
|
||||
werden soll (\ref{auswahl_der_shell}).
|
||||
|
||||
\begin{lstlisting}
|
||||
\begin{flushright}
|
||||
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{listing}[2]{1}
|
||||
#!/bin/sh
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
Dann folgen Kommentare\index{Kommentar}, die den Sinn des Skriptes erl<72>utern
|
||||
(\ref{kommentare}).
|
||||
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
\end{listing}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
Dann folgen Kommentare\index{Kommentar}, die den Sinn des Skriptes erl<72>utern (\ref{kommentare}).
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
\begin{listingcont}
|
||||
#
|
||||
# Startup script for the Apache Web Server
|
||||
#
|
||||
@ -150,109 +84,119 @@ Dann folgen Kommentare\index{Kommentar}, die den Sinn des Skriptes erl
|
||||
# config: /etc/httpd/conf/access.conf
|
||||
# config: /etc/httpd/conf/httpd.conf
|
||||
# config: /etc/httpd/conf/srm.conf
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
Jetzt wird die Datei mit den Funktionen\index{Funktion} eingebunden (\ref{source}).
|
||||
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
\index{source=\texttt{source}}
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
\begin{listingcont}
|
||||
# Source function library.
|
||||
. /etc/rc.d/init.d/functions
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
Hier werden die Aufrufparameter ausgewertet (\ref{case}).
|
||||
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
\index{\$n=\texttt{\$}$n$}\index{Anf<EFBFBD>hrungszeichen}\index{case=\texttt{case}}
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
\begin{listingcont}
|
||||
# See how we were called.
|
||||
case "$1" in
|
||||
start)
|
||||
echo -n "Starting httpd: "
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
Nachdem eine Meldung <20>ber den auszuf<75>hrenden Vorgang ausgegeben wurde, wird die Funktion \texttt{daemon} aus der Funktionsbibliothek ausgef<65>hrt. Diese Funktion startet das Programm, dessen Name hier als Parameter\index{Parameter} <20>bergeben wird. Dann gibt sie eine Meldung <20>ber den Erfolg aus.
|
||||
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
\begin{listingcont}
|
||||
daemon httpd
|
||||
echo
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
Jetzt wird ein Lock-File\footnote{Ein Lock-File signalisiert anderen Prozessen, da<64> ein bestimmter Proze<7A> bereits gestartet ist. So kann ein zweiter Aufruf verhindert werden.} angelegt.
|
||||
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
\index{Anf<EFBFBD>hrungszeichen}\index{touch=\texttt{touch}}
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
\begin{listingcont}
|
||||
touch /var/lock/subsys/httpd
|
||||
;;
|
||||
stop)
|
||||
echo -n "Shutting down http: "
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
Hier passiert im Prinzip das gleiche wie oben, nur da<64> mit der Funktion \texttt{killproc} der Daemon angehalten wird.
|
||||
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
\begin{listingcont}
|
||||
killproc httpd
|
||||
echo
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
Danach werden Lock-File und PID-File\footnote{In einem sogenannten PID-File hinterlegen einige Prozesse ihre Proze<7A>-ID, um anderen Programmen den Zugriff zu erleichtern (z. B. um den Proze<7A> anzuhalten etc).} gel<65>scht.
|
||||
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
\begin{listingcont}
|
||||
rm -f /var/lock/subsys/httpd
|
||||
rm -f /var/run/httpd.pid
|
||||
;;
|
||||
status)
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
Die Funktion \texttt{status} stellt fest, ob der entsprechende Daemon bereits l<>uft, und gibt das Ergebnis aus.
|
||||
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
\begin{listingcont}
|
||||
status httpd
|
||||
;;
|
||||
restart)
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
Bei Aufruf mit dem Parameter\index{Parameter} \textsl{restart} ruft sich das Skript zwei mal selbst auf (in \texttt{\$0} steht der Aufrufname des laufenden Programms). Einmal, um den Daemon zu stoppen, dann, um ihn wieder zu starten.
|
||||
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
\index{\$n=\texttt{\$}$n$}\index{Anf<EFBFBD>hrungszeichen}
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
\begin{listingcont}
|
||||
$0 stop
|
||||
$0 start
|
||||
;;
|
||||
reload)
|
||||
echo -n "Reloading httpd: "
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
Hier sendet die \texttt{killproc}-Funktion dem Daemon ein Signal\index{Signal} das ihm sagt, da<64> er seine Konfiguration neu einlesen soll.
|
||||
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
\index{\$n=\texttt{\$}$n$}\index{Anf<EFBFBD>hrungszeichen}
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
\begin{listingcont}
|
||||
killproc httpd -HUP
|
||||
echo
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {start|stop|restart|reload|status}"
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
Bei aufruf mit einem beliebigen anderen Parameter\index{Parameter} wird eine Kurzhilfe ausgegeben. Dann wird daf<61>r gesorgt, da<64> das Skript mit dem Exit-Code 1 beendet wird. So kann festgestellt werden, ob das Skript ordnungsgem<65><6D> beendet wurde (\ref{exit}).
|
||||
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
\index{exit=\texttt{exit}}
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
\begin{listingcont}
|
||||
exit 1
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
||||
\end{lstlisting}
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
|
||||
|
||||
\section{Parameter<EFBFBD>bergabe in der Praxis}\label{beisp_parameter}\index{Parameter}
|
||||
@ -261,19 +205,21 @@ Es kommt in der Praxis sehr oft vor, da
|
||||
|
||||
Das soll an folgendem Skript verdeutlicht werden. Das Skript kennt die Optionen \texttt{-a} und \texttt{-b}. Letzterer Option mu<6D> ein zus<75>tzlicher Wert mitgegeben werden. Alle anderen Parameter\index{Parameter} werden als Dateinamen interpretiert.
|
||||
|
||||
\footnotesize
|
||||
\index{\$@=\texttt{\$@}}\index{Anf<EFBFBD>hrungszeichen}\index{Backticks}\index{!|!|=\texttt{!|!|}}\index{getopt=\texttt{getopt}}\index{OR}\index{set=\texttt{set}}
|
||||
\begin{lstlisting}
|
||||
\begin{listing}[2]{1}
|
||||
#!/bin/sh
|
||||
set -- `getopt "ab:" "$@"` || {
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
\end{listing}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
Das \texttt{set}\index{set=\texttt{set}}-Kommando belegt den Inhalt der vordefinierten Variablen (\ref{vordefinierte_variablen}) neu, so da<64> es aussieht, als ob dem Skript die R<>ckgabewerte von \texttt{getopt}\index{getopt=\texttt{getopt}} <20>bergeben wurden. Man mu<6D> die beiden Minuszeichen angeben, da sie daf<61>r sorgen, da<64> die Aufrufparameter an \texttt{getopt}\index{getopt=\texttt{getopt}} und nicht an die Shell selbst <20>bergeben werden. Die originalen Parameter\index{Parameter} werden von \texttt{getopt}\index{getopt=\texttt{getopt}} untersucht und modifiziert zur<75>ckgegeben: \texttt{a} und \texttt{b} werden als Parameter\index{Parameter} Markiert, \texttt{b} sogar mit der M<>glichkeit einer zus<75>tzlichen Angabe.
|
||||
|
||||
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}}
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
\begin{listingcont}
|
||||
echo "Anwendung: `basename $0` [-a] [-b Name] Dateien" 1>&2
|
||||
exit 1
|
||||
}
|
||||
@ -281,284 +227,98 @@ echo "Momentan steht in der Kommandozeile folgendes: $*"
|
||||
aflag=0 name=NONE
|
||||
while :
|
||||
do
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
In einer Endlosschleife\index{Endlosschleife}, die man mit Hilfe des Null-Befehls (\texttt{:}, \ref{null-befehl}) baut, werden die `neuen' Parameter\index{Parameter} der Reihe nach untersucht. Wenn ein \texttt{-a} vorkommt, wird die Variable \texttt{aflag} gesetzt. Bei einem \texttt{-b} werden per \texttt{shift}\index{shift=\texttt{shift}} alle Parameter\index{Parameter} nach Links verschoben, dann wird der Inhalt des n<>chsten Parameters\index{Parameter} in der Variablen \texttt{name} gesichert.
|
||||
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
\index{!==\texttt{!=}}\index{\$n=\texttt{\$}$n$}\index{Anf<EFBFBD>hrungszeichen}\index{case=\texttt{case}}\index{shift=\texttt{shift}}
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
\begin{listingcont}
|
||||
case "$1" in
|
||||
-a) aflag=1 ;;
|
||||
-b) shift; name="$1" ;;
|
||||
--) break ;;
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
Wenn ein \texttt{-{}-} erscheint, ist das ein Hinweis darauf, da<64> die Liste der Parameter\index{Parameter} abgearbeitet ist. Dann wird per \texttt{break}\index{break=\texttt{break}} (\ref{break}) die Endlosschleife unterbrochen. Die Aufrufparameter enthalten jetzt nur noch die eventuell angegebenen Dateinamen, die jetzt von dem Restlichen Skript wie gewohnt weiterverarbeitet werden k<>nnen.
|
||||
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
\index{shift=\texttt{shift}}
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
\begin{listingcont}
|
||||
esac
|
||||
shift
|
||||
done
|
||||
shift
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
Am Ende werden die Feststellungen ausgegeben.
|
||||
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
\index{\$*=\texttt{\$*}}\index{Anf<EFBFBD>hrungszeichen}
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
\begin{listingcont}
|
||||
echo "aflag=$aflag / Name = $name / Die Dateien sind $*"
|
||||
|
||||
\end{lstlisting}
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
|
||||
|
||||
\section{Fallensteller: Auf Traps reagieren}\label{traps}\index{trap=\texttt{trap}|(}\index{Signal|(}
|
||||
\section{Fallensteller: Auf Traps
|
||||
reagieren}\label{traps}\index{trap=\texttt{trap}|(}\index{Signal|(}
|
||||
|
||||
Ein laufendes Shell-Skript kann durch Druck auf die Interrupt-Taste
|
||||
(\Ovalbox{CTRL}+\Ovalbox{C}) unterbrochen werden. Durch Druck auf
|
||||
diese Taste wird ein Signal an den entsprechenden Proze<7A> gesandt, das ihn
|
||||
bittet sich zu beenden. Dieses Signal hei<65>t SIGINT (f<>r SIGnal INTerrupt) und
|
||||
tr<EFBFBD>gt die Nummer 2. Das kann ein kleines Problem darstellen, wenn das Skript
|
||||
sich tempor<6F>re Dateien angelegt hat, da diese nach der Ausf<73>hrung nur noch
|
||||
unn<EFBFBD>tig Platz verbrauchen und eigentlich gel<65>scht werden sollten. Man kann
|
||||
sich sicher auch noch wichtigere F<>lle vorstellen, in denen ein Skript
|
||||
bestimmte Aufgaben auf jeden Fall erledigen mu<6D>, bevor es sich beendet.
|
||||
Ein laufendes Shell-Skript kann durch Druck auf die Interrupt-Taste (normalerweise \Ovalbox{CTRL}-\Ovalbox{C}) unterbrochen werden. Durch Druck auf diese Taste wird ein Signal an den entsprechenden Proze<7A> gesandt, das ihn bittet sich zu beenden. Dieses Signal hei<65>t SIGINT (f<>r SIGnal INTerrupt) und tr<74>gt die Nummer 2. Das kann ein kleines Problem darstellen, wenn das Skript sich tempor<6F>re Dateien angelegt hat, da diese nach der Ausf<73>hrung nur noch unn<6E>tig Platz verbrauchen und eigentlich gel<65>scht werden sollten. Man kann sich sicher auch noch wichtigere F<>lle vorstellen, in denen ein Skript bestimmte Aufgaben auf jeden Fall erledigen mu<6D>, bevor es sich beendet.
|
||||
|
||||
Es gibt eine Reihe weiterer Signale, auf die ein Skript reagieren kann. Alle
|
||||
sind in der Man-Page von \texttt{signal} beschrieben. Hier die
|
||||
wichtigsten:\nopagebreak
|
||||
Es gibt eine Reihe weiterer Signale, auf die ein Skript reagieren kann. Alle sind in der Man-Page von \texttt{signal} beschrieben. Hier die wichtigsten:\nopagebreak
|
||||
|
||||
\LTXtable{\textwidth}{tab_signale.tex}
|
||||
|
||||
Wie l<>st man jetzt dieses Problem? Gl<47>cklicherweise verf<72>gt die Shell <20>ber das
|
||||
\texttt{trap}-Kommando, mit dessen Hilfe man auf diese Signale reagieren kann.
|
||||
Die Anwendung soll in folgendem Skript beispielhaft dargestellt werden.
|
||||
Wie l<>st man jetzt dieses Problem? Gl<47>cklicherweise verf<72>gt die Shell <20>ber das \texttt{trap}-Kommando, mit dessen Hilfe man auf diese Signale reagieren kann. Die Anwendung soll in folgendem Skript beispielhaft dargestellt werden.
|
||||
|
||||
Das Skript soll eine komprimierte Textdatei mittels \texttt{zcat} in ein
|
||||
tempor<EFBFBD>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{!=}}
|
||||
\begin{lstlisting}
|
||||
\begin{listing}[2]{1}
|
||||
#!/bin/sh
|
||||
stat=1
|
||||
temp=/tmp/zeige$$
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
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{listing}
|
||||
\normalsize
|
||||
\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.
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
\index{Ticks}\index{!>\&=\texttt{!>\&}}\index{\$n=\texttt{\$}$n$}\index{Ticks}\index{Anf<EFBFBD>hrungszeichen}\index{Backticks}\index{basename=\texttt{basename}}
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
\begin{listingcont}
|
||||
trap 'rm -f $temp; exit $stat' 0
|
||||
trap 'echo "`basename $0`: Ooops..." 1>&2' 1 2 15
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
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{listingcont}
|
||||
\normalsize
|
||||
\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.
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
\index{\$\#=\texttt{\$\#}}\index{!==\texttt{!=}}\index{!>=\texttt{!>}}\index{\$n=\texttt{\$}$n$}\index{Anf<EFBFBD>hrungszeichen}\index{case=\texttt{case}}
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
\begin{listingcont}
|
||||
case $# in
|
||||
1) zcat "$1" > $temp
|
||||
pg $temp
|
||||
stat=0
|
||||
;;
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
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{listingcont}
|
||||
\normalsize
|
||||
\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.
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
\index{!>\&=\texttt{!>\&}}\index{\$n=\texttt{\$}$n$}\index{Anf<EFBFBD>hrungszeichen}\index{Backticks}\index{basename=\texttt{basename}}
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
\begin{listingcont}
|
||||
*) echo "Anwendung: `basename $0` Dateiname" 1>&2
|
||||
esac
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
Wenn \texttt{case} eine andere Parameterzahl feststellt, wird eine Meldung mit
|
||||
der Aufrufsyntax auf die Standard-Fehlerausgabe geschrieben.
|
||||
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
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|)}
|
||||
|
||||
|
||||
\section{Chaoten: Dateien in zuf<75>llige Reihenfolge bringen}\label{chaoten}\index{Zufallszahlen|(}
|
||||
|
||||
Wir wollen uns einen MP3-Player programmieren, der Alle MP3-Dateien aus einem
|
||||
bestimmten Verzeichnisbaum in zuf<75>lliger Reihenfolge abspielt. Damit dieses
|
||||
Problem f<>r uns eine Herausforderung darstellt\footnote{Denn schlie<69>lich hat
|
||||
mpg123 schon von Hause aus eine Random-Funktion.}, wollen wir vor dem Abspielen
|
||||
der jeweiligen Datei etwas mit dem Dateinamen anstellen. Ob das eine einfache
|
||||
Ausgabe per \texttt{echo} ist, oder ob der Name per Sprachsynthese oder auf
|
||||
einem externen Display angezeigt werden soll ist an dieser Stelle egal.
|
||||
|
||||
Das Problem ist, da<64> wir in der Shell nur <20>ber Umwege an Zufallszahlen kommen
|
||||
k<EFBFBD>nnen. Auf Systemen, in denen die Datei \texttt{/dev/urandom} existiert,
|
||||
liefert uns der Kernel aber schon sehr zuf<75>llige Zeichenfolgen. Diese Folgen
|
||||
k<EFBFBD>nnen alle Zeichen enthalten, daher m<>ssen sie vor der Benutzung f<>r unsere
|
||||
Zwecke noch etwas `bereinigt' werden.
|
||||
|
||||
Wie das aussieht, wenn es fertig ist, sieht man im folgenden Skript:
|
||||
|
||||
\index{!==\texttt{!=}}
|
||||
\begin{lstlisting}
|
||||
#!/bin/sh
|
||||
for i in `find $1 -type f -name "*.[mM][pP]3"`; do
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
Hier beginnt eine Schleife, die <20>ber alle Ausgaben des \texttt{find}-Kommandos
|
||||
iteriert. Dabei sucht \texttt{find} nach allen normalen Dateien (\texttt{-type
|
||||
f}), die die Extension .mp3 tragen (\texttt{-name \dq*.[mM][pP]3\dq} -- wir
|
||||
ignorieren Gro<72>- / Kleinschreibung).
|
||||
|
||||
\index{find=\texttt{find}}
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
echo `tr -dc "[:alpha:]" < /dev/urandom | \
|
||||
dd count=8 bs=1 2> /dev/null`$i
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
Hier ist der `magische Teil'. Mit dem \texttt{echo} wird die Ausgabe einer Pipe
|
||||
ausgegeben, gefolgt von dem aktuellen Dateinamen. Diese Pipe enth<74>lt ein
|
||||
\texttt{tr}, der alle ungewollten Zeichen (alles, was kein Textzeichen ist) aus
|
||||
einem Datenstrom entfernt. Die Daten erh<72>lt \texttt{tr} durch die
|
||||
\texttt{<}-Umleitung aus oben genannter Datei.
|
||||
|
||||
Diese Datei liefert `ohne Ende' Zeichen. Wir wollen aber nur acht Zeichen
|
||||
haben, die wir unserem Dateinamen voranstellen k<>nnen. Dazu benutzen wir das
|
||||
Kommando \texttt{dd} mit den angegebenen Parametern. Damit die Erfolgsmeldung
|
||||
von \texttt{dd} nicht die Ausgabe verunstaltet, lenken wir sie nach
|
||||
\texttt{/dev/null} um.
|
||||
\index{tr=\texttt{tr}}\index{dd=\texttt{dd}}
|
||||
|
||||
\index{find=\texttt{find}}
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
done | sort | cut -b 9- | while read i; do
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
Das Ergebnis der obigen Schleife ist also die Liste der Dateinamen, denen
|
||||
jeweils acht zuf<75>llige Zeichen vorangestellt wurden. Die Reihenfolge entspricht
|
||||
allerdings immer noch der Ausgabe von \texttt{find}, wird also nach jedem
|
||||
Durchlauf gleich sein.
|
||||
|
||||
Um das zu <20>ndern, pipen wir die Ausgabe der Schleife durch ein \texttt{sort}.
|
||||
Da die ersten acht Zeichen jeder Zeile zuf<75>llig sind, erhalten wir so eine
|
||||
zuf<EFBFBD>llige Reihenfolge der Zeilen. Jetzt m<>ssen wir nur noch durch ein
|
||||
\texttt{cut} die zuf<75>lligen Zeichen abschneiden, und erhalten so die
|
||||
urspr<EFBFBD>ngliche Liste von Dateien in einer zuf<75>lligen Reihenfolge.
|
||||
|
||||
Diese lesen wir jetzt zeilenweise mittels \texttt{read} ein. In der
|
||||
\texttt{while}-Schleife k<>nnen wir alle erforderlichen Sachen mit dem
|
||||
Dateinamen anstellen. Hier wird er nur mittels \texttt{echo} ausgegeben.
|
||||
\index{sort=\texttt{sort}}\index{cut=\texttt{cut}} \index{read=\texttt{read}}\index{while=\texttt{while}}
|
||||
|
||||
\index{find=\texttt{find}}
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
echo "Jetzt wird $i gespielt"
|
||||
mpg123 "$i"
|
||||
done
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
\index{Zufallszahlen|)}
|
||||
|
||||
|
||||
|
||||
\section{Wer suchet, der findet}\label{beispiele_suchen}\index{grep=\texttt{grep}|(textbf}
|
||||
|
||||
|
||||
\subsection{Prozesse suchen}\label{beispiele_suchen_prozesse}\index{ps=\texttt{ps}|(textbf}\index{pgrep=\texttt{pgrep}|(textbf}
|
||||
|
||||
Im Zusammenhang mit grep st<73><74>t fast jeder Shell-Skripter fr<66>her oder sp<73>ter auf
|
||||
das Problem, da<64> er irgendwas davon abh<62>ngig machen will, ob ein bestimmter
|
||||
Proze<EFBFBD> l<>uft oder nicht. Im Normalfall wird er zuerst folgendes ausprobieren,
|
||||
was aber oft (nicht immer) in die Hose gehen wird:
|
||||
|
||||
\lstinline/ps aux | grep prozessname && echo "l<>uft schon"/
|
||||
|
||||
Der Grund daf<61>r ist, da<64> unter Umst<73>nden in der Ausgabe von \texttt{ps} auch
|
||||
das \texttt{grep}-Kommando samt Parameter (\textit{prozessname}) aufgelistet
|
||||
wird. So findet das \texttt{grep}-Kom\-man\-do sich quasi selbst.
|
||||
|
||||
Abhilfe schafft entweder \texttt{pgrep} (\ref{pgrep}) oder das folgende
|
||||
Konstrukt:
|
||||
|
||||
\lstinline/ps aux | grep "[p]rozessname" && echo "l<>uft schon"/
|
||||
|
||||
Das p ist jetzt als eine Zeichenmenge (regul<EFBFBD>rer Ausdruck) angegeben worden.
|
||||
Jetzt sucht \texttt{grep} also nach dem String \textit{prozessname}, in der
|
||||
Ausgabe von \texttt{ps} erscheint das \texttt{grep}-Kommando allerdings mit
|
||||
\textit{[p]rozessname} und wird somit ignoriert.
|
||||
|
||||
\index{ps=\texttt{ps}|)textbf}\index{pgrep=\texttt{pgrep}|)textbf}
|
||||
|
||||
|
||||
\subsection{Dateiinhalte suchen}\label{beispiele_suchen_dateien}\index{find=\texttt{find}|(textbf}
|
||||
|
||||
Ein weiterer wertvoller Trick, diesmal im Zusammenhang mit \texttt{find}, ist
|
||||
folgendes Szenario: Es gibt ein Verzeichnis mit vielen Unterverzeichnissen,
|
||||
<EFBFBD>berall liegen Perl-Skripte und andere Dateien. Gesucht sind alle Dateien, in
|
||||
denen eine Zeile mit dem Inhalt `strict' vorkommt. Man k<>nnte jetzt
|
||||
folgendes versuchen:
|
||||
|
||||
\lstinline|grep -r strict *|
|
||||
|
||||
Das f<>hrt allerdings dazu, da<64> alle Dateien durchsucht werden, nicht nur die
|
||||
Perl-Skripte. Diese tragen nach unserer Konvention\footnote{Perl-Skripte m<>ssen
|
||||
keine spezielle Extension haben, es sei aber um des Beispiels Willen mal
|
||||
angenommen.} die Extension `.pl'. Wir starten also eine rekursive Suche <20>ber
|
||||
alle Dateien, die dem Muster entsprechen:
|
||||
|
||||
\lstinline|grep -r strict *.pl|
|
||||
|
||||
Und wieder f<>hrt es nicht zu dem gew<65>nschten Ergebnis. Da die
|
||||
Unterverzeichnisse nicht die Extension `*.pl' tragen, werden sie nicht
|
||||
ber<EFBFBD>cksichtigt. F<>r die Suche in Unterverzeichnissen ziehen wir \texttt{find}
|
||||
(Siehe Abschnitt \ref{find}) heran:
|
||||
|
||||
\lstinline|find . -name \*.pl -exec grep strict {} \;|
|
||||
|
||||
Dieser Befehl gibt uns zwar die gefundenen Zeilen aus, nicht aber die Namen der
|
||||
Dateien. Es sieht f<>r \texttt{grep} so aus als ob nur eine Datei durchsucht
|
||||
w<EFBFBD>rde, da besteht keine Notwendigkeit den Namen anzugeben. Das ginge mit dem
|
||||
Parameter \texttt{-l}, allerdings w<>rden uns dann nur noch die Dateinamen
|
||||
angezeigt. Eine Ausgabe mit beiden Informationen erhalten wir mit dem folgenden
|
||||
Konstrukt:
|
||||
|
||||
\lstinline|find . -name \*.pl -exec grep strict /dev/null {} \;|
|
||||
|
||||
Hier durchsucht \texttt{grep} nicht nur die gefundenen Dateien, sondern bei
|
||||
jedem Aufruf auch \texttt{/dev/null}, also den digitalen M<>lleimer der per
|
||||
Definition leer ist. Da es f<>r \texttt{grep} so aussieht als ob mehr als eine
|
||||
Datei durchsucht w<>rden, wird bei jeder Fundstelle sowohl der Dateiname als
|
||||
auch die gefundene Zeile ausgegeben.
|
||||
|
||||
\index{find=\texttt{find}|)textbf}
|
||||
\index{grep=\texttt{grep}|)textbf}
|
||||
|
17
quellen.tex
17
quellen.tex
@ -1,17 +1,10 @@
|
||||
% $Id$
|
||||
\chapter{Quellen}\label{quellen}
|
||||
\chapter{Quellen}
|
||||
|
||||
\begin{itemize}
|
||||
\item Bash Reference Manual (\href{http://www.gnu.org/software/bash/manual/bashref.html}{http://www.gnu.org/software/bash/manual/bashref.html})
|
||||
\item Die Man-Page der Bash
|
||||
\item Die deutschsprachige Shell-Newsgroup (\href{news://de.comp.os.unix.shell}{news://de.comp.os.unix.shell})
|
||||
\item Unix In A Nutshell (\href{http://www.oreilly.com/catalog/unixnut3/}{http://www.oreilly.com/catalog/unixnut3/})
|
||||
\item Unix Power Tools (\href{http://www.oreilly.com/catalog/upt2/}{http://www.oreilly.com/catalog/upt2/})
|
||||
\item Von DOS nach Linux HOWTO (\href{http://www.linuxhaven.de/dlhp/HOWTO/DE-DOS-nach-Linux-HOWTO.html}{http://www.linuxhaven.de/dlhp/HOWTO/DE-DOS-nach-Linux-HOWTO.html})
|
||||
\item Bash Guide for Beginners (\href{http://tldp.org/LDP/Bash-Beginners-Guide/}{http://tldp.org/LDP/Bash-Beginners-Guide/})
|
||||
\item Advanced Bash-Scripting Guide (\href{http://tldp.org/LDP/abs/}{http://tldp.org/LDP/abs/})
|
||||
\item The Open Group Base Specifications
|
||||
\item Single Unix Specifications V2
|
||||
\item Bash Reference Manual (\texttt{http://www.gnu.org/manual/bash-2.02/\\bashref.html})
|
||||
\item Unix In A Nutshell (\texttt{http://www.oreilly.com/catalog/unixnut3/})
|
||||
\item Unix Power Tools (\texttt{http://www.oreilly.com/catalog/upt2/})
|
||||
\item Von DOS nach Linux HOWTO (\texttt{http://www.tu-harburg.de/\\\~{}semb2204/dlhp/HOWTO/DE-DOS-nach-Linux-HOWTO.html})
|
||||
\item ... und eine Menge Skripte, die ich im Laufe der Zeit gelesen habe (das
|
||||
kann ich nur jedem empfehlen - es ist spannender als es sich anh<6E>rt...).
|
||||
\end{itemize}
|
||||
|
@ -1,4 +1,3 @@
|
||||
% $Id$
|
||||
\chapter{Schmutzige Tricks :-)}
|
||||
|
||||
Eigentlich sind diese Tricks gar nicht so schmutzig. Hier ist lediglich eine
|
||||
@ -24,411 +23,29 @@ haben.
|
||||
|
||||
\section{Die Tar-Br<42>cke}
|
||||
|
||||
Eine sogenannte Tar-Br<42>cke benutzt man, wenn eine oder mehrere Dateien zwischen
|
||||
Rechnern <20>bertragen werden sollen, aber kein Dienst wie SCP oder FTP zur
|
||||
Verf<EFBFBD>gung steht. Au<41>erdem hat die Methode den Vorteil, da<64> Benutzerrechte und
|
||||
andere Dateiattribute bei der <20>bertragung erhalten
|
||||
bleiben\footnote{Vorausgesetzt nat<61>rlich, da<64> der Benutzer auf der entfernten
|
||||
Seite <20>ber die n<>tigen Rechte verf<72>gt.}.
|
||||
|
||||
Der Trick besteht darin, auf einer Seite der Verbindung etwas mit \texttt{tar}
|
||||
einzupacken, dies durch eine Pipe auf die andere Seite der Verbindung zu
|
||||
bringen und dort wieder zu entpacken.
|
||||
|
||||
Wenn dem Kommando \texttt{tar} an Stelle eines Dateinamens ein Minus-Zeichen
|
||||
als Archiv gegeben wird, benutzt es~--~je nach der gew<65>hlten Aktion~--~die
|
||||
Standard-Ein- bzw. -Ausgabe. Diese kann an ein weiteres \texttt{tar} <20>bergeben
|
||||
werden um wieder entpackt zu werden.
|
||||
|
||||
Ein Beispiel verdeutlicht diese Kopier-F<>higkeit:
|
||||
|
||||
\lstinline_tar cf - . | ( cd /tmp/backup; tar xf - )_
|
||||
|
||||
Hier wird zun<75>chst der Inhalt des aktuellen Verzeichnisses `verpackt'. Das
|
||||
Resultat wird an die Standard-Ausgabe geschrieben. Auf der Empf<70>ngerseite der
|
||||
Pipe wird eine Subshell ge<67>ffnet. Das ist notwendig, da das empfangende
|
||||
\texttt{tar} in einem anderen Verzeichnis laufen soll. In der Subshell wird
|
||||
zun<EFBFBD>chst das Verzeichnis gewechselt. Dann liest ein \texttt{tar} von der
|
||||
Standard-Eingabe und entpackt alles was er findet. Sobald keine Eingaben mehr
|
||||
kommen, beendet sich der Proze<7A> mitsamt der Subshell.
|
||||
|
||||
Am Ziel-Ort finden sich jetzt die gleichen Dateien wie am Quell-Ort.
|
||||
|
||||
Das lie<69>e sich lokal nat<61>rlich auch anders l<>sen. Man k<>nnte erst ein Archiv
|
||||
erstellen, das dann an anderer Stelle wieder auspacken. Nachteil: Es mu<6D>
|
||||
gen<EFBFBD>gend Platz f<>r das Archiv vorhanden sein. Denkbar w<>re auch ein in den Raum
|
||||
gestelltes
|
||||
|
||||
\lstinline_cp -Rp * /tmp/backup_
|
||||
|
||||
Allerdings fehlen einem dabei mitunter n<>tzliche
|
||||
\texttt{tar}-Optionen\footnote{Mit \texttt{-l} verl<72><6C>t \texttt{tar}
|
||||
beispielsweise nicht das File-System. N<>tzlich wenn nur eine Partition
|
||||
gesichert werden soll.}, und die oben erw<72>hnte Br<42>cke w<>re mit einem reinen
|
||||
\texttt{cp} nicht m<>glich.
|
||||
|
||||
Eine Seite der Pipe kann n<>mlich auch ohne Probleme auf einem entfernten
|
||||
Rechner `stattfinden'. Kommandos wie \texttt{ssh} oder \texttt{rsh} (letzteres
|
||||
nur unter Vorsicht einsetzen!) schlagen die Br<42>cke zu einem anderen System,
|
||||
dort wird entweder gepackt und versendet oder quasi die Subshell gestartet und
|
||||
gelesen. Das sieht wie folgt aus:
|
||||
|
||||
\lstinline_ssh 192.168.2.1 tar clf - / | (cd /mnt/backup; tar xf - )_
|
||||
|
||||
Hier wird auf einem entfernten Rechner die Root-Partition verpackt, per SSH in
|
||||
das lokale System geholt und lokal im Backup-Verzeichnis entpackt.
|
||||
|
||||
Der Weg in die andere Richtung ist ganz <20>hnlich:
|
||||
|
||||
\lstinline_tar cf - datei.txt | ssh 192.168.2.1 "(mkdir -p $PWD ;cd $PWD; tar xf -)"_
|
||||
|
||||
Hier wird die Datei verpackt und versendet. Eine Besonderheit gegen<65>ber dem
|
||||
vorigen Beispiel besteht darin, da<64> das Zielverzeichnis bei Bedarf erstellt
|
||||
wird, bevor die Datei dort entpackt wird. Zur Erkl<6B>rung: Die Variable
|
||||
\texttt{\$PWD} wird, da sie nicht von Ticks `gesichert' wird, schon lokal durch
|
||||
die Shell expandiert. An dieser Stelle erscheint also auf dem entfernten System
|
||||
der Name des aktuellen Verzeichnisses auf dem lokalen System.
|
||||
TODO!!!
|
||||
|
||||
|
||||
\section{Binaries inside}
|
||||
|
||||
Software wird meistens in Form von Paketen verteilt. Entweder handelt es sich
|
||||
dabei um auf das Betriebssystem abgestimmte Installationspakete (rpm, deb, pkg
|
||||
usw.), gepackte Archive (zip, tgz) oder Installationsprogramme. Unter
|
||||
Unix-Systemen bietet sich f<>r letztere die Shell als Tr<54>gersystem an.
|
||||
Shell-Skripte sind mit wenigen Einschr<68>nkungen plattformunabh<62>ngig, sie k<>nnen
|
||||
also ohne vorherige Installations- oder Compilier-Arbeiten gestartet werden und
|
||||
die Umgebung f<>r das zu installierende Programm testen und / oder vorbereiten.
|
||||
|
||||
Abgesehen davon k<>nnen Skripte mit den hier vorgestellten Techniken auch andere
|
||||
Daten, z. B. Bilder oder T<>ne, enthalten.
|
||||
|
||||
Doch wie werden die~--~<7E>blicherweise bin<69>ren~--~Pakete auf das Zielsystem
|
||||
gebracht?
|
||||
|
||||
Im Prinzip gibt es daf<61>r zwei unterschiedliche Verfahren:
|
||||
TODO!!!
|
||||
|
||||
\subsection{Bin<EFBFBD>re Here-Dokumente}
|
||||
\index{Here-Dokument}
|
||||
|
||||
Eine M<>glichkeit ist es, die bin<69>re Datei in Form eines Here-Dokuments
|
||||
mitzuliefern. Da es aber in der Natur einer bin<69>ren Datei liegt nicht-druckbare
|
||||
Zeichen zu enthalten, kann die Datei mit Hilfe des Tools \texttt{uuencode}
|
||||
vorbereitet werden. Das Tool codiert Eingabedateien so, da<64> sie nur noch
|
||||
einfache Textzeichen enthalten.
|
||||
|
||||
Sehen wir uns das folgende einfache Beispiel an. Es ist etwas wild konstruiert
|
||||
und nicht sehr sinnvoll, aber es zeigt das Prinzip.
|
||||
|
||||
\begin{lstlisting}
|
||||
#!/bin/sh
|
||||
|
||||
echo "Das Bild wird ausgepackt..."
|
||||
|
||||
uudecode << 'EOF'
|
||||
begin 644 icon.png
|
||||
MB5!.1PT*&@H````-24A$4@```!8````6"`8```#$M&P[````"7!(67,```L3
|
||||
M```+$P$`FIP8````!&=!34$``+&.?/M1DP```"!C2%)-``!Z)0``@(,``/G_
|
||||
\end{lstlisting}
|
||||
|
||||
Nach einem Hinweis wird also das Here-Dokument als Eingabe f<>r das Tool
|
||||
\texttt{uudecode} benutzt. Erstellt wurde das Dokument mit einer Zeile der
|
||||
folgenden Form:
|
||||
|
||||
\lstinline|uuencode icon.png icon.png|
|
||||
|
||||
Wie man sieht ist der Name der Datei in dem Here-Dokument enthalten. Die Datei
|
||||
wird entpackt und unter diesem gespeichert. In der `realen Welt' mu<6D> an der
|
||||
Stelle auf jeden Fall sichergestellt werden, da<64> keine existierenden Dateien
|
||||
versehentlich <20>berschrieben werden.
|
||||
|
||||
Um diesen Abschnitt nicht allzu lang werden zu lassen <20>berspringen wir einen
|
||||
Teil der Datei.
|
||||
|
||||
\begin{lstlisting}[firstnumber=38]
|
||||
M#-""F4%,@%4.GUZ``"(*`6VW6!S#\>C_?/;__Q<R_S]<P/F7AXDA'I\>@``B
|
||||
K!>E;2S-,]5!A7`,,U'0@GQ6?8H```P`#@&?)O'P'L0````!)14Y$KD)@@@``
|
||||
`
|
||||
end
|
||||
EOF
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Fehler beim Auspacken der Datei"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
display icon.png
|
||||
\end{lstlisting}
|
||||
|
||||
Nach dem Entpacken wird noch der Exit-Code von \texttt{uudecode} <20>berpr<70>ft und
|
||||
im Fehlerfall eine Ausgabe gemacht. Im Erfolgsfall wird das Bild mittels
|
||||
\texttt{display} angezeigt.
|
||||
TODO!!!
|
||||
|
||||
\subsection{Schwanz ab!}
|
||||
|
||||
Diese Variante basiert darauf, da<64> die bin<69>re Datei ohne weitere Codierung an
|
||||
das Shell-Skript angeh<65>ngt wurde. Nachteil dieses Verfahrens ist, da<64> das
|
||||
`abschneidende Kommando' nach jeder <20>nderung der L<>nge des Skriptes angepa<70>t
|
||||
werden mu<6D>.
|
||||
TODO!!!
|
||||
|
||||
Dabei gibt es zwei Methoden, die angeh<65>ngte Datei wieder abzuschneiden. Die
|
||||
einfachere Methode funktioniert mit \texttt{tail}:
|
||||
\section{Dateien, die es nicht gibt}
|
||||
|
||||
\lstinline|tail -n +227 $0 > icon.png|
|
||||
TODO!!!
|
||||
|
||||
Dieses Beispiel geht davon aus, da<64> das Skript selbst 227 Zeilen umfa<66>t. Die
|
||||
bin<EFBFBD>re Datei wurde mit einem Kommando wie \lstinline|cat icon.png >> skript.sh|
|
||||
an das Skript angeh<65>ngt.
|
||||
\subsection{Speichern in nicht existente Dateien}
|
||||
|
||||
F<EFBFBD>r die etwas kompliziertere Variante mu<6D> die L<>nge des eigentlichen
|
||||
Skript-Teiles genau angepa<70>t werden. Wenn das Skript beispielsweise etwa 5,5kB
|
||||
lang ist, m<>ssen genau passend viele Leerzeilen oder Kommentarzeichen angeh<65>ngt
|
||||
werden, damit sich eine L<>nge von 6kB ergibt. Dann kann das Anh<6E>ngsel mit dem
|
||||
Kommando \texttt{dd} in der folgenden Form abgeschnitten werden:
|
||||
TODO!!!
|
||||
|
||||
\lstinline|dd bs=1024 if=$0 of=icon.png skip=6|
|
||||
|
||||
Das Kommando kopiert Daten aus einer Eingabe- in eine Ausgabedatei. Im
|
||||
einzelnen wird hier eine Blockgr<67><72>e (blocksize, bs) von 1024 Bytes festgelegt.
|
||||
Dann werden Eingabe- und Ausgabedatei benannt, dabei wird als Eingabedatei
|
||||
\texttt{\$0} und somit der Name des laufenden Skriptes benutzt. Schlie<69>lich
|
||||
wird festgelegt, da<64> bei der Aktion die ersten sechs Block~--~also die ersten
|
||||
sechs Kilobytes~--~<7E>bersprungen werden sollen.
|
||||
|
||||
Um es nochmal zu betonen: Diese beiden Methoden sind mit Vorsicht zu genie<69>en.
|
||||
Bei der ersten f<>hrt jede zus<75>tzliche oder gel<65>schte Zeile zu einer kaputten
|
||||
Ausgabedatei, bei der zweiten reichen schon einzelne Zeichen. In jedem Fall
|
||||
sollte nach dem Auspacken noch einmal mittels \texttt{sum} oder \texttt{md5sum}
|
||||
eine Checksumme gezogen und verglichen werden.
|
||||
|
||||
\section{Dateien, die es nicht gibt}\label{dateien_die_es_nicht_gibt}
|
||||
|
||||
Eine Eigenart der Behandlung von Dateien unter Unix besteht im Verhalten beim
|
||||
L<EFBFBD>schen. Gel<65>scht wird n<>mlich zun<75>chst nur der Verzeichniseintrag. Der Inode,
|
||||
also die Markierung im Dateisystem unter der die Datei gefunden werden kann,
|
||||
besteht weiterhin. Er wird erst dann freigegeben, wenn er nicht mehr
|
||||
referenziert wird. Physikalisch besteht die Datei also noch, sie wird lediglich
|
||||
im Verzeichnis nicht mehr angezeigt.
|
||||
|
||||
Hat ein Proze<7A> die Datei noch in irgendeiner Form ge<67>ffnet, kann er weiter
|
||||
darauf zugreifen. Erst wenn er die Datei schlie<69>t ist sie tats<74>chlich und
|
||||
unwiederbringlich `weg'.
|
||||
|
||||
Dieser Effekt der `nicht existenten Dateien' l<><6C>t sich an verschiedenen Stellen
|
||||
geschickt einsetzen.
|
||||
|
||||
|
||||
\subsection{Daten aus einer Subshell hochreichen}\label{daten_hochreichen}
|
||||
|
||||
Ein immer wieder auftretendes und oft sehr verwirrendes Problem ist, da<64>
|
||||
Variablen die in einer Subshell definiert wurden au<61>erhalb dieser nicht
|
||||
sichtbar sind (siehe Abschnitt \ref{subshellschleifen}). Dies ist um so
|
||||
<EFBFBD>rgerlicher, als da<64> Subshells auch bei vergleichsweise einfachen Pipelines
|
||||
ge<EFBFBD>ffnet werden.
|
||||
|
||||
Ein Beispiel f<>r ein mi<6D>lingendes Skriptfragment w<>re das folgende:
|
||||
|
||||
\begin{lstlisting}
|
||||
nCounter=0
|
||||
cat datei.txt | while read VAR; do
|
||||
nCounter=`expr $nCounter + 1`
|
||||
done
|
||||
echo "nCounter=$nCounter"
|
||||
\end{lstlisting}
|
||||
|
||||
Die Variable nCounter wird mit 0 initialisiert. Dann wird eine Datei per Pipe
|
||||
in eine \texttt{while}-Schleife geleitet. Innerhalb der Schleife wird f<>r jede
|
||||
eingehende Zeile die Variable hochgez<65>hlt. Am Ende der Schleife enth<74>lt die
|
||||
Variable tats<74>chlich den korrekten Wert, aber da die Pipe eine Subshell
|
||||
ge<EFBFBD>ffnet hat ist der Wert nach Beendigung der Schleife nicht mehr sichtbar. Das
|
||||
\texttt{echo}-Kommando gibt die Zahl 0 aus.
|
||||
|
||||
Es gibt mehrere Ans<6E>tze, diesem Problem zu begegnen. Am einfachsten w<>re es in
|
||||
diesem Fall, dem Rat aus Abschnitt \ref{subshellschleifen} zu folgen und die
|
||||
Subshell geschickt zu vermeiden. Doch das ist leider nicht immer m<>glich. Wie
|
||||
geht man in solchen F<>llen vor?
|
||||
|
||||
Bei einfachen Zahlenwerten k<>nnte beispielsweise ein R<>ckgabewert helfen.
|
||||
Komplexere Informationen k<>nnen in eine tempor<6F>re Datei geschrieben werden, die
|
||||
danach geparst werden m<><6D>te. Wenn die Informationen in Zeilen der Form
|
||||
\lstinline|VARIABLE="Wert"| gespeichert werden, kann die Datei einfach mittels
|
||||
\texttt{source} (Abschnitt \ref{source}) oder einem Konstrukt der folgenden Art
|
||||
gelesen werden:
|
||||
|
||||
\lstinline|eval `cat tempfile`|
|
||||
|
||||
Und genau mit dieser <20>berlegung kommen wir zu einem eleganten~--~wenn auch
|
||||
nicht ganz einfachen~--~Trick.
|
||||
|
||||
Anstatt die Daten in eine tempor<6F>re Datei zu schreiben, wo sie wom<6F>glich durch
|
||||
andere Prozesse ver<65>ndert oder ausgelesen werden k<>nnten, kann man sie auch in
|
||||
`nicht existente' Dateien schreiben. Das folgende Beispiel demonstriert das
|
||||
Verfahren:
|
||||
|
||||
\begin{lstlisting}
|
||||
#!/bin/sh -x
|
||||
TMPNAME="/tmp/`date '+%Y%m%d%H%M%S'`$$.txt"
|
||||
exec 3> "$TMPNAME"
|
||||
exec 4< "$TMPNAME"
|
||||
rm -f "$TMPNAME"
|
||||
\end{lstlisting}
|
||||
|
||||
Bis hierher wurde zun<75>chst eine tempor<6F>re Datei angelegt. Die Filehandles 3 und
|
||||
4 wurden zum Schreiben bzw. Lesen mit dieser Datei verbunden. Daraufhin wurde
|
||||
die Datei entfernt. Die Filehandles verweisen weiterhin auf die Datei, obwohl
|
||||
sie im Dateisystem nicht mehr sichtbar ist.
|
||||
|
||||
Kommen wir zum n<>tzlichen Teil des Skriptes:
|
||||
|
||||
\begin{lstlisting}[firstnumber=6]
|
||||
nCounter=0
|
||||
cat datei.txt | ( while read VAR; do
|
||||
while read VAR; do
|
||||
nCounter=`expr $nCounter + 1`
|
||||
done
|
||||
echo "nCounter=$nCounter"
|
||||
) >&3
|
||||
\end{lstlisting}
|
||||
|
||||
Hier wurde wieder die Variable nCounter initialisiert und in der Subshell die
|
||||
Zeilen gez<65>hlt wie im ersten Beispiel. Allerdings wurde explizit eine Subshell
|
||||
um die Schleife gestartet. Dadurch steht die in der Schleife hochgez<65>hlte
|
||||
Variable auch nach Beendigung der Schleife zur Verf<72>gung, allerdings immernoch
|
||||
nur in der Subshell. Um das zu <20>ndern, wird in Zeile 11 der Wert ausgegeben.
|
||||
Die Ausgaben der Subshell werden in den oben erstellen Deskriptor umgeleitet.
|
||||
|
||||
\begin{lstlisting}[firstnumber=13]
|
||||
echo "(vor eval) nCounter=$nCounter"
|
||||
eval `cat <&4`
|
||||
echo "(nach eval) nCounter=$nCounter"
|
||||
\end{lstlisting}
|
||||
|
||||
Das \texttt{echo}-Kommando in Zeile 13 beweist, da<64> der Wert von nCounter
|
||||
tats<EFBFBD>chlich au<61>erhalb der Subshell nicht zur Verf<72>gung steht. Zun<75>chst.
|
||||
|
||||
In Zeile 14 wird dann die ebenfalls oben schon angesprochene
|
||||
\texttt{eval}-Zeile benutzt, um die Informationen aus dem Filedeskriptor zu
|
||||
lesen, die die Schleife dort hinterlassen hat.
|
||||
|
||||
Abschlie<EFBFBD>end zeigt die Zeile 15, da<64> der Transport tats<74>chlich funktioniert
|
||||
hat, die Variable nCounter ist mit dem Wert aus der Subshell belegt.
|
||||
|
||||
|
||||
\subsection{Dateien gleichzeitig lesen und schreiben}\label{lesen_und_schreiben}
|
||||
|
||||
Es kommt vor, da<64> man eine Datei bearbeiten m<>chte, die hinterher aber wieder
|
||||
unter dem gleichen Namen zur Verf<72>gung stehen soll. Beispielsweise sollen alle
|
||||
Zeilen aus einer Datei entfernt werden, die nicht das Wort \textit{wichtig}
|
||||
enthalten.
|
||||
|
||||
Der erste Versuch an der Stelle wird etwas in der Form
|
||||
|
||||
\lstinline|grep wichtig datei.txt > datei.txt|
|
||||
|
||||
sein. Das kann funktionieren, es kann aber auch in die sprichw<68>rtliche Hose
|
||||
gehen. Das Problem an der Stelle ist, da<64> die Datei an der Stelle gleichzeitig
|
||||
zum Lesen und zum Schreiben ge<67>ffnet wird. Das Ergebnis ist undefiniert.
|
||||
|
||||
Eine Elegante L<>sung besteht darin, einen Filedeskriptor auf die Quelldatei zu
|
||||
legen und diese dann zu l<>schen. Die Datei wird erst dann wirklich aus dem
|
||||
Dateisystem entfernt, wenn kein Deskriptor mehr auf sie zeigt. Dann kann aus
|
||||
dem gerade angelegten Deskriptor gelesen werden, w<>hrend eine neue Datei unter
|
||||
dem alten Namen angelegt wird:
|
||||
|
||||
\begin{lstlisting}
|
||||
#!/bin/sh
|
||||
FILE=datei.txt
|
||||
exec 3< "$FILE"
|
||||
rm "$FILE"
|
||||
grep "wichtig" <&3 > "$FILE"
|
||||
\end{lstlisting}
|
||||
|
||||
Allerdings sollte man bei dieser Methode beachten, da<64> man im Falle eines
|
||||
Fehlers die Quelldaten verliert, da die Datei ja bereits gel<65>scht wurde.
|
||||
|
||||
\section{Auf der Lauer: Wachhunde}\label{wachhunde}\index{Watchdog}
|
||||
|
||||
Es kommt vor, da<64> man einen Proze<7A> startet, bei dem man sich nicht sicher sein
|
||||
kann da<64> er sich auch in absehbarer Zeit wieder beendet. Beispielsweise kann
|
||||
der Timeout f<>r einen Netzwerkzugriff deutlich h<>her liegen als erw<72>nscht, und
|
||||
wenn der `gegnerische' Dienst nicht antwortet bleibt einem nur zu warten.
|
||||
|
||||
Es sei denn, man legt einen geeigneten Wachhund\footnote{Der englische Begriff
|
||||
`Watchdog' ist in diesem Zusammenhang wahrscheinlich gel<65>ufiger...} auf die
|
||||
Lauer, der im Notfall rettend eingreift. In einem Shell-Skript k<>nnte das wie
|
||||
folgt aussehen:
|
||||
|
||||
\begin{lstlisting}
|
||||
#!/bin/sh
|
||||
timeout=5
|
||||
ping 192.168.0.254 &
|
||||
cmdpid=$!
|
||||
\end{lstlisting}
|
||||
|
||||
Bis hierher nichts aufregendes. Eine Variable wird mit dem Timeout belegt, also
|
||||
mit der Anzahl an Sekunden nach denen der zu <20>berwachende Proze<7A> unterbrochen
|
||||
werden soll. Dann wird der zu <20>berwachende Proze<7A> gestartet und mittels \& in
|
||||
den Hintergrund geschickt. Die Proze<7A>-ID des Prozesses wird in der Variablen
|
||||
cmdpid gesichert.
|
||||
|
||||
\begin{lstlisting}[firstnumber=5]
|
||||
(sleep $timeout; kill -9 $cmdpid) &
|
||||
watchdogpid=$!
|
||||
\end{lstlisting}
|
||||
|
||||
In Zeile 5 findet sich der eigentliche Watchdog. Hier wird eine Subshell
|
||||
gestartet, in der zun<75>chst der oben eingestellte Timeout abgewartet und dann
|
||||
der zu <20>berwachende Proze<7A> get<65>tet wird. Diese Subshell wird ebenfalls mit \&
|
||||
in den Hintergrund geschickt. Die ID der Subshell wird in der Variablen
|
||||
watchdogpid gesichert.
|
||||
|
||||
\begin{lstlisting}[firstnumber=7]
|
||||
wait $cmdpid
|
||||
kill $watchdogpid > /dev/null 2>&1
|
||||
exit 0
|
||||
\end{lstlisting}
|
||||
|
||||
Dann wird durch ein \texttt{wait}\index{wait=\texttt{wait}} darauf gewartet,
|
||||
da<EFBFBD> sich der <20>berwachte Proze<7A> beendet. Dabei w<>rde \texttt{wait} bis in alle
|
||||
Ewigkeit warten, w<>re da nicht der Watchdog in der Subshell. Wenn dem die
|
||||
Ausf<EFBFBD>hrung zu lange dauert, sorgt er daf<61>r da<64> der Proze<7A> beendet wird.
|
||||
|
||||
Kommt der <20>berwachte Proze<7A> aber rechtzeitig zur<75>ck, sorgt \texttt{kill} in
|
||||
Zeile 8 daf<61>r da<64> der Wachhund `eingeschl<68>fert' wird.
|
||||
|
||||
Auf diese Weise ist sichergestellt, da<64> der \texttt{ping} auf keinen Fall
|
||||
l<EFBFBD>nger als f<>nf Sekunden l<>uft.
|
||||
|
||||
|
||||
\section{Unter Druck: Auf Tasten warten}\label{tastendruck}\index{Tastendruck}
|
||||
|
||||
Oft baut man in l<>ngere Ausgaben eine Art Warte-Prompt im Stile von `Bitte
|
||||
Enter dr<64>cken um fortzufahren' ein. Gewartet wird dann mit Hilfe des
|
||||
\texttt{read}-Kommandos\index{read=\texttt{read}}.
|
||||
|
||||
Will man nicht nur auf den Druck der Enter-Taste reagieren, sondern auf einen
|
||||
beliebigen Tastendruck, eignet sich das folgende Konstrukt:
|
||||
|
||||
\begin{lstlisting}
|
||||
stty raw -echo
|
||||
inputchar=`dd if=/dev/tty bs=1 count=1 2> /dev/null`
|
||||
stty sane
|
||||
\end{lstlisting}
|
||||
|
||||
Zur Erkl<6B>rung: Mit dem Kommando \texttt{stty}\index{stty=\texttt{stty}} kann
|
||||
ein Terminal konfiguriert werden. Dabei kann es sich sowohl um eine Leitung wie
|
||||
die serielle Schnittstelle des Rechners handeln, als auch um das Terminal an
|
||||
dem der Benutzer sitzt. Jedes Terminal hat eine Reihe von Eigenschaften.
|
||||
Mittels \lstinline|stty raw -echo| wird das Terminal in einen passenden Modus
|
||||
geschaltet. Das \texttt{-echo} sorgt daf<61>r, da<64> eingegebene Zeichen nicht in
|
||||
der Konsole wiedergegeben werden.
|
||||
|
||||
Danach wird mit \texttt{dd}\index{dd=\texttt{dd}} genau ein Zeichen eingelesen.
|
||||
Die Fehlerausgabe von \texttt{dd} wird dabei nach /dev/null umgeleitet, da
|
||||
ansonsten auf der Konsole die Erfolgsmeldungen \textit{1+0 Datens<6E>tze ein, 1+0
|
||||
Datens<EFBFBD>tze aus} erscheinen w<>rden. Das gelesene Zeichen wird in der Variablen
|
||||
\texttt{\$inputchar} gesichert und steht somit zur Verf<72>gung.
|
||||
|
||||
Nach dem Einlesevorgang wird die Konsole schlie<69>lich mittels
|
||||
\lstinline|stty sane| wieder in einen benutzbaren Zustand zur<75>ckversetzt.
|
||||
\subsection{Daten aus einer Subshell hochreichen}
|
||||
|
||||
TODO!!!
|
||||
|
235
shell.tex
235
shell.tex
@ -1,4 +1,3 @@
|
||||
% $Id$
|
||||
%==============================================================================
|
||||
% LaTeX-Schema-Datei schema.tex
|
||||
%==============================================================================
|
||||
@ -7,39 +6,51 @@
|
||||
% Vorspann
|
||||
%==============================================================================
|
||||
|
||||
% Dokumentstil f<>r Buch
|
||||
\documentclass[
|
||||
a4paper, % Seitenformat A4
|
||||
12pt, % 12-Punkt-Schrift
|
||||
BCOR.5cm, % 0,5cm Rand f<>r die Bindung
|
||||
headsepline, % Trennlinie unter die Kopfzeile
|
||||
pointlessnumbers, % Keine Punkte hinter den
|
||||
% Gliederungsnummern
|
||||
halfparskip, % Abst<73>nde zwischen den Abs<62>tzen, statt
|
||||
% Einr<6E>ckung der ersten Zeile
|
||||
% draft, % Entwurfsmodus
|
||||
final, % Release-Modus
|
||||
twoside % Doppelseitig, f<>r Buch
|
||||
]{scrbook}
|
||||
\newif\ifpdf % Feststellen, ob wir PDF oder DVI
|
||||
% erzeugen
|
||||
\ifx\pdfoutput\undefined
|
||||
\pdffalse % Wir haben kein PDFLaTeX
|
||||
\else
|
||||
\pdftrue % Wir haben PDFLaTeX
|
||||
\fi
|
||||
|
||||
\ifpdf % PDF-Einstellungen
|
||||
\pdfoutput=1
|
||||
\pdfcompresslevel=9
|
||||
\pdfinfo{
|
||||
/Author (Ronald Schaten)
|
||||
/CreationDate (D:20000301170300) % (D:YYYYMMDDhhmmss)
|
||||
% /ModDate (D:19980212201000) % ModDate is similar
|
||||
/Title (Shell-Programmierung)
|
||||
/Subject (Shell-Programmierung)
|
||||
/Keywords (Shell)
|
||||
}
|
||||
\pdfcatalog{ % Catalog dictionary of PDF output.
|
||||
/PageMode /UseOutlines
|
||||
/URI (http://www.fi.muni.cz/)
|
||||
}
|
||||
\else % Nicht-PDF-Einstellungen
|
||||
\fi
|
||||
|
||||
% Dokumentstil f<>r Buch
|
||||
\documentclass[a4paper,12pt,draft,twoside]{book}
|
||||
\usepackage{german} % deutsches Paket f<>r Umlaute
|
||||
%\usepackage{t1enc} % DC-Font mit 8 Bit verwenden
|
||||
\usepackage[latin1]{inputenc} % Codepage latin1
|
||||
|
||||
\usepackage{mathptmx} % Andere Schriften benutzen
|
||||
\usepackage[scaled=.90]{helvet}
|
||||
\usepackage{courier}
|
||||
\usepackage{pifont} % f<>r dinglist (Icon neben Text)
|
||||
|
||||
%\usepackage[dvips]{graphicx} % Grafikpaket f<>r Bilder laden
|
||||
%\usepackage{epstopdf} % .eps bei Bedarf nach .pdf wandeln
|
||||
%\usepackage{graphicx} % Grafikpaket f<>r Bilder laden
|
||||
%\DeclareGraphicsRule{.tif}{bmp}{}{} % Grafikformate
|
||||
|
||||
|
||||
%\usepackage{tabularx} % f<>r Tabellen <20>ber die Seitenbreite
|
||||
%\usepackage{longtable} % f<>r Tabellen <20>ber die Seitenbreite
|
||||
%\usepackage{supertabular} % f<>r Tabellen <20>ber die Seitenbreite
|
||||
\usepackage{tabularx} % f<>r Tabellen <20>ber die Seitenbreite
|
||||
\usepackage{longtable} % f<>r Tabellen <20>ber die Seitenbreite
|
||||
\usepackage{supertabular} % f<>r Tabellen <20>ber die Seitenbreite
|
||||
\usepackage{ltxtable} % f<>r Tabellen <20>ber die Seitenbreite
|
||||
|
||||
\ifpdf % PDF-Einstellungen
|
||||
\usepackage{thumbpdf}
|
||||
\else % Nicht-PDF-Einstellungen
|
||||
\fi
|
||||
|
||||
\usepackage{makeidx} % Index wird sp<73>ter eingef<65>gt
|
||||
\makeindex % durch \printindex
|
||||
|
||||
@ -47,39 +58,23 @@
|
||||
|
||||
\usepackage{fancybox} % K<>stchen f<>r Tastendarstellung
|
||||
|
||||
%\usepackage{moreverb} % F<EFBFBD>r Listings
|
||||
\usepackage{listings} % F<>r Listings
|
||||
\lstset{
|
||||
extendedchars=true,
|
||||
backgroundcolor=\color[gray]{0.95},
|
||||
basicstyle=\ttfamily\footnotesize,
|
||||
numbers=left,
|
||||
numberstyle=\scriptsize,
|
||||
stepnumber=2,
|
||||
numbersep=5pt
|
||||
\usepackage{fancyhdr} % Kopf- und Fu<46>zeilen
|
||||
\pagestyle{fancy}
|
||||
\renewcommand{\chaptermark}[1]{\markboth{#1}{}}
|
||||
\renewcommand{\sectionmark}[1]{\markright{\thesection\ #1}}
|
||||
\fancyhf{}
|
||||
\fancyhead[RE]{\bfseries\leftmark}
|
||||
\fancyhead[LO]{\bfseries\rightmark}
|
||||
\fancyhead[RO,LE]{\bfseries\thepage}
|
||||
\renewcommand{\headrulewidth}{0.5pt}
|
||||
\addtolength{\headheight}{2.5pt}
|
||||
\fancypagestyle{plain}{
|
||||
\fancyhead{}
|
||||
\renewcommand{\headrulewidth}{0pt}
|
||||
\fancyfoot[C]{\bfseries\thepage}
|
||||
}
|
||||
|
||||
|
||||
% F<>r PDF
|
||||
\usepackage[
|
||||
pdftitle = {Shell-Programmierung},
|
||||
pdfsubject = {Programmierung~der~Unix-Shell},
|
||||
pdfkeywords = {shell~programmierung},
|
||||
pdfauthor = {Ronald~Schaten},
|
||||
bookmarks,
|
||||
bookmarksopen,
|
||||
bookmarksopenlevel = 1,
|
||||
bookmarksnumbered,
|
||||
linktocpage,
|
||||
colorlinks,
|
||||
linkcolor = black,
|
||||
urlcolor = black
|
||||
]{hyperref}
|
||||
|
||||
%\pdfinfo{/CreationDate (D:20000301170300-01'00')} % (D:YYYYMMDDhhmmss)
|
||||
|
||||
%% /ModDate (D:19980212201000) % ModDate is similar
|
||||
|
||||
\usepackage{moreverb} % F<>r Listings
|
||||
|
||||
\newcommand{\STRUT}{\rule{0in}{3ex}} % Ein vertikaler Abstand f<>r Tabellen
|
||||
|
||||
@ -92,149 +87,56 @@
|
||||
|
||||
\begin{document} % hiermit mu<6D> jedes Dokument beginnen
|
||||
|
||||
% Syntax-Boxen (sybox) definieren:
|
||||
\fboxsep 1.36mm
|
||||
\definecolor{g1}{gray}{0.95}
|
||||
\newsavebox{\syntaxbox}
|
||||
\newenvironment{sybox}
|
||||
{\begin{lrbox}{\syntaxbox}
|
||||
\begin{minipage}{\textwidth}}
|
||||
{\end{minipage}
|
||||
\end{lrbox}
|
||||
{\fcolorbox{g1}{g1}
|
||||
{\parbox{\textwidth}{\usebox{\syntaxbox}\hfill\hbox{}}}}}
|
||||
|
||||
\vspace*{.6in} % Die Titelseite
|
||||
\vspace*{.75in} % Die Titelseite
|
||||
\thispagestyle{empty}
|
||||
\begin{centering}
|
||||
\rule{5in}{.04in}\\ \vspace{.25in}
|
||||
\Huge {\bf SHELL\\ \vspace{.4in} PROGRAMMIERUNG}\\ \vspace{.1in}
|
||||
\rule{5in}{.04in}\\ \vspace{.6in}
|
||||
\large v2.0.1\\
|
||||
\rule{5in}{.04in}\\ \vspace{.5in}
|
||||
\large \today\\ \vspace{.75in}
|
||||
\large von\\ \vspace{.3in}
|
||||
\LARGE {\bf Ronald Schaten} \\ \vspace{.6in}
|
||||
\large ronald@schatenseite.de\\
|
||||
\large http://www.schatenseite.de/\\
|
||||
\end{centering}
|
||||
|
||||
\newpage
|
||||
\thispagestyle{empty} % eine Leerseite
|
||||
|
||||
\begin{quote}
|
||||
\emph{The best way to become acquainted with a subject is to write a book about it.
|
||||
\begin{flushright}(Benjamin Disraeli)\end{flushright}}
|
||||
\end{quote}
|
||||
|
||||
~\vfill
|
||||
|
||||
\footnotesize
|
||||
Die aktuellste Version dieses Dokumentes befindet sich auf
|
||||
\href{http://www.schatenseite.de/}{http://www.schatenseite.de/}.
|
||||
Copyright \copyright{} 2001 Ronald Schaten (\texttt{ronald@schatenseite.de})\bigskip
|
||||
|
||||
Dieses Dokument ist entstanden, weil ich f<>r mich selbst eine kompakte
|
||||
<EFBFBD>bersicht zu diesem Thema haben wollte. Ich beabsichtige nicht, damit in
|
||||
irgendeiner Form Kommerz zu machen. Ich stelle es zur Verf<72>gung, in der
|
||||
Hoffnung, da<64> andere Leute daraus vielleicht einen Nutzen ziehen k<>nnen.
|
||||
\textbf{Aber ich <20>bernehme keine Garantie f<>r die Korrektheit der hier
|
||||
dargestellten Dinge.}
|
||||
Die aktuellste Version dieses Dokumentes befindet sich im World Wide Web auf meiner Homepage (\texttt{http://www.schatenseite.de/}).\bigskip
|
||||
|
||||
Copyright \copyright{} 2000-2005 Ronald Schaten (ronald@schatenseite.de)
|
||||
Dieses Dokument ist entstanden, weil ich f<>r mich selbst eine kompakte <20>bersicht zu diesem Thema haben wollte. Ich beabsichtige nicht, damit in irgendeiner Form Kommerz zu machen. Ich stelle es frei zur Verf<72>gung, in der Hoffnung, da<64> andere Leute daraus vielleicht einen Nutzen ziehen k<>nnen. \textbf{Aber ich <20>bernehme keine Garantie f<>r die Korrektheit der hier dargestellten Dinge.} Mit der Formulierung \textsl{'daraus vielleicht einen Nutzen ziehen k<>nnen'} meine ich nicht, da<64> dieses Dokument~---~oder Teile daraus~---~verkauft werden darf. \textbf{Dieses Dokument darf nur kostenlos weitergegeben werden.}\bigskip
|
||||
|
||||
\textbf{Dieses Dokument steht unter der Creative Commons Lizenz.} Die
|
||||
Weiterverbreitung ist unter gewissen Bedingungen (Namensnennung, keine
|
||||
kommerzielle Nutzung und keine Bearbeitung) erlaubt und gew<65>nscht. Ich habe
|
||||
diese Lizenz gew<65>hlt um sicherzustellen da<64> Verbesserungen am Inhalt des
|
||||
Dokumentes bei mir ankommen, damit ich sie in die `Hauptversion' einflie<69>en
|
||||
lassen kann.
|
||||
|
||||
Die Lizenzbedingungen stehen unter
|
||||
\href{http://creativecommons.org/licenses/by-nc-nd/2.0/de/}{http://creativecommons.org/licenses/by-nc-nd/2.0/de/}.
|
||||
|
||||
|
||||
% <!-- Creative Commons-Lizenzvertrag -->
|
||||
% <a rel="license"
|
||||
% href="http://creativecommons.org/licenses/by-nc-nd/2.0/de/"><img alt="Creative
|
||||
% Commons-Lizenzvertrag" border="0"
|
||||
% src="http://creativecommons.org/images/public/somerights20.gif" /></a><br />
|
||||
% Diese Inhalt ist unter einer <a rel="license"
|
||||
% href="http://creativecommons.org/licenses/by-nc-nd/2.0/de/">Creative
|
||||
% Commons-Lizenz</a> lizenziert.
|
||||
% <!-- /Creative Commons-Lizenzvertrag -->
|
||||
%
|
||||
%
|
||||
% <!--
|
||||
%
|
||||
% <rdf:RDF xmlns="http://web.resource.org/cc/"
|
||||
% xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
% xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
% <Work rdf:about="">
|
||||
% <dc:title>Shell&#45;Programmierung</dc:title>
|
||||
% <dc:date>2005</dc:date>
|
||||
% <dc:description>Einf<6E>hrung in die
|
||||
% Shell&#45;Programmierung</dc:description>
|
||||
% <dc:creator><Agent>
|
||||
% <dc:title>Ronald Schaten</dc:title>
|
||||
% </Agent></dc:creator>
|
||||
% <dc:rights><Agent>
|
||||
% <dc:title>Ronald Schaten</dc:title>
|
||||
% </Agent></dc:rights>
|
||||
% <dc:type rdf:resource="http://purl.org/dc/dcmitype/Text" />
|
||||
% <license rdf:resource="http://creativecommons.org/licenses/by-nc-nd/2.0/de/"
|
||||
% />
|
||||
% </Work>
|
||||
%
|
||||
% <License rdf:about="http://creativecommons.org/licenses/by-nc-nd/2.0/de/">
|
||||
% <permits rdf:resource="http://web.resource.org/cc/Reproduction" />
|
||||
% <permits rdf:resource="http://web.resource.org/cc/Distribution" />
|
||||
% <requires rdf:resource="http://web.resource.org/cc/Notice" />
|
||||
% <requires rdf:resource="http://web.resource.org/cc/Attribution" />
|
||||
% <prohibits rdf:resource="http://web.resource.org/cc/CommercialUse" />
|
||||
% </License>
|
||||
%
|
||||
% </rdf:RDF>
|
||||
%
|
||||
% -->
|
||||
|
||||
Ich danke folgenden Personen, die mir bei der Durchsicht behilflich waren und
|
||||
durch ihre konstruktive Kritik zu Verbesserungen beigetragen haben (in
|
||||
chronologischer Reihenfolge ihres Eingreifens):
|
||||
Ich danke folgenden Personen, die mir bei der Durchsicht behilflich waren und durch ihre konstruktive Kritik zu Verbesserungen beigetragen haben (in chronologischer Reihenfolge ihres Eingreifens):
|
||||
|
||||
\begin{list}{$\bullet$}{\itemsep=-0.5cm}
|
||||
\item J<>rgen Ilse (ilse@asys-h.de)\\
|
||||
\item Christian Perle (christian.perle@tu-clausthal.de)\\
|
||||
\item Andreas Metzler (ametzler@downhill.at.eu.org)\\
|
||||
\item Johannes Kolb (johannes.kolb@web.de)\\
|
||||
\item Falk Friedrich (falk@gmx.de)\\
|
||||
\item Kai Th<54>ne (kai.thoene@gmx.de)\\
|
||||
\item J<>rgen Ilse (\texttt{ilse@asys-h.de})\\
|
||||
\item Christian Perle (\texttt{christian.perle@tu-clausthal.de})\\
|
||||
\item Andreas Metzler (\texttt{ametzler@downhill.at.eu.org})\\
|
||||
\item Johannes Kolb (\texttt{johannes.kolb@web.de})\\
|
||||
\end{list}
|
||||
|
||||
Und ich bitte alle Leser, auf eventuelle Fehler zu achten und mich darauf
|
||||
aufmerksam zu machen. Auch abgesehen davon freue ich mich <20>ber jede
|
||||
R<EFBFBD>ckmeldung.
|
||||
|
||||
Dieses Dokument entstand unter Verwendung von Linux, vim und \LaTeX. Dank an
|
||||
deren Entwickler.
|
||||
|
||||
Und ich bitte alle Leser, auf eventuelle Fehler zu achten und mich darauf aufmerksam zu machen. Auch abgesehen davon freue ich mich <20>ber jede R<>ckmeldung.
|
||||
\normalsize
|
||||
\newpage
|
||||
\pagenumbering{roman}
|
||||
%\renewcommand{\headrulewidth}{0.5pt}
|
||||
\renewcommand{\headrulewidth}{0.5pt}
|
||||
\setcounter{tocdepth}{3}
|
||||
\tableofcontents
|
||||
\newpage
|
||||
\pagenumbering{arabic}
|
||||
% Haupttextteil
|
||||
\include{was_ist_die_shell}
|
||||
\include{wo_sind_unterschiede_zu_dos_batchdateien}
|
||||
\include{wofuer_shell_programmierung}
|
||||
\include{wie_sieht_ein_shell_skript_aus}
|
||||
\include{werkzeugkasten}
|
||||
\include{nuetzliche_shell-kommandos}
|
||||
\include{wo_sind_unterschiede_zu_dos_batchdateien}
|
||||
\appendix
|
||||
\include{beispiele}
|
||||
\include{schmutzige_tricks}
|
||||
\include{quellen}
|
||||
\include{todo}
|
||||
|
||||
\printindex % Index einf<6E>gen
|
||||
|
||||
@ -244,6 +146,11 @@ deren Entwickler.
|
||||
|
||||
\end{document}
|
||||
|
||||
\ifpdf % PDF-Einstellungen
|
||||
\bye
|
||||
\else % Nicht-PDF-Einstellungen
|
||||
\fi
|
||||
|
||||
%==============================================================================
|
||||
% Ende von schema.tex
|
||||
%==============================================================================
|
||||
|
@ -1,4 +1,3 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
|
@ -1,4 +1,3 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
|
@ -1,4 +1,3 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
|
@ -1,4 +1,3 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
|
@ -1,4 +1,3 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
@ -11,10 +10,9 @@
|
||||
\textsl{Befehl}\texttt{ \&} & Ausf<73>hrung von \textsl{Befehl} im Hintergrund \tabularnewline\STRUT
|
||||
\textsl{Befehl1}\texttt{ ; }\textsl{Befehl2} & Befehlsfolge, f<>hrt mehrere Befehle nacheinander aus \tabularnewline\STRUT
|
||||
\texttt{(}\textsl{Befehl1}\texttt{ ; }\textsl{Befehl2}\texttt{)} & Subshell\index{Subshell}, behandelt \textsl{Befehl1} und \textsl{Befehl2} als Befehlsblock und f<>hrt sie in einer Subshell aus \tabularnewline\STRUT
|
||||
\texttt{\{ }\textsl{Befehl1}\texttt{ ; }\textsl{Befehl2}\texttt{; \}} & Befehlsblock; alle Befehle werden in der momentanen Shell ausgef<65>hrt, aber die Ausgaben werden behandelt, als ob nur ein Befehl ausgef<65>hrt w<>rde \tabularnewline\STRUT
|
||||
\texttt{\{ }\textsl{Befehl1}\texttt{ ; }\textsl{Befehl2}\texttt{ \}} & Befehlsblock; alle Befehle werden in der momentanen Shell ausgef<65>hrt, aber die Ausgaben werden behandelt, als ob nur ein Befehl ausgef<65>hrt w<>rde \tabularnewline\STRUT
|
||||
\textsl{Befehl1}\texttt{ | }\textsl{Befehl2} & Pipe\index{Pipe}, verwendet die Ausgabe von \textsl{Befehl1} als Eingabe f<>r \textsl{Befehl2} \tabularnewline\STRUT
|
||||
\textsl{Befehl1}\texttt{ `}\textsl{Befehl2}\texttt{`} & Befehls-Substitution, verwendet die Ausgabe von \textsl{Befehl2} als Argumente\index{Parameter}\index{Argument|see{Parameter}} f<>r \textsl{Befehl1} \tabularnewline\STRUT
|
||||
\textsl{Befehl1}\texttt{ \$(}\textsl{Befehl2}\texttt{)} & Befehls-Substitution, andere Schreibweise\tabularnewline\STRUT
|
||||
\textsl{Befehl1}\texttt{ \&\& }\textsl{Befehl2} & AND\index{AND}, f<>hrt zuerst \textsl{Befehl1} und dann (wenn \textsl{Befehl1} erfolgreich war) \textsl{Befehl2} aus\footnote{Einen <20>hnlichen Mechanismus kennt man aus verschiedenen Programmiersprachen unter dem Begriff \textsl{Kurzschlu<EFBFBD>auswertung}\index{Kurzschlu<EFBFBD>auswertung} bzw. \textsl{lazy evaluation}\index{Lazy Evaluation|see{Kurzschlu<EFBFBD>auswertung}}.} \tabularnewline\STRUT
|
||||
\textsl{Befehl1}\texttt{ || }\textsl{Befehl2} & OR\index{OR}, entweder \textsl{Befehl1} ausf<73>hren oder \textsl{Befehl2} (Wenn \textsl{Befehl1} nicht erfolgreich war)
|
||||
\end{longtable}
|
||||
|
@ -1,4 +1,3 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
|
@ -1,4 +1,3 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
@ -11,8 +10,7 @@
|
||||
\texttt{\$ nroff }\textsl{Datei}\texttt{ \&} & Formatiert die \textsl{Datei} im Hintergrund \tabularnewline\STRUT
|
||||
\texttt{\$ cd; ls} & Sequentieller Ablauf \tabularnewline\STRUT
|
||||
\texttt{\$ (date; who; pwd) > logfile}\index{!>=\texttt{!>}} & F<>hrt die Befehle in einer Subshell\index{Subshell} aus und lenkt alle Ausgaben um \tabularnewline\STRUT
|
||||
\texttt{\$ \{ date; who; pwd; \} > logfile}\index{!>=\texttt{!>}} & Lenkt alle Ausgaben um \tabularnewline\STRUT
|
||||
\texttt{\$ time \{ date; who; pwd; \}}\index{time=\texttt{time}} & Summiert die Laufzeit der drei Kommandos\tabularnewline\STRUT
|
||||
\texttt{\$ \{ date; who; pwd \} > logfile}\index{!>=\texttt{!>}} & Lenkt alle Ausgaben um \tabularnewline\STRUT
|
||||
\texttt{\$ sort }\textsl{Datei}\texttt{ | lp} & Sortiert die \textsl{Datei} und druckt sie\index{sort=\texttt{sort}} \tabularnewline\STRUT
|
||||
\texttt{\$ vi `grep -l ifdef *.c`}\index{*=\texttt{*}}\index{grep=\texttt{grep}} & Editiert die mittels grep gefundenen Dateien \tabularnewline\STRUT
|
||||
\texttt{\$ grep }\textsl{XX Datei}\texttt{ \&\& lp }\textsl{Datei}\index{grep=\texttt{grep}} & Druckt die \textsl{Datei}, wenn sie \textsl{XX} enth<74>lt\index{AND} \tabularnewline\STRUT
|
||||
|
@ -1,4 +1,3 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|X l|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
|
@ -1,4 +1,3 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
|
@ -1,4 +1,3 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|X l|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
|
@ -1,4 +1,3 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|X l|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
|
@ -1,4 +1,3 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|X l|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
|
@ -1,4 +1,3 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|X l|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
|
29
tab_beisp_for.tex
Normal file
29
tab_beisp_for.tex
Normal file
@ -0,0 +1,29 @@
|
||||
\begin{longtable}{|X l|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
\endfirsthead
|
||||
\endhead
|
||||
\endfoot
|
||||
\hline
|
||||
\endlastfoot
|
||||
|
||||
\multicolumn{2}{|X|}{\textsl{Seitenweises Formatieren der Dateien, die auf der Befehlszeile angegeben wurden, und speichern des jeweiligen Ergebnisses:}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{for file do}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{~pr \$file > \$file.tmp~~\# pr: Formatiert Textdateien}\index{!>=\texttt{!>}}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{done}} \\
|
||||
\multicolumn{2}{|X|}{\STRUT\textsl{Durchsuche Kapitel zur Erstellung einer Wortliste (wie \texttt{fgrep -f}):}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{for item in `cat program\_list`~~\# cat: Datei ausgeben}\index{cat=\texttt{cat}}\index{Backticks}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{do}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{~echo \dq Pruefung der Kapitel auf\dq}\index{Anf<EFBFBD>hrungszeichen}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{~echo \dq Referenzen zum Programm \$item ...\dq}\index{Anf<EFBFBD>hrungszeichen}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{~grep -c \dq\$item.[co]\dq~chap*~~\# grep: nach Muster\index{Mustererkennung} suchen}\index{[abc]=\texttt{[}\textsl{abc}\texttt{]}}\index{Anf<EFBFBD>hrungszeichen}\index{grep=\texttt{grep}}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{done}} \\
|
||||
\multicolumn{2}{|X|}{\STRUT\textsl{Ermittle einen Ein-Wort-Titel aus jeder Datei und verwende ihn als neuen Dateinamen:}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{for file do}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{~name=`sed -n 's/NAME: //p' \$file`}\index{!==\texttt{!=}}\index{Backticks}\index{Ticks}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{~~~~~~~~~~\# sed: Skriptsprache zur}\index{sed=\texttt{sed}}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{~~~~~~~~~~\# Textformatierung}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{~mv \$file \$name~~\# mv: Datei verschieben}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{~~~~~~~~~~~~~~~~~\# bzw. umbenennen}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{done}} \\
|
||||
\end{longtable}
|
16
tab_beisp_funktionen.tex
Normal file
16
tab_beisp_funktionen.tex
Normal file
@ -0,0 +1,16 @@
|
||||
\begin{longtable}{|X l|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
\endfirsthead
|
||||
\endhead
|
||||
\endfoot
|
||||
\hline
|
||||
\endlastfoot
|
||||
|
||||
\multicolumn{2}{|X|}{\texttt{count () \{}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{~ls -1 | wc -l~~\# ls: Liste aller Dateien im Verzeichnis}\index{Pipe}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{~~~~~~~~~~~~~~~~\#~~~~~Mit Parameter -1 einspaltig}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{~~~~~~~~~~~~~~~~\# wc: Word-Count, z<>hlt W<>rter}\index{wc=\texttt{wc}}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{~~~~~~~~~~~~~~~~\#~~~~~Mit Parameter -l Zeilen}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{\}}} \\
|
||||
\end{longtable}
|
16
tab_beisp_if.tex
Normal file
16
tab_beisp_if.tex
Normal file
@ -0,0 +1,16 @@
|
||||
\begin{longtable}{|X l|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
\endfirsthead
|
||||
\endhead
|
||||
\endfoot
|
||||
\hline
|
||||
\endlastfoot
|
||||
|
||||
\multicolumn{2}{|X|}{\textsl{F<EFBFBD>ge eine 0 vor Zahlen kleiner 10 ein:}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{if [ \$counter -lt 10 ]; then}\index{;=\texttt{;}}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{~number=0\$counter; else number=\$counter; fi}\index{!==\texttt{!=}}} \\
|
||||
\multicolumn{2}{|X|}{\STRUT\textsl{L<EFBFBD>sche ein Verzeichnis, wenn es existiert:}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{if [ -d \$dir ]; then}\index{!!=\texttt{!!}}\index{;=\texttt{;}}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{~rmdir \$dir; fi~~\# rmdir: Verzeichnis l<>schen}} \\
|
||||
\end{longtable}
|
13
tab_beisp_metazeichen.tex
Normal file
13
tab_beisp_metazeichen.tex
Normal file
@ -0,0 +1,13 @@
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
\endfirsthead
|
||||
\endhead
|
||||
\endfoot
|
||||
\hline
|
||||
\endlastfoot
|
||||
|
||||
\texttt{\$ ls neu*} & Listet alle Dateien, die mit `neu' anfangen \tabularnewline\STRUT
|
||||
\texttt{\$ ls neu?} & Listet `neuX', `neu4', aber nicht `neu10' \tabularnewline\STRUT
|
||||
\texttt{\$ ls [D-R]*} & Listet alle Dateien, die mit einem Gro<72>buchstaben\index{Gro<EFBFBD>buchstaben}\footnote{Nat<EFBFBD>rlich wird in Shell-Skripten --- wie <20>berall in der Unix-Welt --- zwischen Gro<72>- und Kleinschreibung unterschieden.} zwischen D und R anfangen
|
||||
\end{longtable}
|
@ -1,4 +1,3 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
|
@ -1,4 +1,3 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
|
@ -1,4 +1,3 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
|
@ -1,4 +1,3 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
|
15
tab_beisp_nullbefehl.tex
Normal file
15
tab_beisp_nullbefehl.tex
Normal file
@ -0,0 +1,15 @@
|
||||
\begin{longtable}{|X l|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
\endfirsthead
|
||||
\endhead
|
||||
\endfoot
|
||||
\hline
|
||||
\endlastfoot
|
||||
|
||||
\multicolumn{2}{|X|}{\texttt{if who | grep \$1 > /dev/null~~\# who: Liste der Benutzer}\index{Pipe}\index{\$n=\texttt{\$}$n$}\index{!>=\texttt{!>}}\index{who=\texttt{who}}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\# grep: Suche nach Muster}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{then :~~~~~~~~~~~~~~~~~~~~~~~~\# tut nichts}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{~else echo \dq Benutzer \$1 ist nicht angemeldet\dq}\index{Anf<EFBFBD>hrungszeichen}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{fi}} \\
|
||||
\end{longtable}
|
18
tab_beisp_quoting.tex
Normal file
18
tab_beisp_quoting.tex
Normal file
@ -0,0 +1,18 @@
|
||||
\begin{longtable}{|X l|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
\endfirsthead
|
||||
\endhead
|
||||
\endfoot
|
||||
\hline
|
||||
\endlastfoot
|
||||
|
||||
\multicolumn{2}{|X|}{\texttt{\$ echo 'Ticks \dq sch<63>tzen\dq~Anf<6E>hrungszeichen'}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{Ticks \dq sch<63>tzen\dq~Anf<6E>hrungszeichen}} \\
|
||||
\multicolumn{2}{|X|}{\STRUT\texttt{\$ echo \dq Ist dies ein \textbackslash\dq Sonderfall\textbackslash\dq ?\dq}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{Ist dies ein \dq Sonderfall\dq ?}} \\
|
||||
\multicolumn{2}{|X|}{\STRUT\texttt{\$ echo \dq Sie haben `ls | wc -l` Dateien in `pwd`\dq}\index{wc=\texttt{wc}}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{Sie haben 43 Dateien in /home/rschaten}} \\
|
||||
\multicolumn{2}{|X|}{\STRUT\texttt{\$ echo \dq Der Wert von \textbackslash\$x ist \$x\dq}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{Der Wert von \$x ist 100}} \\
|
||||
\end{longtable}
|
@ -1,4 +1,3 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
|
17
tab_beisp_until.tex
Normal file
17
tab_beisp_until.tex
Normal file
@ -0,0 +1,17 @@
|
||||
\begin{longtable}{|X l|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
\endfirsthead
|
||||
\endhead
|
||||
\endfoot
|
||||
\hline
|
||||
\endlastfoot
|
||||
|
||||
\multicolumn{2}{|X|}{\textsl{Warten, bis sich der Administrator einloggt:}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{until who | grep \dq root\dq; do}\index{;=\texttt{;}}\index{Anf<EFBFBD>hrungszeichen}\index{who=\texttt{who}}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{~~~~~~~~~~\# who: Liste der Benutzer}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{~~~~~~~~~~\# grep: Suchen nach Muster}\index{Mustererkennung}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{~sleep 2~~\# sleep: warten}\index{sleep=\texttt{sleep}}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{done}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{echo \dq Der Meister ist anwesend\dq}\index{Anf<EFBFBD>hrungszeichen}} \\
|
||||
\end{longtable}
|
@ -1,4 +1,3 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
@ -11,7 +10,7 @@
|
||||
\texttt{\$ \textsl{h}=\textsl{hoch} \textsl{r}=\textsl{runter} \textsl{l}=} & Weist den drei Variablen Werte zu, wobei \textsl{l} einen leeren Wert erh<72>lt. \tabularnewline\STRUT
|
||||
\texttt{\$ echo \$\{h\}sprung} & Gibt \textsl{hochsprung} aus. Die Klammern m<>ssen gesetzt werden, damit \textsl{h} als Variablenname erkannt werden kann. \tabularnewline\STRUT
|
||||
\texttt{\$ echo \$\{h-\$r\}} & Gibt \textsl{hoch} aus, da die Variable \textsl{h} belegt ist. Ansonsten w<>rde der Wert von \textsl{r} ausgegeben. \tabularnewline\STRUT
|
||||
\texttt{\$ echo \$\{tmp-`date`\}} & Gibt das aktuelle Datum aus, wenn die Variable \textsl{tmp} nicht gesetzt ist. \tabularnewline\STRUT
|
||||
\texttt{\$ echo \$\{tmp-`date`\}} & Gibt das aktuelle Datum aus, wenn die Variable \textsl{tmp} nicht gesetzt ist.\footnote{Der Befehl \texttt{date} gibt das Datum zur<75>ck.} \tabularnewline\STRUT
|
||||
\texttt{\$ echo \$\{l:=\$r\}} & Gibt \textsl{runter} aus, da die Variable \textsl{l} keinen Wert enth<74>lt. Gleichzeitig wird \textsl{l} der Wert von \textsl{r} zugewiesen. \tabularnewline\STRUT
|
||||
\texttt{\$ echo \$l} & Gibt \textsl{runter} aus, da \textsl{l} jetzt den gleichen Inhalt hat wie \textsl{r}.
|
||||
\end{longtable}
|
||||
|
@ -1,4 +1,3 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|X l|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
|
@ -1,4 +1,3 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|X l|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
|
11
tab_break.tex
Normal file
11
tab_break.tex
Normal file
@ -0,0 +1,11 @@
|
||||
\begin{longtable}{|X l|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
\endfirsthead
|
||||
\endhead
|
||||
\endfoot
|
||||
\hline
|
||||
\endlastfoot
|
||||
|
||||
\multicolumn{2}{|X|}{\texttt{break }\textsl{[ n ]}} \\
|
||||
\end{longtable}
|
15
tab_case.tex
Normal file
15
tab_case.tex
Normal file
@ -0,0 +1,15 @@
|
||||
\begin{longtable}{|X l|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
\endfirsthead
|
||||
\endhead
|
||||
\endfoot
|
||||
\hline
|
||||
\endlastfoot
|
||||
|
||||
\multicolumn{2}{|X|}{\texttt{case }\textsl{Wert}\texttt{ in}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{~}\textsl{Muster1}\texttt{) }\textsl{Befehle1}\texttt{;;}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{~}\textsl{Muster2}\texttt{) }\textsl{Befehle2}\texttt{;;}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{~\vdots}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{esac}} \\
|
||||
\end{longtable}
|
11
tab_continue.tex
Normal file
11
tab_continue.tex
Normal file
@ -0,0 +1,11 @@
|
||||
\begin{longtable}{|X l|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
\endfirsthead
|
||||
\endhead
|
||||
\endfoot
|
||||
\hline
|
||||
\endlastfoot
|
||||
|
||||
\multicolumn{2}{|X|}{\texttt{continue }\textsl{[ n ]}} \\
|
||||
\end{longtable}
|
@ -1,4 +1,3 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
|
@ -1,4 +1,3 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
|
@ -1,4 +1,3 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|X|X|X|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
|
@ -1,4 +1,3 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
|
11
tab_exit.tex
Normal file
11
tab_exit.tex
Normal file
@ -0,0 +1,11 @@
|
||||
\begin{longtable}{|X l|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
\endfirsthead
|
||||
\endhead
|
||||
\endfoot
|
||||
\hline
|
||||
\endlastfoot
|
||||
|
||||
\multicolumn{2}{|X|}{\texttt{exit }\textsl{[ n ]}} \\
|
||||
\end{longtable}
|
14
tab_for.tex
Normal file
14
tab_for.tex
Normal file
@ -0,0 +1,14 @@
|
||||
\begin{longtable}{|X l|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
\endfirsthead
|
||||
\endhead
|
||||
\endfoot
|
||||
\hline
|
||||
\endlastfoot
|
||||
|
||||
\multicolumn{2}{|X|}{\texttt{for }\textsl{x [}\texttt{ in }\textsl{Liste ]}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{do}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{~}\textsl{Befehle}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{done}} \\
|
||||
\end{longtable}
|
17
tab_if.tex
Normal file
17
tab_if.tex
Normal file
@ -0,0 +1,17 @@
|
||||
\begin{longtable}{|X l|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
\endfirsthead
|
||||
\endhead
|
||||
\endfoot
|
||||
\hline
|
||||
\endlastfoot
|
||||
|
||||
\multicolumn{2}{|X|}{\texttt{if }\textsl{Bedingung1}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{then }\textsl{Befehle1}} \\
|
||||
\multicolumn{2}{|X|}{\textsl{[}\texttt{ elif }\textsl{Bedingung2}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{ then }\textsl{Befehle2 ]}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{ \vdots}} \\
|
||||
\multicolumn{2}{|X|}{\textsl{[}\texttt{ else }\textsl{Befehle3 ]}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{fi}} \\
|
||||
\end{longtable}
|
@ -1,21 +0,0 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
\endfirsthead
|
||||
\endhead
|
||||
\endfoot
|
||||
\hline
|
||||
\endlastfoot
|
||||
|
||||
\texttt{FILENAME} & Der Name der aktuellen Eingabedatei, oder `-' wenn von der Standard-Eingabe gelesen wird\tabularnewline\STRUT
|
||||
\texttt{FS} & Field Separator, das Trennzeichen nach dem die Felder unterteilt werden \tabularnewline\STRUT
|
||||
\texttt{OFS} & Feldtrennzeichen f<>r die Ausgabe \tabularnewline\STRUT
|
||||
\texttt{RS} & Record Separator, das Trennzeichen nach dem Datens<6E>tze unterteilt werden \tabularnewline\STRUT
|
||||
\texttt{ORS} & Datensatztrennzeichen f<>r die Ausgabe \tabularnewline\STRUT
|
||||
\texttt{NF} & Anzahl der Felder im aktuellen Datensatz \tabularnewline\STRUT
|
||||
\texttt{NR} & Laufende Nummer des aktuellen Datensatzes \tabularnewline\STRUT
|
||||
\texttt{OFMT} & Ausgabeformat f<>r die Ausgabe von Zahlen und Strings, \tabularnewline\STRUT
|
||||
\texttt{\$0} & Der komplette aktuelle Datensatz \tabularnewline\STRUT
|
||||
\texttt{\$}\textsl{n} & Feld \textsl{n} des aktuellen Datensatzes
|
||||
\end{longtable}
|
@ -1,16 +0,0 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
\endfirsthead
|
||||
\endhead
|
||||
\endfoot
|
||||
\hline
|
||||
\endlastfoot
|
||||
|
||||
a-x & & Allen Benutzern werden die Ausf<73>hrungsrechte genommen \tabularnewline\STRUT
|
||||
ug+rw & & Dem Besitzer und der Gruppe werden Lese- und Schreibrechte gegeben \tabularnewline\STRUT
|
||||
u=rw,go-rwx & 600 & Nur der Besitzer kann die Datei lesen und schreiben \tabularnewline\STRUT
|
||||
u=rw,go=r & 644 & Der Besitzer darf lesen und schreiben, alle anderen nur lesen \tabularnewline\STRUT
|
||||
u=rwx,go=rx & 755 & Der Besitzer darf lesen, schreiben und ausf<73>hren, alle anderen nur lesen und ausf<73>hren
|
||||
\end{longtable}
|
@ -1,16 +0,0 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
\endfirsthead
|
||||
\endhead
|
||||
\endfoot
|
||||
\hline
|
||||
\endlastfoot
|
||||
|
||||
\textsl{s=\dq{}Dies ist ein Test\dq{}} & ~ \tabularnewline\STRUT
|
||||
\texttt{echo \dq{}\$s\dq{} | cut -c 2-6} & gibt `ies i' aus \tabularnewline\STRUT
|
||||
\texttt{echo \dq{}\$s\dq{} | cut -d \dq{}~\dq{} -f 2} & gibt `ist' aus \tabularnewline\STRUT
|
||||
\texttt{echo \dq{}\$s\dq{} | cut -d \dq{}~\dq{} -f 2-3} & gibt `ist ein' aus \tabularnewline\STRUT
|
||||
\texttt{echo \dq{}\$s\dq{} | cut -d \dq{}~\dq{} -f 2-} & gibt `ist ein Test' aus
|
||||
\end{longtable}
|
@ -1,16 +0,0 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
\endfirsthead
|
||||
\endhead
|
||||
\endfoot
|
||||
\hline
|
||||
\endlastfoot
|
||||
|
||||
\texttt{-n} & Unterdr<64>ckt den Zeilenumbruch am Ende der Ausgabe \tabularnewline\STRUT
|
||||
\texttt{-e} & Aktiviert die Interpretation von Steuerzeichen. Diese
|
||||
Steuerzeichen werden mit einem Backslash gequoted, der ganze String mu<6D> in
|
||||
Ticks eingeschlossen werden. Beispielsweise gibt \texttt{echo -e
|
||||
'hallo\textbackslash a'} das Wort hallo und einen Piepton aus.
|
||||
\end{longtable}
|
@ -1,19 +0,0 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
\endfirsthead
|
||||
\endhead
|
||||
\endfoot
|
||||
\hline
|
||||
\endlastfoot
|
||||
|
||||
\texttt{foo=42} & Der Variablen namens `foo' wird der Wert `42' zugewiesen. \tabularnewline\STRUT
|
||||
\texttt{a=foo} & Der Variablen namens `a' wird der Wert `foo' zugewiesen. \tabularnewline\STRUT
|
||||
\texttt{b='\$'\$a} & Der Variablen `b' wird ein \$ und der Inhalt der Variablen namens `a' zugewiesen. \tabularnewline\STRUT
|
||||
\texttt{echo \$b} & Der Inhalt der Variablen `b' wird ausgegeben. \tabularnewline\STRUT
|
||||
\textsl{\$foo} & \tabularnewline\STRUT
|
||||
\texttt{eval b='\$'\$a} & Zun<75>chst wird die Zeile nach dem \texttt{eval} expandiert, Variablen werden durch Inhalte ersetzt. Es entsteht also ein neuer Ausdruck: `b=\$foo'. Der wird dann von \texttt{eval} ausgef<65>hrt. \tabularnewline\STRUT
|
||||
\texttt{echo \$b} & Der neue Inhalt der Variablen `b' wird ausgegeben. \tabularnewline\STRUT
|
||||
\textsl{42} &
|
||||
\end{longtable}
|
@ -1,29 +0,0 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
\endfirsthead
|
||||
\endhead
|
||||
\endfoot
|
||||
\hline
|
||||
\endlastfoot
|
||||
|
||||
\texttt{|} & logisches `oder' \tabularnewline\STRUT
|
||||
\texttt{\&} & logisches `und' \tabularnewline\STRUT
|
||||
\texttt{<} & kleiner als \tabularnewline\STRUT
|
||||
\texttt{<=} & kleiner als oder gleich \tabularnewline\STRUT
|
||||
\texttt{=} & gleich \tabularnewline\STRUT
|
||||
\texttt{!=} & ungleich \tabularnewline\STRUT
|
||||
\texttt{>=} & gr<67><72>er als oder gleich \tabularnewline\STRUT
|
||||
\texttt{>} & gr<67><72>er als \tabularnewline\STRUT
|
||||
\texttt{+} & Addition \tabularnewline\STRUT
|
||||
\texttt{-} & Subtraktion \tabularnewline\STRUT
|
||||
\texttt{*} & Multiplikation \tabularnewline\STRUT
|
||||
\texttt{/} & Division \tabularnewline\STRUT
|
||||
\texttt{\%} & Modulo (`Divisionsrest') \tabularnewline\STRUT
|
||||
\texttt{:} & Pattern-Match mit regul<75>ren Ausdr<64>cken \tabularnewline\STRUT
|
||||
\texttt{match} & Analog zu `:' \tabularnewline\STRUT
|
||||
\texttt{substr} & Teil einer Zeichenkette zur<75>ckgeben \tabularnewline\STRUT
|
||||
\texttt{index} & Position einer Zeichenkette in einer anderen finden \tabularnewline\STRUT
|
||||
\texttt{length} & L<>nge einer Zeichenkette
|
||||
\end{longtable}
|
@ -1,31 +0,0 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
\endfirsthead
|
||||
\endhead
|
||||
\endfoot
|
||||
\hline
|
||||
\endlastfoot
|
||||
|
||||
Kriterien: & \tabularnewline\STRUT
|
||||
\texttt{-name }\textsl{pattern} & Suchmuster f<>r den Dateinamen, auch mit Meta-Zeichen (Abschnitt \ref{metazeichen}) \tabularnewline\STRUT
|
||||
\texttt{-perm [-]}\textsl{mode} & Sucht nach Dateien, deren Berechtigungen dem angegebenen Modus entsprechen. Die Notation erfolgt dabei analog zu \texttt{chmod} (Abschnitt \ref{chmod}), wahlweise in der Buchstaben- oder in der Zahlenform \tabularnewline\STRUT
|
||||
\texttt{-type }\textsl{c} & Sucht nach Dateien des angegebenen Typs. Dabei kann f<>r \textsl{c} `b' (block device), `c' (character device), `d' (directory), `l' (symbolic link), `p' (pipe), `f' (regular file), oder `s' (socket) eingesetzt werden \tabularnewline\STRUT
|
||||
\texttt{-user }\textsl{name} & Sucht nach Dateien, die dem angegebenen Benutzer geh<65>ren. Die Angabe kann als Name oder als UID erfolgen \tabularnewline\STRUT
|
||||
\texttt{-group }\textsl{name} & Sucht nach Dateien, die der angegebenen Gruppe geh<65>ren. Die Angabe kann als Name oder als GID erfolgen \tabularnewline\STRUT
|
||||
\texttt{-size }\textsl{n}\texttt{[c]} & Sucht nach Dateien, deren Gr<47><72>e \textsl{n} Blocks\footnote{Blocks geben die Dateigr<67><72>e in Bytes dividiert durch 512 und aufgerundet auf den n<>chsten Integer an. Das hat historische Gr<47>nde.} oder bei nachgestelltem \texttt{c} \textsl{n} Bytes ist \tabularnewline\STRUT
|
||||
\texttt{-atime }\textsl{n} & Sucht nach Dateien, deren letzter Zugriff (access time) \texttt{n}*24 Stunden zur<75>ck liegt \tabularnewline\STRUT
|
||||
\texttt{-ctime }\textsl{n} & Sucht nach Dateien, deren letzte Status<75>nderung (change time) \texttt{n}*24 Stunden zur<75>ck liegt \tabularnewline\STRUT
|
||||
\texttt{-mtime }\textsl{n} & Sucht nach Dateien, deren letzte <20>nderung (modification time) \texttt{n}*24 Stunden zur<75>ck liegt \tabularnewline\STRUT
|
||||
\texttt{-newer }\textsl{file} & Sucht nach Dateien, die j<>nger sind als \textsl{file} \tabularnewline\STRUT
|
||||
Optionen: & \tabularnewline\STRUT
|
||||
\texttt{-xdev} & Nur auf einem Filesystem suchen \tabularnewline\STRUT
|
||||
\texttt{-depth } & Normalerweise wird eine Breitensuche durchgef<65>hrt, dieser Parameter schaltet auf Tiefensuche um \tabularnewline\STRUT
|
||||
Aktionen: & \tabularnewline\STRUT
|
||||
\texttt{-print} & Dies ist default, die gefundenen Dateinamen werden ausgegeben \tabularnewline\STRUT
|
||||
\texttt{-exec }\textsl{kommando}\texttt{ \{\};} & F<>hrt das Kommando f<>r jede
|
||||
Fundstelle aus, an Stelle der geschweiften Klammern wird der gefundene
|
||||
Dateiname eingesetzt. Das abschlie<69>ende Semikolon mu<6D> wegen seiner
|
||||
Sonderbedeutung in der Regel durch einen Backslash gequoted werden
|
||||
\end{longtable}
|
@ -1,20 +0,0 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
\endfirsthead
|
||||
\endhead
|
||||
\endfoot
|
||||
\hline
|
||||
\endlastfoot
|
||||
|
||||
\texttt{-E} & Benutzt erweiterte regul<75>re Ausdr<64>cke \tabularnewline\STRUT
|
||||
\texttt{-F} & Der Suchbegriff wird nicht als regul<75>rer Ausdruck, sondern als `fixed String' benutzt \tabularnewline\STRUT
|
||||
\texttt{-c} & Gibt f<>r jede durchsuchte Datei die Anzahl der Fundstellen aus \tabularnewline\STRUT
|
||||
\texttt{-f} & Liest die Suchbegriffe Zeile f<>r Zeile aus einer Textdatei \tabularnewline\STRUT
|
||||
\texttt{-i} & Ignoriert die Unterscheidung zwischen Gro<72>- und Kleinschreibung \tabularnewline\STRUT
|
||||
\texttt{-l} & Gibt nur die Dateinamen aus \tabularnewline\STRUT
|
||||
\texttt{-n} & Gibt zus<75>tzlich die Zeilennummern der Fundstellen aus \tabularnewline\STRUT
|
||||
\texttt{-q} & Gibt die Fundstellen nicht aus, am Exitcode ist zu erkennen ob etwas gefunden wurde \tabularnewline\STRUT
|
||||
\texttt{-v} & Findet alle Zeilen, in denen das Suchmuster \emph{nicht} vorkommt
|
||||
\end{longtable}
|
@ -1,23 +0,0 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
\endfirsthead
|
||||
\endhead
|
||||
\endfoot
|
||||
\hline
|
||||
\endlastfoot
|
||||
|
||||
\texttt{-1} & Formatiert die Ausgabe einspaltig \tabularnewline\STRUT
|
||||
\texttt{-a} & Zeigt alle Dateien an, auch solche deren Name mit einem Punkt anf<6E>ngt \tabularnewline\STRUT
|
||||
\texttt{-A} & \ding{43} Zeigt `fast alle' Dateien an, also auch alle deren Name mit einem Punkt anf<6E>ngt, allerdings nicht `.' und `..', die in jedem Verzeichnis vorkommen \tabularnewline\STRUT
|
||||
\texttt{-d} & Verzeichnisse werden behandelt wie jede andere Datei auch, ein \texttt{ls -ld verzeichnis} gibt also die Eigenschaften des Verzeichnisses aus, nicht dessen Inhalt \tabularnewline\STRUT
|
||||
\texttt{-h} & \ding{43} Gibt bei einer langen Ausgabe mittels \texttt{-l} die Gr<47><72>e der Datei `human readable' aus, also nicht zwingend in Bytes \tabularnewline\STRUT
|
||||
\texttt{-l} & Lange Ausgabe, inklusiv der Dateiattribute \tabularnewline\STRUT
|
||||
\texttt{-L} & \ding{43} `Dereferenziert' Links vor der Ausgabe. Es werden nicht die Eigenschaften des Links angezeigt, sondern die der verlinkten Datei \tabularnewline\STRUT
|
||||
\texttt{-r} & Sortierreihenfolge umkehren \tabularnewline\STRUT
|
||||
\texttt{-R} & Rekursiv in Verzeichnisse absteigen und deren Inhalte anzeigen \tabularnewline\STRUT
|
||||
\texttt{-S} & \ding{43} Nach der Gr<47><72>e der Datei sortieren \tabularnewline\STRUT
|
||||
\texttt{-t} & Nach der letzten <20>nderungszeit sortieren \tabularnewline\STRUT
|
||||
\texttt{-X} & \ding{43} Nach der Extension (also dem Namensteil nach dem letzten Punkt) sortieren
|
||||
\end{longtable}
|
@ -1,15 +0,0 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
\endfirsthead
|
||||
\endhead
|
||||
\endfoot
|
||||
\hline
|
||||
\endlastfoot
|
||||
|
||||
\texttt{-f} & Normalerweise wird nur nach Proze<7A>-Namen gesucht, mit diesem Parameter wird das volle Kommando (incl. Pfad und Parametern) betrachtet\tabularnewline\STRUT
|
||||
\texttt{-l} & Nicht nur die Proze<7A>-ID, sondern das volle Kommando wird ausgegeben\tabularnewline\STRUT
|
||||
\texttt{-v} & Findet alle Zeilen, in denen das Suchmuster \emph{nicht} vorkommt\tabularnewline\STRUT
|
||||
\texttt{-x} & Sucht nach Kommandos, deren Name dem Muster \emph{exakt} entspricht
|
||||
\end{longtable}
|
@ -1,15 +0,0 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
\endfirsthead
|
||||
\endhead
|
||||
\endfoot
|
||||
\hline
|
||||
\endlastfoot
|
||||
|
||||
\texttt{\%b} & Behandelt die Ausgabe von Backslash-Sequenzen. Die Sequenzen sind im Abschnitt <20>ber \texttt{echo} (\ref{echo}) beschrieben. \tabularnewline\STRUT
|
||||
\texttt{\%s} & Gibt den n<>chsten Datenstring aus \tabularnewline\STRUT
|
||||
\texttt{\%}\textsl{n}\texttt{\$s} & Gibt den \textsl{n}-ten Datenstring aus \tabularnewline\STRUT
|
||||
\texttt{\%[-]}\textsl{m}\texttt{[.}\textsl{n}\texttt{]s} & Gibt den n<>chsten String aus, dazu wird ein Platz von \textsl{m} Zeichen reserviert. Optional k<>nnen nur die ersten \textsl{n} Zeichen ausgegeben oder mit \texttt{-} eine Rechtsb<73>ndige Formatierung festgelegt werden.
|
||||
\end{longtable}
|
@ -1,19 +0,0 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
\endfirsthead
|
||||
\endhead
|
||||
\endfoot
|
||||
\hline
|
||||
\endlastfoot
|
||||
|
||||
\texttt{d} & Keine Adresse angegeben, alle Zeilen werden gel<65>scht \tabularnewline\STRUT
|
||||
\texttt{23d} & Zeile 23 wird gel<65>scht \tabularnewline\STRUT
|
||||
\texttt{\$d} & Die letzte Eingabezeile wird gel<65>scht \tabularnewline\STRUT
|
||||
\texttt{/}\textsl{pattern}\texttt{/d} & Jede Zeile, die den regul<75>ren Ausdruck \textsl{pattern} enth<74>lt wird gel<65>scht \tabularnewline\STRUT
|
||||
\texttt{23,42d} & Die Zeilen 23 bis einschlie<69>lich 42 werden gel<65>scht \tabularnewline\STRUT
|
||||
\texttt{23,\$d} & Von Zeile 23 bis zum Ende wird gel<65>scht \tabularnewline\STRUT
|
||||
\texttt{1,/\^\$/d} & Von der ersten bis zur ersten Leerzeile wird gel<65>scht \tabularnewline\STRUT
|
||||
\texttt{23,42!d} & Alles au<61>er den Zeilen 23 bis 42 wird gel<65>scht
|
||||
\end{longtable}
|
@ -1,17 +0,0 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
\endfirsthead
|
||||
\endhead
|
||||
\endfoot
|
||||
\hline
|
||||
\endlastfoot
|
||||
|
||||
Editieren: & \tabularnewline\STRUT
|
||||
\texttt{/}\textsl{adresse}\texttt{/d} & Zeilen l<>schen \tabularnewline\STRUT
|
||||
\texttt{s/}\textsl{regexp1}\texttt{/}\textsl{regexp2}\texttt{/} & Substitution: Suchen und ersetzen \tabularnewline\STRUT
|
||||
\texttt{y/}\textsl{menge1}\texttt{/}\textsl{menge2}\texttt{/} & Zeichen ersetzen \tabularnewline\STRUT
|
||||
Zeileninformation: & \tabularnewline\STRUT
|
||||
\texttt{/}\textsl{adresse}\texttt{/p} & Zeilen ausgeben
|
||||
\end{longtable}
|
@ -1,16 +0,0 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
\endfirsthead
|
||||
\endhead
|
||||
\endfoot
|
||||
\hline
|
||||
\endlastfoot
|
||||
|
||||
\texttt{-k 3} & Sortiert nach dem dritten Feld \tabularnewline\STRUT
|
||||
\texttt{-k 3.5} & Sortiert nach dem f<>nften Zeichen des dritten Feldes \tabularnewline\STRUT
|
||||
\texttt{-k 3.5r} & Sortiert r<>ckw<6B>rts nach dem f<>nften Zeichen des dritten Feldes \tabularnewline\STRUT
|
||||
\texttt{-k 3,5} & Beachtet bei der Sortierung nur das dritte bis f<>nfte Feld \tabularnewline\STRUT
|
||||
\texttt{-k 3.5,3.8} & Beachtet die Zeichen f<>nf bis acht des dritten Feldes
|
||||
\end{longtable}
|
@ -1,20 +0,0 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
\endfirsthead
|
||||
\endhead
|
||||
\endfoot
|
||||
\hline
|
||||
\endlastfoot
|
||||
|
||||
\texttt{-b} & Ignoriert f<>hrende Leerzeichen \tabularnewline\STRUT
|
||||
\texttt{-c} & Pr<50>ft nur, ob die Eingabedaten bereits sortiert sind \tabularnewline\STRUT
|
||||
\texttt{-f} & Gro<72>- / Kleinschreibung nicht beachten \tabularnewline\STRUT
|
||||
\texttt{-i} & Nur `printable' Zeichen beachten \tabularnewline\STRUT
|
||||
\texttt{-k} & Sortiert nicht nach der ersten, sondern nach der angegebenen Spalte (siehe unten) \tabularnewline\STRUT
|
||||
\texttt{-n} & Numerische Sortierung \tabularnewline\STRUT
|
||||
\texttt{-r} & Sortierreihenfolge umkehren \tabularnewline\STRUT
|
||||
\texttt{-t} & Normalerweise f<>ngt ein Feld (siehe \texttt{-k}) beim <20>bergang von `blank' nach `non-blank' an, mit diesem Parameter k<>nnen ander Feld-Trenner definiert werden \tabularnewline\STRUT
|
||||
\texttt{-u} & Gibt bei identischen Zeilen nur die erste Fundstelle aus (unique)
|
||||
\end{longtable}
|
@ -1,19 +0,0 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
\endfirsthead
|
||||
\endhead
|
||||
\endfoot
|
||||
\hline
|
||||
\endlastfoot
|
||||
|
||||
\texttt{-c} & Anzahl der Vorkommnisse vor die Zeilen schreiben \tabularnewline\STRUT
|
||||
\texttt{-d} & Nur doppelte Zeilen ausgeben, jede nur einmal \tabularnewline\STRUT
|
||||
\texttt{-D} & \ding{43} Alle doppelten Zeilen ausgeben \tabularnewline\STRUT
|
||||
\texttt{-f }\textsl{n} & Die ersten \textsl{n} Felder ignorieren \tabularnewline\STRUT
|
||||
\texttt{-i} & \ding{43} Gro<72>- / Kleinschreibung ignorieren \tabularnewline\STRUT
|
||||
\texttt{-s }\textsl{n} & Die ersten \textsl{n} Zeichen ignorieren \tabularnewline\STRUT
|
||||
\texttt{-u} & Nur einfach vorkommende Zeilen ausgeben \tabularnewline\STRUT
|
||||
\texttt{-w }\textsl{n} & \ding{43} Nur die ersten \textsl{n} Zeichen betrachten
|
||||
\end{longtable}
|
@ -1,4 +1,3 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
|
@ -1,4 +1,3 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|c|c|c|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
|
@ -1,4 +1,3 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
|
@ -1,4 +1,3 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|c|c|c|c|c|c|c|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
|
@ -1,4 +1,3 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
|
@ -1,4 +1,3 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
@ -10,12 +9,11 @@
|
||||
|
||||
\texttt{;} & Befehls-Trennzeichen\index{Befehls>-Trennzeichen} \tabularnewline\STRUT
|
||||
\texttt{\&} & Hintergrund-Verarbeitung \tabularnewline\STRUT
|
||||
\texttt{( ) \{ \}} & Befehlsfolge\index{Befehls>-folge} \tabularnewline\STRUT
|
||||
\texttt{( )} & Befehlsfolge\index{Befehls>-folge} \tabularnewline\STRUT
|
||||
\texttt{|} & Pipe \tabularnewline\STRUT
|
||||
\texttt{< > >\&} & Umlenkungssymbole \tabularnewline\STRUT
|
||||
\texttt{* ? [ ] \~{} + - @ !} & Meta-Zeichen\index{Meta-Zeichen} f<>r Dateinamen \tabularnewline\STRUT
|
||||
\texttt{` ` }(Backticks oder Single Backquotes\footnote{Man erh<72>lt sie <EFBFBD>blicherweise durch \Ovalbox{SHIFT} und die Taste neben dem Backspace.}) & Befehls-Substitution\index{Befehls>-Substitution} \tabularnewline\STRUT
|
||||
\texttt{` ` }(Backticks\footnote{Man erh<72>lt sie durch \Ovalbox{SHIFT} und die Taste neben dem Backspace.}) & Befehls-Substitution\index{Befehls>-Substitution} \tabularnewline\STRUT
|
||||
\texttt{\$} & Variablen-Substitution\index{Variablen>-Substitution} \tabularnewline\STRUT
|
||||
\texttt{\Ovalbox{NEWLINE} \Ovalbox{SPACE} \Ovalbox{TAB}} &
|
||||
Wort-Trennzeichen\footnote{Die Wort-Trennzeichen sind in der vordefinierten Variable \texttt{\$IFS} abgelegt. Siehe Abschnitt \ref{vordefinierte_variablen}.}
|
||||
\texttt{\Ovalbox{NEWLINE} \Ovalbox{SPACE} \Ovalbox{TAB}} & Wort-Trennzeichen\footnote{Die Wort-Trennzeichen sind in der Variable \texttt{\$IFS}\index{\$IFS=\texttt{\$IFS}} abgelegt. Man kann diese Variable auch <20>berschreiben, um elegant Strings zu zerlegen.}
|
||||
\end{longtable}
|
||||
|
@ -1,4 +1,3 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
@ -8,18 +7,17 @@
|
||||
\hline
|
||||
\endlastfoot
|
||||
|
||||
\texttt{\dq~\dq} & (Anf<6E>hrungszeichen oder Double Quotes) Alles zwischen diesen
|
||||
Zeichen ist buchstabengetreu zu interpretieren. Ausnahmen sind folgende
|
||||
Zeichen, die ihre spezielle Bedeutung beibehalten: \texttt{\$ ` \dq}
|
||||
\texttt{\dq~\dq} & (Anf<6E>hrungszeichen) Alles zwischen diesen Zeichen ist
|
||||
buchstabengetreu zu interpretieren. Ausnahmen sind folgende Zeichen, die ihre
|
||||
spezielle Bedeutung beibehalten: \texttt{\$ ` \dq} \tabularnewline\STRUT
|
||||
|
||||
\texttt{' '} & (Ticks\footnote{Sie liegen auf der Tastatur <20>ber der Raute.})
|
||||
Alls zwischen diesen Zeichen wird w<>rtlich genommen, mit Ausnahme eines
|
||||
weiteren \texttt{'} oder eines Backslashes (\texttt{\textbackslash})
|
||||
\tabularnewline\STRUT
|
||||
|
||||
\texttt{' '} & (Ticks oder (Single) Quotes\footnote{Sie liegen auf der Tastatur
|
||||
<EFBFBD>ber der Raute.}) Alls zwischen diesen Zeichen wird w<>rtlich genommen, mit
|
||||
Ausnahme eines weiteren \texttt{'} oder eines Backslashes
|
||||
(\texttt{\textbackslash}) \tabularnewline\STRUT
|
||||
|
||||
\texttt{\textbackslash} & (Backslash\index{Backslash}) Das Zeichen nach einem
|
||||
\textbackslash wird w<>rtlich genommen. Anwendung z.~B. innerhalb von
|
||||
\textbackslash wird w<>rtlich genommen. Anwendung z. B. innerhalb von
|
||||
\texttt{\dq~\dq}, um \texttt{\dq}, \texttt{\$} und \texttt{`} zu entwerten.
|
||||
H<EFBFBD>ufig verwendet zur Angabe von Leerzeichen (space) und Zeilenendezeichen, oder
|
||||
um ein \textbackslash -Zeichen selbst anzugeben.
|
||||
|
@ -1,4 +1,3 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
@ -12,6 +11,6 @@ Nummer & Name & Bedeutung \\
|
||||
|
||||
0 & Normal Exit & Wird durch das \texttt{exit}\index{exit=\texttt{exit}}-Kommando ausgel<65>st. \tabularnewline\STRUT
|
||||
1 & SIGHUP & Wenn die Verbindung abbricht (z. B. wenn das Terminal geschlossen wird). \tabularnewline\STRUT
|
||||
2 & SIGINT & Zeigt einen Interrupt an (\Ovalbox{CTRL}+\Ovalbox{C}). \tabularnewline\STRUT
|
||||
2 & SIGINT & Zeigt einen Interrupt an (\Ovalbox{CTRL}-\Ovalbox{C}). \tabularnewline\STRUT
|
||||
15 & SIGTERM & Wird vom \texttt{kill}\index{kill=\texttt{kill}}-Kommando gesendet.
|
||||
\end{longtable}
|
||||
|
14
tab_until.tex
Normal file
14
tab_until.tex
Normal file
@ -0,0 +1,14 @@
|
||||
\begin{longtable}{|X l|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
\endfirsthead
|
||||
\endhead
|
||||
\endfoot
|
||||
\hline
|
||||
\endlastfoot
|
||||
|
||||
\multicolumn{2}{|X|}{\texttt{until }\textsl{Bedingung}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{do}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{~}\textsl{Befehle}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{done}} \\
|
||||
\end{longtable}
|
@ -1,4 +1,3 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
@ -9,9 +8,9 @@
|
||||
\endlastfoot
|
||||
|
||||
\textsl{Variable}\texttt{=}\textsl{Wert} & Setzt die \textsl{Variable} auf den \textsl{Wert}. Dabei ist unbedingt darauf zu achten, da<64> zwischen dem Variablennamen und dem Gleichheitszeichen keine Leerzeichen stehen. \tabularnewline\STRUT
|
||||
\texttt{\$\{}\textsl{Variable}\texttt{\}} & Nutzt den Wert von \textsl{Variable}. Die Klammern m<>ssen nur angegeben werden, wenn auf die \textsl{Variable} eine Zahl, ein Buchstabe oder ein Unterstrich folgen. \tabularnewline\STRUT
|
||||
\texttt{\$\{}\textsl{Variable}\texttt{:-}\textsl{Wert}\texttt{\}} & Nutzt den Wert von \textsl{Variable}. Falls die \textsl{Variable} nicht gesetzt oder leer ist, wird \textsl{Wert} benutzt. \tabularnewline\STRUT
|
||||
\texttt{\$\{}\textsl{Variable}\texttt{:=}\textsl{Wert}\texttt{\}} & Nutzt den Wert von \textsl{Variable}. Falls die \textsl{Variable} nicht gesetzt oder leer ist, wird \textsl{Wert} benutzt, und \textsl{Variable} erh<72>lt den \textsl{Wert}. \tabularnewline\STRUT
|
||||
\texttt{\$\{}\textsl{Variable}\texttt{:?}\textsl{Wert}\texttt{\}} & Nutzt den Wert von \textsl{Variable}. Falls die \textsl{Variable} nicht gesetzt oder leer ist, wird der \textsl{Wert} ausgegeben und die Shell beendet. Wenn kein \textsl{Wert} angegeben wurde, wird der Text \texttt{parameter null or not set} ausgegeben. \tabularnewline\STRUT
|
||||
\texttt{\$\{}\textsl{Variable}\texttt{:+}\textsl{Wert}\texttt{\}} & \textsl{Wert}, falls die \textsl{Variable} gesetzt und nicht leer ist, andernfalls nichts.
|
||||
\texttt{\$\{}\textsl{Variable}\texttt{\}} & Nutzt den Wert von \textsl{Variable}. Die Klammern m<>ssen nicht mit angegeben werden, wenn die \textsl{Variable} von Trennzeichen umgeben ist. \tabularnewline\STRUT
|
||||
\texttt{\$\{}\textsl{Variable}\texttt{:-}\textsl{Wert}\texttt{\}} & Nutzt den Wert von \textsl{Variable}. Falls die \textsl{Variable} nicht gesetzt ist, wird der \textsl{Wert} benutzt. \tabularnewline\STRUT
|
||||
\texttt{\$\{}\textsl{Variable}\texttt{:=}\textsl{Wert}\texttt{\}} & Nutzt den Wert von \textsl{Variable}. Falls die \textsl{Variable} nicht gesetzt ist, wird der \textsl{Wert} benutzt, und \textsl{Variable} erh<72>lt den \textsl{Wert}. \tabularnewline\STRUT
|
||||
\texttt{\$\{}\textsl{Variable}\texttt{:?}\textsl{Wert}\texttt{\}} & Nutzt den Wert von \textsl{Variable}. Falls die \textsl{Variable} nicht gesetzt ist, wird der \textsl{Wert} ausgegeben und die Shell beendet. Wenn kein \textsl{Wert} angegeben wurde, wird der Text \texttt{parameter null or not set} ausgegeben. \tabularnewline\STRUT
|
||||
\texttt{\$\{}\textsl{Variable}\texttt{:+}\textsl{Wert}\texttt{\}} & Nutzt den \textsl{Wert}, falls die \textsl{Variable} gesetzt ist, andernfalls nichts.
|
||||
\end{longtable}
|
||||
|
@ -1,4 +1,3 @@
|
||||
% $Id$
|
||||
\begin{longtable}{|l|X|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
@ -16,8 +15,6 @@
|
||||
\texttt{\$\$} & Proze<7A>nummer der aktiven Shell \tabularnewline\STRUT
|
||||
\texttt{\$!} & Proze<7A>nummer des letzten Hintergrundprozesses \tabularnewline\STRUT
|
||||
\texttt{\$ERRNO} & Fehlernummer des letzten fehlgeschlagenen Systemaufrufs \tabularnewline\STRUT
|
||||
\texttt{\$IFS} & Feldseparator, wird beispielsweise beim Lesen mittels \texttt{read} benutzt \tabularnewline\STRUT
|
||||
\texttt{\$PATH} & Pfad, in dem nach ausf<73>hrbaren Kommandos gesucht wird\footnote{Mit dem Kommando \texttt{type}\index{type=\texttt{type}} findet man heraus, welches Executable tats<74>chlich verwendet wird.}. Mehrere Eintr<74>ge werden durch Doppelpunkte getrennt angegeben \tabularnewline\STRUT
|
||||
\texttt{\$PWD} & Aktuelles Verzeichnis (wird durch \texttt{cd} gesetzt\footnote{Durch das Kommando \texttt{cd} wird das aktuelle Verzeichnis gewechselt, siehe Abschnitt \ref{cd}.}) \tabularnewline\STRUT
|
||||
\texttt{\$PWD} & Aktuelles Verzeichnis (wird durch \texttt{cd} gesetzt\footnote{Durch das Kommando \texttt{cd} wird das aktuelle Verzeichnis gewechselt.}) \tabularnewline\STRUT
|
||||
\texttt{\$OLDPWD} & Vorheriges Verzeichnis (wird durch \texttt{cd} gesetzt)
|
||||
\end{longtable}
|
||||
|
14
tab_while.tex
Normal file
14
tab_while.tex
Normal file
@ -0,0 +1,14 @@
|
||||
\begin{longtable}{|X l|}
|
||||
% KILLED & LINE!!!! \kill
|
||||
\hline
|
||||
\endfirsthead
|
||||
\endhead
|
||||
\endfoot
|
||||
\hline
|
||||
\endlastfoot
|
||||
|
||||
\multicolumn{2}{|X|}{\texttt{while }\textsl{Bedingung}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{do}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{~}\textsl{Befehle}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{done}} \\
|
||||
\end{longtable}
|
29
todo.tex
29
todo.tex
@ -1,29 +0,0 @@
|
||||
% $Id$
|
||||
\chapter{Routenplanung - Die Zukunft dieses Dokuments}
|
||||
|
||||
Ich werde in dieser Version des Dokumentes nicht alles umgesetzt haben, was mir
|
||||
sinnvoll erscheint. An dieser Stelle sammele ich Ideen f<>r eine n<>chste
|
||||
Version. Kommentare dazu nehme ich jederzeit dankend entgegen.
|
||||
|
||||
\begin{itemize}
|
||||
|
||||
\item \textbf{GNU / Posix:} Bessere Abgrenzung der GNU-Erweiterungen
|
||||
ge\-gen\-<EFBFBD>\-ber dem Posix-Standard, damit die Skripte portabel bleiben und
|
||||
nicht nur auf Linux laufen.
|
||||
|
||||
\item \textbf{Performance:} Ein Kapitel mit Hinweisen, wie Skripte nicht
|
||||
unn<EFBFBD>tig langsam werden.
|
||||
|
||||
\item \textbf{Interaktive Shell:} Exkurs zur interaktiven Benutzung der Bash.
|
||||
Es gibt da eine Reihe hilfreicher Tastenkombinationen, die l<>ngst nicht jedem
|
||||
bekannt sind.
|
||||
|
||||
\item \textbf{HTML-Version:} Ich w<>rde gerne eine HTML-Version zur Verf<72>gung
|
||||
stellen, bin mir aber noch nicht sicher ob das aus den \LaTeX-Quellen geht. Mir
|
||||
liegt dabei die Indizierung der Stichworte am Herzen, die sollte nicht
|
||||
verloren gehen.
|
||||
|
||||
\item \textbf{Glossar:} Verzeichnis von Begriffen wie PID, Prompt, GID, UID,
|
||||
Cron, usw.
|
||||
|
||||
\end{itemize}
|
@ -1,126 +1,45 @@
|
||||
% $Id$
|
||||
\chapter{Was ist die Shell?}\index{Shell}
|
||||
|
||||
Die Shell ist ein Programm, mit dessen Hilfe das System die Benutzerbefehle
|
||||
verstehen kann. Aus diesem Grund wird die Shell auch oft als Befehls- oder
|
||||
Kommandointerpreter bezeichnet.
|
||||
Die Shell ist ein Programm, mit dessen Hilfe das System die Benutzerbefehle verstehen kann. Aus diesem Grund wird die Shell auch oft als Befehls- oder Kommandointerpreter bezeichnet.
|
||||
|
||||
\section{Sinn und Zweck}
|
||||
|
||||
In einem klassischen Unix-System (ohne die grafische Oberfl<66>che X) greifen die
|
||||
Benutzer <20>ber Terminals\index{Terminal} auf das System zu. Auf diesen Terminals
|
||||
k<EFBFBD>nnen nur Textzeichen dargestellt werden. Um dem Benutzer die Arbeit mit dem
|
||||
System effektiv m<>glich zu machen, gibt es die Shell. Die Shell wird dabei f<>r
|
||||
drei Hauptaufgaben benutzt:
|
||||
In einem klassischen Unix-System (ohne die grafische Oberfl<66>che X) greifen die Benutzer <20>ber Terminals\index{Terminal} auf das System zu. Auf diesen Terminals k<>nnen nur Textzeichen dargestellt werden. Um dem Benutzer die Arbeit mit dem System effektiv m<>glich zu machen, gibt es die Shell. Die Shell wird dabei f<>r drei Hauptaufgaben benutzt:
|
||||
\begin{itemize}
|
||||
\item Interaktive Anwendung (Dialog)
|
||||
\item Anwendungsspezifische Anpassung des Unix-Systemverhaltens (Belegen von Umgebungsvariablen)
|
||||
\item Programmierung (Shell-Skripting). Zu diesem Zweck stehen einige Mechanismen zur Verf<72>gung, die aus Hochsprachen bekannt sind (Variablen, Datenstr<74>me, Funktionen usw.).
|
||||
\end{itemize}
|
||||
Urspr<EFBFBD>nglich handelte es sich dabei um ein relativ einfaches Programm, der
|
||||
Bourne Shell (wird oft auch Standard-Shell genannt). Dies ist praktisch die
|
||||
"`Mutter aller Shells"'. Aus dieser entwickelten sich im Laufe der Zeit mehrere
|
||||
Varianten, die alle ihre eigenen Vor- und Nachteile mit sich bringen. Da es
|
||||
unter Unix kein Problem darstellt den Kommandointerpreter auszutauschen, stehen
|
||||
auf den meisten Systemen mehrere dieser Shells zur Verf<72>gung. Welche Variante
|
||||
ein Benutzer verwenden m<>chte ist reine Geschmackssache.
|
||||
Urspr<EFBFBD>nglich handelte es sich dabei um ein relativ einfaches Programm, der Bourne Shell (wird oft auch Standard-Shell genannt). Dies ist praktisch die "`Mutter aller Shells"'. Aus dieser entwickelten sich im Laufe der Zeit mehrere Varianten, die alle ihre eigenen Vor- und Nachteile mit sich bringen. Da es unter Unix kein Problem darstellt den Kommandointerpreter auszutauschen, stehen auf den meisten Systemen mehrere dieser Shells zur Verf<72>gung. Welche Variante ein Benutzer verwenden m<>chte ist reine Geschmackssache.
|
||||
|
||||
\section{Die Qual der Wahl}
|
||||
|
||||
Um die Auswahl einer Shell zu erleichtern, werden hier die wichtigsten
|
||||
Varianten kurz vorgestellt. Sie sind aufgeteilt in Einfach- und Komfort-Shells.
|
||||
Die Komfort-Shells zeichnen sich durch komfortablere Funktionen zur
|
||||
interaktiven Bedienung aus, w<>hrend die Einfach-Versionen <20>blicherweise f<>r die
|
||||
Programmierung benutzt werden.
|
||||
Um die Auswahl einer Shell zu erleichtern, werden hier die wichtigsten Varianten kurz vorgestellt. Sie sind aufgeteilt in Einfach- und Komfort-Shells. Die Komfort-Shells zeichnen sich durch komfortablere Funktionen zur interaktiven Bedienung aus, w<>hrend die Einfach-Versionen <20>blicherweise f<>r die Programmierung benutzt werden.
|
||||
|
||||
\medskip\emph{Einfach-Shells:}\nopagebreak
|
||||
|
||||
\begin{itemize}
|
||||
\item Die
|
||||
Bourne-\index{Bourne-Shell|textbf}\index{Shell>Bourne-|see{Bourne-Shell}} oder
|
||||
Standard-Shell\index{Shell>Standard-|see{Bourne-Shell}}\index{Standard-Shell|see{Bourne-Shell}}
|
||||
(\texttt{sh}\index{sh=\texttt{sh}|see{Bourne-Shell}}) ist die kompakteste und
|
||||
einfachste Form. Sie bietet schon Mechanismen wie die Umlenkung der Ein- oder
|
||||
Ausgaben, Wildcards zur Abk<62>rzung von Dateinamen, Shell-Variablen und einen
|
||||
Satz interner Befehle zum Schreiben von Shell-Prozeduren. Neuere Versionen
|
||||
beherrschen auch das Job-Controlling\index{Job-Controlling}.
|
||||
\item Die Bourne-\index{Bourne-Shell|textbf}\index{Shell>Bourne-|see{Bourne-Shell}} oder Standard-Shell\index{Shell>Standard-|see{Bourne-Shell}}\index{Standard-Shell|see{Bourne-Shell}} (\texttt{sh}\index{sh=\texttt{sh}|see{Bourne-Shell}}) ist die kompakteste und einfachste Form. Sie bietet schon Mechanismen wie die Umlenkung der Ein- oder Ausgaben, Wildcards zur Abk<62>rzung von Dateinamen, Shell-Variablen und einen Satz interner Befehle zum Schreiben von Shell-Prozeduren. Neuere Versionen beherrschen auch das Job-Controlling\index{Job-Controlling}. F<>r die Entwicklung von Shell-Skripten sollte man sich auf diese Shell beschr<68>nken, da sie auf praktisch allen Systemen zur Verf<72>gung steht. So bleiben die Skripte portabel.
|
||||
|
||||
F<EFBFBD>r die Entwicklung von Shell-Skripten sollte man sich auf diese Shell
|
||||
beschr<EFBFBD>nken, da sie auf praktisch allen Systemen zur Verf<72>gung steht. So
|
||||
bleiben die Skripte mit kleinen Einschr<68>nkungen\footnote{Die verschiedenen
|
||||
Implementierungen weisen kleine Unterschiede, z. B. bei der Behandlung von \$@
|
||||
oder den Parametern von \texttt{read} (-r) auf.} portabel.
|
||||
\item Die Korn-Shell\index{Korn-Shell|textbf}\index{Shell>Korn-|see{Korn-Shell}} (\texttt{ksh}\index{ksh=\texttt{ksh}|see{Korn-Shell}}), eine Weiterentwicklung der Bourne-Shell, erlaubt das editieren in der Befehlszeile. Au<41>erdem gibt es hier History\index{History}-Funktionen\footnote{History-Funktionen erm<72>glichen es dem Benutzer, einfach auf zur<75>ckliegende Befehle zur<75>ckgreifen zu k<>nnen.}, eine Ganzzahl-Arithmetik, verbesserte M<>glichkeiten zur Mustererkennung, Aliase\index{Aliase}\footnote{Ein Alias ist eine Abk<62>rzung f<>r einen Befehl. Beispielsweise kann man das H<>ufig benutzte \texttt{ls -la} einfach durch \texttt{la} ersetzen.} und das Job-Controlling\footnote{Unter Job-Controlling versteht man einen Mechanismus, mit dessen Hilfe der Benutzer die Ausf<73>hrung von Prozessen selektiv stoppen oder fortsetzen kann}\index{Job-Controlling}. Au<41>erdem bietet die Korn-Shell im Gegensatz zu fast allen anderen Shells die M<>glichkeit, Aliase und Shell-Funktionen an Subshells zu vererben.
|
||||
|
||||
\item Die
|
||||
Korn-Shell\index{Korn-Shell|textbf}\index{Shell>Korn-|see{Korn-Shell}}
|
||||
(\texttt{ksh}\index{ksh=\texttt{ksh}|see{Korn-Shell}}), eine Weiterentwicklung
|
||||
der Bourne-Shell, erlaubt das Editieren in der Befehlszeile. Au<41>erdem gibt es
|
||||
hier History\index{History}-Funktionen\footnote{History-Funktionen erm<72>glichen
|
||||
es dem Benutzer, einfach auf zur<75>ckliegende Befehle zur<75>ckgreifen zu k<>nnen.},
|
||||
eine Ganzzahl-Arithmetik, verbesserte M<>glichkeiten zur Mustererkennung,
|
||||
Arrays, Aliase\index{Aliase}\footnote{Ein Alias ist eine Abk<62>rzung f<>r einen
|
||||
Befehl. Beispielsweise kann man das H<>ufig benutzte \texttt{ls -la} einfach
|
||||
durch \texttt{la} ersetzen.} und das Job-Controlling\footnote{Unter
|
||||
Job-Controlling versteht man einen Mechanismus, mit dessen Hilfe der Benutzer
|
||||
die Ausf<73>hrung von Prozessen selektiv stoppen oder fortsetzen
|
||||
kann}\index{Job-Controlling}. Au<41>erdem bietet die Korn-Shell im Gegensatz zu
|
||||
fast allen anderen Shells die M<>glichkeit, Aliase und Shell-Funktionen an
|
||||
Subshells zu vererben.
|
||||
|
||||
Die Korn-Shell existiert in verschiedenen Implementierungen, sowohl kommerziell
|
||||
(ksh88), kostenlos (ksh93) als auch frei (pdksh).
|
||||
|
||||
\item Die C-Shell \index{C-Shell|textbf}\index{Shell>C-|see{C-Shell}}
|
||||
(\texttt{csh}\index{csh=\texttt{csh}|see{C-Shell}}) bietet <20>hnliche
|
||||
Annehmlichkeiten wie die Korn-Shell, lehnt sich aber in der Syntax sehr stark
|
||||
an die Programmiersprache C an. Sie sollte nach M<>glichkeit nicht zur
|
||||
Shell-Programmierung benutzt werden, da sie an vielen Stellen nicht so
|
||||
reagiert, wie man es erwarten sollte.
|
||||
\item Die C-Shell \index{C-Shell|textbf}\index{Shell>C-|see{C-Shell}} (\texttt{csh}\index{csh=\texttt{csh}|see{C-Shell}}) bietet <20>hnliche Annehmlichkeiten wie die Korn-Shell, lehnt sich aber in der Syntax sehr stark an die Programmiersprache C an. Sie sollte nach M<>glichkeit nicht zur Shell-Programmierung benutzt werden, da sie an vielen Stellen nicht so reagiert, wie man es erwarten sollte.
|
||||
\end{itemize}
|
||||
|
||||
\medskip\emph{Komfort-Shells:}\nopagebreak
|
||||
|
||||
\begin{itemize}
|
||||
\item Die
|
||||
Bourne-Again-Shell\index{Bourne-Again-Shell|textbf}\index{Shell>Bourne-Again-|see{Bourne-Again-Shell}}\index{Shell>Bash|see{Bourne-Again-Shell}}
|
||||
(\texttt{bash}\index{bash=\texttt{bash}|see{Bourne-Again-Shell}}) ist voll
|
||||
abw<EFBFBD>rtskompatibel zur sh, bietet aber von allen Shells die komfortabelsten
|
||||
Funktionen f<>r das interaktive Arbeiten. Da die Bash ein GNU-Produkt ist, ist
|
||||
sie die Standard-Shell auf allen Linux-Systemen. Sie steht aber auch auf den
|
||||
meisten anderen Unixen zur Verf<72>gung. Die Bash unterst<73>tzt
|
||||
Auto-Completion\index{Auto-Completion|textbf}\footnote{Mit Auto-Completion ist
|
||||
das automatische Vervollst<73>ndigen von Dateinamen\index{Dateinamen} gemeint.},
|
||||
History-Funktionen, Aliase\index{Aliase}, eine Ganzzahl-Arithmetik und
|
||||
indizierte Arrays\index{Array}.
|
||||
\item Die Bourne-Again-Shell\index{Bourne-Again-Shell|textbf}\index{Shell>Bourne-Again-|see{Bourne-Again-Shell}}\index{Shell>Bash|see{Bourne-Again-Shell}} (\texttt{bash}\index{bash=\texttt{bash}|see{Bourne-Again-Shell}}) ist voll abw<62>rtskompatibel zur sh, bietet aber von allen Shells die komfortabelsten Funktionen f<>r das interaktive Arbeiten. Da die Bash ein GNU-Produkt ist, ist sie die Standard-Shell auf allen Linux-Systemen. Sie steht aber auch auf den meisten anderen Unixen zur Verf<72>gung.
|
||||
Die Bash unterst<73>tzt Auto-Completion\index{Auto-Completion|textbf}\footnote{Mit Auto-Completion ist das automatische Vervollst<73>ndigen von Dateinamen\index{Dateinamen} gemeint.}, History-Funktionen, Aliase\index{Aliase}, eine Ganzzahl-Arithmetik und indizierte Arrays\index{Array}.
|
||||
|
||||
\item Die
|
||||
TENEX-C-Shell\index{TENEX-C-Shell|textbf}\index{Shell>TENEX-C-|see{TENEX-C-Shell}}
|
||||
(\texttt{tcsh}\index{tcsh=\texttt{tcsh}|see{TENEX-C-Shell}}) verh<72>lt sich zur
|
||||
C-Shell wie die Bourne-Again-Shell zur Standard-Shell. Sie ist voll kompatibel,
|
||||
bietet aber Kom\-fort-Funk\-tio\-nen wie Kom\-man\-do\-zei\-len-Edi\-tie\-rung,
|
||||
programmierbare Auto-Completion\index{Auto-Completion},
|
||||
Recht\-schreib\-hil\-fen und eine History.
|
||||
|
||||
\item Die Z-Shell\index{Z-Shell|textbf}\index{Shell>Z-|see{Z-Shell}}
|
||||
(\texttt{zsh}\index{zsh=\texttt{zsh}|see{Z-Shell}}) <20>hnelt der Korn-Shell,
|
||||
enth<EFBFBD>lt aber viele Erweiterungen. Die Z-Shell unterst<73>tzt
|
||||
Kom\-mandozeilen-Editing, programmierbares
|
||||
Auto-Completion\index{Auto-Completion}, Shell-Funktionen und eine History.
|
||||
Zudem ist eine Rechtschreibpr<70>fung eingebaut. \end{itemize}
|
||||
\item Die TENEX-C-Shell\index{TENEX-C-Shell|textbf}\index{Shell>TENEX-C-|see{TENEX-C-Shell}} (\texttt{tcsh}\index{tcsh=\texttt{tcsh}|see{TENEX-C-Shell}}) verh<72>lt sich zur C-Shell wie die Bourne-Again-Shell zur Standard-Shell. Sie ist voll kompatibel, bietet aber Komfort-Funktionen wie Kommandozeilen-Editierung, programmierbare Auto-Completion\index{Auto-Completion}, Rechtschreibhilfen und eine History.
|
||||
|
||||
\item Die Z-Shell\index{Z-Shell|textbf}\index{Shell>Z-|see{Z-Shell}} (\texttt{zsh}\index{zsh=\texttt{zsh}|see{Z-Shell}}) <20>hnelt der Korn-Shell, enth<74>lt aber viele Erweiterungen. Die Z-Shell unterst<73>tzt Kommandozeilen-Editing, programmierbares Auto-Completion\index{Auto-Completion}, Shell-Funktionen und eine History. Zudem ist eine Rechtschreibpr<70>fung eingebaut.
|
||||
\end{itemize}
|
||||
|
||||
\medskip\emph{Exoten:}\medskip\nopagebreak
|
||||
|
||||
Desweiteren gibt es noch eine Reihe weiterer Shells, die aber nur selten
|
||||
eingesetzt werden. Dazu geh<65>ren die
|
||||
\texttt{ash}\index{ash|textbf}\index{Shell>ash=\texttt{ash}|see{ash}} (Ein
|
||||
Bourne-Shell-Clone f<>r Rechner mit wenig Speicher.),
|
||||
\texttt{rc}\index{rc|textbf}\index{Shell>rc=\texttt{rc}|see{rc}} (Noch ein
|
||||
Bourne-Shell-Clone, urspr<70>nglich aus AT\&T Plan 9. Klein, schnell und mit eine
|
||||
C-<2D>hnlichen Syntax.),
|
||||
\texttt{esh}\index{esh|textbf}\index{Shell>esh=\texttt{esh}|see{esh}} (Klein
|
||||
und schnell, bietet eine Lisp-<2D>hnliche Sprache),
|
||||
\texttt{sash}\index{sash|textbf}\index{Shell>sash=\texttt{sash}|see{sash}}
|
||||
(System Administrator's Shell - eine statisch gelinkte Shell mit integrierten
|
||||
Stan\-dard-Kom\-man\-dos.).
|
||||
Desweiteren gibt es noch eine Reihe weiterer Shells, die aber nur selten eingesetzt werden. Dazu geh<65>ren die \texttt{ash}\index{ash|textbf}\index{Shell>ash=\texttt{ash}|see{ash}} (Ein Bourne-Shell-Clone f<>r Rechner mit wenig Speicher.), \texttt{rc}\index{rc|textbf}\index{Shell>rc=\texttt{rc}|see{rc}} (Noch ein Bourne-Shell-Clone, urspr<70>nglich aus AT\&T Plan 9. Klein, schnell und mit eine C-<2D>hnlichen Syntax.), \texttt{esh}\index{esh|textbf}\index{Shell>esh=\texttt{esh}|see{esh}} (Klein und schnell, bietet eine Lisp-<2D>hnliche Sprache), \texttt{sash}\index{sash|textbf}\index{Shell>sash=\texttt{sash}|see{sash}} (System Administrator's Shell - eine statisch gelinkte Shell mit integrierten Standard-Kommandos.).
|
||||
|
||||
Diese Liste ist bei weitem nicht vollst<73>ndig.
|
||||
|
1911
werkzeugkasten.tex
1911
werkzeugkasten.tex
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,12 +1,11 @@
|
||||
% $Id$
|
||||
\chapter{Wo sind Unterschiede zu DOS-Batchdateien?}\index{DOS|(textbf}\index{Batchdateien|(textbf}
|
||||
|
||||
Unter DOS werden Batchdateien oft dazu benutzt, lange Kommandos abzuk<75>rzen um
|
||||
die Tipparbeit zu vermindern, oder um sich das Merken von vielen Parametern zu
|
||||
ersparen. Diese Aufgabe <20>berl<72><6C>t man unter Unix am besten den
|
||||
Shell-Aliasen\index{Aliase} oder Shell-Funktionen.
|
||||
Shell-Aliasen\index{Aliase} oder Shell-Funktionen.\bigskip
|
||||
|
||||
Shell-Skripte k<>nnen viel mehr als Batchdateien.
|
||||
Shell-Skripte k<>nnen viel mehr als Batchdateien.\bigskip
|
||||
|
||||
Wie der Name schon sagt, sind Batchdateien im Wesentlichen nur ein `Stapel' von
|
||||
Anweisungen, die nacheinander ausgef<65>hrt werden. Es stehen zwar auch einige
|
||||
@ -24,8 +23,8 @@ DOS keine M
|
||||
erste Kommando vollst<73>ndig ausgef<65>hrt, seine Ausgabe in eine tempor<6F>re Datei
|
||||
geschrieben und danach als Eingabe f<>r das zweite Kommando benutzt. Da<44> so ein
|
||||
Verhalten unter Umst<73>nden schnell zu einer vollen Festplatte f<>hren kann, sieht
|
||||
man bei dem Beispiel in Abschnitt \ref{cdrdao}, in dem eine CD kopiert werden
|
||||
soll.
|
||||
man bei dem Beispiel, in dem eine CD kopiert werden soll (Kapitel \ref{cdrdao},
|
||||
Seite \pageref{cdrdao}).
|
||||
|
||||
Shell-Skripte kann man dagegen eher mit einer `richtigen' Programmiersprache
|
||||
vergleichen. Es stehen alle Konstrukte zur Verf<72>gung, die eine
|
||||
|
@ -1,18 +1,5 @@
|
||||
% $Id$
|
||||
\chapter{Wof<EFBFBD>r Shell-Programmierung?}
|
||||
|
||||
Nat<EFBFBD>rlich stellt sich die Frage, in welchen Situationen ein Shell-Skript der
|
||||
richtige Weg ist, und wann man vielleicht doch besser zu einer interpretierten
|
||||
oder compilierten Sprache greift.
|
||||
|
||||
\section{Wof<EFBFBD>r?}
|
||||
|
||||
Die Shell ist der perfekte Baukasten f<>r das Unix-Paradigma `small is
|
||||
beautiful'. Die mitgelieferten Unix-Standardkommandos sind einfach gehalten,
|
||||
erledigen aber auf effiziente Weise die Arbeit f<>r die sie programmiert wurden.
|
||||
Mit der Shell, bzw. dem Shell-Skript, wird aus dem Heinzelm<6C>nnchen ein starker
|
||||
Riese.
|
||||
|
||||
Shell-Skripte werden im Wesentlichen aus zwei Gr<47>nden geschrieben: Erstens,
|
||||
weil man so st<73>ndig wiederkehrende Kommandos zusammenfassen kann, die man dann
|
||||
mit einem einfachen Aufruf starten kann, und zweitens, weil man so einfache
|
||||
@ -29,19 +16,3 @@ Befehlen ausf
|
||||
Beispiel eine Audio-CD kopieren soll, sollte das Brennprogramm nur dann
|
||||
aufrufen, wenn der Einlesevorgang erfolgreich abgeschlossen wurde.
|
||||
|
||||
\section{Wof<EFBFBD>r nicht?}
|
||||
|
||||
Ein Shell-Skript besteht aus einer Abfolge von System-Tool-Aufrufen. Das hei<65>t,
|
||||
f<EFBFBD>r jeden Schritt in einem Skript wird ein neuer Proze<7A> gestartet. Das kostet
|
||||
eine Menge Systemzeit, die Skripte laufen also vergleichsweise langsam. F<>r
|
||||
komplexe, zeitkritische oder langwierige Aufgaben sollte man also besser zu
|
||||
Perl, Python oder in Extremf<6D>llen zu C / C++ greifen.
|
||||
|
||||
Shell-Skripte k<>nnen als imperativ angesehen werden, f<>r viele Aufgaben ist
|
||||
aber ein objektorientierter Ansatz wesentlich geeigneter. Auch hier ist also
|
||||
der Griff zu einer anderen Sprache angeraten.
|
||||
|
||||
Es gibt zwar ein paar Tools\footnote{Zum Beispiel dialog im Textmodus, oder
|
||||
xmessage unter X.}, mit denen auch Shell-Skripte eine grafische oder
|
||||
textorientierte Benutzeroberfl<66>che (GUI) bekommen k<>nnen, aber das ist trotzdem
|
||||
nicht das nat<61>rliche Terrain der Shell-Programmierung.
|
||||
|
Reference in New Issue
Block a user