Viele Aenderungen

This commit is contained in:
rschaten
2004-12-02 13:54:06 +00:00
parent c0e556e25d
commit 15af99f29e
10 changed files with 873 additions and 57 deletions

0
TODO
View File

View File

@ -27,6 +27,7 @@ haben.
TODO!!! tar-Br<42>cke
%ssh 192.168.2.1 tar clf - / | (cd /mnt; tar xf - )
%tar cf - $j | rsh $i "(mkdir -p $PWD ;cd $PWD; tar xf -)"
\section{Binaries inside}
@ -49,7 +50,7 @@ TODO!!! Dateien, die es nicht gibt
TODO!!! Speichern in nicht existente Dateien
\subsection{Subshell-Schleifen vermeiden}
\subsection{Subshell-Schleifen vermeiden}\label{subshellschleifen}
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.

View File

@ -23,9 +23,15 @@
\usepackage{german} % deutsches Paket f<>r Umlaute
\usepackage[latin1]{inputenc} % Codepage latin1
%\usepackage{graphicx} % Grafikpaket f<>r Bilder laden
\usepackage{mathptmx} % Andere Schriften benutzen
\usepackage[scaled=.90]{helvet}
\usepackage{courier}
%\usepackage[dvips]{graphicx} % Grafikpaket f<>r Bilder laden
%\usepackage{epstopdf} % .eps bei Bedarf nach .pdf wandeln
%\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
@ -93,8 +99,8 @@ TODO: Vern
%\texttt{${}$Id${}$}\bigskip
Die aktuellste Version dieses Dokumentes befindet sich im World Wide Web auf
meiner Homepage (\texttt{http://www.schatenseite.de/}).\bigskip
Die aktuellste Version dieses Dokumentes befindet sich auf
\texttt{http://www.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

View File

@ -12,6 +12,7 @@
\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{\$ 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

View File

@ -0,0 +1,19 @@
% $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} & Alle doppelten Zeilen ausgeben \tabularnewline\STRUT
\texttt{-f }\textsl{n} & Die ersten \textsl{n} Felder ignorieren \tabularnewline\STRUT
\texttt{-i} & Gro<72>- / Kleinschreibung ignorieren \tabularnewline\STRUT
\texttt{-s }\textsl{n} & Die ersten \textsl{n} Zeichen ignorieren \tabularnewline\STRUT
\texttt{-u} & Nur einfach vorkommende Zeilen ausgeben \tabularnewline\STRUT
\texttt{-w }\textsl{n} & Nur die ersten \textsl{n} Zeichen betrachten
\end{longtable}

View File

@ -17,7 +17,7 @@
\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. Mehrere Eintr<74>ge werden durch Doppelpunkte getrennt angegeben \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{\$OLDPWD} & Vorheriges Verzeichnis (wird durch \texttt{cd} gesetzt)
\end{longtable}

View File

@ -69,7 +69,8 @@ Subshells zu vererben.
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}
reagiert, wie man es erwarten sollte.
\end{itemize}
\medskip\emph{Komfort-Shells:}\nopagebreak
@ -90,7 +91,7 @@ indizierte Arrays\index{Array}.
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 Kommandozeilen-Editierung,
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.
@ -114,6 +115,6 @@ C-
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.).
Stan\-dard-Kom\-man\-dos.).
Diese Liste ist bei weitem nicht vollst<73>ndig.

View File

