Umformatiert
This commit is contained in:
		
							
								
								
									
										310
									
								
								beispiele.tex
									
									
									
									
									
								
							
							
						
						
									
										310
									
								
								beispiele.tex
									
									
									
									
									
								
							| @@ -13,34 +13,40 @@ Angenommen, bei der Benutzung eines Rechners tritt ein Problem auf, bei dem nur | ||||
|  | ||||
| Einfacher geht es, wenn wir uns ein kurzes Skript schreiben, das alle 30 Sekunden automatisch <20>berpr<70>ft, ob der Admin angemeldet ist. Wir erreichen das mit dem folgenden Code: | ||||
|  | ||||
| \footnotesize | ||||
| \index{\^=\texttt{\^}}\index{Anf<EFBFBD>hrungszeichen}\index{Pipe}\index{grep=\texttt{grep}}\index{sleep=\texttt{sleep}}\index{who=\texttt{who}} | ||||
| \begin{listing}[2]{1} | ||||
| \begin{lstlisting} | ||||
| #!/bin/sh | ||||
| until who | grep "^root " | ||||
| do sleep 30 | ||||
| done | ||||
| echo Big Brother is watching you! | ||||
| \end{listing} | ||||
| \normalsize | ||||
| \end{lstlisting} | ||||
|  | ||||
| Das Skript f<>hrt also so lange das Kommando aus, bis die Ausf<73>hrung erfolgreich war. Dabei wird die Ausgabe von \texttt{who}\index{who=\texttt{who}} mit einer Pipe (\ref{datenstrom}) in das \texttt{grep}\index{grep=\texttt{grep}}-Kommando umgeleitet. Dieses sucht darin nach einem Auftreten von `\texttt{root~}' am Zeilenanfang. Der R<>ckgabewert von \texttt{grep}\index{grep=\texttt{grep}} ist 0 wenn das Muster\index{Mustererkennung} gefunden wird, 1 wenn es nicht gefunden wird und 2 wenn ein Fehler auftrat. Damit der Rechner nicht die ganze Zeit mit dieser Schleife besch<63>ftigt ist, wird im Schleifenk<6E>rper ein \texttt{sleep 30}\index{sleep=\texttt{sleep}} ausgef<65>hrt, um den Proze<7A> f<>r 30 Sekunden schlafen zu schicken. Sobald der Admin sich eingeloggt hat, wird eine entsprechende Meldung ausgegeben. | ||||
| Das Skript f<>hrt also so lange das Kommando aus, bis die Ausf<73>hrung erfolgreich | ||||
| war. Dabei wird die Ausgabe von \texttt{who}\index{who=\texttt{who}} mit einer | ||||
| Pipe (\ref{datenstrom}) in das \texttt{grep}\index{grep=\texttt{grep}}-Kommando | ||||
| umgeleitet. Dieses sucht darin nach einem Auftreten von `\texttt{root~}' am | ||||
| Zeilenanfang. Der R<>ckgabewert von \texttt{grep}\index{grep=\texttt{grep}} ist | ||||
| 0 wenn das Muster\index{Mustererkennung} gefunden wird, 1 wenn es nicht | ||||
| gefunden wird und 2 wenn ein Fehler auftrat. Damit der Rechner nicht die ganze | ||||
| Zeit mit dieser Schleife besch<63>ftigt ist, wird im Schleifenk<6E>rper ein | ||||
| \lstinline|sleep 30|\index{sleep=\texttt{sleep}} ausgef<65>hrt, um den Proze<7A> f<>r | ||||
| 30 Sekunden schlafen zu schicken. Sobald der Admin sich eingeloggt hat, wird | ||||
| eine entsprechende Meldung ausgegeben. | ||||
|  | ||||
|  | ||||
| \subsection{Schleife, bis ein Kommando erfolglos war} | ||||
|  | ||||
| Analog zum vorhergehenden Beispiel kann man auch ein Skript schreiben, das meldet, sobald sich ein Benutzer abgemeldet hat. Dazu ersetzen wir nur die \texttt{until}- Schleife durch eine entsprechende \texttt{while}-Schleife: | ||||
|  | ||||
| \footnotesize | ||||
| \index{\^=\texttt{\^}}\index{Anf<EFBFBD>hrungszeichen}\index{grep=\texttt{grep}}\index{Pipe}\index{sleep=\texttt{sleep}}\index{who=\texttt{who}} | ||||
| \begin{listing}[2]{1} | ||||
| \begin{lstlisting} | ||||
| #!/bin/sh | ||||
| while who | grep "^root " | ||||
| do sleep 30 | ||||
| done | ||||
| echo Die Katze ist aus dem Haus, Zeit, da<64> die M<>use tanzen! | ||||
| \end{listing} | ||||
| \normalsize | ||||
| \end{lstlisting} | ||||
|  | ||||
| Die Schleife wird n<>mlich dann so lange ausgef<65>hrt, bis \texttt{grep}\index{grep=\texttt{grep}} einen Fehler (bzw. eine erfolglose Suche) zur<75>ckmeldet. | ||||
|  | ||||
| @@ -49,8 +55,7 @@ Die Schleife wird n | ||||
|  | ||||
| \texttt{cat datei.txt | while read i} | ||||
|  | ||||
| \footnotesize | ||||
| \begin{listing}[2]{1} | ||||
| \begin{lstlisting} | ||||
| #!/bin/sh | ||||
| count=0 | ||||
| cat /etc/passwd | while read i; do | ||||
| @@ -61,8 +66,7 @@ cat /etc/passwd | while read i; do | ||||
|   fi | ||||
| done | ||||
| echo Es sind $count Benutzer mit einer ID kleiner 100 eingetragen | ||||
| \end{listing} | ||||
| \normalsize | ||||
| \end{lstlisting} | ||||
|  | ||||
| TODO!!! Daten aus Subshell hochreichen | ||||
|  | ||||
| @@ -76,19 +80,16 @@ Das Skript mu | ||||
|  | ||||
| Das Ergebnis der Ausf<73>hrung wird mit Funktionen\index{Funktion} dargestellt, die aus der Datei \texttt{/etc/rc.d/init.d/functions} stammen. Ebenfalls in dieser Datei sind Funktionen, die einen Dienst starten oder stoppen. | ||||
|  | ||||
| \begin{flushright} | ||||
| Zun<EFBFBD>chst wird festgelegt, da<64> dieses Skript in der Bourne-Shell ausgef<65>hrt werden soll (\ref{auswahl_der_shell}). | ||||
| \end{flushright} | ||||
| \footnotesize | ||||
| \begin{listing}[2]{1} | ||||
|  | ||||
| \begin{lstlisting} | ||||
| #!/bin/sh | ||||
| \end{listing} | ||||
| \normalsize | ||||
| \begin{flushright} | ||||
|  | ||||
| \end{lstlisting} | ||||
|  | ||||
| Dann folgen Kommentare\index{Kommentar}, die den Sinn des Skriptes erl<72>utern (\ref{kommentare}). | ||||
| \end{flushright} | ||||
| \footnotesize | ||||
| \begin{listingcont} | ||||
|  | ||||
| \begin{lstlisting}[firstnumber=last] | ||||
| # | ||||
| # Startup script for the Apache Web Server | ||||
| # | ||||
| @@ -100,119 +101,109 @@ Dann folgen Kommentare\index{Kommentar}, die den Sinn des Skriptes erl | ||||
| # config: /etc/httpd/conf/access.conf | ||||
| # config: /etc/httpd/conf/httpd.conf | ||||
| # config: /etc/httpd/conf/srm.conf | ||||
| \end{listingcont} | ||||
| \normalsize | ||||
| \begin{flushright} | ||||
|  | ||||
| \end{lstlisting} | ||||
|  | ||||
| Jetzt wird die Datei mit den Funktionen\index{Funktion} eingebunden (\ref{source}). | ||||
| \end{flushright} | ||||
| \footnotesize | ||||
|  | ||||
| \index{source=\texttt{source}} | ||||
| \begin{listingcont} | ||||
| \begin{lstlisting}[firstnumber=last] | ||||
| # Source function library. | ||||
| . /etc/rc.d/init.d/functions | ||||
| \end{listingcont} | ||||
| \normalsize | ||||
| \begin{flushright} | ||||
|  | ||||
| \end{lstlisting} | ||||
|  | ||||
| Hier werden die Aufrufparameter ausgewertet (\ref{case}). | ||||
| \end{flushright} | ||||
| \footnotesize | ||||
|  | ||||
| \index{\$n=\texttt{\$}$n$}\index{Anf<EFBFBD>hrungszeichen}\index{case=\texttt{case}} | ||||
| \begin{listingcont} | ||||
| \begin{lstlisting}[firstnumber=last] | ||||
| # See how we were called. | ||||
| case "$1" in | ||||
|   start) | ||||
|         echo -n "Starting httpd: " | ||||
| \end{listingcont} | ||||
| \normalsize | ||||
| \begin{flushright} | ||||
|  | ||||
| \end{lstlisting} | ||||
|  | ||||
| Nachdem eine Meldung <20>ber den auszuf<75>hrenden Vorgang ausgegeben wurde, wird die Funktion \texttt{daemon} aus der Funktionsbibliothek ausgef<65>hrt. Diese Funktion startet das Programm, dessen Name hier als Parameter\index{Parameter} <20>bergeben wird. Dann gibt sie eine Meldung <20>ber den Erfolg aus. | ||||
| \end{flushright} | ||||
| \footnotesize | ||||
| \begin{listingcont} | ||||
|  | ||||
| \begin{lstlisting}[firstnumber=last] | ||||
|         daemon httpd | ||||
|         echo | ||||
| \end{listingcont} | ||||
| \normalsize | ||||
| \begin{flushright} | ||||
|  | ||||
| \end{lstlisting} | ||||
|  | ||||
| Jetzt wird ein Lock-File\footnote{Ein Lock-File signalisiert anderen Prozessen, da<64> ein bestimmter Proze<7A> bereits gestartet ist. So kann ein zweiter Aufruf verhindert werden.} angelegt. | ||||
| \end{flushright} | ||||
| \footnotesize | ||||
|  | ||||
| \index{Anf<EFBFBD>hrungszeichen}\index{touch=\texttt{touch}} | ||||
| \begin{listingcont} | ||||
| \begin{lstlisting}[firstnumber=last] | ||||
|         touch /var/lock/subsys/httpd | ||||
|         ;; | ||||
|   stop) | ||||
|         echo -n "Shutting down http: " | ||||
| \end{listingcont} | ||||
| \normalsize | ||||
| \begin{flushright} | ||||
|  | ||||
| \end{lstlisting} | ||||
|  | ||||
| Hier passiert im Prinzip das gleiche wie oben, nur da<64> mit der Funktion \texttt{killproc} der Daemon angehalten wird. | ||||
| \end{flushright} | ||||
| \footnotesize | ||||
| \begin{listingcont} | ||||
|  | ||||
| \begin{lstlisting}[firstnumber=last] | ||||
|         killproc httpd | ||||
|         echo | ||||
| \end{listingcont} | ||||
| \normalsize | ||||
| \begin{flushright} | ||||
|  | ||||
| \end{lstlisting} | ||||
|  | ||||
| Danach werden Lock-File und PID-File\footnote{In einem sogenannten PID-File hinterlegen einige Prozesse ihre Proze<7A>-ID, um anderen Programmen den Zugriff zu erleichtern (z. B. um den Proze<7A> anzuhalten etc).} gel<65>scht. | ||||
| \end{flushright} | ||||
| \footnotesize | ||||
| \begin{listingcont} | ||||
|  | ||||
| \begin{lstlisting}[firstnumber=last] | ||||
|         rm -f /var/lock/subsys/httpd | ||||
|         rm -f /var/run/httpd.pid | ||||
|         ;; | ||||
|   status) | ||||
| \end{listingcont} | ||||
| \normalsize | ||||
| \begin{flushright} | ||||
|  | ||||
| \end{lstlisting} | ||||
|  | ||||
| Die Funktion \texttt{status} stellt fest, ob der entsprechende Daemon bereits l<>uft, und gibt das Ergebnis aus. | ||||
| \end{flushright} | ||||
| \footnotesize | ||||
| \begin{listingcont} | ||||
|  | ||||
| \begin{lstlisting}[firstnumber=last] | ||||
|         status httpd | ||||
|         ;; | ||||
|   restart) | ||||
| \end{listingcont} | ||||
| \normalsize | ||||
| \begin{flushright} | ||||
|  | ||||
| \end{lstlisting} | ||||
|  | ||||
| Bei Aufruf mit dem Parameter\index{Parameter} \textsl{restart} ruft sich das Skript zwei mal selbst auf (in \texttt{\$0} steht der Aufrufname des laufenden Programms). Einmal, um den Daemon zu stoppen, dann, um ihn wieder zu starten. | ||||
| \end{flushright} | ||||
| \footnotesize | ||||
|  | ||||
| \index{\$n=\texttt{\$}$n$}\index{Anf<EFBFBD>hrungszeichen} | ||||
| \begin{listingcont} | ||||
| \begin{lstlisting}[firstnumber=last] | ||||
|         $0 stop | ||||
|         $0 start | ||||
|         ;; | ||||
|   reload) | ||||
|         echo -n "Reloading httpd: " | ||||
| \end{listingcont} | ||||
| \normalsize | ||||
| \begin{flushright} | ||||
|  | ||||
| \end{lstlisting} | ||||
|  | ||||
| Hier sendet die \texttt{killproc}-Funktion dem Daemon ein Signal\index{Signal} das ihm sagt, da<64> er seine Konfiguration neu einlesen soll. | ||||
| \end{flushright} | ||||
| \footnotesize | ||||
|  | ||||
| \index{\$n=\texttt{\$}$n$}\index{Anf<EFBFBD>hrungszeichen} | ||||
| \begin{listingcont} | ||||
| \begin{lstlisting}[firstnumber=last] | ||||
|         killproc httpd -HUP | ||||
|         echo | ||||
|         ;; | ||||
|   *) | ||||
|         echo "Usage: $0 {start|stop|restart|reload|status}" | ||||
| \end{listingcont} | ||||
| \normalsize | ||||
| \begin{flushright} | ||||
|  | ||||
| \end{lstlisting} | ||||
|  | ||||
| Bei aufruf mit einem beliebigen anderen Parameter\index{Parameter} wird eine Kurzhilfe ausgegeben. Dann wird daf<61>r gesorgt, da<64> das Skript mit dem Exit-Code 1 beendet wird. So kann festgestellt werden, ob das Skript ordnungsgem<65><6D> beendet wurde (\ref{exit}). | ||||
| \end{flushright} | ||||
| \footnotesize | ||||
|  | ||||
| \index{exit=\texttt{exit}} | ||||
| \begin{listingcont} | ||||
| \begin{lstlisting}[firstnumber=last] | ||||
|         exit 1 | ||||
| esac | ||||
|  | ||||
| exit 0 | ||||
| \end{listingcont} | ||||
| \normalsize | ||||
|  | ||||
| \end{lstlisting} | ||||
|  | ||||
|  | ||||
| \section{Parameter<EFBFBD>bergabe in der Praxis}\label{beisp_parameter}\index{Parameter} | ||||
| @@ -221,21 +212,19 @@ Es kommt in der Praxis sehr oft vor, da | ||||
|  | ||||
| Das soll an folgendem Skript verdeutlicht werden. Das Skript kennt die Optionen \texttt{-a} und \texttt{-b}. Letzterer Option mu<6D> ein zus<75>tzlicher Wert mitgegeben werden. Alle anderen Parameter\index{Parameter} werden als Dateinamen interpretiert. | ||||
|  | ||||
| \footnotesize | ||||
| \index{\$@=\texttt{\$@}}\index{Anf<EFBFBD>hrungszeichen}\index{Backticks}\index{!|!|=\texttt{!|!|}}\index{getopt=\texttt{getopt}}\index{OR}\index{set=\texttt{set}} | ||||
| \begin{listing}[2]{1} | ||||
| \begin{lstlisting} | ||||
| #!/bin/sh | ||||
| set -- `getopt "ab:" "$@"` || { | ||||
| \end{listing} | ||||
| \normalsize | ||||
| \begin{flushright} | ||||
|  | ||||
| \end{lstlisting} | ||||
|  | ||||
| Das \texttt{set}\index{set=\texttt{set}}-Kommando belegt den Inhalt der vordefinierten Variablen (\ref{vordefinierte_variablen}) neu, so da<64> es aussieht, als ob dem Skript die R<>ckgabewerte von \texttt{getopt}\index{getopt=\texttt{getopt}} <20>bergeben wurden. Man mu<6D> die beiden Minuszeichen angeben, da sie daf<61>r sorgen, da<64> die Aufrufparameter an \texttt{getopt}\index{getopt=\texttt{getopt}} und nicht an die Shell selbst <20>bergeben werden. Die originalen Parameter\index{Parameter} werden von \texttt{getopt}\index{getopt=\texttt{getopt}} untersucht und modifiziert zur<75>ckgegeben: \texttt{a} und \texttt{b} werden als Parameter\index{Parameter} Markiert, \texttt{b} sogar mit der M<>glichkeit einer zus<75>tzlichen Angabe. | ||||
|  | ||||
| Wenn dieses Kommando fehlschl<68>gt ist das ein Zeichen daf<61>r, da<64> falsche Parameter\index{Parameter} <20>bergeben wurden. Also wird nach einer entsprechenden Meldung das Programm mit Exit-Code 1 verlassen. | ||||
| \end{flushright} | ||||
| \footnotesize | ||||
|  | ||||
| \index{\$n=\texttt{\$}$n$}\index{Null-Befehl}\index{!>\&=\texttt{!>\&}}\index{!==\texttt{!=}}\index{Anf<EFBFBD>hrungszeichen}\index{Backticks}\index{basename=\texttt{basename}} | ||||
| \begin{listingcont} | ||||
| \begin{lstlisting}[firstnumber=last] | ||||
|    echo "Anwendung: `basename $0` [-a] [-b Name] Dateien" 1>&2 | ||||
|    exit 1 | ||||
| } | ||||
| @@ -243,41 +232,38 @@ echo "Momentan steht in der Kommandozeile folgendes: $*" | ||||
| aflag=0 name=NONE | ||||
| while : | ||||
| do | ||||
| \end{listingcont} | ||||
| \normalsize | ||||
| \begin{flushright} | ||||
|  | ||||
| \end{lstlisting} | ||||
|  | ||||
| In einer Endlosschleife\index{Endlosschleife}, die man mit Hilfe des Null-Befehls (\texttt{:}, \ref{null-befehl}) baut, werden die `neuen' Parameter\index{Parameter} der Reihe nach untersucht. Wenn ein \texttt{-a} vorkommt, wird die Variable \texttt{aflag} gesetzt. Bei einem \texttt{-b} werden per \texttt{shift}\index{shift=\texttt{shift}} alle Parameter\index{Parameter} nach Links verschoben, dann wird der Inhalt des n<>chsten Parameters\index{Parameter} in der Variablen \texttt{name} gesichert. | ||||
| \end{flushright} | ||||
| \footnotesize | ||||
|  | ||||
| \index{!==\texttt{!=}}\index{\$n=\texttt{\$}$n$}\index{Anf<EFBFBD>hrungszeichen}\index{case=\texttt{case}}\index{shift=\texttt{shift}} | ||||
| \begin{listingcont} | ||||
| \begin{lstlisting}[firstnumber=last] | ||||
|    case "$1" in | ||||
|     -a) aflag=1 ;; | ||||
|     -b) shift; name="$1" ;; | ||||
|     --) break ;; | ||||
| \end{listingcont} | ||||
| \normalsize | ||||
| \begin{flushright} | ||||
|  | ||||
| \end{lstlisting} | ||||
|  | ||||
| Wenn ein \texttt{-{}-} erscheint, ist das ein Hinweis darauf, da<64> die Liste der Parameter\index{Parameter} abgearbeitet ist. Dann wird per \texttt{break}\index{break=\texttt{break}} (\ref{break}) die Endlosschleife unterbrochen. Die Aufrufparameter enthalten jetzt nur noch die eventuell angegebenen Dateinamen, die jetzt von dem Restlichen Skript wie gewohnt weiterverarbeitet werden k<>nnen.  | ||||
| \end{flushright} | ||||
| \footnotesize | ||||
|  | ||||
| \index{shift=\texttt{shift}} | ||||
| \begin{listingcont} | ||||
| \begin{lstlisting}[firstnumber=last] | ||||
|    esac | ||||
|    shift | ||||
| done | ||||
| shift | ||||
| \end{listingcont} | ||||
| \normalsize | ||||
| \begin{flushright} | ||||
|  | ||||
| \end{lstlisting} | ||||
|  | ||||
| Am Ende werden die Feststellungen ausgegeben. | ||||
| \end{flushright} | ||||
| \footnotesize | ||||
|  | ||||
| \index{\$*=\texttt{\$*}}\index{Anf<EFBFBD>hrungszeichen} | ||||
| \begin{listingcont} | ||||
| \begin{lstlisting}[firstnumber=last] | ||||
| echo "aflag=$aflag / Name = $name / Die Dateien sind $*" | ||||
| \end{listingcont} | ||||
| \normalsize | ||||
|  | ||||
| \end{lstlisting} | ||||
|  | ||||
|  | ||||
| \section{Fallensteller: Auf Traps  | ||||
| @@ -293,50 +279,45 @@ Wie l | ||||
|  | ||||
| Das Skript soll eine komprimierte Textdatei mittels \texttt{zcat} in ein tempor<6F>res File entpacken, dieses mit \texttt{pg} seitenweise anzeigen und nachher wieder l<>schen. | ||||
|  | ||||
| \footnotesize | ||||
| \index{!==\texttt{!=}} | ||||
| \begin{listing}[2]{1} | ||||
| \begin{lstlisting} | ||||
| #!/bin/sh | ||||
| stat=1 | ||||
| temp=/tmp/zeige$$ | ||||
| \end{listing} | ||||
| \normalsize | ||||
| \begin{flushright} | ||||
|  | ||||
| \end{lstlisting} | ||||
|  | ||||
| Zun<EFBFBD>chst werden zwei Variablen belegt, die im weiteren Verlauf benutzt werden sollen. In \texttt{stat} wird der Wert abgelegt, den das Skript im Falle eines Abbruchs als Exit-Status zur<75>ckliefern soll. Die Variable \texttt{temp} enth<74>lt den Namen f<>r eine tempor<6F>re Datei. Dieser setzt sich zusammen aus \texttt{/tmp/zeige} und der Proze<7A>nummer des laufenden Skripts. So soll sichergestellt werden, da<64> noch keine Datei mit diesem Namen existiert. | ||||
| \end{flushright} | ||||
| \footnotesize | ||||
|  | ||||
| \index{Ticks}\index{!>\&=\texttt{!>\&}}\index{\$n=\texttt{\$}$n$}\index{Ticks}\index{Anf<EFBFBD>hrungszeichen}\index{Backticks}\index{basename=\texttt{basename}} | ||||
| \begin{listingcont} | ||||
| \begin{lstlisting}[firstnumber=last] | ||||
| trap 'rm -f $temp; exit $stat' 0 | ||||
| trap 'echo "`basename $0`: Ooops..." 1>&2' 1 2 15 | ||||
| \end{listingcont} | ||||
| \normalsize | ||||
| \begin{flushright} | ||||
|  | ||||
| \end{lstlisting} | ||||
|  | ||||
| Hier werden die Traps definiert. Bei Signal 0 wird die tempor<6F>re Datei gel<65>scht und der Wert aus der Variable \texttt{stat} als Exit-Code zur<75>ckgegeben. Dabei wird dem \texttt{rm}-Kommando der Parameter\index{Parameter} \texttt{-f} mitgegeben, damit keine Fehlermeldung ausgegeben wird, falls die Datei (noch) nicht existiert. Dieser Fall tritt bei jedem Beenden des Skriptes auf, also sowohl bei einem normalen Ende, als auch beim Exit-Kommando, bei einem Interrupt oder bei einem Kill\index{kill=\texttt{kill}}. Der zweite Trap reagiert auf die Signale 1, 2 und 15. Das hei<65>t, er wird bei jedem unnormalen Ende ausgef<65>hrt. Er gibt eine entsprechende Meldung auf die Standard-Fehlerausgabe (\ref{datenstrom}) aus. Danach wird das Skript beendet, und der erste Trap wird ausgef<65>hrt.  | ||||
| \end{flushright} | ||||
| \footnotesize | ||||
|  | ||||
| \index{\$\#=\texttt{\$\#}}\index{!==\texttt{!=}}\index{!>=\texttt{!>}}\index{\$n=\texttt{\$}$n$}\index{Anf<EFBFBD>hrungszeichen}\index{case=\texttt{case}} | ||||
| \begin{listingcont} | ||||
| \begin{lstlisting}[firstnumber=last] | ||||
| case $# in | ||||
|  1) zcat "$1" > $temp | ||||
|     pg $temp | ||||
|     stat=0 | ||||
|     ;; | ||||
| \end{listingcont} | ||||
| \normalsize | ||||
| \begin{flushright} | ||||
|  | ||||
| \end{lstlisting} | ||||
|  | ||||
| Jetzt kommt die eigentliche Funktionalit<69>t des Skriptes: Das \texttt{case}-Kommando (\ref{case}) testet die Anzahl der <20>bergebenen Parameter\index{Parameter}. Wenn genau ein Parameter\index{Parameter} <20>bergeben wurde, entpackt \texttt{zcat} die Datei, die im ersten Parameter\index{Parameter} angegeben wurde, in die tempor<6F>re Datei. Dann folgt die Seitenweise Ausgabe mittels \texttt{pg}. Nach Beendigung der Ausgabe wird der Status in der Variablen auf 0 gesetzt, damit beim Skriptende der korrekte Exit-Code zur<75>ckgegeben wird. | ||||
| \end{flushright} | ||||
| \footnotesize | ||||
|  | ||||
| \index{!>\&=\texttt{!>\&}}\index{\$n=\texttt{\$}$n$}\index{Anf<EFBFBD>hrungszeichen}\index{Backticks}\index{basename=\texttt{basename}} | ||||
| \begin{listingcont} | ||||
| \begin{lstlisting}[firstnumber=last] | ||||
|  *) echo "Anwendung: `basename $0` Dateiname" 1>&2 | ||||
| esac | ||||
| \end{listingcont} | ||||
| \normalsize | ||||
| \begin{flushright} | ||||
|  | ||||
| \end{lstlisting} | ||||
|  | ||||
| Wenn \texttt{case} eine andere Parameterzahl feststellt, wird eine Meldung mit der Aufrufsyntax auf die Standard-Fehlerausgabe geschrieben. | ||||
| \end{flushright} | ||||
| \index{trap=\texttt{trap}|)}\index{Signal|)} | ||||
|  | ||||
|  | ||||
| @@ -358,27 +339,25 @@ Zwecke noch etwas `bereinigt' werden. | ||||
|  | ||||
| Wie das aussieht, wenn es fertig ist, sieht man im folgenden Skript: | ||||
|  | ||||
| \footnotesize | ||||
| \index{!==\texttt{!=}} | ||||
| \begin{listing}[2]{1} | ||||
| \begin{lstlisting} | ||||
| #!/bin/sh | ||||
| for i in `find $1 -type f -name "*.[mM][pP]3"`; do | ||||
| \end{listing} | ||||
| \normalsize | ||||
| \begin{flushright} | ||||
|  | ||||
| \end{lstlisting} | ||||
|  | ||||
| Hier beginnt eine Schleife, die <20>ber alle Ausgaben des \texttt{find}-Kommandos | ||||
| iteriert. Dabei sucht \texttt{find} nach allen normalen Dateien (\texttt{-type | ||||
| f}), die die Extension .mp3 tragen (\texttt{-name \dq*.[mM][pP]3\dq} -- wir | ||||
| ignorieren Gro<72>- / Kleinschreibung). | ||||
| \end{flushright} | ||||
| \footnotesize | ||||
|  | ||||
| \index{find=\texttt{find}} | ||||
| \begin{listingcont} | ||||
| \begin{lstlisting}[firstnumber=last] | ||||
|   echo `tr -dc "[:alpha:]" < /dev/urandom | \ | ||||
|         dd count=8 bs=1 2> /dev/null`$i | ||||
| \end{listingcont} | ||||
| \normalsize | ||||
| \begin{flushright} | ||||
|  | ||||
| \end{lstlisting} | ||||
|  | ||||
| Hier ist der `magische Teil'. Mit dem \texttt{echo} wird die Ausgabe einer Pipe | ||||
| ausgegeben, gefolgt von dem aktuellen Dateinamen. Diese Pipe enth<74>lt ein | ||||
| \texttt{tr}, der alle ungewollten Zeichen (alles, was kein Textzeichen ist) aus | ||||
| @@ -391,14 +370,13 @@ Kommando \texttt{dd} mit den angegebenen Parametern. Damit die Erfolgsmeldung | ||||
| von \texttt{dd} nicht die Ausgabe verunstaltet, lenken wir sie nach | ||||
| \texttt{/dev/null} um. | ||||
| \index{tr=\texttt{tr}}\index{dd=\texttt{dd}} | ||||
| \end{flushright} | ||||
| \footnotesize | ||||
|  | ||||
| \index{find=\texttt{find}} | ||||
| \begin{listingcont} | ||||
| \begin{lstlisting}[firstnumber=last] | ||||
| done | sort | cut -b 9- | while read i; do | ||||
| \end{listingcont} | ||||
| \normalsize | ||||
| \begin{flushright} | ||||
|  | ||||
| \end{lstlisting} | ||||
|  | ||||
| Das Ergebnis der obigen Schleife ist also die Liste der Dateinamen, denen | ||||
| jeweils acht zuf<75>llige Zeichen vorangestellt wurden. Die Reihenfolge entspricht | ||||
| allerdings immer noch der Ausgabe von \texttt{find}, wird also nach jedem | ||||
| @@ -414,15 +392,15 @@ Diese lesen wir jetzt zeilenweise mittels \texttt{read} ein. In der | ||||
| \texttt{while}-Schleife k<>nnen wir alle erforderlichen Sachen mit dem | ||||
| Dateinamen anstellen. Hier wird er nur mittels \texttt{echo} ausgegeben. | ||||
| \index{sort=\texttt{sort}}\index{cut=\texttt{cut}} \index{read=\texttt{read}}\index{while=\texttt{while}} | ||||
| \end{flushright} | ||||
| \footnotesize | ||||
|  | ||||
| \index{find=\texttt{find}} | ||||
| \begin{listingcont} | ||||
| \begin{lstlisting}[firstnumber=last] | ||||
|   echo "Jetzt wird $i gespielt" | ||||
|   mpg123 "$i" | ||||
| done | ||||
| \end{listingcont} | ||||
| \normalsize | ||||
|  | ||||
| \end{lstlisting} | ||||
|  | ||||
| \index{Zufallszahlen|)} | ||||
|  | ||||
|  | ||||
| @@ -437,8 +415,7 @@ das Problem, da | ||||
| Proze<EFBFBD> l<>uft oder nicht. Im Normalfall wird er zuerst folgendes ausprobieren, | ||||
| was aber oft (nicht immer) in die Hose gehen wird: | ||||
|  | ||||
| \texttt{ps aux | grep }\textit{prozessname}\texttt{ \&\& echo \dq}\textit{l<EFBFBD>uft | ||||
| schon}\texttt{\dq} | ||||
| \lstinline/ps aux | grep prozessname && echo "l<>uft schon"/ | ||||
|  | ||||
| Der Grund daf<61>r ist, da<64> unter Umst<73>nden in der Ausgabe von \texttt{ps} auch | ||||
| das \texttt{grep}-Kommando samt Parameter (\textit{prozessname}) aufgelistet | ||||
| @@ -447,8 +424,7 @@ wird. So findet das \texttt{grep}-Kom\-man\-do sich quasi selbst. | ||||
| Abhilfe schafft entweder \texttt{pgrep} (\ref{pgrep}) oder das folgende | ||||
| Konstrukt: | ||||
|  | ||||
| \texttt{ps aux | grep \dq}\textit{[p]rozessname}\texttt{\dq~\&\& echo | ||||
| \dq}\textit{l<EFBFBD>uft schon}\texttt{\dq} | ||||
| \lstinline/ps aux | grep "[p]rozessname" && echo "l<>uft schon"/ | ||||
|  | ||||
| Das p ist jetzt als eine Zeichenmenge (regul<EFBFBD>rer Ausdruck) angegeben worden. | ||||
| Jetzt sucht \texttt{grep} also nach dem String \textit{prozessname}, in der | ||||
| @@ -466,7 +442,7 @@ folgendes Szenario: Es gibt ein Verzeichnis mit vielen Unterverzeichnissen, | ||||
| denen eine Zeile mit dem Inhalt `strict' vorkommt. Man k<>nnte jetzt | ||||
| folgendes versuchen: | ||||
|  | ||||
| \texttt{grep -r strict *} | ||||
| \lstinline|grep -r strict *| | ||||
|  | ||||
| Das f<>hrt allerdings dazu, da<64> alle Dateien durchsucht werden, nicht nur die | ||||
| Perl-Skripte. Diese tragen nach unserer Konvention\footnote{Perl-Skripte m<>ssen | ||||
| @@ -474,14 +450,14 @@ keine spezielle Extension haben, es sei aber um des Beispiels Willen mal | ||||
| angenommen.} die Extension `.pl'. Wir starten also eine rekursive Suche <20>ber | ||||
| alle Dateien, die dem Muster entsprechen: | ||||
|  | ||||
| \texttt{grep -r strict *.pl} | ||||
| \lstinline|grep -r strict *.pl| | ||||
|  | ||||
| Das f<>hrt wieder nicht zu dem gew<65>nschten Ergebnis. Da die Unterverzeichnisse | ||||
| nicht die Extension `*.pl' tragen, werden sie nicht ber<65>cksichtigt. F<>r die | ||||
| Suche in Unterverzeichnissen ziehen wir \texttt{find} (Siehe Abschnitt | ||||
| \ref{find}) heran: | ||||
|  | ||||
| \texttt{find . -name \textbackslash*.pl -exec grep \{\} \textbackslash;} | ||||
| \lstinline|find . -name \*.pl -exec grep strict {} \;| | ||||
|  | ||||
| Dieser Befehl gibt uns zwar die gefundenen Zeilen aus, nicht aber die Namen der | ||||
| Dateien. Es sieht f<>r \texttt{grep} so aus als ob nur eine Datei durchsucht | ||||
| @@ -490,7 +466,7 @@ Parameter \texttt{-l}, allerdings w | ||||
| angezeigt. Eine Ausgabe mit beiden Informationen erhalten wir mit dem folgenden | ||||
| Konstrukt: | ||||
|  | ||||
| \texttt{find . -name \textbackslash*.pl -exec grep strict /dev/null \{\} \textbackslash;} | ||||
| \lstinline|find . -name \*.pl -exec grep strict /dev/null {} \;| | ||||
|  | ||||
| Hier durchsucht \texttt{grep} nicht nur die gefundenen Dateien, sondern bei | ||||
| jedem Aufruf auch \texttt{/dev/null}, also den digitalen M<>lleimer der per | ||||
|   | ||||
| @@ -57,8 +57,7 @@ z | ||||
|  | ||||
| Folgendes Skript funktioniert nicht: | ||||
|  | ||||
| \footnotesize | ||||
| \begin{listing}[2]{1} | ||||
| \begin{lstlisting} | ||||
| #!/bin/sh | ||||
| count=0 | ||||
| cat /etc/passwd | while read i; do | ||||
| @@ -69,8 +68,7 @@ cat /etc/passwd | while read i; do | ||||
|   fi | ||||
| done | ||||
| echo Es sind $count Benutzer mit einer ID kleiner 100 eingetragen | ||||
| \end{listing} | ||||
| \normalsize | ||||
| \end{lstlisting} | ||||
|  | ||||
| Was ist passiert? | ||||
|  | ||||
| @@ -91,8 +89,7 @@ praktisch nur lokal zur Verf | ||||
| Neben der Methode in \ref{daten_hochreichen} bietet sich hier eine viel | ||||
| einfachere L<>sung an: | ||||
|  | ||||
| \footnotesize | ||||
| \begin{listing}[2]{1} | ||||
| \begin{lstlisting} | ||||
| #!/bin/sh | ||||
| count=0 | ||||
| while read i; do | ||||
| @@ -103,8 +100,7 @@ while read i; do | ||||
|   fi | ||||
| done < /etc/passwd | ||||
| echo Es sind $count Benutzer mit einer ID kleiner 100 eingetragen | ||||
| \end{listing} | ||||
| \normalsize | ||||
| \end{lstlisting} | ||||
|  | ||||
| Hier befindet sich die Schleife nicht in einer Pipe, daher wird sie auch nicht | ||||
| in einer Subshell ausgef<65>hrt. Man kann auf das \texttt{cat}-Kommando verzichten | ||||
| @@ -124,7 +120,7 @@ enthalten. | ||||
|  | ||||
| Der erste Versuch an der Stelle wird etwas in der Form | ||||
|  | ||||
| \texttt{grep }\textit{wichtig datei.txt}\texttt{ > }\textit{datei.txt} | ||||
| \lstinline|grep wichtig datei.txt > datei.txt| | ||||
|  | ||||
| sein. Das kann funktionieren, es kann aber auch in die sprichw<68>rtliche Hose | ||||
| gehen. Das Problem an der Stelle ist, da<64> die Datei an der Stelle gleichzeitig | ||||
| @@ -136,15 +132,13 @@ Dateisystem entfernt, wenn kein Deskriptor mehr auf sie zeigt. Dann kann aus | ||||
| dem gerade angelegten Deskriptor gelesen werden, w<>hrend eine neue Datei unter | ||||
| dem alten Namen angelegt wird: | ||||
|  | ||||
| \footnotesize | ||||
| \begin{listing}[2]{1} | ||||
| \begin{lstlisting} | ||||
| #!/bin/sh | ||||
| FILE=datei.txt | ||||
| exec 3< "$FILE" | ||||
| rm "$FILE" | ||||
| grep "wichtig" <&3 > "$FILE" | ||||
| \end{listing} | ||||
| \normalsize | ||||
| \end{lstlisting} | ||||
|  | ||||
| Allerdings sollte man bei dieser Methode beachten, da<64> man im Falle eines | ||||
| Fehlers die Quelldaten verliert, da die Datei ja bereits gel<65>scht wurde. | ||||
|   | ||||
							
								
								
									
										11
									
								
								shell.tex
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								shell.tex
									
									
									
									
									
								
							| @@ -45,6 +45,17 @@ | ||||
