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 überprüft, ob der Admin angemeldet ist. Wir erreichen das mit dem folgenden Code:
|
||||
|
||||
\footnotesize
|
||||
\index{\^=\texttt{\^}}\index{Anführungszeichen}\index{Pipe}\index{grep=\texttt{grep}}\index{sleep=\texttt{sleep}}\index{who=\texttt{who}}
|
||||
\begin{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ührung erfolgreich
|
||||
war. Dabei wird die Ausgabe von \texttt{who}\index{who=\texttt{who}} mit einer
|
||||
Pipe (\ref{datenstrom}) in das \texttt{grep}\index{grep=\texttt{grep}}-Kommando
|
||||
umgeleitet. Dieses sucht darin nach einem Auftreten von `\texttt{root~}' am
|
||||
Zeilenanfang. Der Rückgabewert von \texttt{grep}\index{grep=\texttt{grep}} ist
|
||||
0 wenn das Muster\index{Mustererkennung} gefunden wird, 1 wenn es nicht
|
||||
gefunden wird und 2 wenn ein Fehler auftrat. Damit der Rechner nicht die ganze
|
||||
Zeit mit dieser Schleife beschäftigt ist, wird im Schleifenkörper ein
|
||||
\lstinline|sleep 30|\index{sleep=\texttt{sleep}} ausgeführt, um den Prozeß für
|
||||
30 Sekunden schlafen zu schicken. Sobald der Admin sich eingeloggt hat, wird
|
||||
eine entsprechende Meldung ausgegeben.
|
||||
Das Skript führt also so lange das Kommando aus, bis die Ausführung erfolgreich war. Dabei wird die Ausgabe von \texttt{who}\index{who=\texttt{who}} mit einer Pipe (\ref{datenstrom}) in das \texttt{grep}\index{grep=\texttt{grep}}-Kommando umgeleitet. Dieses sucht darin nach einem Auftreten von `\texttt{root~}' am Zeilenanfang. Der Rückgabewert von \texttt{grep}\index{grep=\texttt{grep}} ist 0 wenn das Muster\index{Mustererkennung} gefunden wird, 1 wenn es nicht gefunden wird und 2 wenn ein Fehler auftrat. Damit der Rechner nicht die ganze Zeit mit dieser Schleife beschäftigt ist, wird im Schleifenkörper ein \texttt{sleep 30}\index{sleep=\texttt{sleep}} ausgeführt, um den Prozeß für 30 Sekunden schlafen zu schicken. Sobald der Admin sich eingeloggt hat, wird eine entsprechende Meldung ausgegeben.
|
||||
|
||||
|
||||
\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ü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ß die Mäuse tanzen!"
|
||||
\end{lstlisting}
|
||||
echo Die Katze ist aus dem Haus, Zeit, daß die Mäuse tanzen!
|
||||
\end{listing}
|
||||
\normalsize
|
||||
|
||||
Die Schleife wird nämlich dann so lange ausgeführt, bis
|
||||
\texttt{grep}\index{grep=\texttt{grep}} einen Fehler (bzw. eine erfolglose
|
||||
Suche) zurückmeldet.
|
||||
Die Schleife wird nämlich dann so lange ausgeführt, bis \texttt{grep}\index{grep=\texttt{grep}} einen Fehler (bzw. eine erfolglose Suche) zurückmeldet.
|
||||
|
||||
|
||||
\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ä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 übergibt. Das \texttt{read}-Kommando in der
|
||||
Schleife liest die einzelnen Zeilen aus, dann folgt ein Bißchen Auswertung.
|
||||
|
||||
Es ist zu beobachten, daß bei der Ausgabe in Zeile 7 die Variable
|
||||
\texttt{\$count} korrekte Werte enthält. Um so unverständlicher ist es, daß sie
|
||||
nach der Vollendung der Schleife wieder den Wert 0 enthält.
|
||||
|
||||
Das liegt daran, daß diese Schleife als Teil einer Pipe in einer Subshell
|
||||
ausgeführt wird. Die Variable \texttt{\$count} steht damit in der Schleife
|
||||
praktisch nur lokal zur Verfü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ü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örige Runlevel initialisiert wird.
|
||||
Dieses Skript dient dazu, den Apache HTTP-Server zu starten. Es wird während des Bootvorgangs gestartet, wenn der dazugehörige Runlevel initialisiert wird.
|
||||
|
||||
Das Skript muß 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} übergeben wurden, wird
|
||||
eine entsprechende Meldung angezeigt.
|
||||
Das Skript muß 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} übergeben wurden, wird eine entsprechende Meldung angezeigt.
|
||||
|
||||
Das Ergebnis der Ausfü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ü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ächst wird festgelegt, daß dieses Skript in der Bourne-Shell ausgeführt
|
||||
werden soll (\ref{auswahl_der_shell}).
|
||||
|
||||
\begin{lstlisting}
|
||||
\begin{flushright}
|
||||
Zunächst wird festgelegt, daß dieses Skript in der Bourne-Shell ausgeführt werden soll (\ref{auswahl_der_shell}).
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
\begin{listing}[2]{1}
|
||||
#!/bin/sh
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
Dann folgen Kommentare\index{Kommentar}, die den Sinn des Skriptes erläutern
|
||||
(\ref{kommentare}).
|
||||
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
\end{listing}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
Dann folgen Kommentare\index{Kommentar}, die den Sinn des Skriptes erlä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ü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 über den auszuführenden Vorgang ausgegeben wurde, wird die Funktion \texttt{daemon} aus der Funktionsbibliothek ausgeführt. Diese Funktion startet das Programm, dessen Name hier als Parameter\index{Parameter} übergeben wird. Dann gibt sie eine Meldung über den Erfolg aus.
|
||||
|
||||
\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ß ein bestimmter Prozeß bereits gestartet ist. So kann ein zweiter Aufruf verhindert werden.} angelegt.
|
||||
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
\index{Anführungszeichen}\index{touch=\texttt{touch}}
|
||||
\begin{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ß 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ß-ID, um anderen Programmen den Zugriff zu erleichtern (z. B. um den Prozeß anzuhalten etc).} gelö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ü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ß er seine Konfiguration neu einlesen soll.
|
||||
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
\index{\$n=\texttt{\$}$n$}\index{Anfü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ür gesorgt, daß das Skript mit dem Exit-Code 1 beendet wird. So kann festgestellt werden, ob das Skript ordnungsgemäß beendet wurde (\ref{exit}).
|
||||
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
\index{exit=\texttt{exit}}
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
\begin{listingcont}
|
||||
exit 1
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
||||
\end{lstlisting}
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
|
||||
|
||||
\section{Parameterü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ß ein zusätzlicher Wert mitgegeben werden. Alle anderen Parameter\index{Parameter} werden als Dateinamen interpretiert.
|
||||
|
||||
\footnotesize
|
||||
\index{\$@=\texttt{\$@}}\index{Anführungszeichen}\index{Backticks}\index{!|!|=\texttt{!|!|}}\index{getopt=\texttt{getopt}}\index{OR}\index{set=\texttt{set}}
|
||||
\begin{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ß es aussieht, als ob dem Skript die Rückgabewerte von \texttt{getopt}\index{getopt=\texttt{getopt}} übergeben wurden. Man muß die beiden Minuszeichen angeben, da sie dafür sorgen, daß die Aufrufparameter an \texttt{getopt}\index{getopt=\texttt{getopt}} und nicht an die Shell selbst übergeben werden. Die originalen Parameter\index{Parameter} werden von \texttt{getopt}\index{getopt=\texttt{getopt}} untersucht und modifiziert zurückgegeben: \texttt{a} und \texttt{b} werden als Parameter\index{Parameter} Markiert, \texttt{b} sogar mit der Möglichkeit einer zusätzlichen Angabe.
|
||||
|
||||
Wenn dieses Kommando fehlschlägt ist das ein Zeichen dafür, daß falsche Parameter\index{Parameter} übergeben wurden. Also wird nach einer entsprechenden Meldung das Programm mit Exit-Code 1 verlassen.
|
||||
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
\index{\$n=\texttt{\$}$n$}\index{Null-Befehl}\index{!>\&=\texttt{!>\&}}\index{!==\texttt{!=}}\index{Anführungszeichen}\index{Backticks}\index{basename=\texttt{basename}}
|
||||
\begin{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ü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ß 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ü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ß gesandt, das ihn
|
||||
bittet sich zu beenden. Dieses Signal heißt SIGINT (für SIGnal INTerrupt) und
|
||||
trägt die Nummer 2. Das kann ein kleines Problem darstellen, wenn das Skript
|
||||
sich temporäre Dateien angelegt hat, da diese nach der Ausführung nur noch
|
||||
unnötig Platz verbrauchen und eigentlich gelöscht werden sollten. Man kann
|
||||
sich sicher auch noch wichtigere Fälle vorstellen, in denen ein Skript
|
||||
bestimmte Aufgaben auf jeden Fall erledigen muß, 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ß gesandt, das ihn bittet sich zu beenden. Dieses Signal heißt SIGINT (für SIGnal INTerrupt) und trägt die Nummer 2. Das kann ein kleines Problem darstellen, wenn das Skript sich temporäre Dateien angelegt hat, da diese nach der Ausführung nur noch unnötig Platz verbrauchen und eigentlich gelöscht werden sollten. Man kann sich sicher auch noch wichtigere Fälle vorstellen, in denen ein Skript bestimmte Aufgaben auf jeden Fall erledigen muß, 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ücklicherweise verfügt die Shell ü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ücklicherweise verfügt die Shell ü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ä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ä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ächst werden zwei Variablen belegt, die im weiteren Verlauf benutzt werden
|
||||
sollen. In \texttt{stat} wird der Wert abgelegt, den das Skript im Falle eines
|
||||
Abbruchs als Exit-Status zurückliefern soll. Die Variable \texttt{temp} enthält
|
||||
den Namen für eine temporäre Datei. Dieser setzt sich zusammen aus
|
||||
\texttt{/tmp/zeige} und der Prozeßnummer des laufenden Skripts. So soll
|
||||
sichergestellt werden, daß noch keine Datei mit diesem Namen existiert.
|
||||
|
||||
\end{listing}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
Zunächst werden zwei Variablen belegt, die im weiteren Verlauf benutzt werden sollen. In \texttt{stat} wird der Wert abgelegt, den das Skript im Falle eines Abbruchs als Exit-Status zurückliefern soll. Die Variable \texttt{temp} enthält den Namen für eine temporäre Datei. Dieser setzt sich zusammen aus \texttt{/tmp/zeige} und der Prozeßnummer des laufenden Skripts. So soll sichergestellt werden, daß noch keine Datei mit diesem Namen existiert.
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
\index{Ticks}\index{!>\&=\texttt{!>\&}}\index{\$n=\texttt{\$}$n$}\index{Ticks}\index{Anführungszeichen}\index{Backticks}\index{basename=\texttt{basename}}
|
||||
\begin{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äre Datei gelöscht
|
||||
und der Wert aus der Variable \texttt{stat} als Exit-Code zurückgegeben. Dabei
|
||||
wird dem \texttt{rm}-Kommando der Parameter\index{Parameter} \texttt{-f}
|
||||
mitgegeben, damit keine Fehlermeldung ausgegeben wird, falls die Datei (noch)
|
||||
nicht existiert. Dieser Fall tritt bei jedem Beenden des Skriptes auf, also
|
||||
sowohl bei einem normalen Ende, als auch beim Exit-Kommando, bei einem
|
||||
Interrupt oder bei einem Kill\index{kill=\texttt{kill}}. Der zweite Trap
|
||||
reagiert auf die Signale 1, 2 und 15. Das heißt, er wird bei jedem unnormalen
|
||||
Ende ausgeführt. Er gibt eine entsprechende Meldung auf die
|
||||
Standard-Fehlerausgabe (\ref{datenstrom}) aus. Danach wird das Skript beendet,
|
||||
und der erste Trap wird ausgeführt.
|
||||
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
Hier werden die Traps definiert. Bei Signal 0 wird die temporäre Datei gelöscht und der Wert aus der Variable \texttt{stat} als Exit-Code zurückgegeben. Dabei wird dem \texttt{rm}-Kommando der Parameter\index{Parameter} \texttt{-f} mitgegeben, damit keine Fehlermeldung ausgegeben wird, falls die Datei (noch) nicht existiert. Dieser Fall tritt bei jedem Beenden des Skriptes auf, also sowohl bei einem normalen Ende, als auch beim Exit-Kommando, bei einem Interrupt oder bei einem Kill\index{kill=\texttt{kill}}. Der zweite Trap reagiert auf die Signale 1, 2 und 15. Das heißt, er wird bei jedem unnormalen Ende ausgeführt. Er gibt eine entsprechende Meldung auf die Standard-Fehlerausgabe (\ref{datenstrom}) aus. Danach wird das Skript beendet, und der erste Trap wird ausgeführt.
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
\index{\$\#=\texttt{\$\#}}\index{!==\texttt{!=}}\index{!>=\texttt{!>}}\index{\$n=\texttt{\$}$n$}\index{Anführungszeichen}\index{case=\texttt{case}}
|
||||
\begin{lstlisting}[firstnumber=last]
|
||||
\begin{listingcont}
|
||||
case $# in
|
||||
1) zcat "$1" > $temp
|
||||
pg $temp
|
||||
stat=0
|
||||
;;
|
||||
|
||||
\end{lstlisting}
|
||||
|
||||
Jetzt kommt die eigentliche Funktionalität des Skriptes: Das
|
||||
\texttt{case}-Kommando (\ref{case}) testet die Anzahl der übergebenen
|
||||
Parameter\index{Parameter}. Wenn genau ein Parameter\index{Parameter} übergeben
|
||||
wurde, entpackt \texttt{zcat} die Datei, die im ersten
|
||||
Parameter\index{Parameter} angegeben wurde, in die temporäre Datei. Dann folgt
|
||||
die Seitenweise Ausgabe mittels \texttt{pg}. Nach Beendigung der Ausgabe wird
|
||||
der Status in der Variablen auf 0 gesetzt, damit beim Skriptende der korrekte
|
||||
Exit-Code zurückgegeben wird.
|
||||
|
||||
\end{listingcont}
|
||||
\normalsize
|
||||
\begin{flushright}
|
||||
Jetzt kommt die eigentliche Funktionalität des Skriptes: Das \texttt{case}-Kommando (\ref{case}) testet die Anzahl der übergebenen Parameter\index{Parameter}. Wenn genau ein Parameter\index{Parameter} übergeben wurde, entpackt \texttt{zcat} die Datei, die im ersten Parameter\index{Parameter} angegeben wurde, in die temporäre Datei. Dann folgt die Seitenweise Ausgabe mittels \texttt{pg}. Nach Beendigung der Ausgabe wird der Status in der Variablen auf 0 gesetzt, damit beim Skriptende der korrekte Exit-Code zurückgegeben wird.
|
||||
\end{flushright}
|
||||
\footnotesize
|
||||
\index{!>\&=\texttt{!>\&}}\index{\$n=\texttt{\$}$n$}\index{Anführungszeichen}\index{Backticks}\index{basename=\texttt{basename}}
|
||||
\begin{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ällige Reihenfolge bringen}\label{chaoten}\index{Zufallszahlen|(}
|
||||
|
||||
Wir wollen uns einen MP3-Player programmieren, der Alle MP3-Dateien aus einem
|
||||
bestimmten Verzeichnisbaum in zufälliger Reihenfolge abspielt. Damit dieses
|
||||
Problem für uns eine Herausforderung darstellt\footnote{Denn schließ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ß wir in der Shell nur über Umwege an Zufallszahlen kommen
|
||||
können. Auf Systemen, in denen die Datei \texttt{/dev/urandom} existiert,
|
||||
liefert uns der Kernel aber schon sehr zufällige Zeichenfolgen. Diese Folgen
|
||||
kö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 über alle Ausgaben des \texttt{find}-Kommandos
|
||||
iteriert. Dabei sucht \texttt{find} nach allen normalen Dateien (\texttt{-type
|
||||
f}), die die Extension .mp3 tragen (\texttt{-name \dq*.[mM][pP]3\dq} -- wir
|
||||
ignorieren Groß- / Kleinschreibung).
|
||||
|
||||
\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ält ein
|
||||
\texttt{tr}, der alle ungewollten Zeichen (alles, was kein Textzeichen ist) aus
|
||||
einem Datenstrom entfernt. Die Daten erhä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ä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 ändern, pipen wir die Ausgabe der Schleife durch ein \texttt{sort}.
|
||||
Da die ersten acht Zeichen jeder Zeile zufällig sind, erhalten wir so eine
|
||||
zufällige Reihenfolge der Zeilen. Jetzt müssen wir nur noch durch ein
|
||||
\texttt{cut} die zufälligen Zeichen abschneiden, und erhalten so die
|
||||
ursprüngliche Liste von Dateien in einer zufä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ößt fast jeder Shell-Skripter früher oder später auf
|
||||
das Problem, daß er irgendwas davon abhängig machen will, ob ein bestimmter
|
||||
Prozeß 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ür ist, daß unter Umstä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ä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,
|
||||
ü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ß 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 über
|
||||
alle Dateien, die dem Muster entsprechen:
|
||||
|
||||
\lstinline|grep -r strict *.pl|
|
||||
|
||||
Und wieder führt es nicht zu dem gewünschten Ergebnis. Da die
|
||||
Unterverzeichnisse nicht die Extension `*.pl' tragen, werden sie nicht
|
||||
berücksichtigt. Für die Suche in Unterverzeichnissen ziehen wir \texttt{find}
|
||||
(Siehe Abschnitt \ref{find}) heran:
|
||||
|
||||
\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ü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ö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ücke}
|
||||
|
||||
Eine sogenannte Tar-Brücke benutzt man, wenn eine oder mehrere Dateien zwischen
|
||||
Rechnern übertragen werden sollen, aber kein Dienst wie SCP oder FTP zur
|
||||
Verfügung steht. Außerdem hat die Methode den Vorteil, daß Benutzerrechte und
|
||||
andere Dateiattribute bei der Ãœbertragung erhalten
|
||||
bleiben\footnote{Vorausgesetzt natürlich, daß der Benutzer auf der entfernten
|
||||
Seite über die nötigen Rechte verfü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ählten Aktion~--~die
|
||||
Standard-Ein- bzw. -Ausgabe. Diese kann an ein weiteres \texttt{tar} ü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ächst der Inhalt des aktuellen Verzeichnisses `verpackt'. Das
|
||||
Resultat wird an die Standard-Ausgabe geschrieben. Auf der Empfängerseite der
|
||||
Pipe wird eine Subshell geöffnet. Das ist notwendig, da das empfangende
|
||||
\texttt{tar} in einem anderen Verzeichnis laufen soll. In der Subshell wird
|
||||
zunä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ß mitsamt der Subshell.
|
||||
|
||||
Am Ziel-Ort finden sich jetzt die gleichen Dateien wie am Quell-Ort.
|
||||
|
||||
Das ließe sich lokal natürlich auch anders lösen. Man könnte erst ein Archiv
|
||||
erstellen, das dann an anderer Stelle wieder auspacken. Nachteil: Es muß
|
||||
genü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äßt \texttt{tar}
|
||||
beispielsweise nicht das File-System. Nützlich wenn nur eine Partition
|
||||
gesichert werden soll.}, und die oben erwähnte Brü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ü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 ä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über dem
|
||||
vorigen Beispiel besteht darin, daß das Zielverzeichnis bei Bedarf erstellt
|
||||
wird, bevor die Datei dort entpackt wird. Zur Erklä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ägersystem an.
|
||||
Shell-Skripte sind mit wenigen Einschränkungen plattformunabhä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~--~üblicherweise binären~--~Pakete auf das Zielsystem
|
||||
gebracht?
|
||||
|
||||
Im Prinzip gibt es dafür zwei unterschiedliche Verfahren:
|
||||
TODO!!!
|
||||
|
||||
\subsection{Binäre Here-Dokumente}
|
||||
\index{Here-Dokument}
|
||||
|
||||
Eine Möglichkeit ist es, die binäre Datei in Form eines Here-Dokuments
|
||||
mitzuliefern. Da es aber in der Natur einer binä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ß 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ß an der
|
||||
Stelle auf jeden Fall sichergestellt werden, daß keine existierenden Dateien
|
||||
versehentlich überschrieben werden.
|
||||
|
||||
Um diesen Abschnitt nicht allzu lang werden zu lassen ü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} überprü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ß die binäre Datei ohne weitere Codierung an
|
||||
das Shell-Skript angehängt wurde. Nachteil dieses Verfahrens ist, daß das
|
||||
`abschneidende Kommando' nach jeder Änderung der Länge des Skriptes angepaßt
|
||||
werden muß.
|
||||
TODO!!!
|
||||
|
||||
Dabei gibt es zwei Methoden, die angehä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ß das Skript selbst 227 Zeilen umfaßt. Die
|
||||
binäre Datei wurde mit einem Kommando wie \lstinline|cat icon.png >> skript.sh|
|
||||
an das Skript angehängt.
|
||||
\subsection{Speichern in nicht existente Dateien}
|
||||
|
||||
Für die etwas kompliziertere Variante muß die Länge des eigentlichen
|
||||
Skript-Teiles genau angepaßt werden. Wenn das Skript beispielsweise etwa 5,5kB
|
||||
lang ist, müssen genau passend viele Leerzeilen oder Kommentarzeichen angehängt
|
||||
werden, damit sich eine Länge von 6kB ergibt. Dann kann das Anhä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öß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ßlich
|
||||
wird festgelegt, daß bei der Aktion die ersten sechs Block~--~also die ersten
|
||||
sechs Kilobytes~--~übersprungen werden sollen.
|
||||
|
||||
Um es nochmal zu betonen: Diese beiden Methoden sind mit Vorsicht zu genießen.
|
||||
Bei der ersten führt jede zusätzliche oder gelö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öschen. Gelöscht wird nämlich zunä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ß die Datei noch in irgendeiner Form geöffnet, kann er weiter
|
||||
darauf zugreifen. Erst wenn er die Datei schließt ist sie tatsächlich und
|
||||
unwiederbringlich `weg'.
|
||||
|
||||
Dieser Effekt der `nicht existenten Dateien' läß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ß
|
||||
Variablen die in einer Subshell definiert wurden außerhalb dieser nicht
|
||||
sichtbar sind (siehe Abschnitt \ref{subshellschleifen}). Dies ist um so
|
||||
ärgerlicher, als daß Subshells auch bei vergleichsweise einfachen Pipelines
|
||||
geöffnet werden.
|
||||
|
||||
Ein Beispiel für ein miß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ählt. Am Ende der Schleife enthält die
|
||||
Variable tatsächlich den korrekten Wert, aber da die Pipe eine Subshell
|
||||
geö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ä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äre Datei geschrieben werden, die
|
||||
danach geparst werden müß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 Ãœberlegung kommen wir zu einem eleganten~--~wenn auch
|
||||
nicht ganz einfachen~--~Trick.
|
||||
|
||||
Anstatt die Daten in eine temporäre Datei zu schreiben, wo sie womöglich durch
|
||||
andere Prozesse verä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ächst eine temporä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ählt wie im ersten Beispiel. Allerdings wurde explizit eine Subshell
|
||||
um die Schleife gestartet. Dadurch steht die in der Schleife hochgezählte
|
||||
Variable auch nach Beendigung der Schleife zur Verfügung, allerdings immernoch
|
||||
nur in der Subshell. Um das zu ä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ß der Wert von nCounter
|
||||
tatsächlich außerhalb der Subshell nicht zur Verfügung steht. Zunä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ßend zeigt die Zeile 15, daß der Transport tatsä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ß man eine Datei bearbeiten möchte, die hinterher aber wieder
|
||||
unter dem gleichen Namen zur Verfü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örtliche Hose
|
||||
gehen. Das Problem an der Stelle ist, daß die Datei an der Stelle gleichzeitig
|
||||
zum Lesen und zum Schreiben geö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ß man im Falle eines
|
||||
Fehlers die Quelldaten verliert, da die Datei ja bereits gelöscht wurde.
|
||||
|
||||
\section{Auf der Lauer: Wachhunde}\label{wachhunde}\index{Watchdog}
|
||||
|
||||
Es kommt vor, daß man einen Prozeß startet, bei dem man sich nicht sicher sein
|
||||
kann daß er sich auch in absehbarer Zeit wieder beendet. Beispielsweise kann
|
||||
der Timeout für einen Netzwerkzugriff deutlich höher liegen als erwü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ä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 überwachende Prozeß unterbrochen
|
||||
werden soll. Dann wird der zu überwachende Prozeß gestartet und mittels \& in
|
||||
den Hintergrund geschickt. Die Prozeß-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ächst der oben eingestellte Timeout abgewartet und dann
|
||||
der zu überwachende Prozeß getö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ß sich der überwachte Prozeß beendet. Dabei würde \texttt{wait} bis in alle
|
||||
Ewigkeit warten, wäre da nicht der Watchdog in der Subshell. Wenn dem die
|
||||
Ausführung zu lange dauert, sorgt er dafür daß der Prozeß beendet wird.
|
||||
|
||||
Kommt der überwachte Prozeß aber rechtzeitig zurück, sorgt \texttt{kill} in
|
||||
Zeile 8 dafür daß der Wachhund `eingeschläfert' wird.
|
||||
|
||||
Auf diese Weise ist sichergestellt, daß der \texttt{ping} auf keinen Fall
|
||||
lä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ü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ä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ür, daß 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ätze ein, 1+0
|
||||
Datensätze aus} erscheinen würden. Das gelesene Zeichen wird in der Variablen
|
||||
\texttt{\$inputchar} gesichert und steht somit zur Verfügung.
|
||||
|
||||
Nach dem Einlesevorgang wird die Konsole schließlich mittels
|
||||
\lstinline|stty sane| wieder in einen benutzbaren Zustand zurü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ände zwischen den Absätzen, statt
|
||||
% Einrü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 über die Seitenbreite
|
||||
%\usepackage{longtable} % für Tabellen über die Seitenbreite
|
||||
%\usepackage{supertabular} % für Tabellen über die Seitenbreite
|
||||
\usepackage{tabularx} % für Tabellen über die Seitenbreite
|
||||
\usepackage{longtable} % für Tabellen über die Seitenbreite
|
||||
\usepackage{supertabular} % für Tabellen über die Seitenbreite
|
||||
\usepackage{ltxtable} % für Tabellen über die Seitenbreite
|
||||
|
||||
\ifpdf % PDF-Einstellungen
|
||||
\usepackage{thumbpdf}
|
||||
\else % Nicht-PDF-Einstellungen
|
||||
\fi
|
||||
|
||||
\usepackage{makeidx} % Index wird später eingefügt
|
||||
\makeindex % durch \printindex
|
||||
|
||||
@ -47,39 +58,23 @@
|
||||
|
||||
\usepackage{fancybox} % Kästchen für Tastendarstellung
|
||||
|
||||
%\usepackage{moreverb} % Fü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ß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ß 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
|
||||
Ãœbersicht zu diesem Thema haben wollte. Ich beabsichtige nicht, damit in
|
||||
irgendeiner Form Kommerz zu machen. Ich stelle es zur Verfügung, in der
|
||||
Hoffnung, daß andere Leute daraus vielleicht einen Nutzen ziehen können.
|
||||
\textbf{Aber ich ü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 Übersicht zu diesem Thema haben wollte. Ich beabsichtige nicht, damit in irgendeiner Form Kommerz zu machen. Ich stelle es frei zur Verfügung, in der Hoffnung, daß andere Leute daraus vielleicht einen Nutzen ziehen können. \textbf{Aber ich ü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ß 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ünscht. Ich habe
|
||||
diese Lizenz gewählt um sicherzustellen daß Verbesserungen am Inhalt des
|
||||
Dokumentes bei mir ankommen, damit ich sie in die `Hauptversion' einfließ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ü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ö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 über jede
|
||||
Rü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 ü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ü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ü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ührt, aber die Ausgaben werden behandelt, als ob nur ein Befehl ausgeführt würde \tabularnewline\STRUT
|
||||
\texttt{\{ }\textsl{Befehl1}\texttt{ ; }\textsl{Befehl2}\texttt{ \}} & Befehlsblock; alle Befehle werden in der momentanen Shell ausgeführt, aber die Ausgaben werden behandelt, als ob nur ein Befehl ausgefü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 ähnlichen Mechanismus kennt man aus verschiedenen Programmiersprachen unter dem Begriff \textsl{Kurzschlußauswertung}\index{Kurzschlußauswertung} bzw. \textsl{lazy evaluation}\index{Lazy Evaluation|see{Kurzschlußauswertung}}.} \tabularnewline\STRUT
|
||||
\textsl{Befehl1}\texttt{ || }\textsl{Befehl2} & OR\index{OR}, entweder \textsl{Befehl1} ausfü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ä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ührungszeichen}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{~echo \dq Referenzen zum Programm \$item ...\dq}\index{Anfü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ü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ü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ö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ßbuchstaben\index{Großbuchstaben}\footnote{Natürlich wird in Shell-Skripten --- wie überall in der Unix-Welt --- zwischen Groß- 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ü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ützen\dq~Anführungszeichen'}} \\
|
||||
\multicolumn{2}{|X|}{\texttt{Ticks \dq schützen\dq~Anfü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ü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ü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ä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ück.} \tabularnewline\STRUT
|
||||
\texttt{\$ echo \$\{l:=\$r\}} & Gibt \textsl{runter} aus, da die Variable \textsl{l} keinen Wert enthä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ä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ü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ühren, alle anderen nur lesen und ausfü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ü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ß 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ä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ü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ößer als oder gleich \tabularnewline\STRUT
|
||||
\texttt{>} & größ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ären Ausdrücken \tabularnewline\STRUT
|
||||
\texttt{match} & Analog zu `:' \tabularnewline\STRUT
|
||||
\texttt{substr} & Teil einer Zeichenkette zurü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ören. Die Angabe kann als Name oder als UID erfolgen \tabularnewline\STRUT
|
||||
\texttt{-group }\textsl{name} & Sucht nach Dateien, die der angegebenen Gruppe gehören. Die Angabe kann als Name oder als GID erfolgen \tabularnewline\STRUT
|
||||
\texttt{-size }\textsl{n}\texttt{[c]} & Sucht nach Dateien, deren Größe \textsl{n} Blocks\footnote{Blocks geben die Dateigröße in Bytes dividiert durch 512 und aufgerundet auf den nächsten Integer an. Das hat historische Grü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ück liegt \tabularnewline\STRUT
|
||||
\texttt{-ctime }\textsl{n} & Sucht nach Dateien, deren letzte Statusänderung (change time) \texttt{n}*24 Stunden zurück liegt \tabularnewline\STRUT
|
||||
\texttt{-mtime }\textsl{n} & Sucht nach Dateien, deren letzte Änderung (modification time) \texttt{n}*24 Stunden zurü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ü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ßende Semikolon muß 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äre Ausdrücke \tabularnewline\STRUT
|
||||
\texttt{-F} & Der Suchbegriff wird nicht als regulä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ß- und Kleinschreibung \tabularnewline\STRUT
|
||||
\texttt{-l} & Gibt nur die Dateinamen aus \tabularnewline\STRUT
|
||||
\texttt{-n} & Gibt zusä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ängt \tabularnewline\STRUT
|
||||
\texttt{-A} & \ding{43} Zeigt `fast alle' Dateien an, also auch alle deren Name mit einem Punkt anfä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öß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öße der Datei sortieren \tabularnewline\STRUT
|
||||
\texttt{-t} & Nach der letzten Ä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ß-Namen gesucht, mit diesem Parameter wird das volle Kommando (incl. Pfad und Parametern) betrachtet\tabularnewline\STRUT
|
||||
\texttt{-l} & Nicht nur die Prozeß-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 ü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ü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öscht \tabularnewline\STRUT
|
||||
\texttt{23d} & Zeile 23 wird gelöscht \tabularnewline\STRUT
|
||||
\texttt{\$d} & Die letzte Eingabezeile wird gelöscht \tabularnewline\STRUT
|
||||
\texttt{/}\textsl{pattern}\texttt{/d} & Jede Zeile, die den regulären Ausdruck \textsl{pattern} enthält wird gelöscht \tabularnewline\STRUT
|
||||
\texttt{23,42d} & Die Zeilen 23 bis einschließlich 42 werden gelöscht \tabularnewline\STRUT
|
||||
\texttt{23,\$d} & Von Zeile 23 bis zum Ende wird gelöscht \tabularnewline\STRUT
|
||||
\texttt{1,/\^\$/d} & Von der ersten bis zur ersten Leerzeile wird gelöscht \tabularnewline\STRUT
|
||||
\texttt{23,42!d} & Alles außer den Zeilen 23 bis 42 wird gelö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ä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üft nur, ob die Eingabedaten bereits sortiert sind \tabularnewline\STRUT
|
||||
\texttt{-f} & Groß- / 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 Ü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ß- / 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ält sie üblicherweise durch \Ovalbox{SHIFT} und die Taste neben dem Backspace.}) & Befehls-Substitution\index{Befehls>-Substitution} \tabularnewline\STRUT
|
||||
\texttt{` ` }(Backticks\footnote{Man erhä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 ü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ü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ü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 ü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
|
||||
ü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ä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ö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ß 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ä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ä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ßnummer der aktiven Shell \tabularnewline\STRUT
|
||||
\texttt{\$!} & Prozeß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ührbaren Kommandos gesucht wird\footnote{Mit dem Kommando \texttt{type}\index{type=\texttt{type}} findet man heraus, welches Executable tatsächlich verwendet wird.}. Mehrere Einträ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\-ü\-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ö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ü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äche X) greifen die
|
||||
Benutzer ü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:
|
||||
In einem klassischen Unix-System (ohne die grafische Oberfläche X) greifen die Benutzer ü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ügung, die aus Hochsprachen bekannt sind (Variablen, Datenströme, Funktionen usw.).
|
||||
\end{itemize}
|
||||
Ursprü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ügung. Welche Variante
|
||||
ein Benutzer verwenden möchte ist reine Geschmackssache.
|
||||
Ursprü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ü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 ü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 ü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ü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ü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änken, da sie auf praktisch allen Systemen zur Verfügung steht. So bleiben die Skripte portabel.
|
||||
|
||||
Für die Entwicklung von Shell-Skripten sollte man sich auf diese Shell
|
||||
beschränken, da sie auf praktisch allen Systemen zur Verfügung steht. So
|
||||
bleiben die Skripte mit kleinen Einschrä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ßerdem gibt es hier History\index{History}-Funktionen\footnote{History-Funktionen ermöglichen es dem Benutzer, einfach auf zurückliegende Befehle zurückgreifen zu können.}, eine Ganzzahl-Arithmetik, verbesserte Möglichkeiten zur Mustererkennung, Aliase\index{Aliase}\footnote{Ein Alias ist eine Abkü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ührung von Prozessen selektiv stoppen oder fortsetzen kann}\index{Job-Controlling}. Auß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ßerdem gibt es
|
||||
hier History\index{History}-Funktionen\footnote{History-Funktionen ermöglichen
|
||||
es dem Benutzer, einfach auf zurückliegende Befehle zurückgreifen zu können.},
|
||||
eine Ganzzahl-Arithmetik, verbesserte Möglichkeiten zur Mustererkennung,
|
||||
Arrays, Aliase\index{Aliase}\footnote{Ein Alias ist eine Abkü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ührung von Prozessen selektiv stoppen oder fortsetzen
|
||||
kann}\index{Job-Controlling}. Auß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 ä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 ä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ä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ügung. Die Bash unterstützt
|
||||
Auto-Completion\index{Auto-Completion|textbf}\footnote{Mit Auto-Completion ist
|
||||
das automatische Vervollstä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ä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ügung.
|
||||
Die Bash unterstützt Auto-Completion\index{Auto-Completion|textbf}\footnote{Mit Auto-Completion ist das automatische Vervollstä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ä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}}) ähnelt der Korn-Shell,
|
||||
enthält aber viele Erweiterungen. Die Z-Shell unterstützt
|
||||
Kom\-mandozeilen-Editing, programmierbares
|
||||
Auto-Completion\index{Auto-Completion}, Shell-Funktionen und eine History.
|
||||
Zudem ist eine Rechtschreibprü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ä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}}) ähnelt der Korn-Shell, enthält aber viele Erweiterungen. Die Z-Shell unterstützt Kommandozeilen-Editing, programmierbares Auto-Completion\index{Auto-Completion}, Shell-Funktionen und eine History. Zudem ist eine Rechtschreibprü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ö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ünglich aus AT\&T Plan 9. Klein, schnell und mit eine
|
||||
C-ähnlichen Syntax.),
|
||||
\texttt{esh}\index{esh|textbf}\index{Shell>esh=\texttt{esh}|see{esh}} (Klein
|
||||
und schnell, bietet eine Lisp-ä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ö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ünglich aus AT\&T Plan 9. Klein, schnell und mit eine C-ähnlichen Syntax.), \texttt{esh}\index{esh|textbf}\index{Shell>esh=\texttt{esh}|see{esh}} (Klein und schnell, bietet eine Lisp-ä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ä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ürzen um
|
||||
die Tipparbeit zu vermindern, oder um sich das Merken von vielen Parametern zu
|
||||
ersparen. Diese Aufgabe überläß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ührt werden. Es stehen zwar auch einige
|
||||
@ -24,8 +23,8 @@ DOS keine M
|
||||
erste Kommando vollständig ausgeführt, seine Ausgabe in eine temporäre Datei
|
||||
geschrieben und danach als Eingabe für das zweite Kommando benutzt. Daß so ein
|
||||
Verhalten unter Umstä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ügung, die eine
|
||||
|
@ -1,18 +1,5 @@
|
||||
% $Id$
|
||||
\chapter{Wofür Shell-Programmierung?}
|
||||
|
||||
Natü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ü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ännchen ein starker
|
||||
Riese.
|
||||
|
||||
Shell-Skripte werden im Wesentlichen aus zwei Gründen geschrieben: Erstens,
|
||||
weil man so stä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ür nicht?}
|
||||
|
||||
Ein Shell-Skript besteht aus einer Abfolge von System-Tool-Aufrufen. Das heißt,
|
||||
für jeden Schritt in einem Skript wird ein neuer Prozeß 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ä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äche (GUI) bekommen können, aber das ist trotzdem
|
||||
nicht das natürliche Terrain der Shell-Programmierung.
|
||||
|
Loading…
Reference in New Issue
Block a user