Umformatiert

This commit is contained in:
rschaten
2004-12-10 14:38:03 +00:00
parent 15af99f29e
commit 464f0bcf77
6 changed files with 417 additions and 333 deletions

View File

@ -38,21 +38,71 @@ zugleich einer der verwirrendsten Anf
werden. Das geht mit dem Unix-Kommando
\texttt{chmod}\index{chmod=\texttt{chmod}} und wird in Abschnitt \ref{chmod}
ausf<EFBFBD>hrlich beschrieben. An dieser Stelle reicht uns ein Aufruf in der Form
\texttt{chmod 755 dateiname}, um das Skript f<>r alle Benutzer ausf<73>hrbar zu
\lstinline/chmod 755 name/, um das Skript f<>r alle Benutzer ausf<73>hrbar zu
machen.
Dann kann das Skript gestartet werden. Da sich aus Sicherheitsgr<67>nden auf den
meisten Systemen das aktuelle Verzeichnis nicht im Pfad des Benutzers befindet,
mu<EFBFBD> man der Shell noch mitteilen, wo sie zu suchen hat: Mit \texttt{./name}
wird versucht, im aktuellen Verzeichnis (\texttt{./}) ein Programm namens
\texttt{name} auszuf<75>hren.
mu<EFBFBD> man der Shell noch mitteilen, wo sie zu suchen hat: Mit \lstinline|./name|
wird versucht, im aktuellen Verzeichnis (\lstinline|./|) ein Programm namens
\lstinline|name| auszuf<75>hren.
Auf den meisten Systemen befindet sich im Pfad ein Verweis auf das Verzeichnis
\texttt{bin} unterhalb des Home-Verzeichnisses eines Benutzers. Das bedeutet
da<EFBFBD> man Skripte die immer wieder benutzt werden sollen dort ablegen kann, so
da<EFBFBD> sie auch ohne eine Pfadangabe gefunden werden. Wie der Pfad genau aussieht
kann man an der Shell durch Eingabe von \texttt{echo
\$PATH}\index{\$PATH=\texttt{\$PATH}} herausfinden.
kann man an der Shell durch Eingabe von \lstinline/echo $PATH/\index{\$PATH=\texttt{\$PATH}} herausfinden.
\section{Fehlersuche}
Es gibt f<>r Shell-Skripte keine wirklichen Debugger, aber trotzdem verf<72>gt man
<EFBFBD>ber einige bew<65>hrte Methoden zum Aufsp<73>ren von Fehlern:
\begin{itemize}
\item Debug-Ausgaben: Das wohl einfachste Mittel um herauszufinden was im
Skript vor sich geht sind wohl regelm<6C><6D>ige Debug-Ausgaben. Dazu f<>gt man
einfach an `strategisch wichtigen' Punkten im Skript \texttt{echo}-Zeilen ein,
die Auskunft <20>ber den Status geben.
\item Syntax-Check: Wenn man das Skript in der Form
\lstinline|sh -n ./skriptname| aufruft, wird es nicht wirklich ausgef<65>hrt.
Lediglich die Syntax der Kommandos wird gepr<70>ft. Diese Methode findet nat<61>rlich
keine logischen Fehler, und selbst wenn dieser Aufruf ohne Probleme durchl<68>uft
kann sich zur Laufzeit noch ein anderer Fehler einschleichen.
\item \texttt{set -x}: Wenn in einem Skript der Aufruf \lstinline|set -x|
abgesetzt wird, gibt die Shell jede Zeile nach der Expandierung aber vor der
Ausf<EFBFBD>hrung aus. Dadurch ist klar ersichtlich wann welche Kommandos mit welchen
Parametern ausgef<65>hrt werden. Um den Effekt wieder aufzuheben benutzt man
\lstinline|set +x|. Man kann die Option auch auf das komplette Skript anwenden
ohne sie in das Skript einbauen zu m<>ssen. Dazu startet man das Skript nicht
einfach durch \lstinline|./skriptname| sondern durch
\lstinline|sh -x ./skriptname|.
\item \texttt{set -v}: Dies funktioniert genau wie \lstinline|set -x|, auch der
Aufruf <20>ber \lstinline|sh -v ./skriptname| funktioniert. Diese Option gibt jede
Zeile vor der Ausf<73>hrung aus, allerdings im Gegensatz zu \texttt{-x} nicht in
der expandierten sondern in der vollen Form.
\item System-Log: F<>r das direkte Debuggen ist dieser Weg weniger geeignet,
aber gerade in unbeobachtet laufenden Skripten sollte man unerwartete Zust<73>nde
oder besondere Ereignisse im System-Log festhalten. Dies geschieht mit dem
Kommando \texttt{logger}, das in Abschnitt \ref{logger} beschrieben wird.
\item \texttt{script}: Mit dem Kommando \texttt{script} kann eine Sitzung an
der Shell vollst<73>ndig protokolliert werden, inclusive aller Ein- und Ausgaben.
Das umfa<66>t sogar Dr<44>cke auf die Pfeiltasten oder auf Backspace. So kann auch
eine l<>ngere Sitzung mit vielen Ein- und Ausgaben nach dem Testlauf in aller
Ruhe analysiert werden. Das Kommando wird in Abschnitt \ref{script}
beschrieben.
TODO: Debuggen
%http://localhost/~rschaten/doku/abs-guide/debugging.html#FTN.AEN14050
%-> trapping signals
\end{itemize}
\section{R<EFBFBD>ckgabewerte}\label{exitcode}\index{R<EFBFBD>ckgabewert|(textbf}\index{Exit-Code|see{R<EFBFBD>ckgabewert}}\index{Exit-Status|see{R<EFBFBD>ckgabewert}}
@ -84,7 +134,7 @@ verschiedenen Wert. Das wird im folgenden Beispiel deutlich:
Normalerweise wird man den Exit-Code nicht in dieser Form abfragen. Sinnvoller
ist folgendes Beispiel, in dem eine Datei erst gedruckt wird, und dann~--~falls
der Ausdruck erfolgreich war ~--~el<EFBFBD>scht wird:
der Ausdruck erfolgreich war~--~gel<EFBFBD>scht wird:
\LTXtable{\textwidth}{tab_beisp_exitcode_lpr.tex}
@ -341,7 +391,7 @@ erzeugen.
\section{Arithmetik-Expansion\label{arithmetikexpansion}\index{Arithmetik-Expansion|(textbf}}
Auch hier werden Klammern expandiert. Allerdings gleich doppelte Klammern. Mit
einem Konstrukt in der Form \texttt{i=\$((\$i + 1))} k<>nnen einfache
einem Konstrukt in der Form \lstinline|i=$(($i + 1))| k<>nnen einfache
Berechnungen angestellt werden.
Dabei wird der Ausdruck in den Klammern bewertet als ob er in doppelten
@ -366,9 +416,9 @@ genau eine Parent-Proze
jeweiligen Proze<7A> erzeugt hat. Man spricht in diesem Zusammenhang tats<74>chlich
von Eltern- bzw. Kind-Prozessen.
Diese Zusammenh<6E>nge lassen sich sehr sch<63>n durch die Ausgabe des Kommandos
\texttt{pstree} oder \texttt{ps -efH} darstellen, letzteres zeigt auch gleich
die PIDs und die PPIDs an.
Diese Zusammenh<6E>nge lassen sich sehr sch<63>n durch die Ausgabe eines Kommandos
wie \texttt{pstree} oder \lstinline|ps -efH| darstellen, letzteres zeigt auch
gleich die PIDs und die PPIDs an.
Wenn in einer Shell ein Kommando gestartet wird, ist es ein Kind dieser Shell.
Wird ein Skript gestartet, <20>ffnet es sich seine eigene Shell (siehe
@ -424,15 +474,15 @@ In der ersten Zeile eines Shell-Skriptes sollte definiert werden, mit welchem
Programm das Skript ausgef<65>hrt werden soll. Das System <20>ffnet dann eine
Subshell\index{Subshell} und f<>hrt das restliche Skript in dieser aus.
Die Angabe erfolgt <20>ber eine Zeile in der Form \verb\#!/bin/sh\, wobei unter
\verb\/bin/sh\ die entsprechende Shell (in diesem Fall die Bourne-Shell) liegt.
Dieser Eintrag wirkt nur dann, wenn er in der ersten Zeile und der ersten
Spalte des Skripts steht.
Die Angabe erfolgt <20>ber eine Zeile in der Form \lstinline|#!/bin/sh|, wobei
unter \lstinline|/bin/sh| die entsprechende Shell (in diesem Fall die
Bourne-Shell) liegt. Dieser Eintrag wirkt nur dann, wenn er in der ersten Zeile
und der ersten Spalte des Skripts steht.
Dieser Mechanismus ist bei der Bourne-Shell nicht vorhanden, er wurde mit den
moderneren Shells eingef<65>hrt um eben durch die Angabe von \verb\#!/bin/sh\ die
Bourne-Shell f<>r die Ausf<73>hrung von Shell-Skripten benutzen zu k<>nnen. In der
Bourne-Shell wirkt das f<>hrende \verb\#\ als Kommentarzeichen.
moderneren Shells eingef<65>hrt um eben durch die Angabe von \lstinline|#!/bin/sh|
die Bourne-Shell f<>r die Ausf<73>hrung von Shell-Skripten benutzen zu k<>nnen. In
der Bourne-Shell wirkt das f<>hrende \verb\#\ als Kommentarzeichen.
\index{Shell>Auswahl der\ldots|)}
@ -450,24 +500,38 @@ Dieser Befehl tut nichts, au
Ein Shell-Skript kann in keiner Weise Einflu<6C> auf die umgebende Shell nehmen. Das hei<65>t, da<64> es beispielsweise nicht m<>glich ist, in einem Skript Variablen zu setzen, die dann in der aufrufenden Shell zur Verf<72>gung stehen. Genauso wenig ist es m<>glich, da<64> ein Skript den Pfad <20>ndert, in dem man sich befindet. Der Grund f<>r dieses Verhalten ist die Systemsicherheit. Man will verhindern, da<64> ein Skript unbemerkt <20>nderungen an der Benutzerumgebung vornimmt.
Wenn es aber doch gew<65>nscht wird, da<64> ein Skript die Umgebung des Benutzers <20>ndern kann, dann mu<6D> es mit dem Source-Kommando aufgerufen werden. Das wird in der Form \verb\source skriptname\ bzw. \verb\. skriptname\ angegeben. Er bewirkt <20>hnliches wie ein \verb\#include\ in der Programmiersprache C.
Wenn es aber doch gew<65>nscht wird, da<64> ein Skript die Umgebung des Benutzers
<EFBFBD>ndern kann, dann mu<6D> es mit dem Source-Kommando aufgerufen werden. Das wird in
der Form \lstinline|source skriptname| bzw. \lstinline|. skriptname| angegeben.
Er bewirkt <20>hnliches wie ein \verb\#include\ in der Programmiersprache C.
Die `gesourcte' Datei wird eingelesen und ausgef<65>hrt, als ob ihr Inhalt an der Stelle des Befehls stehen w<>rde. Diese Methode wird zum Beispiel beim Login in den Konfigurationsdateien des Benutzers (z. B. \verb\.profile\, \verb\.bashrc\) oder w<>hrend des Bootvorgangs in den Init-Skripten benutzt, um immer wieder ben<65>tigte Funktionen (Starten eines Dienstes, Statusmeldungen auf dem Bildschirm etc.) in einer zentralen Datei pflegen zu k<>nnen (siehe Beispiel unter~\ref{init-skript}).
Die `gesourcte' Datei wird eingelesen und ausgef<65>hrt, als ob ihr Inhalt an der
Stelle des Befehls stehen w<>rde. Diese Methode wird zum Beispiel beim Login in
den Konfigurationsdateien des Benutzers (z. B. \verb\.profile\, \verb\.bashrc\)
oder w<>hrend des Bootvorgangs in den Init-Skripten benutzt, um immer wieder
ben<EFBFBD>tigte Funktionen (Starten eines Dienstes, Statusmeldungen auf dem
Bildschirm etc.) in einer zentralen Datei pflegen zu k<>nnen (siehe Beispiel
unter~\ref{init-skript}).
\index{source=\texttt{source}|)}
\subsection{Funktionen}\label{funktionen}\index{Funktion|(textbf}
Es ist in der Shell auch m<>glich, <20>hnlich wie in einer `richtigen' Programmiersprache Funktionen zu deklarieren und zu benutzen. Da die Bourne-Shell (\verb\sh\) nicht <20>ber Aliase\index{Aliase} verf<72>gt, k<>nnen einfache Funktionen als Ersatz dienen.
Es ist in der Shell auch m<>glich, <20>hnlich wie in einer `richtigen'
Programmiersprache Funktionen zu deklarieren und zu benutzen. Da die
Bourne-Shell (\texttt{sh}) nicht <20>ber Aliase\index{Aliase} verf<72>gt, k<>nnen
einfache Funktionen als Ersatz dienen.
Der R<>ckgabewert einer Funktion ist gleich dem R<>ckgabewert des letzten in der
Funktion aufgerufenen Kommandos, es sei denn man gibt mittels
\verb\return\ (Siehe \ref{return}) explizit einen anderen Wert zur<75>ck.
\texttt{return} (Siehe \ref{return}) explizit einen anderen Wert zur<75>ck.
\medskip\emph{Beispiel:} Die Funktion gibt die Anzahl der Dateien im aktuellen
Verzeichnis aus. Aufgerufen wird diese Funktion wie ein Befehl, also einfach
durch die Eingabe von \verb\count\.\nopagebreak
durch die Eingabe von \texttt{count}.
\LTXtable{\textwidth}{tab_beisp_funktionen.tex}
\index{Funktion|)}