Umformatiert
This commit is contained in:
@@ -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|)}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user