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