| \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\scriptsize, | ||||
|         numbers=left, | ||||
|         numberstyle=\tiny, | ||||
|         stepnumber=2, | ||||
|         numbersep=5pt | ||||
| } | ||||
|  | ||||
|  | ||||
|                                        % F<>r PDF | ||||
| \usepackage[ | ||||
|   | ||||
| @@ -10,10 +10,10 @@ | ||||
|  | ||||
| \texttt{-c} & Anzahl der Vorkommnisse vor die Zeilen schreiben \tabularnewline\STRUT | ||||
| \texttt{-d} & Nur doppelte Zeilen ausgeben, jede nur einmal \tabularnewline\STRUT | ||||
| \texttt{-D} & Alle doppelten Zeilen ausgeben \tabularnewline\STRUT | ||||
| \texttt{-D} & GNU-Erweiterung: Alle doppelten Zeilen ausgeben \tabularnewline\STRUT | ||||
| \texttt{-f }\textsl{n} & Die ersten \textsl{n} Felder ignorieren \tabularnewline\STRUT | ||||
| \texttt{-i} & Gro<72>- / Kleinschreibung ignorieren \tabularnewline\STRUT | ||||
| \texttt{-i} & GNU-Erweiterung: Gro<72>- / Kleinschreibung ignorieren \tabularnewline\STRUT | ||||
| \texttt{-s }\textsl{n} & Die ersten \textsl{n} Zeichen ignorieren \tabularnewline\STRUT | ||||
| \texttt{-u} & Nur einfach vorkommende Zeilen ausgeben \tabularnewline\STRUT | ||||
| \texttt{-w }\textsl{n} & Nur die ersten \textsl{n} Zeichen betrachten | ||||
| \texttt{-w }\textsl{n} & GNU-Erweiterung: Nur die ersten \textsl{n} Zeichen betrachten | ||||
| \end{longtable} | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| % $Id$ | ||||
| \chapter{Werkzeugkasten}\label{werkzeugkasten} | ||||
|  | ||||
| Durch die gezeigten Steuerungsm<73>glichkeiten stehen dem Shell-Pro\-grammie\-rer | ||||
| M<EFBFBD>g\-lich\-kei\-ten offen, fast alle g<>ngigen Algorithmen zu implementieren. Es | ||||
| ist tats<74>chlich in der Shell m<>glich, Sortier- oder Suchfunktionen zu | ||||
| @@ -43,6 +44,14 @@ typische Aufgaben beschrieben. Diese enthalten `Links' zu den in Frage | ||||
| kommenden Werkzeugen. Danach gibt es eine alphabetische Aufz<66>hlung der | ||||
| wichtigsten Kommandos. | ||||
|  | ||||
| Das GNU-Projekt\marginpar{GNU!} hat vielen Kommandos n<>tzliche Parameter | ||||
| zugef<EFBFBD>gt, einige der hier beschriebenen Tools stehen ausschlie<69>lich auf | ||||
| GNU-Systemen zur Verf<72>gung. Da diese Optionen nicht auf allen Unix-Systemen zur | ||||
| Verf<EFBFBD>gung stehen, werden die betroffenen Stellen wie dieser Absatz am Rand mit | ||||
| `GNU!' markiert. Wenn diese Kommandos und Optionen benutzt werden mu<6D> also das | ||||
| Zielsystem ber<65>cksichtigt werden, im Zweifelsfall sollten die Skripte | ||||
| ausf<EFBFBD>hrlich getestet werden. | ||||
|  | ||||
| \section{N<EFBFBD>gel...}\label{naegel} | ||||
|  | ||||
| \subsection{Ein- und Ausgabe}\label{ein_und_ausgabe} | ||||
| @@ -66,6 +75,7 @@ Dateien auf der Festplatte. | ||||
| \item \texttt{echo} (\ref{echo}): Daten ausgeben | ||||
| \item \texttt{grep} (\ref{grep}): In Dateien suchen | ||||
| \item \texttt{head} (\ref{head}): Dateianfang ausgeben | ||||
| \item \texttt{logger} (\ref{logger}): Text ins System-Log schreiben | ||||
| \item \texttt{printf} (\ref{printf}): Formatierte Datenausgabe | ||||
| \item \texttt{read} (\ref{read}): Zeilen einlesen | ||||
| \item \texttt{tail} (\ref{tail}): Dateiende ausgeben | ||||
| @@ -215,8 +225,7 @@ Eine weitere Gemeinsamkeit ist die Art der Ein- und Ausgabe. Wenn eine | ||||
| Eingabedatei angegeben wird, wird diese verarbeitet. Ansonsten wird die | ||||
| Standard-Eingabe gelesen. Ausgaben erfolgen immer auf der Standard-Ausgabe. | ||||
|  | ||||
| \footnotesize | ||||
| \begin{listing}[2]{1} | ||||
| \begin{lstlisting} | ||||
| # Aufruf als Filter: | ||||
| kommando1 | awk '{ print $1; print $2 }' | kommando2 | ||||
|  | ||||
| @@ -233,15 +242,14 @@ awk ' | ||||
| # Alternativ k<>nnen die Kommandos auch in eine eigene Datei gespeichert und | ||||
| # <20>ber den Parameter -f eingebunden werden: | ||||
| awk -f script.awk datei.txt | ||||
| \end{listing} | ||||
| \normalsize | ||||
| \end{lstlisting} | ||||
|  | ||||
| Neben dem Parameter \texttt{-f} zum Einlesen der Programmdatei gibt es noch den | ||||
| Parameter \texttt{-F} mit dem der Feld-Trenner angegeben werden kann. Die | ||||
| folgende Zeile gibt beispielsweise alle Benutzernamen und deren User-IDs aus | ||||
| der Doppelpunktseparierten Datei \texttt{/etc/passwd} aus: | ||||
|  | ||||
| \texttt{awk -F: '\{ print \$1\dq hat ID \dq\$3 \}' /etc/passwd} | ||||
| \lstinline|awk -F: '{ print $1" hat ID "$3 }' /etc/passwd| | ||||
|  | ||||
| \subsubsection{Muster und Prozeduren} | ||||
|  | ||||
| @@ -291,8 +299,7 @@ mit den TeX-Dateien weiter unten. | ||||
|  | ||||
| Hier ein paar Einfache Beispiele f<>r Blocks aus Mustern und Prozeduren: | ||||
|  | ||||
| \footnotesize | ||||
| \begin{listing}[2]{1} | ||||
| \begin{lstlisting} | ||||
| # Das erste Feld jeder Zeile ausgeben: | ||||
| { print $1 } | ||||
|  | ||||
| @@ -335,8 +342,7 @@ END { summe /= 1024; print "Die Gr | ||||
| # ausgeben, verarbeitet die Ausgabe von 'df': | ||||
| BEGIN { OFS="|" } | ||||
| /^\/dev\// { print $1,$5 } | ||||
| \end{listing} | ||||
| \normalsize | ||||
| \end{lstlisting} | ||||
|  | ||||
| \index{awk=\texttt{awk}|)} | ||||
|  | ||||
| @@ -377,17 +383,17 @@ an vielen, teilweise sehr unterschiedlich gelagerten Aufgaben wertvolle | ||||
| Dienste. | ||||
|  | ||||
| Durch Umlenklung der Ausgabe k<>nnen Dateien erzeugt und erweitert werden. So | ||||
| k<EFBFBD>nnen mehrere Dateien per \texttt{cat datei1.txt datei2.txt > datei.txt} | ||||
| k<EFBFBD>nnen mehrere Dateien per \lstinline|cat datei1.txt datei2.txt > datei.txt| | ||||
| verkettet werden. | ||||
|  | ||||
| Au<EFBFBD>erdem kann man mit einem Aufruf in der Art \texttt{cat datei.txt | kommando} | ||||
| Daten an ein Programm <20>bergeben, das nur von der Standardeingabe lesen kann | ||||
| (Filter). | ||||
| Au<EFBFBD>erdem kann man mit einem Aufruf in der Art | ||||
| \lstinline|cat datei.txt | kommando| Daten an ein Programm <20>bergeben, das nur | ||||
| von der Standardeingabe lesen kann (Filter). | ||||
|  | ||||
| \texttt{cat} verf<72>gt <20>ber eine Reihe von Parametern, um die Ausgabe zu | ||||
| formatieren, so k<>nnen mit \texttt{-n} bzw. \texttt{-b} die Zeilen numeriert | ||||
| werden, oder mit \texttt{-s} mehrere Zeilen zu einer einzigen zusammengefa<66>t | ||||
| werden. | ||||
| GNU-\texttt{cat}\marginpar{GNU!} verf<72>gt <20>ber eine Reihe von Parametern, um die | ||||
| Ausgabe zu formatieren, so k<>nnen mit \texttt{-n} bzw. \texttt{-b} die Zeilen | ||||
| numeriert werden, oder mit \texttt{-s} mehrere Zeilen zu einer einzigen | ||||
| zusammengefa<EFBFBD>t werden. | ||||
|  | ||||
| \index{cat=\texttt{cat}|)} | ||||
|  | ||||
| @@ -458,8 +464,9 @@ Zur Verdeutlichung ein paar Beispiele, wo es m | ||||
|  | ||||
| \LTXtable{\textwidth}{tab_kommandos_chmod_beispiele.tex} | ||||
|  | ||||
| Am wichtigsten sind also die Aufrufe \texttt{chmod 644 datei} und \texttt{chmod | ||||
| 755 datei}, je nachdem ob die Datei ausf<73>hrbar sein soll oder nicht. | ||||
| Am wichtigsten sind also die Aufrufe \lstinline|chmod 644 datei| und | ||||
| \lstinline|chmod 755 datei|, je nachdem ob die Datei ausf<73>hrbar sein soll oder | ||||
| nicht. | ||||
|  | ||||
| \index{chmod=\texttt{chmod}|)} | ||||
|  | ||||
| @@ -482,9 +489,9 @@ Will man lediglich die Gruppen-ID  | ||||
|  | ||||
|  | ||||
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||||
| \subsection{chpasswd}\index{chpasswd=\texttt{chpasswd}|(textbf} | ||||
| \subsection{chpasswd}\index{chpasswd=\texttt{chpasswd}|(textbf}\marginpar{GNU!} | ||||
|  | ||||
| Mit diesem Kommando bietet sich dem Administrator des Systems die | ||||
| Mit diesem GNU-Kommando bietet sich dem Administrator des Systems die | ||||
| M<EFBFBD>g\-lich\-keit, scriptgesteuert die Pa<50>w<EFBFBD>rter f<>r neue Benutzer zu vergeben. | ||||
| Manuell <20>ndert man ein Pa<50>wort mit dem Kommando | ||||
| \texttt{passwd}\index{passwd=\texttt{passwd}}, allerdings l<>scht (flusht) | ||||
| @@ -511,7 +518,23 @@ diese Datei nicht allgemein lesbar ist. | ||||
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||||
| \subsection{cmp}\label{cmp}\index{cmp=\texttt{cmp}|(textbf} | ||||
|  | ||||
| TODO!!! cmp GNU? | ||||
| Mit \texttt{cmp} werden zwei Dateien verglichen. Wenn die beiden Dateien | ||||
| identisch sind gibt es keine Ausgabe, ansonsten wird die Position des ersten | ||||
| Unterschiedes ausgegeben. | ||||
|  | ||||
| Einer der beiden anzugebenden Dateinamen kann auch durch \texttt{-} ersetzt | ||||
| werden, dann wird die Standard-Eingabe mit der anderen angegebenen Datei | ||||
| verglichen. | ||||
|  | ||||
| Mit dem Parameter \texttt{-l} werden alle abweichenden Bytes aufgelistet, | ||||
| jeweils mit der Position (dezimal) und den beiden Bytes (oktal). | ||||
|  | ||||
| Durch \texttt{-s} l<><6C>t sich die Ausgabe von Unterschieden unterdr<64>cken, der | ||||
| Exit-Status gibt weiterhin das Ergebnis an. | ||||
|  | ||||
| In der GNU-Version\marginpar{GNU!} gibt es auch Parameter, mit denen Bereiche | ||||
| der Datei vom Vergleich ausgeschlossen werden k<>nnen (\texttt{-i}), oder mit | ||||
| denen nur die ersten n Bytes der Dateien verglichen werden (\texttt{-n}). | ||||
|  | ||||
| \index{cmp=\texttt{cmp}|)} | ||||
|  | ||||
| @@ -552,7 +575,15 @@ Dateien in Spalten zusammengef | ||||
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||||
| \subsection{diff}\label{diff}\index{diff=\texttt{diff}|(textbf} | ||||
|  | ||||
| TODO!!! diff | ||||
| Mit \texttt{diff} werden zwei Dateien verglichen, und die <20>nderungen auf der | ||||
| Standardausgabe aufgelistet, die n<>tig sind um die erste an die zweite Datei | ||||
| anzupassen. | ||||
|  | ||||
| Mit dem Parameter \texttt{-r} k<>nnen auch ganze Verzeichnisse rekursiv | ||||
| verglichen werden. | ||||
|  | ||||
| Die ausgegebenen Listen k<>nnen mit dem \texttt{patch}-Kommando auf Dateien | ||||
| angewandt werden um sie auf den ge<67>nderten Stand zu bringen. | ||||
|  | ||||
| \index{diff=\texttt{diff}|)} | ||||
|  | ||||
| @@ -602,7 +633,7 @@ Variablen zu bilden. | ||||
|  | ||||
| Eine wichtige Anwendung f<>r dieses Kommando ist der Fall, wenn eigentlich ein | ||||
| Array\index{Array} gebraucht w<>rde. Der Inhalt eines Array-Elements kann | ||||
| beispielsweise mittels \texttt{eval echo \textbackslash\$arr\$index} ausgegeben | ||||
| beispielsweise mittels \lstinline|eval echo \$arr$index| ausgegeben | ||||
| werden, dabei ist \texttt{arr} der Name des Arrays und \texttt{index} der Name | ||||
| der Variablen, die den Index des auszugebenden Elementes enth<74>lt. | ||||
|  | ||||
| @@ -625,7 +656,7 @@ wichtigsten Operatoren lauten wie folgt: | ||||
|  | ||||
| Bei einigen Sonderzeichen ist deren Bedeutung in der Shell zu ber<65>cksichtigen, | ||||
| sie sind also durch Anf<6E>hrungszeichen oder Backslashes zu quoten: | ||||
| \texttt{i=`expr \$i \textbackslash{}* 3`}. | ||||
| \lstinline|i=`expr $i \* 3`|. | ||||
|  | ||||
| Eine andere M<>glichkeit f<>r einfache Rechnungen besteht in der sogenannten | ||||
| Arith\-me\-tik-Ex\-pan\-sion (Siehe \ref{arithmetikexpansion}). | ||||
| @@ -666,8 +697,7 @@ Vorkommen gr | ||||
| Da die reine Beschreibung der Parameter manchmal etwas verwirrend ist, folgen | ||||
| hier ein paar praktische Beispiele: | ||||
|  | ||||
| \footnotesize | ||||
| \begin{listing}[2]{1} | ||||
| \begin{lstlisting} | ||||
| # Suche alle Eintr<74>ge in bzw. unter dem aktuellen Verzeichnis: | ||||
| find . | ||||
| # Suche alle normalen Dateien mit der Endung txt unter /home: | ||||
| @@ -680,8 +710,7 @@ find ~ -size +10000000c -exec ls -l {} \; | ||||
| # Suche alle Eintr<74>ge im Homeverzeichnis, die innerhalb der letzten zwei Tage | ||||
| # ge<67>ndert wurden: | ||||
| find ~ -mtime -2 | ||||
| \end{listing} | ||||
| \normalsize | ||||
| \end{lstlisting} | ||||
|  | ||||
| Wenn mittels \texttt{-exec} weitere Kommandos gestartet werden, sollte beachtet | ||||
| werden da<64> mindestens ein Proze<7A> pro Fundstelle gestartet wird. Das kostet sehr | ||||
| @@ -755,8 +784,7 @@ Daneben stehen noch eine Reihe weiterer Signale zur Verf | ||||
| Es gibt verschiedene Wege, das Signal abzusetzen. Welchen man w<>hlt ist | ||||
| Geschmackssache. Hier ein paar Beispiele: | ||||
|  | ||||
| \footnotesize | ||||
| \begin{listing}[2]{1} | ||||
| \begin{lstlisting} | ||||
| # Die folgenden Befehle sind gleichwertig. Alle senden ein HUP an Proze<7A>-ID 42: | ||||
| kill -1 42 | ||||
| kill -HUP 42 | ||||
| @@ -770,8 +798,7 @@ kill -9 -1 | ||||
|  | ||||
| # SIGTERM an mehrere Prozesse senden: | ||||
| kill 123 456 789 | ||||
| \end{listing} | ||||
| \normalsize | ||||
| \end{lstlisting} | ||||
|  | ||||
| Siehe auch: Das Beispiel `Fallensteller' in Abschnitt \ref{traps} zeigt, wie | ||||
| ein Skript auf Signale reagieren kann. | ||||
| @@ -780,12 +807,12 @@ ein Skript auf Signale reagieren kann. | ||||
|  | ||||
|  | ||||
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||||
| \subsection{killall}\label{killall}\index{killall=\texttt{killall}|(textbf} | ||||
| \subsection{killall}\label{killall}\index{killall=\texttt{killall}|(textbf}\marginpar{GNU!} | ||||
|  | ||||
| Im Abschnitt <20>ber \texttt{kill} (\ref{kill}) wird beschrieben, wie man ein | ||||
| Signal an einen Proze<7A> schickt, dessen ID bekannt ist. Kennt man die ID nicht, | ||||
| oder will man das Signal an mehrere Prozesse schicken, kann dieses Kommando | ||||
| eine gro<72>e Hilfe darstellen. | ||||
| oder will man das Signal an mehrere Prozesse schicken, kann dieses Kommando auf | ||||
| GNU-Systemen eine gro<72>e Hilfe darstellen. | ||||
|  | ||||
| Mit dem Parameter \texttt{-i} wird vor jedem Signal interaktiv gefragt, ob es | ||||
| geschickt werden soll. Mit \texttt{-v} wird angegeben, ob die Signale | ||||
| @@ -803,6 +830,22 @@ zur Verf | ||||
| \index{killall=\texttt{killall}|)} | ||||
|  | ||||
|  | ||||
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||||
| \subsection{logger}\label{logger}\index{logger=\texttt{logger}|(textbf} | ||||
|  | ||||
| Mit \texttt{logger} werden Nachrichten an die Log-Mechanismen des Systems | ||||
| geschickt. So k<>nnen auch unbeobachtet laufende Skripte <20>ber ihr tun | ||||
| informieren. | ||||
|  | ||||
| Der zu loggende Text wird einfach als Parameter <20>bergeben. | ||||
|  | ||||
| Die GNU-Version\marginpar{GNU!} verf<72>gt <20>ber einige Parameter, unter anderem | ||||
| kann die Nachricht mit \texttt{-s} parallel zum System-Log auch auf der | ||||
| Standard-Fehlerausgabe ausgegeben werden. | ||||
|  | ||||
| \index{logger=\texttt{logger}|)} | ||||
|  | ||||
|  | ||||
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||||
| \subsection{ls}\label{ls}\index{ls=\texttt{ls}|(textbf} | ||||
|  | ||||
| @@ -812,7 +855,7 @@ oder angegebenen Verzeichnis auf, das Kommando hat aber auch sehr viele | ||||
| Parameter mit denen sich die Ausgabe anpassen l<><6C>t. Hier sind die wichtigsten, | ||||
| eine vollst<73>ndige Auflistung bietet wie immer die Man-Page: | ||||
|  | ||||
| \LTXtable{\textwidth}{tab_kommandos_ls_parameter.tex} | ||||
| \marginpar{GNU!}\LTXtable{\textwidth}{tab_kommandos_ls_parameter.tex} | ||||
|  | ||||
| Besonders informativ gibt sich der Parameter \texttt{-l}, da damit auch die | ||||
| Eigent<EFBFBD>mer und die Berechtigungen der Dateien angezeigt werden. Die Ausgabe hat | ||||
| @@ -893,7 +936,7 @@ gedreht. | ||||
|  | ||||
|  | ||||
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||||
| \subsection{pgrep}\label{pgrep}\index{pgrep=\texttt{pgrep}|(textbf} | ||||
| \subsection{pgrep}\label{pgrep}\index{pgrep=\texttt{pgrep}|(textbf}\marginpar{GNU!} | ||||
|  | ||||
| Eine h<>ufig wiederkehrende Aufgabe ist es, zu sehen ob ein bestimmter Proze<7A> | ||||
| existiert oder nicht. Falls das Kommando \texttt{pgrep} zur Verf<72>gung steht, | ||||
| @@ -901,7 +944,7 @@ kannn man auf das Konstrukt mit \texttt{ps} und \texttt{grep} verzichten. Der | ||||
| folgende Aufruf liefert alle Proze<7A>-IDs, deren Name httpd enth<74>lt, inclusive | ||||
| des vollen Kommandos: | ||||
|  | ||||
| \texttt{pgrep -lf httpd} | ||||
| \lstinline|pgrep -lf httpd| | ||||
|  | ||||
| <EFBFBD>ber weitere Parameter l<><6C>t sich genauer spezifizieren, wonach gesucht werden | ||||
| soll, hier die wichtigsten: | ||||
| @@ -912,7 +955,7 @@ Die Ausgabe enth | ||||
| sich als Parameter f<>r andere Programme benutzen. Das folgende Beispiel liefert | ||||
| detaillierte Informationen <20>ber alle xterm-Prozesse: | ||||
|  | ||||
| \texttt{ps -fp \$(pgrep -d, -x xterm)} | ||||
| \lstinline|ps -fp $(pgrep -d, -x xterm)| | ||||
|  | ||||
| Siehe auch: Abschnitt \ref{beispiele_suchen_prozesse}. | ||||
|  | ||||
| @@ -920,7 +963,7 @@ Siehe auch: Abschnitt \ref{beispiele_suchen_prozesse}. | ||||
|  | ||||
|  | ||||
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||||
| \subsection{pkill}\label{pkill}\index{pkill=\texttt{pkill}|(textbf} | ||||
| \subsection{pkill}\label{pkill}\index{pkill=\texttt{pkill}|(textbf}\marginpar{GNU!} | ||||
|  | ||||
| Dieses Kommando ist eng verwandt mit \texttt{pgrep} (Siehe Abschnitt | ||||
| \ref{pgrep}), es versteht im Wesentlichen die gleichen Parameter. Allerdings | ||||
| @@ -934,7 +977,7 @@ diese Funktion wird im Abschnitt zu \texttt{kill} (\ref{kill}) n | ||||
| beschrieben. Das folgende Kommando veranla<6C>t beispielsweise den Syslog-Daemon, | ||||
| seine Konfiguration neu einzulesen: | ||||
|  | ||||
| \texttt{pkill -HUP syslogd} | ||||
| \lstinline|pkill -HUP syslogd| | ||||
|  | ||||
| Das Kommando \texttt{killall} (Abschnitt \ref{killall}) bietet eine <20>hnliche | ||||
| Funktionalit<EFBFBD>t, allerdings fehlen ihm einige Parameter. Trotzdem sollte im | ||||
| @@ -954,7 +997,7 @@ Dabei enth | ||||
| bestimmten Regeln durch die Daten ersetzt werden. | ||||
|  | ||||
| Der Format-String folgt im Wesentlichen den gleichen Regeln wie in der | ||||
| C-Version. N<>heres dazu erf<72>hrt man mit \texttt{man 3 printf}. | ||||
| C-Version. N<>heres dazu erf<72>hrt man mit \lstinline|man 3 printf|. | ||||
|  | ||||
| Hier die wichtigsten Parameter f<>r den Format-String: | ||||
|  | ||||
| @@ -965,15 +1008,13 @@ Daten. Im folgenden Beispiel werden alle Benutzernamen, deren | ||||
| Home-Verzeichnisse und Default-Shells aus der Datei \texttt{/etc/passwd} | ||||
| extrahiert und <20>bersichtlich ausgegeben: | ||||
|  | ||||
| \footnotesize | ||||
| \begin{listing}[2]{1} | ||||
| \begin{lstlisting} | ||||
| #!/bin/sh | ||||
| IFS=: | ||||
| while read user pass uid gid name home shell; do | ||||
|   printf "%-15s %-25s %s\n" $user $home $shell | ||||
| done < /etc/passwd | ||||
| \end{listing} | ||||
| \normalsize | ||||
| \end{lstlisting} | ||||
|  | ||||
| Zur Erinnerung: Die vordefinierte Variable | ||||
| \texttt{\$IFS}\index{\$IFS=\texttt{\$IFS}} ist der Feld-Separator, die | ||||
| @@ -1001,12 +1042,12 @@ In Skripten m | ||||
| aktiv ist, ob also zum Beispiel ein bestimmter Serverdienst l<>uft. Dazu macht | ||||
| man \texttt{ps} <20>ber Optionen gespr<70>chiger. | ||||
|  | ||||
| Das Kommando versteht in der GNU-Version zwei unterschiedliche Arten von | ||||
| Optionen. Den sogenannten Unix- bzw. Posix-Stil und den BSD-Stil. Zus<75>tzlich | ||||
| gibt es noch ausf<73>hrliche Parameter, aber die sollen hier nicht beschrieben | ||||
| werden. Die jeweiligen Formen stehen nicht auf allen Systemen zur Verf<72>gung, | ||||
| wenn ein Skript beispielsweise auch unter Solaris benutzt werden soll ist man | ||||
| gezwungen, die Unix-Parametrisierung zu benutzen. | ||||
| Das Kommando versteht in der GNU-Version\marginpar{GNU!} zwei unterschiedliche | ||||
| Arten von Optionen. Den sogenannten Unix- bzw. Posix-Stil und den BSD-Stil. | ||||
| Zus<EFBFBD>tzlich gibt es noch ausf<73>hrliche Parameter, aber die sollen hier nicht | ||||
| beschrieben werden. Die jeweiligen Formen stehen nicht auf allen Systemen zur | ||||
| Verf<EFBFBD>gung, wenn ein Skript beispielsweise auch unter Solaris benutzt werden | ||||
| soll ist man gezwungen, die Unix-Parametrisierung zu benutzen. | ||||
|  | ||||
| Unix-Parameter zeichnen sich durch die <20>bliche Angabe mit Bindestrich aus. | ||||
| BSD-Pa\-ra\-me\-ter werden ohne Bindestrich angegeben, was neben den meisten | ||||
| @@ -1016,8 +1057,7 @@ Es gibt sehr viele verschiedene Parameter, die beste Informationsquelle ist wie | ||||
| immer die Man-Page bzw. ein entsprechendes Buch. Hier werden nur ein paar | ||||
| typische Aufrufbeispiele gezeigt, deren Ausgabe sich jeder selber ansehen kann: | ||||
|  | ||||
| \footnotesize | ||||
| \begin{listing}[2]{1} | ||||
| \begin{lstlisting} | ||||
| # Alle Prozesse auflisten, Unix-Syntax: | ||||
| ps -e | ||||
| ps -ef | ||||
| @@ -1041,8 +1081,7 @@ ps -C syslogd -o pid= | ||||
|  | ||||
| # Nur den Namen des Prozesses mit der ID 42 ausgeben: | ||||
| ps -p 42 -o comm= | ||||
| \end{listing} | ||||
| \normalsize | ||||
| \end{lstlisting} | ||||
|  | ||||
| F<EFBFBD>r die Suche nach Prozessen bestimmten Namens steht auf manchen Systemen auch | ||||
| das Kommando \texttt{pgrep} (Abschnitt \ref{pgrep}) zur Verf<72>gung. | ||||
| @@ -1070,36 +1109,38 @@ alle Zeichen, die in der vordefinierten Variable | ||||
| Wenn keine Variablennamen angegeben werden, wird die Eingabe in der Variable | ||||
| \texttt{REPLY} abgelegt. | ||||
|  | ||||
| Normalerweise wird eine Eingabezeile mit einem Newline abgeschlossen. Mit dem | ||||
| Parameter \texttt{-d} ist es m<>glich, ein anderes Zeilenendezeichen anzugeben. | ||||
| Beispielsweise liest \texttt{read -d \dq~\dq~var} alle Zeichen bis zum ersten | ||||
| Leerzeichen in die Variable \texttt{var} ein. | ||||
|  | ||||
| Wenn nur eine bestimmte Zahl von Zeichen gelesen werden soll, kann diese durch | ||||
| den Parameter \texttt{-n} angegeben werden. Der Befehl \texttt{read -n 5 var} | ||||
| liest die ersten f<>nf Zeichen in die Variable \texttt{var} ein. Demzufolge kann | ||||
| ein Skript durch ein \texttt{read -n 1} dazu gebracht werden, auf einen | ||||
| einzelnen Tastendruck~--~nicht zwingend ein Return~--~zu warten. | ||||
|  | ||||
| Mit dem Parameter \texttt{-p} kann man einen Prompt, also eine | ||||
| Eingabeaufforderung ausgeben lassen. \texttt{read -p \dq{}Gib was ein:\dq~var} | ||||
| schreibt also erst den Text \textit{Gib was ein:} auf das Terminal, bevor die | ||||
| Eingaben in die Variable \texttt{var} <20>bernommen werden. Dieser Prompt wird nur | ||||
| an einem interaktiven Terminal ausgegeben, also nicht in einem Skript das seine | ||||
| Eingaben aus einer Datei oder aus einem Stream erh<72>lt. | ||||
|  | ||||
| Sonderzeichen k<>nnen w<>hrend der Eingabe normalerweise mittels eines Backslash | ||||
| vor der Interpretation gesch<63>tzt werden. Ein Backslash vor einem Newline | ||||
| bewirkt also eine mehrzeilige Eingabe. Dieses Verhalten kann mit dem Parameter | ||||
| \texttt{-r} abgeschaltet werden. | ||||
|  | ||||
| Normalerweise wird eine Eingabezeile mit einem Newline abgeschlossen. Mit dem | ||||
| Parameter \texttt{-d}\marginpar{GNU!} ist es m<>glich, ein anderes | ||||
| Zeilenendezeichen anzugeben.  Beispielsweise liest | ||||
| \lstinline|read -d " " var| alle Zeichen bis zum ersten Leerzeichen in die | ||||
| Variable \texttt{var} ein. | ||||
|  | ||||
| Wenn nur eine bestimmte Zahl von Zeichen gelesen werden soll, kann diese durch | ||||
| den Parameter \texttt{-n}\marginpar{GNU!} angegeben werden. Der Befehl | ||||
| \lstinline|read -n 5 var| liest die ersten f<>nf Zeichen in die Variable | ||||
| \texttt{var} ein. Demzufolge kann ein Skript durch ein \lstinline|read -n 1| | ||||
| dazu gebracht werden, auf einen einzelnen Tastendruck~--~nicht zwingend ein | ||||
| Return~--~zu warten. | ||||
|  | ||||
| Mit dem Parameter \texttt{-p}\marginpar{GNU!} kann man einen Prompt, also eine | ||||
| Eingabeaufforderung ausgeben lassen. \lstinline|read -p "Gib was ein:" var| | ||||
| schreibt also erst den Text \textit{Gib was ein:} auf das Terminal, bevor die | ||||
| Eingaben in die Variable \texttt{var} <20>bernommen werden. Dieser Prompt wird nur | ||||
| an einem interaktiven Terminal ausgegeben, also nicht in einem Skript das seine | ||||
| Eingaben aus einer Datei oder aus einem Stream erh<72>lt. | ||||
|  | ||||
| Wenn die Eingabe von einem Terminal kommt und nicht auf dem Bildschirm | ||||
| erscheinen soll, zum Beispiel bei Pa<50>wortabfragen, kann die Ausgabe mit dem | ||||
| Parameter \texttt{-s} (Silent) unterdr<64>ckt werden. | ||||
| Parameter \texttt{-s}\marginpar{GNU!} (Silent) unterdr<64>ckt werden. | ||||
|  | ||||
| Mit \texttt{-t} kann ein Time-Out definiert werden, nach dessen Ablauf das | ||||
| Kommando mit einem Fehler abbricht. Dieser Parameter ist nur bei interaktiver | ||||
| Eingabe oder beim Lesen aus einer Pipe aktiv. | ||||
| Mit \texttt{-t}\marginpar{GNU!} kann ein Time-Out definiert werden, nach dessen | ||||
| Ablauf das Kommando mit einem Fehler abbricht. Dieser Parameter ist nur bei | ||||
| interaktiver Eingabe oder beim Lesen aus einer Pipe aktiv. | ||||
|  | ||||
| Der R<>ckgabewert des \texttt{read}-Kommandos ist 0, es sei denn es trat ein | ||||
| Timeout oder ein EOF auf. | ||||
| @@ -1119,8 +1160,8 @@ Verzeichnisse k | ||||
| Gegensatz zu \texttt{rmdir} werden dann auch s<>mtliche enthaltenen Dateien und | ||||
| Unterverzeichnisse gel<65>scht. | ||||
|  | ||||
| Die GNU-Version von \texttt{rm} unterst<73>tzt zus<75>tzlich den Parameter | ||||
| \texttt{-v}, mit dem jeder L<>schvorgang ausgegeben wird. | ||||
| Die GNU-Version\marginpar{GNU!} von \texttt{rm} unterst<73>tzt zus<75>tzlich den | ||||
| Parameter \texttt{-v}, mit dem jeder L<>schvorgang ausgegeben wird. | ||||
|  | ||||
| \index{rm=\texttt{rm}|)} | ||||
|  | ||||
| @@ -1142,7 +1183,7 @@ nicht-leere Verzeichnisse k | ||||
|  | ||||
|  | ||||
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||||
| \subsection{script}\label{script}\index{script=\texttt{script}|(textbf} | ||||
| \subsection{script}\label{script}\index{script=\texttt{script}|(textbf}\marginpar{GNU!} | ||||
|  | ||||
| Dieses Kommando eignet sich vorz<72>glich f<>r das Debuggen fertiger Skripte. Man | ||||
| ruft es in Verbindung mit einem Dateinamen auf. Dieser Aufruf startet eine neue | ||||
| @@ -1176,8 +1217,7 @@ nur die g | ||||
|  | ||||
| \subsubsection{Aufruf} | ||||
|  | ||||
| \footnotesize | ||||
| \begin{listing}[2]{1} | ||||
| \begin{lstlisting} | ||||
| # Aufruf als Stream-Editor: | ||||
| kommando1 | sed 's/alt/neu/' | kommando2 | ||||
|  | ||||
| @@ -1200,13 +1240,12 @@ s/alt/neu/ | ||||
| # Alternativ k<>nnen die Kommandos auch in eine eigene Datei gespeichert und | ||||
| # <20>ber den Parameter -f eingebunden werden: | ||||
| sed -f script.sed datei.txt | ||||
| \end{listing} | ||||
| \normalsize | ||||
| \end{lstlisting} | ||||
|  | ||||
| Neben den oben erw<72>hnten Parametern kann \texttt{sed} auch mit \texttt{-n} | ||||
| ruhig gestellt werden. Damit werden die Zeilen nur dann ausgegeben, wenn das | ||||
| mittels `p' explizit gefordert wird. Die GNU-Version stellt noch ein paar | ||||
| Parameter zur Verf<72>gung, die Man-Page verr<72>t n<>heres. | ||||
| mittels `p' explizit gefordert wird. Die GNU-Version\marginpar{GNU!} stellt | ||||
| noch ein paar Parameter zur Verf<72>gung, die Man-Page verr<72>t n<>heres. | ||||
|  | ||||
| \subsubsection{Addressierung} | ||||
|  | ||||
| @@ -1278,8 +1317,7 @@ gehen soll werden hier keine komplexen Sachen vorgestellt, sondern nur ein paar | ||||
| Einzeiler. Nichtsdestotrotz k<>nnen es auch diese unscheinbaren Aufrufe in sich | ||||
| haben. | ||||
|  | ||||
| \footnotesize | ||||
| \begin{listing}[2]{1} | ||||
| \begin{lstlisting} | ||||
| ### SUCHEN UND ERSETZEN | ||||
|  | ||||
| # Im kompletten Text 'rot' durch 'blau' ersetzen: | ||||
| @@ -1355,25 +1393,24 @@ sed '/./!d'                           # Methode 2 | ||||
|  | ||||
| # Alle Leerzeilen am Dateianfang l<>schen: | ||||
| sed '/./,$!d' | ||||
| \end{listing} | ||||
| \normalsize | ||||
| \end{lstlisting} | ||||
|  | ||||
| \index{sed=\texttt{sed}|)} | ||||
|  | ||||
|  | ||||
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||||
| \subsection{seq}\label{seq}\index{seq=\texttt{seq}|(textbf} | ||||
| \subsection{seq}\label{seq}\index{seq=\texttt{seq}|(textbf}\marginpar{GNU!} | ||||
|  | ||||
| Oft wird eine auf- oder absteigende Sequenz aufeinanderfolgender Zahlen | ||||
| ben<EFBFBD>tigt, beispielsweise um eine Schleife 100 mal zu durchlaufen. Es ist nicht | ||||
| sehr performant bei jedem Schleifendurchlauf hochzuz<75>hlen und dann die | ||||
| entstandene Zahl mit dem Limit zu vergleichen. Daher nimmt man an der Stelle | ||||
| \texttt{seq} zur Hilfe. | ||||
| \texttt{seq} zur Hilfe, wenn es zur Verf<72>gung steht. | ||||
|  | ||||
| Die zu z<>hlenden Werte werden durch drei unterschiedliche Arten der | ||||
| Parametrisierung definiert: Ein Aufruf in der Form \texttt{seq 10} gibt die | ||||
| Zahlen von 1 bis 10 aus. Mit \texttt{seq 10 20} wird von 10 bis 20 gez<65>hlt, und | ||||
| \texttt{seq 20 -2 10} z<>hlt in zweierschritten r<>ckw<6B>rts von 20 nach 10. | ||||
| Parametrisierung definiert: Ein Aufruf in der Form \lstinline|seq 10| gibt die | ||||
| Zahlen von 1 bis 10 aus. Mit \lstinline|seq 10 20| wird von 10 bis 20 gez<65>hlt, | ||||
| und \lstinline|seq 20 -2 10| z<>hlt in zweierschritten r<>ckw<6B>rts von 20 nach 10. | ||||
|  | ||||
| Per default kommen die Werte zeilenweise, mit dem Parameter \texttt{-s} kann | ||||
| aber auch ein anderes Trennzeichen definiert werden. Will man etwas numerieren | ||||
| @@ -1390,13 +1427,13 @@ mit f | ||||
| Das Kommando \texttt{sleep} veranla<6C>t die Shell, f<>r eine angegebene Zeit zu | ||||
| warten. Die Zeit wird dabei in Sekunden angegeben. | ||||
|  | ||||
| In der GNU-Variante von \texttt{sleep} kann die Einheit der angegebenen | ||||
| Zeitspanne durch Suffixe definiert werden: \texttt{sleep 10s} schl<68>ft zehn | ||||
| Sekunden, \texttt{sleep 10m} zehn Minuten. Genauso werden Stunden (h) und Tage | ||||
| (d) definiert. | ||||
| In der GNU-Variante\marginpar{GNU!} von \texttt{sleep} kann die Einheit der | ||||
| angegebenen Zeitspanne durch Suffixe definiert werden: \lstinline|sleep 10s| | ||||
| schl<EFBFBD>ft zehn Sekunden, \lstinline|sleep 10m| zehn Minuten. Genauso werden | ||||
| Stunden (h) und Tage (d) definiert. | ||||
|  | ||||
| Au<EFBFBD>erdem kann die GNU-Variante auch mit nicht-Integer Zeiten arbeiten: | ||||
| \texttt{sleep 0.5} schl<68>ft eine halbe Sekunde. | ||||
| \lstinline|sleep 0.5| schl<68>ft eine halbe Sekunde. | ||||
|  | ||||
| \index{sleep=\texttt{sleep}|)} | ||||
|  | ||||
| @@ -1447,6 +1484,9 @@ Parameter \texttt{-n} steuern. | ||||
| Mit dem Parameter \texttt{-f} (follow) gibt \texttt{tail} neue Zeilen aus, | ||||
| sobald sie an die Datei angeh<65>ngt werden. | ||||
|  | ||||
| Die GNU-Version\marginpar{GNU!} kann auch das Ende mehrere Dateien ausgeben | ||||
| bzw. verfolgen, wenn mehrere Namen angegeben werden. | ||||
|  | ||||
| \index{tail=\texttt{tail}|)} | ||||
|  | ||||
|  | ||||
| @@ -1517,8 +1557,7 @@ in der Man-Page. | ||||
|  | ||||
| Die folgenden Beispiele verdeutlichen die Anwendung: | ||||
|  | ||||
| \footnotesize | ||||
| \begin{listing}[2]{1} | ||||
| \begin{lstlisting} | ||||
| text="Dies ist ein Testtext" | ||||
|  | ||||
| # kleine Umlaute durch grosse ersetzen: | ||||
| @@ -1544,8 +1583,7 @@ echo "$text" | tr -s "a-zA-Z" | ||||
| # doppelte Buchstaben l<>schen, mit Zeichenklasse: | ||||
| echo "$text" | tr -s "[:alpha:]" | ||||
| # -> Dies ist ein Testext | ||||
| \end{listing} | ||||
| \normalsize | ||||
| \end{lstlisting} | ||||
|  | ||||
| \index{tr=\texttt{tr}|)} | ||||
|  | ||||
| @@ -1564,7 +1602,7 @@ mehrere Bedingungen die zum Ausf | ||||
| Kommando gibt zm Beispiel eine Fehlermeldung aus wenn sein Skript ein Signal 1 | ||||
| (HUP), 2 (INT) oder 15 (TERM) erh<72>lt: | ||||
|  | ||||
| \texttt{trap 'echo \dq`basename \$0`: Ooops...\dq 1>\&2' 1 2 15} | ||||
| \lstinline|trap 'echo "`basename $0`: Ooops..." 1>&2' 1 2 15| | ||||
|  | ||||
| Die Zeile ist dem Beispiel aus Abschnitt \ref{traps} entnommen, dort findet | ||||
| sich auch nochmal eine ausf<73>hrliche Erkl<6B>rung. | ||||
| @@ -1601,13 +1639,14 @@ Weitaus h | ||||
| Zeilen z<>hlen lassen. Weiterhin kann man Bytes (\texttt{-c}) oder Zeichen | ||||
| (\texttt{-m}) z<>hlen lassen. | ||||
|  | ||||
| Der Parameter \texttt{-L} gibt die L<>nge der l<>ngsten enthaltenen Zeile aus. | ||||
| Der Parameter \texttt{-L} gibt in der GNU-Version \marginpar{GNU!} die L<>nge | ||||
| der l<>ngsten enthaltenen Zeile aus. | ||||
|  | ||||
| \index{wc=\texttt{wc}|)} | ||||
|  | ||||
|  | ||||
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||||
| \subsection{which}\label{which}\index{which=\texttt{which}|(textbf} | ||||
| \subsection{which}\label{which}\index{which=\texttt{which}|(textbf}\marginpar{GNU!} | ||||
|  | ||||
| Sucht im Pfad (vordefinierte Variable | ||||
| \texttt{\$PATH}\index{\$PATH=\texttt{\$PATH}}, siehe Abschnitt | ||||
| @@ -1633,8 +1672,8 @@ mit deren aktueller Konsole und der Anmeldezeit aus. | ||||
|  | ||||
| Bisweilen kommt man in die Verlegenheit, versehentlich zu lange Einzeiler | ||||
| geschrieben zu haben. Neben den F<>llen, in denen der Tipp-Eifer <20>berhand | ||||
| genommen hat handelt es sich in aller Regel um Zeilen in der Art `\texttt{grep | ||||
| 'text' \$(find / -name \textbackslash*.txt)}'. Dieses Kommando sucht alle | ||||
| genommen hat handelt es sich in aller Regel um Zeilen in der Art | ||||
| \lstinline|grep 'text' $(find / -name \*.txt)|. Dieses Kommando sucht alle | ||||
| Dateien mit der Endung txt, die im System vorhanden sind. Diese werden `in die | ||||
| Kommandozeile eingebaut'. Wenn sehr viele Dateien gefunden werden, wird die | ||||
| Zeile zu lang f<>r die Shell\footnote{Die maximale L<>nge der Kommandozeile | ||||
| @@ -1642,23 +1681,23 @@ unterscheidet sich von System zu System}. | ||||
|  | ||||
| Ein weiterer und in der Praxis mindestens ebenso sinnvoller Einsatzzweck ist | ||||
| das Vermeiden von Schleifen. Das obige Problem lie<69>e sich auch mit einer Zeile | ||||
| in der Form `\texttt{find / -name \textbackslash*.txt -exec grep 'text' \{\} | ||||
| \textbackslash;}'. Allerdings h<>tte das den Nachteil, da<64> f<>r jede gefundene | ||||
| Datei ein neuer \texttt{grep} gestartet werden mu<6D>. Das kostet Resourcen. | ||||
| in der Form \lstinline|find / -name \*.txt -exec grep 'text' {} \;| l<>sen. | ||||
| Allerdings h<>tte das den Nachteil, da<64> f<>r jede gefundene Datei ein neuer | ||||
| \texttt{grep} gestartet werden mu<6D>. Das kostet Resourcen. | ||||
|  | ||||
| Beide Probleme werden durch eine Zeile in der Form `\texttt{find / -name | ||||
| \textbackslash*.txt | xargs grep 'text'}' umgangen. Dabei liest \texttt{xargs} | ||||
| aus der Standardeingabe die Parameter, die dann an den \texttt{grep}-Aufruf | ||||
| angeh<EFBFBD>ngt werden. Sollten zu viele Dateien gefunden werden, wird \texttt{grep} | ||||
| mehrfach aufgerufen, allerdings im Gegensatz zum obigen Beispiel nicht einmal | ||||
| pro Fundstelle. | ||||
| Beide Probleme werden durch eine Zeile in der Form | ||||
| \lstinline+find / -name \*.txt | xargs grep 'text'+ umgangen. Dabei liest | ||||
| \texttt{xargs} aus der Standardeingabe die Parameter, die dann an den | ||||
| \texttt{grep}-Aufruf angeh<EFBFBD>ngt werden. Sollten zu viele Dateien gefunden | ||||
| werden, wird \texttt{grep} mehrfach aufgerufen, allerdings im Gegensatz zum | ||||
| obigen Beispiel nicht einmal pro Fundstelle. | ||||
|  | ||||
| Neben einigen anderen Parametern informiert die Manpage <EFBFBD>ber die Option | ||||
| \texttt{-r}. Damit kann vermieden werden, da<64> \texttt{xargs} das Kommando | ||||
| startet wenn keine Eingabe vorhanden ist. Bezogen auf das angegebene Beispiel | ||||
| w<EFBFBD>rde \texttt{grep} ohne Dateinamen gestartet, wenn \texttt{find} nichts | ||||
| findet. Es w<>rde auf Input von der Standardeingabe warten, der aber | ||||
| wahrscheinlich nicht kommt. Das Skript w<>rde h<>ngen, wenn der Parameter | ||||
| \texttt{-r} nicht angewandt w<>rde. | ||||
| Neben einigen anderen Parametern informiert die Manpage der | ||||
| GNU-Version\marginpar{GNU!} <20>ber die Option \texttt{-r}. Damit kann vermieden | ||||
| werden, da<64> \texttt{xargs} das Kommando startet wenn keine Eingabe vorhanden | ||||
| ist. Bezogen auf das angegebene Beispiel w<EFBFBD>rde \texttt{grep} ohne Dateinamen | ||||
| gestartet, wenn \texttt{find} nichts findet. Es w<>rde auf Input von der | ||||
| Standardeingabe warten, der aber wahrscheinlich nicht kommt. Das Skript w<>rde | ||||
| h<EFBFBD>ngen, wenn der Parameter \texttt{-r} nicht angewandt w<>rde. | ||||
|  | ||||
| \index{xargs=\texttt{xargs}|)} | ||||
|   | ||||
| @@ -38,21 +38,71 @@ zugleich einer der verwirrendsten Anf | ||||
| werden. Das geht mit dem Unix-Kommando | ||||
| \texttt{chmod}\index{chmod=\texttt{chmod}} und wird in Abschnitt \ref{chmod} | ||||
| ausf<EFBFBD>hrlich beschrieben. An dieser Stelle reicht uns ein Aufruf in der Form | ||||
| \texttt{chmod 755 dateiname}, um das Skript f<>r alle Benutzer ausf<73>hrbar zu | ||||
| \lstinline/chmod 755 name/, um das Skript f<>r alle Benutzer ausf<73>hrbar zu | ||||
| machen. | ||||
|  | ||||
| Dann kann das Skript gestartet werden. Da sich aus Sicherheitsgr<67>nden auf den | ||||
| meisten Systemen das aktuelle Verzeichnis nicht im Pfad des Benutzers befindet, | ||||
| mu<EFBFBD> man der Shell noch mitteilen, wo sie zu suchen hat: Mit \texttt{./name} | ||||
| wird versucht, im aktuellen Verzeichnis (\texttt{./}) ein Programm namens | ||||
| \texttt{name} auszuf<75>hren. | ||||
| mu<EFBFBD> man der Shell noch mitteilen, wo sie zu suchen hat: Mit \lstinline|./name| | ||||
| wird versucht, im aktuellen Verzeichnis (\lstinline|./|) ein Programm namens | ||||
| \lstinline|name| auszuf<75>hren. | ||||
|  | ||||
| Auf den meisten Systemen befindet sich im Pfad ein Verweis auf das Verzeichnis | ||||
| \texttt{bin} unterhalb des Home-Verzeichnisses eines Benutzers. Das bedeutet | ||||
| da<EFBFBD> man Skripte die immer wieder benutzt werden sollen dort ablegen kann, so | ||||
| da<EFBFBD> sie auch ohne eine Pfadangabe gefunden werden. Wie der Pfad genau aussieht | ||||
| kann man an der Shell durch Eingabe von \texttt{echo | ||||
| \$PATH}\index{\$PATH=\texttt{\$PATH}} herausfinden. | ||||
| kann man an der Shell durch Eingabe von \lstinline/echo $PATH/\index{\$PATH=\texttt{\$PATH}} herausfinden. | ||||
|  | ||||
|  | ||||
| \section{Fehlersuche} | ||||
|  | ||||
| Es gibt f<>r Shell-Skripte keine wirklichen Debugger, aber trotzdem verf<72>gt man | ||||
| <EFBFBD>ber einige bew<65>hrte Methoden zum Aufsp<73>ren von Fehlern: | ||||
|  | ||||
| \begin{itemize} | ||||
|  | ||||
| \item Debug-Ausgaben: Das wohl einfachste Mittel um herauszufinden was im | ||||
| Skript vor sich geht sind wohl regelm<6C><6D>ige Debug-Ausgaben. Dazu f<>gt man | ||||
| einfach an `strategisch wichtigen' Punkten im Skript \texttt{echo}-Zeilen ein, | ||||
| die Auskunft <20>ber den Status geben. | ||||
|  | ||||
| \item Syntax-Check: Wenn man das Skript in der Form | ||||
| \lstinline|sh -n ./skriptname| aufruft, wird es nicht wirklich ausgef<65>hrt. | ||||
| Lediglich die Syntax der Kommandos wird gepr<70>ft. Diese Methode findet nat<61>rlich | ||||
| keine logischen Fehler, und selbst wenn dieser Aufruf ohne Probleme durchl<68>uft | ||||
| kann sich zur Laufzeit noch ein anderer Fehler einschleichen. | ||||
|  | ||||
| \item \texttt{set -x}: Wenn in einem Skript der Aufruf \lstinline|set -x| | ||||
| abgesetzt wird, gibt die Shell jede Zeile nach der Expandierung aber vor der | ||||
| Ausf<EFBFBD>hrung aus. Dadurch ist klar ersichtlich wann welche Kommandos mit welchen | ||||
| Parametern ausgef<65>hrt werden. Um den Effekt wieder aufzuheben benutzt man | ||||
| \lstinline|set +x|. Man kann die Option auch auf das komplette Skript anwenden | ||||
| ohne sie in das Skript einbauen zu m<>ssen. Dazu startet man das Skript nicht | ||||
| einfach durch \lstinline|./skriptname| sondern durch | ||||
| \lstinline|sh -x ./skriptname|. | ||||
|  | ||||
| \item \texttt{set -v}: Dies funktioniert genau wie \lstinline|set -x|, auch der | ||||
| Aufruf <20>ber \lstinline|sh -v ./skriptname| funktioniert. Diese Option gibt jede | ||||
| Zeile vor der Ausf<73>hrung aus, allerdings im Gegensatz zu \texttt{-x} nicht in | ||||
| der expandierten sondern in der vollen Form. | ||||
|  | ||||
| \item System-Log: F<>r das direkte Debuggen ist dieser Weg weniger geeignet, | ||||
| aber gerade in unbeobachtet laufenden Skripten sollte man unerwartete Zust<73>nde | ||||
| oder besondere Ereignisse im System-Log festhalten. Dies geschieht mit dem | ||||
| Kommando \texttt{logger}, das in Abschnitt \ref{logger} beschrieben wird. | ||||
|  | ||||
| \item \texttt{script}: Mit dem Kommando \texttt{script} kann eine Sitzung an | ||||
| der Shell vollst<73>ndig protokolliert werden, inclusive aller Ein- und Ausgaben. | ||||
| Das umfa<66>t sogar Dr<44>cke auf die Pfeiltasten oder auf Backspace. So kann auch | ||||
| eine l<>ngere Sitzung mit vielen Ein- und Ausgaben nach dem Testlauf in aller | ||||
| Ruhe analysiert werden. Das Kommando wird in Abschnitt \ref{script} | ||||
| beschrieben. | ||||
|  | ||||
| TODO: Debuggen | ||||
| %http://localhost/~rschaten/doku/abs-guide/debugging.html#FTN.AEN14050 | ||||
| %-> trapping signals | ||||
|  | ||||
| \end{itemize} | ||||
|  | ||||
|  | ||||
| \section{R<EFBFBD>ckgabewerte}\label{exitcode}\index{R<EFBFBD>ckgabewert|(textbf}\index{Exit-Code|see{R<EFBFBD>ckgabewert}}\index{Exit-Status|see{R<EFBFBD>ckgabewert}} | ||||
| @@ -84,7 +134,7 @@ verschiedenen Wert. Das wird im folgenden Beispiel deutlich: | ||||
|  | ||||
| Normalerweise wird man den Exit-Code nicht in dieser Form abfragen. Sinnvoller | ||||
| ist folgendes Beispiel, in dem eine Datei erst gedruckt wird, und dann~--~falls | ||||
| der Ausdruck erfolgreich war ~--~el<EFBFBD>scht wird: | ||||
| der Ausdruck erfolgreich war~--~gel<EFBFBD>scht wird: | ||||
|  | ||||
| \LTXtable{\textwidth}{tab_beisp_exitcode_lpr.tex} | ||||
|  | ||||
| @@ -341,7 +391,7 @@ erzeugen. | ||||
| \section{Arithmetik-Expansion\label{arithmetikexpansion}\index{Arithmetik-Expansion|(textbf}} | ||||
|  | ||||
| Auch hier werden Klammern expandiert. Allerdings gleich doppelte Klammern. Mit | ||||
| einem Konstrukt in der Form \texttt{i=\$((\$i + 1))} k<>nnen einfache | ||||
| einem Konstrukt in der Form \lstinline|i=$(($i + 1))| k<>nnen einfache | ||||
| Berechnungen angestellt werden. | ||||
|  | ||||
| Dabei wird der Ausdruck in den Klammern bewertet als ob er in doppelten | ||||
| @@ -366,9 +416,9 @@ genau eine Parent-Proze | ||||
| jeweiligen Proze<7A> erzeugt hat. Man spricht in diesem Zusammenhang tats<74>chlich | ||||
| von Eltern- bzw. Kind-Prozessen. | ||||
|  | ||||
| Diese Zusammenh<6E>nge lassen sich sehr sch<63>n durch die Ausgabe des Kommandos | ||||
| \texttt{pstree} oder \texttt{ps -efH} darstellen, letzteres zeigt auch gleich | ||||
| die PIDs und die PPIDs an. | ||||
| Diese Zusammenh<6E>nge lassen sich sehr sch<63>n durch die Ausgabe eines Kommandos | ||||
| wie \texttt{pstree} oder \lstinline|ps -efH| darstellen, letzteres zeigt auch | ||||
| gleich die PIDs und die PPIDs an. | ||||
|  | ||||
| Wenn in einer Shell ein Kommando gestartet wird, ist es ein Kind dieser Shell. | ||||
| Wird ein Skript gestartet, <20>ffnet es sich seine eigene Shell (siehe | ||||
| @@ -424,15 +474,15 @@ In der ersten Zeile eines Shell-Skriptes sollte definiert werden, mit welchem | ||||
| Programm das Skript ausgef<65>hrt werden soll. Das System <20>ffnet dann eine | ||||
| Subshell\index{Subshell} und f<>hrt das restliche Skript in dieser aus. | ||||
|  | ||||
| Die Angabe erfolgt <20>ber eine Zeile in der Form \verb\#!/bin/sh\, wobei unter | ||||
| \verb\/bin/sh\ die entsprechende Shell (in diesem Fall die Bourne-Shell) liegt. | ||||
| Dieser Eintrag wirkt nur dann, wenn er in der ersten Zeile und der ersten | ||||
| Spalte des Skripts steht. | ||||
| Die Angabe erfolgt <20>ber eine Zeile in der Form \lstinline|#!/bin/sh|, wobei | ||||
| unter \lstinline|/bin/sh| die entsprechende Shell (in diesem Fall die | ||||
| Bourne-Shell) liegt. Dieser Eintrag wirkt nur dann, wenn er in der ersten Zeile | ||||
| und der ersten Spalte des Skripts steht. | ||||
|  | ||||
| Dieser Mechanismus ist bei der Bourne-Shell nicht vorhanden, er wurde mit den | ||||
| moderneren Shells eingef<65>hrt um eben durch die Angabe von \verb\#!/bin/sh\ die | ||||
| Bourne-Shell f<>r die Ausf<73>hrung von Shell-Skripten benutzen zu k<>nnen. In der | ||||
| Bourne-Shell wirkt das f<>hrende \verb\#\ als Kommentarzeichen. | ||||
| moderneren Shells eingef<65>hrt um eben durch die Angabe von \lstinline|#!/bin/sh| | ||||
| die Bourne-Shell f<>r die Ausf<73>hrung von Shell-Skripten benutzen zu k<>nnen. In | ||||
| der Bourne-Shell wirkt das f<>hrende \verb\#\ als Kommentarzeichen. | ||||
|  | ||||
| \index{Shell>Auswahl der\ldots|)} | ||||
|  | ||||
| @@ -450,24 +500,38 @@ Dieser Befehl tut nichts, au | ||||
|  | ||||
| Ein Shell-Skript kann in keiner Weise Einflu<6C> auf die umgebende Shell nehmen. Das hei<65>t, da<64> es beispielsweise nicht m<>glich ist, in einem Skript Variablen zu setzen, die dann in der aufrufenden Shell zur Verf<72>gung stehen. Genauso wenig ist es m<>glich, da<64> ein Skript den Pfad <20>ndert, in dem man sich befindet. Der Grund f<>r dieses Verhalten ist die Systemsicherheit. Man will verhindern, da<64> ein Skript unbemerkt <20>nderungen an der Benutzerumgebung vornimmt. | ||||
|  | ||||
| Wenn es aber doch gew<65>nscht wird, da<64> ein Skript die Umgebung des Benutzers <20>ndern kann, dann mu<6D> es mit dem Source-Kommando aufgerufen werden. Das wird in der Form \verb\source skriptname\ bzw. \verb\. skriptname\ angegeben. Er bewirkt <20>hnliches wie ein \verb\#include\ in der Programmiersprache C. | ||||
| Wenn es aber doch gew<65>nscht wird, da<64> ein Skript die Umgebung des Benutzers | ||||
| <EFBFBD>ndern kann, dann mu<6D> es mit dem Source-Kommando aufgerufen werden. Das wird in | ||||
| der Form \lstinline|source skriptname| bzw. \lstinline|. skriptname| angegeben. | ||||
| Er bewirkt <20>hnliches wie ein \verb\#include\ in der Programmiersprache C. | ||||
|  | ||||
| Die `gesourcte' Datei wird eingelesen und ausgef<65>hrt, als ob ihr Inhalt an der Stelle des Befehls stehen w<>rde. Diese Methode wird zum Beispiel beim Login in den Konfigurationsdateien des Benutzers (z. B. \verb\.profile\, \verb\.bashrc\) oder w<>hrend des Bootvorgangs in den Init-Skripten benutzt, um immer wieder ben<65>tigte Funktionen (Starten eines Dienstes, Statusmeldungen auf dem Bildschirm etc.) in einer zentralen Datei pflegen zu k<>nnen (siehe Beispiel unter~\ref{init-skript}). | ||||
| Die `gesourcte' Datei wird eingelesen und ausgef<65>hrt, als ob ihr Inhalt an der | ||||
| Stelle des Befehls stehen w<>rde. Diese Methode wird zum Beispiel beim Login in | ||||
| den Konfigurationsdateien des Benutzers (z. B. \verb\.profile\, \verb\.bashrc\) | ||||
| oder w<>hrend des Bootvorgangs in den Init-Skripten benutzt, um immer wieder | ||||
| ben<EFBFBD>tigte Funktionen (Starten eines Dienstes, Statusmeldungen auf dem | ||||
| Bildschirm etc.) in einer zentralen Datei pflegen zu k<>nnen (siehe Beispiel | ||||
| unter~\ref{init-skript}). | ||||
| \index{source=\texttt{source}|)} | ||||
|  | ||||
|  | ||||
| \subsection{Funktionen}\label{funktionen}\index{Funktion|(textbf} | ||||
|  | ||||
| Es ist in der Shell auch m<>glich, <20>hnlich wie in einer `richtigen' Programmiersprache Funktionen zu deklarieren und zu benutzen. Da die Bourne-Shell (\verb\sh\) nicht <20>ber Aliase\index{Aliase} verf<72>gt, k<>nnen einfache Funktionen als Ersatz dienen. | ||||
| Es ist in der Shell auch m<>glich, <20>hnlich wie in einer `richtigen' | ||||
| Programmiersprache Funktionen zu deklarieren und zu benutzen. Da die | ||||
| Bourne-Shell (\texttt{sh}) nicht <20>ber Aliase\index{Aliase} verf<72>gt, k<>nnen | ||||
| einfache Funktionen als Ersatz dienen. | ||||
|  | ||||
| Der R<>ckgabewert einer Funktion ist gleich dem R<>ckgabewert des letzten in der | ||||
| Funktion aufgerufenen Kommandos, es sei denn man gibt mittels | ||||
| \verb\return\ (Siehe \ref{return}) explizit einen anderen Wert zur<75>ck. | ||||
| \texttt{return} (Siehe \ref{return}) explizit einen anderen Wert zur<75>ck. | ||||
|  | ||||
| \medskip\emph{Beispiel:} Die Funktion gibt die Anzahl der Dateien im aktuellen | ||||
| Verzeichnis aus. Aufgerufen wird diese Funktion wie ein Befehl, also einfach | ||||
| durch die Eingabe von \verb\count\.\nopagebreak | ||||
| durch die Eingabe von \texttt{count}. | ||||
|  | ||||
| \LTXtable{\textwidth}{tab_beisp_funktionen.tex} | ||||
|  | ||||
| \index{Funktion|)} | ||||
|  | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user