Inhaltsverzeichnis
Ich gebe hier einige Startimpulse, um Programmierung im Debian-System zumindest so weit zu erlernen, dass der Programmcode aus Debian-Quellpaketen zwecks Fehlersuche nachverfolgt werden kann. Hier einige erwähnenswerte Pakete und dazugehörige Dokumentation:
Tabelle 12.1. Liste von Paketen für die Programmierung
Paket | Popcon | Größe | Dokumentation |
---|---|---|---|
autoconf
|
V:41, I:282 | 1846 |
"info autoconf " aus dem
autoconf-doc -Paket
|
automake
|
V:42, I:279 | 1830 |
"info automake " aus dem
automake1.10-doc -Paket
|
bash
|
V:791, I:999 | 6469 |
"info bash " aus dem bash-doc -Paket
|
bison
|
V:9, I:103 | 2815 |
"info bison " aus dem bison-doc -Paket
|
cpp
|
V:319, I:770 | 42 |
"info cpp " aus dem cpp-doc -Paket
|
ddd
|
V:0, I:10 | 4184 |
"info ddd " aus dem ddd-doc -Paket
|
exuberant-ctags
|
V:5, I:37 | 341 | exuberant-ctags(1) |
flex
|
V:9, I:93 | 1279 |
"info flex " aus dem flex-doc -Paket
|
gawk
|
V:368, I:454 | 2558 |
"info gawk " aus dem gawk-doc -Paket
|
gcc
|
V:165, I:604 | 45 |
"info gcc " aus dem gcc-doc -Paket
|
gdb
|
V:13, I:114 | 9789 |
"info gdb " aus dem gdb-doc -Paket
|
gettext
|
V:48, I:312 | 5843 |
"info gettext " aus dem
gettext-doc -Paket
|
gfortran
|
V:11, I:98 | 16 |
"info gfortran " aus dem
gfortran-doc -Paket (Fortran 95)
|
fpc
|
I:3 | 121 | fpc(1)
bzw. die HTML-Variante aus dem fp-docs -Paket (Pascal)
|
glade
|
V:0, I:8 | 1730 | Hilfe verfügbar über das Menü (UI Builder) |
libc6
|
V:935, I:999 | 12771 |
"info libc " aus dem glibc-doc - und
glibc-doc-reference -Paket
|
make
|
V:157, I:609 | 1592 |
"info make " aus dem make-doc -Paket
|
xutils-dev
|
V:1, I:12 | 1466 | imake(1), xmkmf(1) usw. |
mawk
|
V:372, I:997 | 242 | mawk(1) |
perl
|
V:610, I:992 | 705 | perl(1)
bzw. die HTML-Seiten aus dem perl-doc - oder
perl-doc-html -Paket
|
python
|
V:293, I:923 | 68 | python(1)
bzw. die HTML-Seiten aus dem python-doc -Paket |
tcl
|
V:31, I:414 | 22 | tcl(3)
und detaillierte Handbuchseiten (manpages) aus dem
tcl-doc -Paket |
tk
|
V:30, I:406 | 22 | tk(3)
und detaillierte Handbuchseiten (manpages) aus dem
tk-doc -Paket |
ruby
|
V:137, I:318 | 35 | ruby(1)
und die interaktive Referenz aus dem ri -Paket |
vim
|
V:106, I:398 | 3231 |
Hilfe-Menü (F1) aus dem vim-doc -Paket
|
susv2
|
I:0 | 16 | die "Single UNIX Specifications v2" |
susv3
|
I:0 | 16 | die "Single UNIX Specifications v3" |
Handbuchseiten (manpages) sind verfügbar, indem Sie nach Installation der
manpages
- und manpages-dev
-Pakete
"man programmname
" eingeben. Informationen über
GNU-Werkzeuge erhalten Sie über "info programmname
" nach
Installation der entsprechenden Dokumentationspakete. Sie müssen unter
Umständen die Bereiche contrib
und
non-free
des Archivs zusätzlich zu
main
freigeben, da einige GFDL-Dokumentation als nicht
DFSG-frei angesehen wird.
![]() |
Warnung |
---|---|
Verwenden Sie nicht " |
![]() |
Achtung |
---|---|
Sie sollten Software, die direkt aus den Quellen kompiliert wurden, in
" |
![]() |
Tipp |
---|---|
Die Code-Beispiele zum Erzeugen des Songs "99 Bottles of Beer" sollten Ihnen gute Ideen zu nahezu allen Programmiersprachen liefern. |
Das Shellskript ist eine Textdatei mit gesetztem Ausführungsbit und enthält Befehle in der folgenden Form:
#!/bin/sh ... Befehle
Die erste Zeile spezifiziert den Shell-Interpreter, der den Inhalt dieser Datei liest und ausführt.
Das Lesen von Shellskripten ist der beste Weg, um zu verstehen, wie ein Unix-artiges System arbeitet. Ich gebe hier einige Hinweise zur Shellprogrammierung. Lesen Sie "Shell Mistakes" (http://www.greenend.org.uk/rjk/2001/04/shell.html), um aus Fehlern zu lernen.
Anders als der interaktive Shell-Modus (lesen Sie Abschnitt 1.5, „Der einfache Shell-Befehl“ und Abschnitt 1.6, „Unix-ähnliche Textverarbeitung“) verwenden Shellskripte häufig Parameter, bedingte Ausdrücke und Schleifen.
Viele Systemskripte können von jeder POSIX-konformen Shell (lesen Sie Tabelle 1.13, „Liste von Shell-Programmen“) interpretiert werden. Die Standard-Shell
für das System ist "/bin/sh
", was ein symbolischer Link
auf das entsprechende Programm ist:
bash(1)
für Lenny
oder älter;
dash(1)
für Squeeze
oder neuer.
Vermeiden Sie, in Shellskripten Bashisms oder Zshisms (speziell für Bash oder Zsh angepasste Shell-Befehle) zu verwenden, damit sie auf alle POSIX-Shells portierbar sind. Sie können dies mittels checkbashisms(1) überprüfen.
Tabelle 12.2. Liste typischer Bashisms
Gut: POSIX | Vermeiden: Bashism |
---|---|
if [ "$foo" = "$bar" ] ; then …
|
if [ "$foo" == "$bar" ] ; then …
|
diff -u datei.c.orig datei.c
|
diff -u datei.c{.orig,}
|
mkdir /foobar /foobaz
|
mkdir /foo{bar,baz}
|
funktionsname() { … }
|
function funktionsname() { … }
|
Oktalformat: "\377 "
|
Hexadezimalformat: "\xff "
|
Der Befehl "echo
" muss mit Vorsicht verwendet werden, da
seine Implementierung sich zwischen Shell-Builtins und externen Befehlen
unterscheidet:
vermeiden Sie die Verwendung jeglicher Befehlsoptionen außer
"-n
";
vermeiden Sie die Verwendung von Escape-Sequenzen in Zeichenketten, da deren Handhabung unterschiedlich ist.
![]() |
Anmerkung |
---|---|
Obwohl die Option " |
![]() |
Tipp |
---|---|
Nutzen Sie den " |
Einige spezielle Shellparameter werden oft in Shellskripten verwendet:
Tabelle 12.3. Liste von Shellparametern
Shellparameter | Wert |
---|---|
$0
|
Name der Shell oder des Shellskripts |
$1
|
erstes (1.) Shellargument |
$9
|
neuntes (9.) Shellargument |
$#
|
Anzahl der Parameter |
"$*"
|
"$1 $2 $3 $4 … "
|
"$@"
|
"$1" "$2" "$3" "$4" …
|
$?
|
Beendigungs-Status des zuletzt ausgeführten Befehls |
$$
|
Prozessnummer (PID) des Shellskripts |
$!
|
PID des zuletzt ausgeführten Hintergrundbefehls |
Grundlegende Parameterauswertungen, die Sie sich einprägen sollten:
Tabelle 12.4. Liste von Parameterauswertungen
Parameterauswertung |
Wert, falls var gesetzt ist
|
Wert, falls var nicht gesetzt ist
|
---|---|---|
${var:-string}
|
"$var "
|
"string "
|
${var:+string}
|
"string "
|
"null "
|
${var:=string}
|
"$var "
|
"string " (und ausführen von
"var=string ")
|
${var:?string}
|
"$var "
|
Ausgabe von "string " auf stderr (und mit Fehlerstatus beenden)
|
Hierbei ist der Doppelpunkt ":
" in allen Operatoren
optional:
mit ":
" = Operatortest
für existiert und nicht Null;
ohne ":
" =
Operatortest nur für existiert.
Tabelle 12.5. Liste von Shellparameterersetzungen
Parameterersetzung | Ergebnis |
---|---|
${var%suffix}
|
entferne kleinstes Suffix-Muster |
${var%%suffix}
|
entferne größtes Suffix-Muster |
${var#prefix}
|
entferne kleinstes Prefix-Muster |
${var##prefix}
|
entferne größtes Prefix-Muster |
Jeder Befehl gibt einen Beendigungs-Status (Exit-Status) zurück, der für einen bedingten Ausdruck verwendet werden kann:
Erfolg: 0 ("Wahr/True")
Fehler: nicht 0 ("Falsch/False")
![]() |
Anmerkung |
---|---|
"0" im Kontext eines bedingten Ausdrucks für die Shell bedeutet "Wahr", während "0" im Kontext eines bedingten Ausdrucks für ein C-Programm "Falsch" bedeutet. |
![]() |
Anmerkung |
---|---|
" |
Grundlegende Ausdrucksformen für bedingte Ausdrücke, die Sie sich einprägen sollten:
"<befehl> &&
<bei_erfolg_auch_diesen_befehl_ausführen> || true
"
"<befehl> ||
<falls_kein_erfolg_auch_diesen_befehl_ausführen> || true
"
ein mehrzeiliger Skriptschnipsel wie dieser:
if [ <bedingter_ausdruck> ]; then <bei_erfolg_diesen_befehl_ausführen> else <falls_kein_erfolg_diesen_befehl_ausführen> fi
Hierbei ist das "|| true
" am Ende erforderlich, um
sicherzustellen, dass das Shellskript sich bei dieser Zeile nicht
fälschlicherweise beendet, wenn die Shell mit der
"-e
"-Option aufgerufen wird.
Tabelle 12.6. Liste von Dateivergleichsoperatoren in bedingten Ausdrücken
Gleichung | Wahr wenn … |
---|---|
-e <datei>
|
<datei> existiert |
-d <datei>
|
<datei> existiert und ein Verzeichnis ist |
-f <datei>
|
<datei> existiert und eine reguläre Datei ist |
-w <datei>
|
<datei> existiert und schreibbar ist |
-x <datei>
|
<datei> existiert und ausführbar ist |
<datei1> -nt <datei2>
|
<datei1> neuer als <datei2> ist (Änderungszeitpunkt) |
<datei1> -ot <datei2>
|
<datei1> älter als <datei2> ist (Änderungszeitpunkt) |
<datei1> -ef <datei2>
|
<datei1> und <datei2> die gleiche Device- und Inode-Nummer haben |
Tabelle 12.7. Liste von String-Vergleichsoperatoren im bedingten Ausdruck
Gleichung | Wahr wenn … |
---|---|
-z <str>
|
die Länge von <str> gleich Null ist |
-n <str>
|
die Länge von <str> nicht Null ist |
<str1> = <str2>
|
<str1> und <str2> gleich sind |
<str1> != <str2>
|
<str1> und <str2> ungleich sind |
<str1> < <str2>
|
<str1> in der Sortierung vor <str2> erscheint (Locale-abhängig) |
<str1> > <str2>
|
<str1> in der Sortierung hinter <str2> erscheint (Locale-abhängig) |
Arithmetische Ganzzahlvergleicher in
bedingten Ausdrücken sind "-eq
",
"-ne
", "-lt
",
"-le
", "-gt
" und
"-ge
".
Es gibt mehrere Ausdrucksweisen für Schleifen, die in POSIX-Shells genutzt werden können:
"for x in foo1 foo2 … ; do befehl ; done
" führt Schleifen
aus, indem Einträge aus der Liste "foo1 foo2 …
" der
Variable "x
" zugewiesen werden und dann
"befehl
" ausgeführt wird.
"while bedingung ; do befehl ; done
" wiederholt
"befehl
", solange "bedingung
" wahr
ist.
"until bedingung ; do befehl ; done
" wiederholt
"befehl
", solange "bedingung
" nicht
wahr ist.
"break
" ermöglicht, die Bearbeitung der Schleife zu
beenden.
"continue
" ermöglicht, den nächsten Umlauf der Schleife
fortzusetzen.
![]() |
Tipp |
---|---|
Die der C-Sprache ähnliche nummerische Wiederholung
(Iteration) kann realisiert werden, indem
seq(1)
für die Erzeugung der " |
Die Shell verarbeitet ein Skript im Prinzip in der folgenden Abfolge:
Die Shell liest eine Zeile.
Die Shell gruppiert Teile der Zeile zu zusammengehörigen Ausdrücken (Token) zusammen, wenn
diese sich innerhalb von "…"
oder '…'
befinden.
Die Shell splittet andere Teile der Zeile in einzelne Ausdrücke (Token) auf, wenn diese wie folgt von einander getrennt sind:
Whitespace-Zeichen: <Leerzeichen> <Tabulator>
<newline>
Metazeichen: < > | ; & ( )
Die Shell prüft jeden Ausdruck auf Schlüsselworte (wenn nicht innerhalb von
"…"
oder '…'
), um deren Verhalten
anzupassen.
Schlüsselwörter sind: if then
elif else fi for in while unless do done case esac
Die Shell expandiert Alias-Befehle (wenn
nicht innerhalb von "…"
oder '…'
).
Die Shell expandiert eine Tilde (wenn
nicht innerhalb von "…"
oder '…'
):
"~
" → Heimatverzeichnis des aktuellen Benutzers
"~<benutzer>
" → Heimatverzeichnis von
<benutzer>
Die Shell expandiert Parameter in deren
Wert (wenn nicht innerhalb von '…'
):
Parameter:
"$PARAMETER
" oder "${PARAMETER}
"
Die Shell expandiert Befehlsersetzungen / command
substitutions (wenn nicht innerhalb von '…'
):
"$( befehl )
" → die Ausgabe von
"befehl
"
"` befehl `
" → die Ausgabe von
"befehl
"
Die Shell expandiert Pfadnamenmuster in
die passenden Dateinamen (wenn nicht innerhalb von "…"
oder '…'
):
*
→ jegliche Zeichen (eins oder mehrere)
?
→ irgendein (nur ein) Zeichen
[…]
→ jegliche Zeichen von denen in
"…
"
Die Shell sucht befehl in folgenden Definitionen und führt ihn aus:
Funktions-Definition
Builtin (integrierter Befehl)
ausführbare Datei in
"$PATH
"
Die Shell geht zur nächsten Zeile und wiederholt diesen kompletten Ablauf vom Anfang.
Einfache Anführungszeichen innerhalb von doppelten Anführungszeichen haben keine Wirkung.
Das Ausführen von "set -x
" in der Shell oder das Aufrufen
einer Shell mit der Option "-x
" veranlasst die Shell,
alle ausgeführten Befehle auch auf dem Bildschirm auszugeben. Dies ist sehr
nützlich zur Fehlersuche.
Um Ihr Shellprogramm innerhalb des Debian-Systems möglichst weit portierbar zu machen, ist es eine gute Idee, die zu nutzenden Hilfsprogramme auf diejenigen einzuschränken, welche durch die essential-Pakete bereitgestellt werden:
"aptitude search ~E
" listet alle essential-Pakete auf;
"dpkg -L <paketname> |grep '/man/man.*/'
" listet
Handbuchseiten (manpages) derjenigen Befehle auf, die von dem Paket
<paketname>
bereitgestellt werden.
Tabelle 12.8. Liste der Pakete, die kleine Hilfsprogramme für Shellskripte enthalten
Paket | Popcon | Größe | Beschreibung |
---|---|---|---|
coreutils
|
V:891, I:999 | 17478 | Grundlegende GNU-Werkzeuge |
debianutils
|
V:925, I:999 | 230 | verschiedene Hilfsprogramme speziell für Debian |
bsdmainutils
|
V:60, I:996 | 26 | Sammlung weiterer FreeBSD-Hilfsprogramme |
bsdutils
|
V:673, I:999 | 393 | grundlegende Kommandos aus 4.4BSD-Lite |
moreutils
|
V:11, I:35 | 237 | zusätzliche Unix-Hilfsprogramme |
![]() |
Tipp |
---|---|
Obwohl |
Die Schnittstelle zwischen einem Shellprogramm und dem Benutzer
("Bedienoberfläche") kann über die plumpe Verwendung von
echo
und read
hinaus mit einer
interaktiven Oberfläche aufgewertet werden, indem eines der sogenannten
Dialog-Programme genutzt wird:
Tabelle 12.9. Liste von Programmen für die Benutzerschnittstelle
Paket | Popcon | Größe | Beschreibung |
---|---|---|---|
x11-utils
|
V:180, I:599 | 712 | xmessage(1): eine Nachricht oder Abfrage in einem Fenster anzeigen (X) |
whiptail
|
V:87, I:995 | 71 | nutzerfreundliche Dialogboxen von Shellskripten anzeigen (newt) |
dialog
|
V:15, I:123 | 1222 | nutzerfreundliche Dialogboxen von Shellskripten anzeigen (ncurses) |
zenity
|
V:87, I:409 | 384 | grafische Dialogboxen von Shellskripten anzeigen (gtk2.0) |
ssft
|
V:0, I:0 | 75 | Werkzeug für Shellskript-Oberflächen (Aufrufprogramm für zenity, kdialog und dialog mit gettext) |
gettext
|
V:48, I:312 | 5843 |
"/usr/bin/gettext.sh ": Nachricht übersetzen
|
Hier ist ein einfaches Skript, das ein ISO-Image aus RS02-Daten erzeugt, welche von dvdisaster(1) bereitgestellt werden.
#!/bin/sh -e # gmkrs02 : Copyright (C) 2007 Osamu Aoki <osamu@debian.org>, Public Domain #set -x error_exit() { echo "$1" >&2 exit 1 } # Variablen initialisieren DATA_ISO="$HOME/Desktop/iso-$$.img" LABEL=$(date +%Y%m%d-%H%M%S-%Z) if [ $# != 0 ] && [ -d "$1" ]; then DATA_SRC="$1" else # Auswahl eines Verzeichnisses zur Erzeugung des ISO-Images DATA_SRC=$(zenity --file-selection --directory \ --title="Select the directory tree root to create ISO image") \ || error_exit "Exit on directory selection" fi # Größe des Archivs überprüfen xterm -T "Check size $DATA_SRC" -e du -s $DATA_SRC/* SIZE=$(($(du -s $DATA_SRC | awk '{print $1}')/1024)) if [ $SIZE -le 520 ] ; then zenity --info --title="Dvdisaster RS02" --width 640 --height 400 \ --text="The data size is good for CD backup:\\n $SIZE MB" elif [ $SIZE -le 3500 ]; then zenity --info --title="Dvdisaster RS02" --width 640 --height 400 \ --text="The data size is good for DVD backup :\\n $SIZE MB" else zenity --info --title="Dvdisaster RS02" --width 640 --height 400 \ --text="The data size is too big to backup : $SIZE MB" error_exit "The data size is too big to backup :\\n $SIZE MB" fi # Nur xterm hat eine sicher funktionierende -e-Option # Rohes ISO-Image erzeugen rm -f "$DATA_ISO" || true xterm -T "genisoimage $DATA_ISO" \ -e genisoimage -r -J -V "$LABEL" -o "$DATA_ISO" "$DATA_SRC" # Eine zusätzliche RS02-Redundanz erzeugen xterm -T "dvdisaster $DATA_ISO" -e dvdisaster -i "$DATA_ISO" -mRS02 -c zenity --info --title="Dvdisaster RS02" --width 640 --height 400 \ --text="ISO/RS02 data ($SIZE MB) \\n created at: $DATA_ISO" # EOF (Dateiende)
Sie möchten vielleicht für solch ein Skript einen Starter auf der
Arbeitsfläche erstellen; nutzen Sie etwas wie
"/usr/local/bin/gmkrs02 %d
".
Make ist ein Werkzeug, um Gruppen von Programmen
zu betreuen. Bei Ausführung des Befehls
make(1)
liest make
die Regeldatei "Makefile
"
und aktualisiert ein Ziel (Target), falls sich Dateien, von denen das
Makefile abhängt, seit der letzten Modifizierung des Targets verändert haben
oder falls das Target nicht existiert. Die Ausführungen dieser
Aktualisierungen können zeitgleich erfolgen.
Die Syntax der Regeldatei ist folgende:
target: [ Voraussetzungen ... ] [TAB] befehl1 [TAB] -befehl2 # Fehler ignorieren [TAB] @befehl3 # Ausgabe unterdrücken
Hierbei ist "[TAB]
" ein TAB-Code. Jede Zeile wird nach
Ersetzung der Variablen durch die Shell interpretiert. Verwenden Sie
"\
" am Ende einer Zeile, um den Befehl in der nächsten
Zeile fortzusetzen. Zur Angabe von Umgebungsvariablen müssen Sie statt
"$
" hier "$$
" schreiben.
Implizite Regeln für das Target und Voraussetzungen können z.B. wie folgt angegeben werden:
%.o: %.c header.h
Hier enthält das Target das Zeichen "%
" (exakt eines
davon). Das "%
" passt auf jeden nicht leeren Teil-String
in den eigentlichen Dateinamen des Targets. Auch die Voraussetzungen nutzen
auf ähnliche Art ein "%
", um den Bezug zum Namen des
Targets anzuzeigen.
Tabelle 12.10. Liste von automatischen make-Variablen
automatische Variable | Wert |
---|---|
$@
|
Target |
$<
|
erste Voraussetzung |
$?
|
alle neueren Voraussetzungen |
$^
|
alle Voraussetzungen |
$*
|
"% " trifft auf den Stamm im Target-Muster zu
|
Tabelle 12.11. Liste von make-Variablenexpandierungen
Variablenexpandierung | Beschreibung |
---|---|
foo1 := bar
|
einmalige Expandierung |
foo2 = bar
|
rekursive Expandierung |
foo3 += bar
|
anhängen |
Führen Sie "make -p -f/dev/null
" aus, um alle internen
automatischen Regeln zu sehen.
Sie können wie folgt eine korrekte Umgebung zum Kompilieren von in der C-Programmiersprache geschriebenen Programmen einrichten:
# apt-get install glibc-doc manpages-dev libc6-dev gcc build-essential
Das Paket libc6-dev
(d.h. die GNU-C-Bibliothek) bietet
als C-Standard-Bibliothek eine
Sammlung von Header-Dateien und Bibliotheksroutinen, die von der C-Sprache
genutzt werden.
Referenzen für C finden Sie über:
"info libc
" (Referenz für Funktionen der C-Bibliothek)
gcc(1)
und "info gcc
"
jeglicher_funktionsname_aus_der_c_bibliothek(3)
Kernighan & Ritchie, "The C Programming Language", 2. Ausgabe (Prentice Hall)
Hier ein einfaches Beispiel zum Kompilieren von
"example.c
" mit der Bibliothek "libm
"
in eine ausführbare Datei "run_example
":
$ cat > example.c << EOF #include <stdio.h> #include <math.h> #include <string.h> int main(int argc, char **argv, char **envp){ double x; char y[11]; x=sqrt(argc+7.5); strncpy(y, argv[0], 10); /* prevent buffer overflow */ y[10] = '\0'; /* fill to make sure string ends with '\0' */ printf("%5i, %5.3f, %10s, %10s\n", argc, x, y, argv[1]); return 0; } EOF $ gcc -Wall -g -o run_example example.c -lm $ ./run_example 1, 2.915, ./run_exam, (null) $ ./run_example 1234567890qwerty 2, 3.082, ./run_exam, 1234567890qwerty
Hierbei wird "-lm
" benötigt, um die Bibliothek
"/usr/lib/libm.so
" aus dem libc6
-Paket
für
sqrt(3)
zu verlinken. Die eigentliche Bibliothek liegt in "/lib/
"
und hat den Dateinamen "libm.so.6
", was ein symbolischer
Link auf "libm-2.7.so
" ist.
Schauen Sie sich den letzten Parameter im ausgegebenen Text an. Dort werden
mehr als 10 Zeichen ausgegeben, obwohl "%10s
" angegeben
wurde.
Die Verwendung von Funktionen, die Zeiger auf Speicherbereiche ohne Bereichsüberprüfung nutzen (wie sprintf(3) und strcpy(3)), wird missbilligt, um das Ausnutzen von Pufferüberläufen zu verhindern, die obige Überlaufeffekte in Gang bringen. Verwenden Sie stattdessen snprintf(3) und strncpy(3).
Debugging ist ein wichtiger Teil der Programmieraktivitäten. Das Wissen darüber, wie man in Programmen einen Fehler sucht, macht Sie zu einem guten Debian-Nutzer, der aussagekräftige Fehlerberichte erstellen kann.
Das primäre Programm zur Fehlersuche (Debugger) im Debian-System ist gdb(1), welches Ihnen erlaubt, ein Programm zu inspizieren, während es läuft.
Wir installieren gdb
und zugehörige Programme wie folgt:
# apt-get install gdb gdb-doc build-essential devscripts
Eine gute Einführung zu gdb
erhalten Sie mit
"info gdb
" oder im
Netz. Hier ein einfaches Beispiel zur Verwendung von
gdb(1)
bei einem Programm namens "program
", kompiliert mit der
Option "-g
", um Debugging-Informationen auszugeben.
$ gdb program (gdb) b 1 # Haltepunkt in Zeile 1 setzen (gdb) run args # Programm mit Argumenten ausführen (gdb) next # nächste Zeile ... (gdb) step # einen Schritt vorwärts ... (gdb) p parm # parm ausgeben ... (gdb) p parm=12 # Wert auf 12 setzen ... (gdb) quit
![]() |
Tipp |
---|---|
Viele gdb(1)-Befehle können abgekürzt werden. Vervollständigungen funktionieren wie in der Shell mit der Tabulator-Taste. |
Da alle installierten Binärdateien im Debian-System standardmäßig auf das
Nötige reduziert sein sollten, sind in normalen Paketen die meisten
Debugging-Symbole entfernt. Zur Fehlersuche in Debian-Paketen mittels
gdb(1)
müssen entsprechende *-dbg
- oder
*-dbgsym
-Pakete installiert werden
(z.B. libc6-dbg
im Fall von libc6
,
oder coreutils-dbgsym
für coreutils
).
Pakete im alten Stil stellen ein zugehöriges *-dbg
-Paket
bereit. Es liegt direkt im Debian-main-Archiv, bei dem Originalpaket
selbst. Neuere Pakete können automatisch beim Bau
*-dbgsym
-Pakete generieren und diese Debug-Pakete werden
in dem separaten Archiv debian-debug
abgelegt. Bitte lesen Sie die entsprechenden Artikel im Debian Wiki, wenn Sie
weitere Informationen benötigen.
Falls ein Paket, bei dem eine Fehlersuche durchgeführt werden soll, kein
*-dbg
- oder *-dbgsym
-Paket anbietet,
müssen Sie es händisch neu bauen und dann installieren, wie hier:
$ mkdir /path/new ; cd /path/new $ sudo apt-get update $ sudo apt-get dist-upgrade $ sudo apt-get install fakeroot devscripts build-essential $ apt-get source package_name $ cd package_name* $ sudo apt-get build-dep ./
Beheben Sie die Fehler, falls erforderlich.
Erhöhen Sie die Paketversion auf eine Versionsbezeichnung, die nicht mit
offiziellen Debian-Versionen kollidiert (Sie können z.B. ein
"+debug1
" anhängen, wenn Sie eine existierende
Paketversion neu kompilieren, oder Sie hängen "~pre1
" an,
wenn Sie eine noch nicht veröffentlichte Paketversion selbst
kompilieren). Verwenden Sie dazu:
$ dch -i
Kompilieren und installieren Sie ein Paket mit Debugging-Symbolen wie folgt:
$ export DEB_BUILD_OPTIONS=nostrip noopt $ debuild $ cd .. $ sudo debi <paketname>*.changes
Sie müssen die Build-Skripte des Pakets überprüfen und sicherstellen, dass
"CFLAGS=-g -Wall
" zum Kompilieren der Binärdateien
verwendet wird.
Wenn Sie einen Programmabsturz erlitten haben, ist es eine gute Idee, einen Fehlerbericht einzureichen und an diesen per Kopieren-und-Einfügen Backtrace-Informationen (Daten zur Rückverfolgung von Vorgängen in Programmen zwecks Fehleranalyse) anzuhängen.
Solche Backtrace-Informationen lassen sich wie folgt gewinnen:
Lassen Sie das Programm unter gdb(1) laufen.
Reproduzieren Sie den Absturz.
Dies bringt Sie zurück zum gdb
-Prompt.
Geben Sie "bt
" am gdb
-Prompt ein.
Falls sich das Programm aufgehängt hat, können Sie es mittels
Strg-C
in dem Terminal, in dem gdb
läuft, beenden und zum gdb
-Prompt zurückgelangen.
![]() |
Tipp |
---|---|
Oft stellt man fest, dass in den Backtrace-Informationen eine oder mehrere
der ersten Zeilen " |
$ MALLOC_CHECK_=2 gdb hello
Tabelle 12.12. Liste erweiterter gdb-Befehle
Befehl | Beschreibung |
---|---|
(gdb) thread apply all bt
|
Backtrace für alle Threads eines Multi-Thread-Programms auslesen |
(gdb) bt full
|
Parameter auslesen, die auf dem Aufruf-Stack der Funktionsaufrufe aufgelaufen sind |
(gdb) thread apply all bt full
|
Backtrace und Parameter als Kombination der vorangegangenen Optionen auslesen |
(gdb) thread apply all bt full 10
|
Backtrace und Parameter für die ersten 10 Aufrufe auslesen, um irrelevante Ausgaben abzuschneiden |
(gdb) set logging on
|
Protokoll der Ausgabe von gdb in eine Datei schreiben
(Standard ist "gdb.txt ")
|
Wenn ein GNOME-Programm preview1
einen X-Fehler empfangen
hat, sollten Sie eine Meldung wie diese sehen:
The program 'preview1' received an X Window System error.
Sollte dies der Fall sein, können Sie versuchen, das Programm mit der Option
"--sync
" zu starten und einen Haltepunkt für die Funktion
"gdk_x_error
" zu setzen, um einen Backtrace zu bekommen.
Verwenden Sie ldd(1) wie hier, um zu ermitteln, von welchen Bibliotheken ein Programm abhängt:
$ ldd /bin/ls librt.so.1 => /lib/librt.so.1 (0x4001e000) libc.so.6 => /lib/libc.so.6 (0x40030000) libpthread.so.0 => /lib/libpthread.so.0 (0x40153000) /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
Damit ls(1) in einer "chroot"-Umgebung funktioniert, müssen die obigen Bibliotheken in der "chroot"-Umgebung vorhanden sein.
Lesen Sie dazu Abschnitt 9.3.6, „Programmaktivitäten verfolgen“.
Es gibt verschiedene Werkzeuge zur Erkennung von Speicherlecks in Debian:
Tabelle 12.13. Liste von Werkzeugen zur Erkennung von Speicherlecks
Paket | Popcon | Größe | Beschreibung |
---|---|---|---|
libc6-dev
|
V:249, I:620 | 14357 | mtrace(1): malloc-Debugging-Funktionalität in glibc |
valgrind
|
V:6, I:46 | 80378 | Speicher-Debugging- und Analyse-Programm |
electric-fence
|
V:0, I:5 | 70 | malloc(3)-Debugging-Programm |
leaktracer
|
V:0, I:3 | 57 | Werkzeug zur Verfolgung von Speicherlecks in C++-Programmen |
libdmalloc5
|
V:0, I:3 | 393 | Bibliothek zur Fehlersuche bei Speicherzuweisungen |
Es gibt lint-ähnliche Werkzeuge für die statische Code-Analyse:
Tabelle 12.14. Liste von Werkzeugen für die statische Code-Analyse
Paket | Popcon | Größe | Beschreibung |
---|---|---|---|
splint
|
V:0, I:4 | 2315 | Werkzeug zur statischen Überprüfung von C-Programmen auf Programmfehler |
flawfinder
|
V:0, I:0 | 181 | Werkzeug zur Durchsuchung von Quellcode auf Sicherheitsschwächen |
perl
|
V:610, I:992 | 705 | Interpreter mit internem statischen Code-Prüfmechanismus: B::Lint(3perl) |
pylint
|
V:2, I:13 | 1371 | Statisches Prüfprogramm für Python-Code |
weblint-perl
|
V:0, I:1 | 32 | Ein Syntax- und (Minimal-)Stil-Prüfprogramm für HTML |
linklint
|
V:0, I:0 | 344 | schneller Linkchecker und Werkzeug für die Webseitenpflege |
libxml2-utils
|
V:22, I:246 | 182 | Hilfsprogramme zur Validierung von XML-Dateien mit xmllint(1) |
Flex ist ein Lex-kompatibler schneller lexikalischer Analysegenerator.
Eine Einführung zu
flex(1)
finden Sie in "info flex
".
Sie müssen Ihre eigenen "main()
"- und
"yywrap()
"-Funktionen bereitstellen oder Ihr Programm
sollte wie folgt aussehen, um ohne eine Bibliothek zu kompilieren (dies ist
so, weil "yywrap
" ein Makro ist und "%option
main
" implizit "%option noyywrap
" aktiviert):
%option main %% .|\n ECHO ; %%
Alternativ könnten Sie mit der "-lfl
"-Linker-Option am
Ende Ihrer
cc(1)-Kommandozeile
kompilieren (wie AT&T-Lex mit "-ll
"). Es wird in
diesem Fall kein "%option
" benötigt.
Einige Pakete stellen Yacc-kompatible LR-Parser- oder LALR-Parser-Generatoren in Debian bereit:
Tabelle 12.15. Liste Yacc-kompatibler LALR-Parser-Generatoren
Paket | Popcon | Größe | Beschreibung |
---|---|---|---|
bison
|
V:9, I:103 | 2815 | GNU LALR-Parser-Generator |
byacc
|
V:0, I:6 | 160 | Berkeley LALR-Parser-Generator |
btyacc
|
V:0, I:0 | 243 |
rückverfolgender Parser-Generator basierend auf byacc
|
Eine Einführung zu
bison(1)
finden Sie in "info bison
".
Sie müssen Ihre eigenen "main()
"- und
"yyerror()
"-Funktionen
bereitstellen. "main()
" ruft
"yyparse()
" auf, das wiederum
"yylex()
" aufruft, was gewöhnlich von FleX erzeugt wird.
%% %%
Autoconf ist ein Werkzeug zum Erzeugen von Shellskripten, welche Quellpakete automatisch so konfigurieren, dass sie sich unter Verwendung des vollständigen GNU-Build-Systems an viele UNIX-artige Systeme anpassen.
autoconf(1)
erzeugt das Konfigurationsskript
"configure
". "configure
" erzeugt
automatisch ein angepasstes "Makefile
" aus einer
"Makefile.in
"-Vorlage.
![]() |
Warnung |
---|---|
Überschreiben Sie keine Systemdateien, wenn Sie Ihre selbst kompilierten Programme installieren. |
Debian verändert keine Dateien unter "/usr/local/
" oder
"/opt
". Wenn Sie also ein Programm aus den Quellen
kompilieren, sollten Sie es in "/usr/local/
"
installieren, damit es nicht mit Debian kollidiert.
$ cd src $ ./configure --prefix=/usr/local $ make $ make install # hiermit werden die Dateien auf dem System installiert.
Wenn Sie noch den Original-Quellcode haben, dieser autoconf(1)/automake(1) nutzt und Sie noch wissen, wie Sie es konfiguriert haben, verfahren Sie wie folgt, um das Programm zu deinstallieren:
$ ./configure "alle-optionen-die-sie-damals-angegeben-haben" # make uninstall
Wenn Sie sich absolut sicher sind, dass der Installationsprozess Dateien nur
unter "/usr/local/
" abgelegt hat und und es nichts
Wichtiges mehr dort gibt, können Sie alternativ auch alles löschen, wie
hier:
# find /usr/local -type f -print0 | xargs -0 rm -f
Falls Sie nicht sicher sind, wo die Dateien installiert sind, sollten Sie
einen Blick auf
checkinstall(8)
aus dem checkinstall
-Paket werfen, das einen leeren Pfad
für die Deinstallation liefert. Es unterstützt jetzt auch die Erzeugung
eines Debian-Pakets mit der Option "-D
".
Obwohl man jedes AWK-Skript mittels a2p(1) automatisiert nach Perl umschreiben kann, werden einzeilige AWK-Skripte am besten per Hand nach Perl konvertiert.
Denken wir an folgende AWK-Skriptzeile:
awk '($2=="1957") { print $3 }' |
Sie ist äquivalent zu jeder der folgenden Zeilen:
perl -ne '@f=split; if ($f[1] eq "1957") { print "$f[2]\n"}' |
perl -ne 'if ((@f=split)[1] eq "1957") { print "$f[2]\n"}' |
perl -ne '@f=split; print $f[2] if ( $f[1]==1957 )' |
perl -lane 'print $F[2] if $F[1] eq "1957"' |
perl -lane 'print$F[2]if$F[1]eq+1957' |
Das letzte ist eine Knobelaufgabe. Es nutzt die Vorteile folgender Perl-Funktionalitäten:
Der Whitespace ist optional.
Es existiert eine automatische Konvertierung von Zahlen zu Zeichenketten.
Details zu den Befehlszeilenoptionen finden Sie in perlrun(1). Haben Sie Bedarf an noch verrückteren Perl-Skripten, könnte Perl Golf interessant sein.
Einfache interaktive dynamische Webseiten können wie folgt erstellt werden:
Abfragen werden mittels HTML-Formularen dem Browser-Nutzer präsentiert.
Das Ausfüllen und Anklicken von Formulareinträgen sendet einen URL-String mit kodierten Parametern vom Browser zum Webserver:
"http://www.foo.dom/cgi-bin/program.pl?WERT1=WERT1&WERT2=WERT2&WERT3=WERT3
"
"http://www.foo.dom/cgi-bin/program.py?VAR1=WERT1&VAR2=WERT2&VAR3=WERT3
"
"http://www.foo.dom/program.php?VAR1=WERT1&VAR2=WERT2&VAR3=WERT3
"
"%nn
" in einer URL wird durch ein Zeichen mit
hexadezimalem nn
-Wert ersetzt.
Die Umgebungsvariable wird gesetzt als: "ABFRAGE_STRING="VAR1=WERT1
VAR2=WERT2 VAR3=WERT3"
".
Ein CGI-Programm (irgendeines von
"program.*
") auf dem Webserver führt sich selbst mit der
Umgebungsvariable "$ABFRAGE_STRING
" aus.
Die Standardausgabe (stdout
) eines CGI-Programms wird zum
Webbrowser gesandt und dort als interaktive dynamische Webseite angezeigt.
Aus Sicherheitsgründen wird empfohlen, keinen eigenen zusammengebastelten Code zum Parsen von CGI-Parametern zu verwenden. Es gibt dafür etablierte Module in Perl und Python. PHP unterstützt diese Funktionalitäten. Wenn eine Speicherung der Daten auf dem Client nötig ist, werden HTTP-Cookies verwendet. Ist eine Verarbeitung der Daten auf dem Client erforderlich, wird häufig Javascript genutzt.
Für weitere Informationen wird auf das Common Gateway Interface, die Apache Software Foundation und JavaScript verwiesen.
Die Suche nach "CGI tutorial" auf Google durch Eingabe der kodierten URL http://www.google.com/search?hl=en&ie=UTF-8&q=CGI+tutorial direkt in der Adresszeile des Browsers ist eine gute Möglichkeit, das CGI-Skript auf dem Google-Server in Aktion zu beobachten.
Es gibt verschiedene Programme zur Übersetzung von Quellcode:
Tabelle 12.16. Liste von Programmen zur Übersetzung von Quellcode
Paket | Popcon | Größe | Schlüsselwort | Beschreibung |
---|---|---|---|---|
perl
|
V:610, I:992 | 705 | AWK → PERL | Quellcode von AWK nach PERL konvertieren: a2p(1) |
f2c
|
V:0, I:6 | 442 | FORTRAN → C | Quellcode von FORTRAN 77 nach C/C++ konvertieren: f2c(1) |
intel2gas
|
V:0, I:0 | 178 | intel → gas | Konvertierer von NASM (Intel-Format) nach GNU Assembler (GAS) |
Wenn Sie ein Debian-Paket erstellen möchten, lesen Sie folgendes:
Kapitel 2, Debian-Paketmanagement, um die Grundlagen des Paketsystems zu verstehen;
Abschnitt 2.7.13, „Ein Paket auf das Stable-System portieren“, um den grundlegenden Portierungsprozess zu verstehen;
Abschnitt 9.10.4, „Chroot-System“, um die grundlegenden chroot-Techniken zu verstehen;
debuild(1), pbuilder(1) und pdebuild(1);
Abschnitt 12.4.2, „Fehlersuche in einem Debian-Paket (Debugging)“ für Informationen zum Rekompilieren von Quellcode zwecks Fehlersuche (Debugging);
Debian-Leitfaden für neue
Paketbetreuer als Einführung (aus dem
maint-guide
-Paket);
Debian-Entwicklerreferenz
(aus dem developers-reference
-Paket);
Debian Policy-Handbuch (aus dem
debian-policy
-Paket);
Handbuch für
Debian-Paketbetreuer (aus dem debmake-doc
-Paket).
Es gibt auch Pakete wie debmake
,
dh-make
, dh-make-perl
usw., die beim
Paketieren helfen.