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ührlich beschrieben. An dieser Stelle reicht uns ein Aufruf in der Form
\texttt{chmod 755 dateiname}, um das Skript für alle Benutzer ausführbar zu
\lstinline/chmod 755 name/, um das Skript für alle Benutzer ausführbar zu
machen.
Dann kann das Skript gestartet werden. Da sich aus Sicherheitsgründen auf den
meisten Systemen das aktuelle Verzeichnis nicht im Pfad des Benutzers befindet,
muß 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ühren.
muß 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ü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ß man Skripte die immer wieder benutzt werden sollen dort ablegen kann, so
daß 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ügt man
über einige bewährte Methoden zum Aufspüren von Fehlern:
\begin{itemize}
\item Debug-Ausgaben: Das wohl einfachste Mittel um herauszufinden was im
Skript vor sich geht sind wohl regelmäßige Debug-Ausgaben. Dazu fügt man
einfach an `strategisch wichtigen' Punkten im Skript \texttt{echo}-Zeilen ein,
die Auskunft über den Status geben.
\item Syntax-Check: Wenn man das Skript in der Form
\lstinline|sh -n ./skriptname| aufruft, wird es nicht wirklich ausgeführt.
Lediglich die Syntax der Kommandos wird geprüft. Diese Methode findet natürlich
keine logischen Fehler, und selbst wenn dieser Aufruf ohne Probleme durchlä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ührung aus. Dadurch ist klar ersichtlich wann welche Kommandos mit welchen
Parametern ausgefü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 über \lstinline|sh -v ./skriptname| funktioniert. Diese Option gibt jede
Zeile vor der Ausfü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ä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ändig protokolliert werden, inclusive aller Ein- und Ausgaben.
Das umfaßt sogar Drü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ückgabewerte}\label{exitcode}\index{Rückgabewert|(textbf}\index{Exit-Code|see{Rückgabewert}}\index{Exit-Status|see{Rü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öscht wird:
der Ausdruck erfolgreich war~--~gelö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ß erzeugt hat. Man spricht in diesem Zusammenhang tatsächlich
von Eltern- bzw. Kind-Prozessen.
Diese Zusammenhänge lassen sich sehr schö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änge lassen sich sehr schö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, ö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ührt werden soll. Das System öffnet dann eine
Subshell\index{Subshell} und führt das restliche Skript in dieser aus.
Die Angabe erfolgt ü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 ü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ührt um eben durch die Angabe von \verb\#!/bin/sh\ die
Bourne-Shell für die Ausführung von Shell-Skripten benutzen zu können. In der
Bourne-Shell wirkt das führende \verb\#\ als Kommentarzeichen.
moderneren Shells eingeführt um eben durch die Angabe von \lstinline|#!/bin/sh|
die Bourne-Shell für die Ausfü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ß auf die umgebende Shell nehmen. Das heißt, daß es beispielsweise nicht möglich ist, in einem Skript Variablen zu setzen, die dann in der aufrufenden Shell zur Verfügung stehen. Genauso wenig ist es möglich, daß ein Skript den Pfad ändert, in dem man sich befindet. Der Grund für dieses Verhalten ist die Systemsicherheit. Man will verhindern, daß ein Skript unbemerkt Änderungen an der Benutzerumgebung vornimmt.
Wenn es aber doch gewünscht wird, daß ein Skript die Umgebung des Benutzers ändern kann, dann muß es mit dem Source-Kommando aufgerufen werden. Das wird in der Form \verb\source skriptname\ bzw. \verb\. skriptname\ angegeben. Er bewirkt ähnliches wie ein \verb\#include\ in der Programmiersprache C.
Wenn es aber doch gewünscht wird, daß ein Skript die Umgebung des Benutzers
ändern kann, dann muß es mit dem Source-Kommando aufgerufen werden. Das wird in
der Form \lstinline|source skriptname| bzw. \lstinline|. skriptname| angegeben.
Er bewirkt ähnliches wie ein \verb\#include\ in der Programmiersprache C.
Die `gesourcte' Datei wird eingelesen und ausgefü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ö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ü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ö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, ähnlich wie in einer `richtigen' Programmiersprache Funktionen zu deklarieren und zu benutzen. Da die Bourne-Shell (\verb\sh\) nicht über Aliase\index{Aliase} verfügt, können einfache Funktionen als Ersatz dienen.
Es ist in der Shell auch möglich, ähnlich wie in einer `richtigen'
Programmiersprache Funktionen zu deklarieren und zu benutzen. Da die
Bourne-Shell (\texttt{sh}) nicht über Aliase\index{Aliase} verfü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ück.
\texttt{return} (Siehe \ref{return}) explizit einen anderen Wert zurü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|)}