@ -1,5 +1,5 @@
% $Id$
\chapter{N<EFBFBD>tzliche Shell-Kommandos}\label{nuetzliche_shell-kommandos}
\chapter{Werkzeugkasten}\label{werkzeugkasten}
Durch die gezeigten Steuerungsm<73>glichkeiten stehen dem Shell-Pro\-grammie\-rer
M<EFBFBD>g\-lich\-kei\-ten offen, fast alle g<>ngigen Algorithmen zu implementieren. Es
ist tats<74>chlich in der Shell m<>glich, Sortier- oder Suchfunktionen zu
@ -68,11 +68,30 @@ Dateien auf der Festplatte.
\item \texttt{head} (\ref{head}): Dateianfang ausgeben
\item \texttt{printf} (\ref{printf}): Formatierte Datenausgabe
\item \texttt{read} (\ref{read}): Zeilen einlesen
\item \texttt{sort} (\ref{sort}): Zeilenweises Sortieren
\item \texttt{tail} (\ref{tail}): Dateiende ausgeben
\end{itemize}
\subsection{Dateiinhalte bearbeiten}\label{dateiinhalte}
Nat<EFBFBD>rlich bietet die Shell eine Reihe von Befehlen, um die Inhalte von Dateien
zu bearbeiten. Diese Auflistung ist in weiten Teilen deckungsgleich mit der
Liste der Tools zur Manipulation von Pipes, auch diese Kommandos kommen also
in mehreren Situationen zum Einsatz.
\begin{itemize}
\item \texttt{awk} (\ref{awk}): In einer Pipe editieren
\item \texttt{cmp} (\ref{cmp}): Bin<69>re Dateien vergleichen
\item \texttt{cut} (\ref{cut}): Teile einer Zeile ausschneiden
\item \texttt{diff} (\ref{diff}): Textdateien vergleichen
\item \texttt{paste} (\ref{paste}): Dateien zusammenf<6E>hren
\item \texttt{sed} (\ref{sed}): In einer Pipe editieren
\item \texttt{sort} (\ref{sort}): Zeilenweises Sortieren
\item \texttt{tr} (\ref{tr}): Zeichen ersetzen
\item \texttt{uniq} (\ref{uniq}): Doppelte Zeilen suchen
\end{itemize}
\subsection{Pfade und Dateien}\label{pfade_und_dateien}
Eine der Hauptaufgaben von Shell-Skripten ist nat<61>rlich das Hantieren mit
@ -85,10 +104,12 @@ Datei kann viel mehr sein als nur ein paar Daten im Filesystem.
\begin{itemize}
\item \texttt{basename} (\ref{basename}): Den Namen einer Datei (ohne Pfad) ausgeben
\item \texttt{cd} (\ref{cd}): Verzeichnis wechseln
\item \texttt{cp} (\ref{cp}): Dateien kopieren
\item \texttt{chgrp} (\ref{chgrp}): Gruppen-ID einer Datei <20>ndern
\item \texttt{chmod} (\ref{chmod}): Zugriffsrechte einer Datei <20>ndern
\item \texttt{chown} (\ref{chown}): Eigent<6E>mer einer Datei <20>ndern
\item \texttt{cmp} (\ref{cmp}): Bin<69>re Dateien vergleichen
\item \texttt{dirname} (\ref{dirname}): Den Pfad zu einer Datei (ohne den Namen) ausgeben
\item \texttt{find} (\ref{find}): Dateien suchen
\item \texttt{mkdir} (\ref{mkdir}): Verzeichnisse anlegen
@ -96,6 +117,7 @@ Datei kann viel mehr sein als nur ein paar Daten im Filesystem.
\item \texttt{rm} (\ref{rm}): Dateien l<>schen
\item \texttt{rmdir} (\ref{rmdir}): Verzeichnisse l<>schen
\item \texttt{touch} (\ref{touch}): Eine leere Datei anlegen, bzw. das Zugriffsdatum einer Datei <20>ndern
\item \texttt{which} (\ref{which}): Ausf<73>hrbare Dateien suchen
\item \texttt{xargs} (\ref{xargs}): Ausgaben eines Kommandos als Parameter eines anderen Kommandos benutzen
\end{itemize}
@ -120,12 +142,14 @@ und ausgef
kleinsten geeigneten Hammer nehmen.
\begin{itemize}
\item \texttt{awk} (\ref{awk}): In einer Pipe editieren
\item \texttt{cut} (\ref{cut}): Teile einer Zeile ausschneiden
\item \texttt{grep} (\ref{grep}): In einer Pipe suchen
\item \texttt{sed} (\ref{sed}): In einer Pipe editieren
\item \texttt{awk} (\ref{awk}): In einer Pipe editieren
\item \texttt{sort} (\ref{sort}): Zeilenweises Sortieren
\item \texttt{tee} (\ref{tee}): Datenstrom in einer Datei protokollieren
\item \texttt{tr} (\ref{tr}): Zeichen ersetzen
\item \texttt{uniq} (\ref{uniq}): Doppelte Zeilen suchen
\item \texttt{wc} (\ref{wc}): Zeilen, W<>rter oder Zeichen z<>hlen
\end{itemize}
@ -149,6 +173,7 @@ Verf
\item \texttt{ps} (\ref{ps}): Proze<7A>liste ausgeben
\item \texttt{pgrep} (\ref{pgrep}): Bestimmte Prozesse suchen
\item \texttt{pkill} (\ref{pkill}): Bestimmte Prozesse t<>ten
\item \texttt{trap} (\ref{trap}): Auf Signale reagieren
\end{itemize}
@ -164,7 +189,154 @@ ausgiebigere Informationen empfehle ich entsprechende B
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{awk}\label{awk}\index{awk=\texttt{awk}|(textbf}
TODO!!! awk
<EFBFBD>ber die Skriptsprache \texttt{awk} wurden schon ganze B<>cher geschrieben, eine
vollst<EFBFBD>ndige Beschreibung w<>rde den Rahmen dieses Dokumentes bei weitem
sprengen. Hier werden nur ein paar grundlegende Techniken beschrieben, die
h<EFBFBD>ufig im Zusammenhang mit Shell-Skripten auftauchen.
Oben wurde \texttt{awk} `Skriptsprache' genannt. Das ist insofern richtig, als
da<EFBFBD> es eine m<>chtige und komplexe Syntax zur Verf<72>gung stellt, um Texte
automatisiert zu bearbeiten. Es f<>llt somit in die gleiche Tool-Kategorie wie
\texttt{sed} (Abschnitt \ref{sed}).
Es unterscheidet sich aber in seinen grundlegenden Prinzipien entscheidend von
den meisten anderen Programmiersprachen: \texttt{awk} arbeitet `Datenbasiert'.
Das bedeutet, da<64> zun<75>chst die Daten spezifiziert werden mit denen gearbeitet
werden soll, dann folgen die auszuf<75>hrenden Kommandos. Das Prinzip wird schnell
klar, wenn man sich einige der Beispiele weiter unten ansieht.
\subsubsection{Aufruf}
Auch der Aufruf erfolgt analog zu \texttt{sed}: Bei einfachen Aufgaben kann das
\texttt{awk}-Programm direkt an der Kommandozeile mitgegeben werden, komplexere
Programme werden in Dateien gespeichert und von dort gelesen.
Eine weitere Gemeinsamkeit ist die Art der Ein- und Ausgabe. Wenn eine
Eingabedatei angegeben wird, wird diese verarbeitet. Ansonsten wird die
Standard-Eingabe gelesen. Ausgaben erfolgen immer auf der Standard-Ausgabe.
\footnotesize
\begin{listing}[2]{1}
# Aufruf als Filter:
kommando1 | awk '{ print $1; print $2 }' | kommando2
# Aufruf mit einer zu bearbeitenden Datei:
awk '{ print $1; print $2 }' datei.txt
# In einem Skript kann das Kommando auch <20>ber mehrere Zeilen gehen:
awk '
{
print $1;
print $2;
}' datei.txt
# Alternativ k<>nnen die Kommandos auch in eine eigene Datei gespeichert und
# <20>ber den Parameter -f eingebunden werden:
awk -f script.awk datei.txt
\end{listing}
\normalsize
Neben dem Parameter \texttt{-f} zum Einlesen der Programmdatei gibt es noch den
Parameter \texttt{-F} mit dem der Feld-Trenner angegeben werden kann. Die
folgende Zeile gibt beispielsweise alle Benutzernamen und deren User-IDs aus
der Doppelpunktseparierten Datei \texttt{/etc/passwd} aus:
\texttt{awk -F: '\{ print \$1\dq hat ID \dq\$3 \}' /etc/passwd}
\subsubsection{Muster und Prozeduren}
Die Skripte f<>r \texttt{awk} bestehen aus Bl<42>cken von Mustern und Prozeduren.
Ein Block hat den folgenden Aufbau:
\textsl{muster}\texttt{ \{ }\textsl{prozedur}\texttt{ \}}
Dabei sind beide Bestandteile des Blockes Optional: Wird das Muster
weggelassen, wird die Prozedur auf alle Textbestandteile angewandt. Und wird
keine Prozedur angegeben, wird der betroffene Text einfach ausgegeben.
Das Muster kann dabei auf verschiedene Weise angegeben werden:
\begin{itemize}
\item Als regul<75>rer Ausdruck (siehe Abschnitt \ref{mustererkennung}),
eingebettet in Slashes: \texttt{/}\textsl{muster}\texttt{/}
\item Als relationaler Ausdruck, bei dem bestimmte Kriterien auf die
Eingabedaten zutreffen m<>ssen. Mit \texttt{\$2>\$1} werden beispielsweise
Zeilen angesprochen, deren zweites Feld einen gr<67><72>eren Wert hat als das erste.
\item Mit Operatoren f<>r das Pattern-Matching, <20>hnlich wie in Perl (\texttt{\~}
oder \texttt{!\~})
\item \texttt{BEGIN} kennzeichnet Prozeduren, die vor der Bearbeitung anderer
Bl<EFBFBD>cke zum Tragen kommen sollen.
\item Analog dazu gibt es ein \texttt{END}, mit dem abschlie<69>ende Aktionen
gekennzeichnet werden.
\end{itemize}
Abgesehen von \texttt{BEGIN} und \texttt{END} k<>nnen die Muster auch durch
logische Operatoren (\texttt{\&\&}, \texttt{||} oder \texttt{!}) kombiniert
werden. Durch Komma getrennt besteht die M<>glichkeit, Wirkungsbereiche zu
definieren.
Die Prozeduren k<>nnen Variablen- oder Array-Zuweisungen, Ausgabeanweisungen,
Funktionsaufrufe oder Kontrollstrukturen enthalten.
\subsubsection{Variablen}
Es gibt in \texttt{awk} eine Reihe eingebauter Variablen, die in Mustern oder
Prozeduren verwendet werden k<>nnen:
\LTXtable{\textwidth}{tab_kommandos_awk_variablen.tex}
Eigene Variablen k<>nnen nach Belieben verwendet werden, siehe dazu das Beispiel
mit den TeX-Dateien weiter unten.
\subsubsection{Beispiele}
Hier ein paar Einfache Beispiele f<>r Blocks aus Mustern und Prozeduren:
\footnotesize
\begin{listing}[2]{1}
# Das erste Feld jeder Zeile ausgeben:
{ print $1 }
# Alle Zeilen ausgeben, die 'regexp' enthalten:
/regexp/
# Das erste Feld jeder Zeile ausgeben, die 'regexp' enth<74>lt:
/regexp/ { print $1 }
# Datens<6E>tze mit mehr als zwei Feldern ausw<73>hlen:
NF > 2
# Das dritte und das zweite Feld jeder Zeile ausgeben, deren erstes Feld den
# String 'WICHTIG' enth<74>lt:
$1 ~ /WICHTIG/ { print $3, $2 }
# Die Vorkommen von 'muster' z<>hlen, und deren Anzahl ausgeben:
/muster/ { ++x }
END { print x }
# Alle Zeilen mit weniger als 23 Zeichen ausgeben:
length($0) < 23
# Alle Zeilen ausgeben, die mit 'Name:' anfangen und exakt sieben Felder
# enthalten:
NF == 7 && /^Name:/
# Alle Felder der Eingabedaten zeilenweise in umgekehrter Reihenfolge ausgeben:
{
for (i = NF; i >= 1; i--)
print $i
}
# Die Gr<47><72>e aller TeX-Dateien addieren, die Summe in kB umrechnen und ausgeben,
# verarbeitet die Ausgabe von 'ls -l':
/.*tex/ { summe += $5 }
END { summe /= 1024; print "Die Gr<47><72>e aller TeX-Files betr<74>gt", summe, "kB" }
# Pipe-Separierte Liste aller gemounteten Partitionen und derer F<>llst<73>nde
# ausgeben, verarbeitet die Ausgabe von 'df':
BEGIN { OFS="|" }
/^\/dev\// { print $1,$5 }
\end{listing}
\normalsize
\index{awk=\texttt{awk}|)}
@ -220,6 +392,14 @@ werden.
\index{cat=\texttt{cat}|)}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{cd}\label{cd}\index{cd=\texttt{cd}|(textbf}
Mit dem Kommando \texttt{cd} wird das aktuelle Verzeichnis gewechselt.
\index{cd=\texttt{cd}|)}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{chgrp}\label{chgrp}\index{chgrp=\texttt{chgrp}|(textbf}
@ -328,6 +508,14 @@ diese Datei nicht allgemein lesbar ist.
\index{chpasswd=\texttt{chpasswd}|)}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{cmp}\label{cmp}\index{cmp=\texttt{cmp}|(textbf}
TODO!!! cmp GNU?
\index{cmp=\texttt{cmp}|)}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{cp}\label{cp}\index{cp=\texttt{cp}|(textbf}
@ -355,9 +543,20 @@ der Formate N, N-, N-M oder -M benutzt werden.
\LTXtable{\textwidth}{tab_kommandos_cut_beispiele.tex}
Praktisch das Gegenst<73>ck zu \texttt{cut} ist \texttt{paste}, damit werden
Dateien in Spalten zusammengef<65>hrt. N<>hrers dazu in Abschnitt \ref{paste}.
\index{cut=\texttt{cut}|)}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{diff}\label{diff}\index{diff=\texttt{diff}|(textbf}
TODO!!! diff
\index{diff=\texttt{diff}|)}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{dirname}\label{dirname}\index{dirname=\texttt{dirname}|(textbf}
@ -437,7 +636,72 @@ Arith\-me\-tik-Ex\-pan\-sion (Siehe \ref{arithmetikexpansion}).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{find}\label{find}\index{find=\texttt{find}|(textbf}
TODO!!! find
Auf einem modernen System sind nicht selten mehrere zehn- oder hunderttausend
Dateien vorhanden. Um eine bestimmte Datei anhand komplexer Kriterien ausfindig
zu machen benutzt man \texttt{find}.
Bei einem Aufruf wird zuerst das zu durchsuchende Verzeichnis, dann die
Suchkriterien und eventuell abschlie<69>end die durchzuf<75>hrenden Aktionen
angegeben.
Die Angabe der Suchkriterien ist sehr vielseitig, hier werden nur die
wichtigsten Optionen beschrieben. Wie immer empfehle ich das Studium der
Man-Page oder eines entsprechenden Buches.
\LTXtable{\textwidth}{tab_kommandos_find_parameter.tex}
Die verschiedenen Suchkriterien k<>nnen kombiniert werden. Mit \texttt{-a} oder
\texttt{-o} erreicht man eine logische AND- bzw. OR-Verkn<6B>pfung, mit einem
vorangestellten \texttt{!} k<>nnen Kriterien negiert werden. Die AND-Verkn<6B>pfung
mu<EFBFBD> nicht explizit angegeben werden, wenn mehrere Kriterien verwandt werden.
Komplexere Ausdr<64>cke k<>nnen durch runde Klammern gruppiert werden, dabei ist
jedoch deren Sonderbedeutung in der Shell entsprechend zu quoten (Siehe
Abschnitt \ref{quoting}).
Bei der Angabe numerischer Parameter zu den Suchkriterien wird normalerweise
nach dem exakten Wert gesucht. Statt eines einfachen \textsl{n} kann jedoch
auch \textsl{+n} oder \textsl{-n} angegeben werden, damit wird dann nach
Vorkommen gr<67><72>er bzw. kleiner als \textsl{n} gesucht.
Da die reine Beschreibung der Parameter manchmal etwas verwirrend ist, folgen
hier ein paar praktische Beispiele:
\footnotesize
\begin{listing}[2]{1}
# Suche alle Eintr<74>ge in bzw. unter dem aktuellen Verzeichnis:
find .
# Suche alle normalen Dateien mit der Endung txt unter /home:
find /home -type f -name \*.txt
# Suche alle Eintr<74>ge au<61>er symbolischen Links, in die jeder schreiben darf:
find / \! -type l -perm 777
# Suche alle Dateien unter dem Homeverzeichnis, deren Gr<47><72>e 10000000 Bytes
# <20>bersteigt und gib sie ausf<73>hrlich aus:
find ~ -size +10000000c -exec ls -l {} \;
# Suche alle Eintr<74>ge im Homeverzeichnis, die innerhalb der letzten zwei Tage
# ge<67>ndert wurden:
find ~ -mtime -2
\end{listing}
\normalsize
Wenn mittels \texttt{-exec} weitere Kommandos gestartet werden, sollte beachtet
werden da<64> mindestens ein Proze<7A> pro Fundstelle gestartet wird. Das kostet sehr
viel, unter Umst<73>nden macht der Einsatz von \texttt{xargs} (Abschnitt
\ref{xargs}) Sinn.
Die Ausf<73>hrung von \texttt{find} erzeugt unter Umst<73>nden sehr viel Last auf der
Festplatte, bei Netzlaufwerken auch Netzwerkbandbreite. In einigen F<>llen
bieten sich alternative Suchverfahren an:
\textbf{Alternative 1:} Falls man den Namen der zu suchenden Datei kennt, und
das Locate-System installiert ist kann man die Datei auch mittels
\texttt{locate} suchen. Das ist ressourcenschonender, da nicht `live' das
Filesystem durchforstet wird, sondern nur die Locate-Datenbank. Diese wird
allerdings im Regelfall nur einmal t<>glich aktualisiert, die Suche taugt nicht
f<EFBFBD>r schnell wechselnde Best<73>nde.
\textbf{Alternative 2:} Sucht man nach einer ausf<73>hrbaren Datei, die im Pfad
vorhanden ist (`Wo liegt eigentlich Firefox?'), dann sucht man mittels
\texttt{which} (Abschnitt \ref{which}).
Siehe auch: Abschnitt \ref{beispiele_suchen_dateien}.
@ -473,11 +737,44 @@ werden allerdings nicht die letzten Zeilen angezeigt, sondern die ersten.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{kill}\label{kill}\index{kill=\texttt{kill}|(textbf}
TODO!!! kill
Die landl<64>ufige Annahme ist, da<64> man mit dem \texttt{kill}-Kom\-man\-do
Prozesse `umbringt'. Das ist zwar wahr, aber nicht die ganze Wahrheit.
<EFBFBD>brigens: Die landl<64>ufige Annahme ist, da<64> man mit dem
\texttt{kill}-Kom\-man\-do Prozesse `umbringt'. Das ist zwar wahr, aber nicht
die ganze Wahrheit.
Im Prinzip sendet \texttt{kill} lediglich ein Signal an einen Proze<7A>. Ohne
weitere Parameter ist das tats<74>chlich ein SIGTERM, das den Proze<7A> im Regelfall
dazu bewegt sich zu beenden. Jeder Admin kennt das Verfahren, einem h<>ngenden
Proze<EFBFBD> mittels \texttt{kill -9} den Gnadenschu<68> zu geben. Die 9 steht dabei f<>r
das Signal mit der Nummer 9, SIGKILL. Noch ein gebr<62>uchliches Signal ist SIGHUP
(1), der `Hangup'. Historisch wurde das gesendet wenn die Leitung zum Rechner
aufgelegt wurde, mittlerweile ist es g<>ngige Praxis damit einen Daemon neu zu
initialisieren.
Daneben stehen noch eine Reihe weiterer Signale zur Verf<72>gung. Mit \texttt{kill
-l} kann man sich eine Liste ansehen.
Es gibt verschiedene Wege, das Signal abzusetzen. Welchen man w<>hlt ist
Geschmackssache. Hier ein paar Beispiele:
\footnotesize
\begin{listing}[2]{1}
# Die folgenden Befehle sind gleichwertig. Alle senden ein HUP an Proze<7A>-ID 42:
kill -1 42
kill -HUP 42
kill -SIGHUP 42
kill -s 1 42
kill -s HUP 42
kill -s SIGHUP 42
# virtueller Selbstmord: Alle Prozesse umbringen, die man umbringen kann:
kill -9 -1
# SIGTERM an mehrere Prozesse senden:
kill 123 456 789
\end{listing}
\normalsize
Siehe auch: Das Beispiel `Fallensteller' in Abschnitt \ref{traps} zeigt, wie
ein Skript auf Signale reagieren kann.
\index{kill=\texttt{kill}|)}
@ -509,14 +806,45 @@ zur Verf
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{ls}\label{ls}\index{ls=\texttt{ls}|(textbf}
Den Inhalt von Verzeichnissen im Dateisystem bringt man mit \texttt{ls} in
Erfahrung. Ein einfacher Aufruf listet lediglich die Dateinamen im aktuellen
oder angegebenen Verzeichnis auf, das Kommando hat aber auch sehr viele
Parameter mit denen sich die Ausgabe anpassen l<><6C>t. Hier sind die wichtigsten,
eine vollst<73>ndige Auflistung bietet wie immer die Man-Page:
\LTXtable{\textwidth}{tab_kommandos_ls_parameter.tex}
Besonders informativ gibt sich der Parameter \texttt{-l}, da damit auch die
Eigent<EFBFBD>mer und die Berechtigungen der Dateien angezeigt werden. Die Ausgabe hat
die folgende Form:
\texttt{-rw-r--r-- 1 rschaten users 6252 Nov 19 14:14 shell.tex}
Die linke Spalte der Ausgabe zeigt die bestehenden Berechtigungen. Es ist ein
Block in der Form `drwxrwxrwx'. An Stelle des d k<>nnen auch andere Buchstaben
stehen, hier wird der Dateityp angegeben, also ob es sich um eine einfache
Datei (-), ein Verzeichnis (d), einen Link (l) oder <20>hnliches\footnote{Siehe
Man-Page} handelt. An Stelle der rwx-Bl<42>cke k<>nnen auch Striche stehen, die
stehen f<>r nicht gesetzte Attribute.
Man-Page} handelt. Die rwx-Bl<42>cke geben die Dateiberechtigungen jeweils f<>r den
Besitzer, die Gruppe und andere User an. Dabei steht das r f<>r read, w f<>r
write und x f<>r execute. An ihrer Stelle k<>nnen auch Striche stehen, die
repr<EFBFBD>sentieren nicht gesetzte Attribute. Die Datei im Beispiel ist also f<>r
ihren Besitzer les- und schreibbar, f<>r alle anderen nur lesbar. Die
Berechtigungen werden mit dem Kommando \texttt{chmod} (Abschnitt \ref{chmod})
gesetzt.
TODO!!! ls
Die n<>chste Spalte stellt die Anzahl der Links dar, die auf diese Datei
verweisen, im Beispiel existiert die Datei an nur einer Stelle im Filesystem.
Dann folgen der Benutzer und die Gruppe, denen die Datei geh<65>rt. Diese
Parameter werden mit \texttt{chown} (Abschnitt \ref{chown}) bzw. \texttt{chgrp}
(Abschnitt \ref{chgrp}) gesetzt.
Es folgt die Gr<47><72>e der Datei in Bytes, sowie das Datum der letzten <20>nderung.
Liegt dieses mehr als ein halbes Jahr zur<75>ck wird an Stelle der Uhrzeit die
Jahreszahl angegeben, es gilt also Vorsicht walten zu lassen, wenn dieser Wert
in Skripten benutzt werden soll.
Abschlie<EFBFBD>end wird der Name der jeweiligen Datei ausgegeben.
\index{ls=\texttt{ls}|)}
@ -545,6 +873,25 @@ wird der Vorgang interaktiv, vor jeder Dateibewegung wird nachgefragt.
\index{mv=\texttt{mv}|)}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{paste}\label{paste}\index{paste=\texttt{paste}|(textbf}
W<EFBFBD>hrend mit \texttt{cut} (Abschnitt \ref{cut}) Dateien spaltenweise zerlegt
werden, werden sie mit \texttt{paste} zusammengef<65>hrt. Die Dateinamen werden
als Parameter <20>bergeben, woraufhin Zeile f<>r Zeile die Inhalte aller Dateien zu
einer Tabelle gemacht werden.
Die Spalten werden standardm<64><6D>ig durch Tabulatorzeichen getrennt, man kann mit
dem Parameter \texttt{-d} auch ein oder mehrere andere Trennzeichen definieren.
Werden mehrere Zeichen angegeben, werden sie der Reihe nach zum trennen der
Spalten benutzt.
Mit \texttt{-s} wird die Tabelle transponiert, also praktisch um 90 Grad
gedreht.
\index{paste=\texttt{paste}|)}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{pgrep}\label{pgrep}\index{pgrep=\texttt{pgrep}|(textbf}
@ -640,7 +987,65 @@ dazu steht im Abschnitt
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{ps}\label{ps}\index{ps=\texttt{ps}|(textbf}
TODO!!! ps
Mit \texttt{ps} gibt man einen Schnappschu<68> des Zustandes der aktuell laufenden
Prozesse aus\footnote{Wenn man interaktiv den Zustand der laufenden Prozesse
beobachten m<>chte, benutzt man \texttt{top}, das eignet sich jedoch nicht zur
Shell-Programmierung und wird deshalb nicht ausf<73>hrlich beschrieben.}.
Ohne weitere Parameter listet \texttt{ps} alle Prozesse auf, die dem
aufrufenden Benutzer geh<65>ren und die mit dem aktuellen Terminal assoziiert
sind. Angezeigt werden dann die Proze<7A>-ID, das Terminal, die verbrauchte
CPU-Zeit und der Name des laufenden Kommandos.
In Skripten m<>chte man <20>blicherweise feststellen, ob ein bestimmtes Kommando
aktiv ist, ob also zum Beispiel ein bestimmter Serverdienst l<>uft. Dazu macht
man \texttt{ps} <20>ber Optionen gespr<70>chiger.
Das Kommando versteht in der GNU-Version zwei unterschiedliche Arten von
Optionen. Den sogenannten Unix- bzw. Posix-Stil und den BSD-Stil. Zus<75>tzlich
gibt es noch ausf<73>hrliche Parameter, aber die sollen hier nicht beschrieben
werden. Die jeweiligen Formen stehen nicht auf allen Systemen zur Verf<72>gung,
wenn ein Skript beispielsweise auch unter Solaris benutzt werden soll ist man
gezwungen, die Unix-Parametrisierung zu benutzen.
Unix-Parameter zeichnen sich durch die <20>bliche Angabe mit Bindestrich aus.
BSD-Pa\-ra\-me\-ter werden ohne Bindestrich angegeben, was neben den meisten
anderen Kommandos etwas ungewohnt aussieht.
Es gibt sehr viele verschiedene Parameter, die beste Informationsquelle ist wie
immer die Man-Page bzw. ein entsprechendes Buch. Hier werden nur ein paar
typische Aufrufbeispiele gezeigt, deren Ausgabe sich jeder selber ansehen kann:
\footnotesize
\begin{listing}[2]{1}
# Alle Prozesse auflisten, Unix-Syntax:
ps -e
ps -ef
ps -eF
ps -ely
# Alle Prozesse auflisten, BSD-Syntax:
ps ax
ps axu
# Proze<7A>baum ausgeben. Das ist in Skripten weniger Sinnvoll, wird hier aber
# angegeben weil es so eine praktische Funktion ist... :-)
ps -ejH
ps axjf
# Alle Prozesse ausgeben, die nicht dem Benutzer `root' geh<65>ren:
ps -U root -u root -N
# Nur die Proze<7A>-ID von Syslog ausgeben:
ps -C syslogd -o pid=
# Nur den Namen des Prozesses mit der ID 42 ausgeben:
ps -p 42 -o comm=
\end{listing}
\normalsize
F<EFBFBD>r die Suche nach Prozessen bestimmten Namens steht auf manchen Systemen auch
das Kommando \texttt{pgrep} (Abschnitt \ref{pgrep}) zur Verf<72>gung.
Siehe auch: Abschnitt \ref{beispiele_suchen_prozesse}.
@ -755,7 +1160,203 @@ debuggen, da sowohl Ein- als auch Ausgaben in dem Logfile sichtbar sind.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{sed}\label{sed}\index{sed=\texttt{sed}|(textbf}
TODO!!! sed
Der `Stream Editor' \texttt{sed} stellt, <20>hnlich wie \texttt{awk} (Abschnitt
\ref{awk}) eigentlich eine eigene Skriptsprache dar. Er wird auch
`nicht-interaktiver Editor' genannt. Die Kommandos sind minimalistisch, aber
exakt auf die Aufgabe zugeschnitten.
\texttt{sed} liest Zeilenweise aus einer Datei, wenn keine Datei angegeben
wurde wird von der Standard-Eingabe gelesen. Auf die eingelesenen Zeilen wird
dann ein mehr oder weniger kompliziertes \texttt{sed}-Skript angewendet, bevor
auf der Standard-Ausgabe die Resultate ausgegeben werden.
Eine vollst<73>ndige Beschreibung von \texttt{sed} w<>rde an dieser Stelle den
Rahmen sprengen, es gibt aber im Handel gute B<>cher zu dem Thema. Hier sollen
nur die g<>ngigsten Kommandos und einige Anwendungsbeispiele genannt werden.
\subsubsection{Aufruf}
\footnotesize
\begin{listing}[2]{1}
# Aufruf als Stream-Editor:
kommando1 | sed 's/alt/neu/' | kommando2
# Aufruf mit einer zu bearbeitenden Datei:
sed 's/alt/neu/' datei.txt
# Wenn mehr als ein Kommando ausgef<65>hrt werden soll, mu<6D> der Parameter -e
# verwendet werden:
sed -e 's/alt/neu/' -e '/loeschen/d' datei.txt
# Man kann auch mehrere Kommandos mit einem -e aufrufen, wenn sie durch ein
# Semikolon getrennt werden:
sed 's/alt/neu/; /loeschen/d' datei.txt
# In einem Skript kann das Kommando auch <20>ber mehrere Zeilen gehen:
sed '
s/alt/neu/
/loeschen/d' datei.txt
# Alternativ k<>nnen die Kommandos auch in eine eigene Datei gespeichert und
# <20>ber den Parameter -f eingebunden werden:
sed -f script.sed datei.txt
\end{listing}
\normalsize
Neben den oben erw<72>hnten Parametern kann \texttt{sed} auch mit \texttt{-n}
ruhig gestellt werden. Damit werden die Zeilen nur dann ausgegeben, wenn das
mittels `p' explizit gefordert wird. Die GNU-Version stellt noch ein paar
Parameter zur Verf<72>gung, die Man-Page verr<72>t n<>heres.
\subsubsection{Addressierung}
Durch die Adressierung k<>nnen Befehle gezielt auf bestimmte Zeilen angewandt
werden. Dabei k<>nnen einem Befehl keine, eine oder zwei Adressen mitgegeben
werden.
Wenn keine Zeilen adressiert werden, wirkt der Befehl auf alle Zeilen.
Wenn eine Adresse mitgegeben wird, wirkt der Befehl auf alle Zeilen die durch
diese Adresse angesprochen werden. Das k<>nnen, zum Beispiel bei einem regul<75>ren
Ausdruck, auch mehrere Zeilen sein.
Werden zwei Adressen angegeben, wirkt der Befehl auf die erste betroffene
Zeile, sowie auf alle weiteren bis zur zweiten angegebenen Zeile. Die beiden
Adressen m<>ssen durch ein Komma getrennt angegeben werden.
Die Auswahl der Zeilen kann durch ein an die Adresse angeh<65>ngtes Rufzeichen
negiert werden, der Befehl wirkt dann also auf alle Zeilen die \textbf{nicht}
adressiert wurden.
Aber wie sehen solche Adre<72>angeben aus? Die folgende Tabelle zeigt einige
Beispiele anhand des Kommandos `d', mit dem Zeilen gel<65>scht werden:
\LTXtable{\textwidth}{tab_kommandos_sed_adressen.tex}
Adressen k<>nnen auch vor geschweiften Klammern stehen, dann wirken sie auf die
komplette Befehlsfolge innerhalb der Klammern.
\subsubsection{Kommandos}
Es gibt eine ganze Reihe von Kommandos, diese Beschreibung konzentriert sich
aber auf die wichtigsten `Brot und Butter-Kommandos'. In den Beispielen weiter
unten kommen auch andere Kommandos vor, die k<>nnen bei Bedarf anhand der
einschl<EFBFBD>gigen Quellen nachgeschlagen werden.
\LTXtable{\textwidth}{tab_kommandos_sed_kommandos.tex}
Mit \texttt{s} wird substituiert. Das hei<65>t, in der Eingabezeile wird nach
einem Muster gesucht, und im Erfolgsfall wird es ersetzt. Wichtigster
Modifikator f<>r dieses Kommando ist \texttt{g}, damit wird `global' ersetzt,
falls mehrere Fundstellen in einer Zeile vorkommen. Der Aufruf sieht wie folgt
aus:
\texttt{s/Suchmuster/Ersatzmuster/g}
Im Ersatzmuster k<>nnen auch Teile der Fundstelle wieder vorkommen, wenn sie
durch Klammern in einen Puffer kopiert werden:
\texttt{s/Seite ([0-9]*) von ([0-9]*)/\textbackslash{}1 aus \textbackslash{}2/}
Mit \texttt{y} hingegen werden einzelne Buchstaben durch andere vertauscht. Das
folgende Kommando wandelt alle eingehenden Kleinbuchstaben in Gro<72>buchstaben
um\footnote{Umlaute und Sonderzeichen ausgeschlossen}:
\texttt{y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/}
Normalerweise werden alle Eingabezeilen nach der Bearbeitung wieder ausgegeben,
unabh<EFBFBD>ngig davon ob sie ver<65>ndert wurden oder nicht. Das Verhalten kann <20>ber
den Kommandozeilenparameter \texttt{-n} abgeschaltet werden. Da dann allerdings
nichts mehr ausgegeben wird kann durch ein an ein Kommando angeh<65>ngtes
\texttt{p} bestimmt werden, da<64> die Ver<65>nderten Zeilen~--~und nur
die~--~ausgegeben werden.
\subsubsection{Beispiele}
Da es in diesem Text nicht um \texttt{sed}-Skripte, sondern um Shell-Skripte
gehen soll werden hier keine komplexen Sachen vorgestellt, sondern nur ein paar
Einzeiler. Nichtsdestotrotz k<>nnen es auch diese unscheinbaren Aufrufe in sich
haben.
\footnotesize
\begin{listing}[2]{1}
### SUCHEN UND ERSETZEN
# Im kompletten Text 'rot' durch 'blau' ersetzen:
sed 's/rot/blau/' # Ersetzt nur das erste Vorkommen in jeder Zeile
sed 's/rot/blau/4' # Ersetzt nur das vierte Vorkommen in jeder Zeile
sed 's/rot/blau/g' # Ersetzt nur jedes Vorkommen in jeder Zeile
# 'rot' durch 'blau' ersetzen, aber NUR in Zeilen die auch 'gelb' enthalten:
sed '/gelb/s/rot/blau/g'
# 'rot' durch 'blau' ersetzen, AUSSER in Zeilen die auch 'gelb' enthalten:
sed '/gelb/!s/rot/blau/g'
# 'rosa', 'hellrot' und 'magenta' durch 'pink' ersetzen:
sed 's/rosa/pink/g;s/hellrot/pink/g;s/magenta/pink/g'
gsed 's/rosa\|hellrot\|magenta/pink/g' # nur in GNU sed
# Jede Zeile um f<>nf Leerzeichen einr<6E>cken:
# lies: 'ersetze jeden Zeilenanfang durch f<>nf Leerzeichen'
sed 's/^/ /'
# F<>hrende Blanks (Leerzeichen, Tabulatoren) von den Zeilenanf<6E>ngen l<>schen:
# ACHTUNG: An Stelle des \t mu<6D> der Tabulator gedr<64>ckt werden, die Darstellung
# als \t versteht nicht jedes sed!
sed 's/^[ \t]*//'
# Schliessende Blanks vom Zeilenende l<>schen, siehe oben:
sed 's/[ \t]*$//'
# F<>hrende und schlie<69>ende Blanks l<>schen:
sed 's/^[ \t]*//;s/[ \t]*$//'
# Wenn eine Zeile mit Backslash aufh<66>rt den Zeilenumbruch entfernen:
sed -e :a -e '/\\$/N; s/\\\n//; ta'
### BESTIMMTE ZEILEN AUSGEBEN
# Nur Zeile 42 ausgeben:
sed -n '42p' # Methode 1
sed '42!d' # Methode 2
# Nur die Zeilen 23-42 ausgeben (inklusive):
sed -n '23,42p' # Methode 1
sed '23,42!d' # Methode 2
# Von einem regul<75>ren Ausdruck bis zum Dateiende ausgeben:
sed -n '/regexp/,$p'
# Den Bereich zwischen zwei regul<75>ren Ausdr<64>cken ausgeben (inklusive):
sed -n '/rot/,/blau/p'
# Nur Zeilen mit mindestens 42 Zeichen ausgeben:
sed -n '/^.\{42\}/p'
# Nur Zeilen mit h<>chstens 42 Zeichen ausgeben:
sed -n '/^.\{42\}/!p' # Methode 1, analog zu oben
sed '/^.\{42\}/d' # Methode 2, einfachere Syntax
### BESTIMMTE ZEILEN L<>SCHEN
# Die ersten zehn Zeilen l<>schen:
sed '1,10d'
# Die letzte Zeile l<>schen:
sed '$d'
# Alles au<61>er dem Bereich zwischen zwei regul<75>ren Ausdr<64>cken ausgeben:
sed '/rot/,/blau/d'
# Alle Leerzeilen l<>schen:
sed '/^$/d' # Methode 1
sed '/./!d' # Methode 2
# Alle Leerzeilen am Dateianfang l<>schen:
sed '/./,$!d'
\end{listing}
\normalsize
\index{sed=\texttt{sed}|)}
@ -882,6 +1483,113 @@ Referenzdatei angepa
\index{touch=\texttt{touch}|)}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{tr}\label{tr}\index{tr=\texttt{tr}|(textbf}
Will man ganze Worte oder komplexe Muster in Dateien oder Pipes suchen und
ersetzen, greift man <20>blicherweise zu \texttt{sed} (Abschnitt \ref{sed}). F<>r
einzelne Buchstaben nimmt man hingegen \texttt{tr}.
Normalerweise wird \texttt{tr} mit zwei Zeichenketten als Parametern
aufgerufen und <20>bernimmt die zu konvertierenden Daten von der Standard-Eingabe.
Jedes Zeichen im eingehenden Datenstrom wird anhand der beiden Zeichenketten
ersetzt, dabei wird das erste Zeichen der ersten Kette durch das erste Zeichen
der zweiten Kette ersetzt, das zweite durch das zweite, und so weiter.
Ist die zweite Zeichenkette l<>nger als die erste, werden <20>bersch<63>ssige Zeichen
ignoriert. Ist die zweite Zeichenkette k<>rzer als die erste, wird ihr letztes
Zeichen so lange wiederholt bis sie gleich sind. Durch den Parameter
\texttt{-t} kann dieses Verhalten abgeschaltet werden, so da<64> <20>bersch<63>ssige
Zeichen abgeschnitten werden.
Mit dem Parameter \texttt{-c} wird die erste Zeichenkette `invertiert', es
werden also alle Zeichen ersetzt die nicht darin vorkommen.
\texttt{tr} kann aber auch mit nur einer Zeichenkette aufgerufen werden, wenn
die Parameter \texttt{-d} oder \texttt{-s} benutzt werden. Mit \texttt{-d}
werden alle Zeichen aus dem Eingabestrom gel<65>scht, die in der Zeichenkette
vorkommen. Mit \texttt{-s} werden doppelt vorkommende Zeichen durch ein
einzelnes ersetzt.
Die Zeichenketten an sich k<>nnen <20>brigens nicht nur Buchstaben oder Zahlen
enthalten, sondern auch Sonderzeichen oder Zeichenklassen. N<>heres dazu steht
in der Man-Page.
Die folgenden Beispiele verdeutlichen die Anwendung:
\footnotesize
\begin{listing}[2]{1}
text="Dies ist ein Testtext"
# kleine Umlaute durch grosse ersetzen:
echo "$text" | tr aeiou AEIOU
# -> DIEs Ist EIn TEsttExt
# Kleinbuchstaben durch Gro<72>buchstaben ersetzen:
echo "$text" | tr a-z A-Z
# -> DIES IST EIN TESTTEXT
# alle Vokale durch Unterstriche ersetzen:
echo "$text" | tr aeiouAEIOU _
# -> D__s _st __n T_stt_xt
# Gro<72>buchstaben l<>schen:
echo "$text" | tr -d A-Z
# -> ies ist ein esttext
# doppelte Buchstaben l<>schen:
echo "$text" | tr -s "a-zA-Z"
# -> Dies ist ein Testext
# doppelte Buchstaben l<>schen, mit Zeichenklasse:
echo "$text" | tr -s "[:alpha:]"
# -> Dies ist ein Testext
\end{listing}
\normalsize
\index{tr=\texttt{tr}|)}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{trap}\label{trap}\index{trap=\texttt{trap}|(textbf}
Wie alle anderen Prozesse in einem Unix-System auch, so k<>nnen auch
Shell-Skripte Signale empfangen. Diese k<>nnen durch Kommandos wie \texttt{kill}
(Abschnitt \ref{kill}) geschickt worden sein, oder zum Beispiel durch einen
Tastatur-Interrupt.
Mit \texttt{trap} kann ein Skript darauf vorbereitet werden, ein oder mehrere
Signale zu empfangen. Beim Aufruf wird eine Aktion mitgegeben, und eine oder
mehrere Bedingungen die zum Ausf<73>hren der Aktion f<>hren sollen. Das folgende
Kommando gibt zm Beispiel eine Fehlermeldung aus wenn sein Skript ein Signal 1
(HUP), 2 (INT) oder 15 (TERM) erh<72>lt:
\texttt{trap 'echo \dq`basename \$0`: Ooops...\dq 1>\&2' 1 2 15}
Die Zeile ist dem Beispiel aus Abschnitt \ref{traps} entnommen, dort findet
sich auch nochmal eine ausf<73>hrliche Erkl<6B>rung.
\index{trap=\texttt{trap}|)}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{uniq}\label{uniq}\index{uniq=\texttt{uniq}|(textbf}
Mit dem Kommando \texttt{uniq} werden doppelt vorkommende Zeilen in einer
Eingabedatei oder der eingehenden Pipe (Standard-Eingabe) bearbeitet. Per
default steht `bearbeitet' an dieser Stelle f<>r `gel<65>scht', aber durch
Parameter kann dieses Verhalten angepa<70>t werden:
\LTXtable{\textwidth}{tab_kommandos_uniq_parameter.tex}
Achtung: \texttt{uniq} betrachtet beim Vergleich nur direkt aufeinander
folgende Zeilen. Sollen alle Duplikate Dateiweit betrachtet werden, bietet sich
ein `vorsortieren' mit \texttt{sort} (Abschnitt \ref{sort}) an, vielleicht
sogar ausschlie<69>lich ein \texttt{sort -u}.
\index{uniq=\texttt{uniq}|)}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{wc}\label{wc}\index{wc=\texttt{wc}|(textbf}
@ -898,6 +1606,19 @@ Der Parameter \texttt{-L} gibt die L
\index{wc=\texttt{wc}|)}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{which}\label{which}\index{which=\texttt{which}|(textbf}
Sucht im Pfad (vordefinierte Variable
\texttt{\$PATH}\index{\$PATH=\texttt{\$PATH}}, siehe Abschnitt
\ref{vordefinierte_variablen}) nach einer Ausf<73>hrbaren Datei. Wenn mehrere
Dateien auf das Suchwort passen wird die erste Fundstelle ausgegeben, also die
Datei die tats<74>chlich ausgef<65>hrt w<>rde. Mit \texttt{-a} werden alle Fundstellen
ausgegeben.
\index{which=\texttt{which}|)}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{who}\label{who}\index{who=\texttt{who}|(textbf}

View File

@ -2,27 +2,31 @@
\chapter{Wie sieht ein Shell-Skript aus?}
Wie schon erw<72>hnt, kann ein Shell-Skript beinahe alles, was eine `richtige'
Programmiersprache auch kann. Bei der Entwicklung sollte man nur bedenken, da<64>
gerade die Ausf<EFBFBD>hrung von externen Kommandos~--~und das ist eine der
Standard-Techniken bei der Shell-Programmierung~--~nur sehr langsam vonstatten
geht. F<>r Anwendungen bei denen z. B. viele Rechnungen oder Stringbearbeitungen
gemacht werden m<>ssen, sollte man also ggf. die Benutzung einer anderen
Sprache, beispielsweise Perl\index{Perl}, in Erw<72>gung ziehen.
gerade die Aus\-f<EFBFBD>h\-rung von externen Kommandos~--~und das ist eine der
Standard-Techniken bei der Shell-Pro\-gram\-mie\-rung~--~nur sehr langsam
vonstatten geht. F<>r Anwendungen bei denen z. B. viele Rechnungen oder
Stringbearbeitungen gemacht werden m<>ssen, sollte man also ggf. die Benutzung
einer anderen Sprache, beispielsweise Perl\index{Perl}, in Erw<72>gung ziehen.
In der Shell stehen viele Mechanismen zur Verf<72>gung, die auch aus anderen Sprachen bekannt sind. Um den Umfang dieses Dokuments nicht zu sprengen, werden an dieser Stelle nur die wichtigsten vorgestellt.
\section{Grunds<EFBFBD>tzliches}
\section{HowTo}
Zun<EFBFBD>chst soll die Frage gekl<6B>rt werden, wie man <20>berhaupt ein ausf<73>hrbares Shell-Skript schreibt. Dabei wird vorausgesetzt, da<64> dem Benutzer der Umgang mit mindestens einem Texteditor\index{Texteditor} (\texttt{vi}\index{vi=\texttt{vi}}, \texttt{emacs}\index{emacs=\texttt{emacs}} etc.) bekannt ist.
Zun<EFBFBD>chst soll die Frage gekl<6B>rt werden, wie man <20>berhaupt ein ausf<73>hrbares
Shell-Skript schreibt. Dabei wird vorausgesetzt, da<64> dem Benutzer der Umgang
mit mindestens einem Texteditor\index{Texteditor}
(\texttt{vi}\index{vi=\texttt{vi}}, \texttt{emacs}\index{emacs=\texttt{emacs}}
etc.) bekannt ist.
Bei der Erstellung oder Bearbeitung von Shell-Skripten mu<6D> darauf geachtet
werden, da<64> sich keine CR/LF-Zeilenumbr<62>che einschleichen, wie dies leicht bei
der Benutzung von MS-DOS bzw. Windows-Systemen zur Bearbeitung von Skripten
<EFBFBD>ber das Netzwerk passieren kann.
\subsection{HowTo}
Zun<EFBFBD>chst mu<6D> mit Hilfe des Editors eine Textdatei angelegt werden, in die der `Quelltext' geschrieben wird. Wie der aussieht, sollte man anhand der folgenden Abschnitte und der Beispiele im Anhang erkennen k<>nnen. Beim Schreiben sollte man nicht mit den Kommentaren\index{Kommentar} geizen, da ein Shell-Skript auch schon mal sehr unleserlich werden kann.
Zun<EFBFBD>chst mu<6D> mit Hilfe des Editors eine Textdatei angelegt werden, in die der
`Quelltext' geschrieben wird. Dabei mu<6D> darauf geachtet werden, da<64> sich keine
CR/LF-Zei\-len\-um\-br<EFBFBD>\-che einschleichen, wie dies leicht bei der Benutzung
von MS-DOS bzw. Windows-Systemen zur Bearbeitung von Skripten <EFBFBD>ber das Netzwerk
passieren kann. Wie der Quelltext aussieht, sollte man anhand der folgenden
Abschnitte und der Beispiele im Anhang erkennen k<>nnen. Beim Schreiben sollte
man nicht mit den Kommentaren\index{Kommentar} geizen, da ein Shell-Skript auch
schon mal sehr unleserlich werden kann.
Nach dem Abspeichern der Datei unter einem geeigneten Namen\footnote{Bitte
\emph{nicht} den Namen \texttt{test}\index{test=\texttt{test}} verwenden. Es
@ -32,25 +36,16 @@ ausgef
zugleich einer der verwirrendsten Anf<6E>ngerfehler. Mehr zu dem
\texttt{test}-Kommando unter \ref{bedingungen}.} mu<6D> die sie ausf<73>hrbar gemacht
werden. Das geht mit dem Unix-Kommando
\texttt{chmod}\index{chmod=\texttt{chmod}}. Rechte k<>nnen unter Unix getrennt
f<EFBFBD>r den Benutzer (user, \texttt{u}), die Gruppe (group, \texttt{g}) oder andere
(others, \texttt{o}) vergeben werden. Au<41>erdem kann man die Rechte f<>r alle
Gruppen zusammen (all, a) setzen. Man kann getrennt die Rechte f<>r das lesen
(read, \texttt{r}), das schreiben (write, \texttt{w}) und die Ausf<73>hrung
(execution, \texttt{x}) vergeben. Damit die Datei f<>r einen Benutzer wirklich
ausf<EFBFBD>hrbar ist, mu<6D> er das Lese- und das
Ausf<EFBFBD>hrungsrecht\index{Aus<EFBFBD>hrungsrecht} haben. Um die Rechte zu setzen, mu<6D> man
\texttt{chmod} in Parametern mitgeben, worauf sich das Kommando bezieht, ob das
Recht gesetzt (\texttt{+}) oder weggenommen (\texttt{-}) werden soll, und
welche Rechte gemeint sind. Damit alle Benutzer das Skript ausf<73>hren d<>rfen,
benutzt man das Kommando \texttt{chmod ugo+rx name} oder einfach \texttt{chmod
+rx name}. Mit \texttt{chmod u+x name} hat nur der Besitzer der Datei
Ausf<EFBFBD>hrungsrechte.
\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
machen.
Um ein Shell-Skript ausf<73>hren zu k<>nnen braucht es aus der Sicht des
ausf<EFBFBD>hrenden Benutzers mindestens die Rechte zum Lesen (r) und Ausf<73>hren (x).
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<6D> 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.
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.
Auf den meisten Systemen befindet sich im Pfad ein Verweis auf das Verzeichnis
\texttt{bin} unterhalb des Home-Verzeichnisses eines Benutzers. Das bedeutet
@ -60,7 +55,7 @@ kann man an der Shell durch Eingabe von \texttt{echo
\$PATH}\index{\$PATH=\texttt{\$PATH}} herausfinden.
\subsection{R<EFBFBD>ckgabewerte}\label{exitcode}\index{R<EFBFBD>ckgabewert|(textbf}\index{Exit-Code|see{R<EFBFBD>ckgabewert}}\index{Exit-Status|see{R<EFBFBD>ckgabewert}}
\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}}
Wenn unter Unix ein Proze<7A> beendet wird, gibt er einen R<>ckgabewert (auch
Exit-Code oder Exit-Status genannt) an seinen aufrufenden Proze<7A> zur<75>ck. So
@ -281,7 +276,9 @@ Ausdruck}}\index{Ausdruck|see{Regul
wesentlich mehr M<>glichkeiten als die relativ einfachen Wildcards f<>r
Dateinamen.
In der folgenden Tabelle wird gezeigt, in welchen Unix-Tools welche Zeichen zur Verf<72>gung stehen. Eine ausf<73>hrlichere Beschreibung der Eintr<74>ge findet sich auf Seite \pageref{beschreibung_der_muster}. \nopagebreak
In der folgenden Tabelle wird gezeigt, in welchen Unix-Tools welche Zeichen zur
Ver\-f<EFBFBD>\-gung stehen. Eine ausf<73>hrlichere Beschreibung der Eintr<74>ge findet sich
auf Seite \pageref{beschreibung_der_muster}. \nopagebreak
\LTXtable{\textwidth}{tab_mustererkennung_muster.tex}
Bei einigen Tools (\texttt{ex}, \texttt{sed} und \texttt{ed}) werden zwei Muster angegeben: Ein Suchmuster (links) und ein Ersatzmuster (rechts). Nur die folgenden Zeichen sind in einem Ersatzmuster g<>ltig:\nopagebreak
@ -358,6 +355,54 @@ F
\index{Arithmetik-Expansion|)}
\section{Eltern und Kinder: Proze<7A>ordnung\label{prozessordnung}\index{Prozess|(textbf}\index{PID|see{Prozess}}\index{Parent-Prozess|see{Prozess}}\index{PPID|see{Prozess}}\index{Subshell|(textbf}}
Jedes laufende Programm auf einem Unixoiden System besteht aus einem oder
mehreren Prozessen, die jeweils eine eigene Proze<7A>-ID (PID) haben. Erzeugt ein
Programm mehrere Prozesse, sind die zu einer Proze<7A>gruppe zusammengefa<66>t. Jeder
laufende Proze<7A>\footnote{Es gibt eine Ausnahme: der Init-Proze<7A>, der immer die
PID 1 hat, hat keine Eltern. Er stammt direkt vom Kernel ab.} verf<72>gt <20>ber
genau eine Parent-Proze<7A>-ID (PPID). Das ist die ID des Prozesses, der den
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.
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
\ref{auswahl_der_shell}) und f<>hrt sich innerhalb dieser aus. Die Shell des
Skriptes ist dabei ein Kind der interaktiven Shell, die einzelnen Kommandos des
Skriptes sind Kinder der Skript-Shell.
Eine solche Shell-in-Shell-Umgebung wird `Subshell' genannt, dieser
Mechanismus~--~und somit auch der Begriff~--~tauchen immer wieder auf.
Wichtig in diesem Zusammenhang ist das Verst<73>ndnis f<>r die Vererbung zwischen
den beteiligten Prozessen. Wenn in einer Shell eine Variable definiert und
exportiert wird, existiert diese auch f<>r die Kind-Prozesse. Gleiches gilt
beispielsweise f<>r einen Verzeichnis-Wechsel. Umgekehrt gilt dies nicht: ein
Proze<EFBFBD> kann die Umgebung des Parent-Prozesses nicht ver<65>ndern. Das geschieht
nicht zuletzt aus Sicherheitsgr<67>nden so.
Will man die <20>nderungen eines Skriptes <20>bernehmen~--~beispielsweise wenn ein
Skript die Benutzerumgebung konfigurieren soll (.bashrc, .profile und
Konsorten)~--~mu<6D> das explizit angefordert werden. Dazu ruft man es mit einem
vorangestellten \texttt{source}\index{source=\texttt{source}} bzw. in der
Kurzform mit einem vorangestellten Punkt auf. Weiteres zu dem Thema findet sich
im Abschnitt \ref{source}.
Besonders mu<6D> man diesen Umstand im Hinterkopf behalten, wenn mit
Pipelines\index{Pipe} (siehe Abschnitt \ref{befehlsformen}) gearbeitet wird.
Dabei werden auch Kommandos in Subshells ausgef<65>hrt, was dann dazu f<>hrt da<64>
Variablen belegt werden die dann nach Ausf<73>hrung der Pipeline pl<70>tzlich wieder
leer sind. Die Abschnitte \ref{subshellschleifen} und \ref{daten_hochreichen}
widmen sich diesem mitunter recht <20>rgerlichen Thema.
\index{Prozess|)}\index{Subshell|)}
\section{Programmablaufkontrolle}
Bei der Shell-Programmierung verf<72>gt man <20>ber <20>hnliche Konstrukte wie bei anderen Programmiersprachen, um den Ablauf des Programms zu steuern. Dazu geh<65>ren Funktionsaufrufe, Schleifen, Fallunterscheidungen und dergleichen.\nopagebreak

View File

@ -1,6 +1,12 @@
% $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.
@ -23,3 +29,19 @@ 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.