% Filename:      tpp.tex
% Purpose:       template file for tpp latex export
% Authors:       (c) Andreas Gredler, Michael Prokop http://grml.org/
% License:       This file is licensed under the GPL v2.
% Latest change: Fre Apr 15 20:34:37 CEST 2005
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\documentclass{beamer}

\mode<presentation>
{
  \usetheme{Montpellier}
  \setbeamercovered{transparent}
}

\usepackage[german]{babel}
\usepackage{umlaut}
\usepackage[latin1]{inputenc}
\usepackage{times}
\usepackage[T1]{fontenc}

\begin{document}
\begin{frame}[fragile]
\begin{verbatim}

\author{Tim Weber <scy-talk-bash@scytale.name>}
\title[Bash für CTFler]{Bash für CTFler}
\date{2008 Nov 12}
\begin{frame}
        \titlepage
      \end{frame}


\end{verbatim}
\end{frame}
\section{Die Unix-Philosophie}
\begin{frame}[fragile]
\begin{verbatim}

Schreibe Computerprogramme so, dass sie nur eine
Aufgabe erledigen und diese gut machen.

Schreibe Programme so, dass sie zusammen arbeiten.

Schreibe Programme so, dass sie Textdateien
verarbeiten, denn dies ist eine universelle
Schnittstelle.

\end{verbatim}
\end{frame}
\section{Was ist die bash?}
\begin{frame}[fragile]
\begin{verbatim}

"Bourne-again shell", Anspielung darauf, dass sie
eine Weiterentwicklung der Bourne-Shell ist.
Entwickelt Ende der 80er.

Viele Alternativen (zsh, csh, ksh, ash, ...).

Gemeinsamer Standard (POSIX), Shellscripte
_sollten_ portierbar sein. (Sind sie aber selten.)

Eigentlich nur Benutzerinterface sowie "Mittler"
zwischen einzelnen Befehlen, die manchmal zwar
direkt in die Shell eingebaut sind (z.B. echo),
aber meist zu anderen Paketen (z.B. coreutils).

\end{verbatim}
\end{frame}
\section{Befehlssyntax}
\begin{frame}[fragile]
\begin{verbatim}

$ variable=wert    # Wichtig: ohne Leerzeichen
$ echo $variable
wert
$ echo "$variable mit double quotes" '$variable
mit single quotes'
wert mit double quotes $variable mit single quotes
$ echo 'Jetzt kommt ein Verzeichnislisting:'; ls
Jetzt kommt ein Verzeichnislisting:
a.txt   b.txt

\end{verbatim}
\end{frame}
\section{Ein- und Ausgabe}
\begin{frame}[fragile]
\begin{verbatim}

Unter Unix ist bekanntlich alles eine Datei. Will
ein Programm mit einer Datei arbeiten, bekommt es
vom Betriebssystem einen Handle auf diese Datei
zurück (beliebige Zahl, also eine "Zugriffs-ID").

Vordefinierte Handles: 0 (Standardeingabe), 1
(Standardausgabe), 2 (Standardfehlerausgabe).

Diese werden vom Betriebssystem oder der Shell
bereits mit den korrekten "Dateien" verbunden,
z.B. der Tastatur, dem Bildschirm, einer echten
Datei oder einer Pipe ("Röhre"), die zu einem
anderen Programm führt.

\end{verbatim}
\end{frame}
\section{Der Befehl cat (concatenate)}
\begin{frame}[fragile]
\begin{verbatim}

$ cat a.txt
Das hier ist Text.
$ cat b.txt
Hier steht auch Text drin.
$ cat b.txt a.txt
Hier steht auch Text drin.
Das hier ist Text.

\end{verbatim}
\end{frame}
\section{Der Befehl echo}
\begin{frame}[fragile]
\begin{verbatim}

Gibt den angegebenen Text aus.

Der Unterschied zu cat liegt darin, dass die
Parameter nicht Dateinamen, sondern direkt den
Text angeben.

$ echo Hallo.
Hallo.
$ cat Hallo.
cat: Hallo.: No such file or directory.

\end{verbatim}
\end{frame}
\section{Der Befehl head}
\begin{frame}[fragile]
\begin{verbatim}

Zeigt nur die ersten X Zeilen einer Datei an
(Standard: 10).

Alternative auch: die ersten X Byte, oder "alle
bis auf die letzten X Zeilen/Byte".

$ head -n 2 erlkoenig.txt
Wer reitet so spät durch Nacht und Wind?
Es ist der Vater mit seinem Kind.
$ head -c 7 erlkoenig.txt
Wer rei
$ head -n -3 allemeineentchen.txt
Alle meine Entchen
Schwimmen auf dem See

\end{verbatim}
\end{frame}
\section{Der Befehl tail}
\begin{frame}[fragile]
\begin{verbatim}

Zeigt nur die letzten X Zeilen oder Byte an, bzw.
"alle bis auf die ersten X Zeilen/Byte".

$ tail -n 1 erlkoenig.txt
In seinem Arm das Kind war tot.
$ tail -c 5 erlkoenig.txt
tot.
$ tail -n -4 allemeineentchen.txt
Schwänzchen in die Höh'.

\end{verbatim}
\end{frame}
\section{Der Befehl wc (word count)}
\begin{frame}[fragile]
\begin{verbatim}

$ cat a.txt
Das hier ist Text.
$ wc a.txt
 1  4 19 a.txt
$ wc -l a.txt
1 a.txt

\end{verbatim}
\end{frame}
\section{Umleiten in eine Datei}
\begin{frame}[fragile]
\begin{verbatim}

 > 

Leitet die Ausgabe in eine Datei, die neu angelegt
wird. Falls sie bereits existiert, wird sie
überschrieben.

Hier gilt der Grundsatz: "Unix wurde nicht
entwickelt, um seine Benutzer daran zu hindern,
dumme Dinge zu tun, denn das würde diese auch
davon abhalten, schlaue Dinge zu tun." (Doug Gwyn)

$ cat a.txt > b.txt
$ cat b.txt
Das hier ist Text.

\end{verbatim}
\end{frame}
\section{Anhängen an eine Datei}
\begin{frame}[fragile]
\begin{verbatim}

 >> 

Leitet die Ausgabe in eine Datei und hängt dabei
an den bestehenden Inhalt an. Falls die Datei noch
nicht existiert, wird sie angelegt.

$ cat a.txt >> b.txt
$ cat b.txt
Das hier ist Text.
Das hier ist Text.

\end{verbatim}
\end{frame}
\section{A Series of Tubes}
\begin{frame}[fragile]
\begin{verbatim}

 | 

Verbindet die Standardausgabe des linken Befehls
mit der Standardeingabe des rechten Befehls. Auf
Deutsch: Leitet die Ausgabe des ersten Befehls an
den zweiten.

$ echo Hier kommt Kurt. > kurt.txt
$ cat kurt.txt b.txt | wc -l
3
Merke: Wenn gar keine Dateien als Parameter
angegeben werden, lesen die meisten Befehle von
der Standardeingabe.

\end{verbatim}
\end{frame}
\section{Standardeingabe von der Tastatur}
\begin{frame}[fragile]
\begin{verbatim}

Falls die Standardeingabe für einen Befehl nicht
aus einer Pipe kommt, liest er eben von der
Tastatur (die ja die "Default-Standardeingabe"
ist), und zwar so lange, bis man über die
Tastenkombination Strg+D (abgekürzt ^D) sagt, dass
der Eingabestrom beendet ist. (Wenn dein Script
irgendwie "hängt", ist ein vergessener
Eingabedateiname oft der Grund.)

$ wc -l
Ich muss durch den Monsun
Hinter die Welt
Ans Ende der Zeit
^D
3

\end{verbatim}
\end{frame}
\section{Standardeingabe ändern}
\begin{frame}[fragile]
\begin{verbatim}

Eingabe aus einer Datei (<), direkt bis zum Nennen
eines Stoppwortes (<<, praktisch in Scripts) oder
wie bei einer echo-Pipe (<<<).

$ wc -w < kurt.txt
3
$ wc -l <<PUDEL
Wieso, weshalb, warum?
Wer nicht fragt bleibt dumm.
PUDEL
2
$ wc -m <<< 'Du Homofuerst.'
15

\end{verbatim}
\end{frame}
\section{Einzelne Felder ausgeben mit cut}
\begin{frame}[fragile]
\begin{verbatim}

Splittet eine Eingabedatei zeilenweise in mehrere
Felder auf, die durch den Delimiter (Parameter
"-d") getrennt sind.

$ head -n 1 /etc/passwd
root:x:0:0:root:/root:/bin/zsh
$ head -n 1 /etc/passwd | cut -d : -f 1,7
root:/bin/zsh
$ head -n 2 /etc/passwd | cut -c 2-4
oot
ash

\end{verbatim}
\end{frame}
\section{Daten sortieren mit sort}
\begin{frame}[fragile]
\begin{verbatim}

Sortiert die Eingabedaten auf recht flexible Weise
(siehe --help). Standard: Alphabetisch.

Alphabetische Benutzerliste:
$ cut -d : -f 1 /etc/passwd | sort | head -n 3
ajaxterm
arpwatch
avahi
$ sort -t : -n -r -k 3 /etc/passwd | head -n 2
nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
grml:x:1000:1000::/home/grml:/bin/zsh

\end{verbatim}
\end{frame}
\section{Dubletten entfernen mit uniq}
\begin{frame}[fragile]
\begin{verbatim}

Entfernt doppelt vorkommende Zeilen in der
Eingabe, die allerdings bereits vorsortiert sein
muss. Hat außerdem noch ein paar lustige
Bonusfunktionen, wie immer siehe --help.

Alle auf dem System von irgendeinem Benutzer
verwendeten Shells:
$ cut -d : -f 7 | sort | uniq
/bin/bash
/bin/false
/bin/sh
/bin/sync
/bin/zsh
/dev/null
/usr/sbin/nologin

\end{verbatim}
\end{frame}
\section{Schleifen mit for}
\begin{frame}[fragile]
\begin{verbatim}

for ZAEHLER in WERT1 WERT2 WERT3 WERTn; do
   BEFEHLE
done

$ for x in a b c; do echo "$x" > "${x}.txt"; cat
"${x}.txt"; done
a
b
c
$ for x in ?.txt; do mv "$x" "${x}.aha"; done; ls
a.txt.aha   b.txt.aha   c.txt.aha

\end{verbatim}
\end{frame}
\section{Zählende for-Schleifen}
\begin{frame}[fragile]
\begin{verbatim}

$ # Maximale Kompatibilität, minimale
Geschwindigkeit:
$ # "seq" aus den coreutils
$ seq 1 10
1 2 3 4 5 6 7 8 9 10
$ for i in $(seq 1 10); do echo -n .; done; echo
..........
$ # Ab bash 3:
$ for i in {1..10}; do echo -n .; done; echo
..........
$ # Womöglich auch bash-only, kA...
$ for (( i=1; i<10; i++ )); do echo -n .; done;
echo
..........

\end{verbatim}
\end{frame}
\section{Verzweigung mit if}
\begin{frame}[fragile]
\begin{verbatim}

if BEFEHL; then
   BEFEHLE
elif BEFEHL; then
   BEFEHLE
else
   BEFEHLE
fi

$ if mkdir verzeichnis; then echo Erstellt; else
echo PANIK; fi
Erstellt.

\end{verbatim}
\end{frame}
\section{Verwendung von Ausgaben mit $()}
\begin{frame}[fragile]
\begin{verbatim}

$ date +%F
2008-11-12
$ echo Heute ist Workshop. > "$(date +%F).txt"
$ ls
2008-11-12.txt
$ cat 2008-11-12.txt
Heute ist Workshop.
`Backticks` sind äquivalent, aber nicht
schachtelbar und schwerer zu lesen, daher wird $()
dringend empfohlen.

\end{verbatim}
\end{frame}
\section{Rechnen und so mit expr}
\begin{frame}[fragile]
\begin{verbatim}

$ expr 9 - 12
-3
$ expr length foobar
6
$ expr index foobar b
4
Die einzelnen Operanden einer Rechenanweisung
müssen als einzelne Parameter übergeben werden
(also mit Leerzeichen abgetrennt). Von der Shell
ausgewertete Zeichen wie * (Multiplikation) müssen
natürlich mit \ oder Singlequotes escaped werden.

expr arbeitet nur mit ganzen Zahlen. Für
komplexere Berechnungen hilft bc, aber auch bash
kann in begrenztem Maße rechnen: $(()).

\end{verbatim}
\end{frame}
\section{HTTP-Zugriffe mit wget und curl}
\begin{frame}[fragile]
\begin{verbatim}

wget ist auf den meisten Systemen verfügbar,
während curl praktische Funktionen zum Senden von
Daten und Simulieren von Formularaktivitäten
besitzt, daher sollte man zumindest mit beiden
Tools ansatzweise umgehen können.

$ # Äquivalente Nutzung von wget und curl (Ausgabe
auf stdout):
$ wget -q -O -
http://scytale.name/files/scytale.opml | head -n 1
<opml version="2.0">
$ curl -s
https://scytale.name/files/2007/11/eurosignal.py |
wc
    154     563    4717

Merke: "-" ist bei vielen Tools eine Abkürzung für
die Standardausgabe. Alternativ kann man meist
auch "/dev/stdout" verwenden.

\end{verbatim}
\end{frame}
\section{Zeichen ersetzen mit tr (translate)}
\begin{frame}[fragile]
\begin{verbatim}

$ echo foo | tr o e
fee
$ echo 'Drei Chinesen mit nem Kontrabass' | tr
aeiou i
Drii Chinisin mit nim Kintribiss
$ # Kombination von "Löschen" und "Komplement":
$ echo 0621 / 181-2342 | tr -cd 0-9
06211812342

\end{verbatim}
\end{frame}
\section{Filtern mit grep: Parameter}
\begin{frame}[fragile]
\begin{verbatim}

-i  case-insensitive (Groß-/Kleinschreibung
ignorieren)
-E  erweiterte reguläre Ausdrücke (auch "egrep")
-v  nur Zeilen, die _nicht_ matchen
-q  keine Ausgabe, nur Returncode ob Match oder
nicht
-o  nur matchenden Teil der Zeile ausgeben
-c  nur Anzahl matchender Zeilen ausgeben
-l  nur Namen der matchenden Dateien ausgeben
-m  nach X Matches Suche in der Datei beenden
-r  rekursives Matchen in Unterverzeichnissen
-H  Dateiname mit ausgeben (-h zum Deaktivieren)
-n  Zeilennummer mit ausgeben

\end{verbatim}
\end{frame}
\section{Filtern mit grep: Beispiele}
\begin{frame}[fragile]
\begin{verbatim}

grep arbeitet zeilenweise, Matches über mehrere
Zeilen hinweg sind also nicht möglich (aber man
kann z.B. mit "tr -d '\n'" schummeln).

$ # Flags aus einer Datei holen.
$ grep -oE '[0-9a-f]{32}' foo.txt
f16928d17c54213e06e68224b5bba68a
96a92e6d00292f85b09ca5ba0d7d9806
$ # URLs aus den Chatlogs fischen.
$ grep -Ero '[a-z0-9+-]+://[^ ]+' ~/.irssi/logs
[...]

\end{verbatim}
\end{frame}
\section{Manipulationen mit sed (stream editor)}
\begin{frame}[fragile]
\begin{verbatim}

s[uche]/Ausdruck/Ersetzung/Flags
$ echo foo dee doo | sed -e 's/oo/u/g' -e
's/ee/i/g'
fu di du
$ echo Bar Foo | sed -r -e 's/^(.+) (.+)$/\2 \1/'
Foo Bar
$ echo -e 'ab5\nxyz\no2u' | sed -rn -e
's/.*([0-9]+).*/\1/p'
5
2
Flags: g (global, mehr als ein Match pro Zeile), p
(print, Ergebnis ausgeben (in Kombination mit
-n)).
Parameter: -r (erweiterte Ausdrücke), -n (nur
Matches mit p-Flag ausgeben, nicht matchende
Zeilen nicht).

\end{verbatim}
\end{frame}
\section{Interessantes, das weg gelassen werden musste}
\begin{frame}[fragile]
\begin{verbatim}

find, tee, case, tac, der Unterschied zwischen [
und [[, Befehle gruppieren mit () und {},
Funktionen, Aliase

\end{verbatim}
\end{frame}
\section{Ach ja...}
\begin{frame}[fragile]
\begin{verbatim}

Man machte mich nach dem Vortrag darauf
aufmerksam, dass es praktisch wäre, die Leute
darauf hinzuweisen, dass man Bash-Befehle auch in
einer Datei niederschreiben kann, um sie dann alle
auf einmal auszuführen; sowas nennt sich dann ein
"Script".

Ich hielt das für trivial genug, um es nicht zu
erwähnen, aber ja, das kann man. Präferierte
Dateinamenserweiterung ist .sh, man kann das
Script mit "chmod u+x dateiname.sh" ausführbar
machen, wenn als erste Zeile folgendes in der
Datei steht:

#!/bin/bash
\end{verbatim}
\end{frame}
\end{document}
    %%%%% END OF FILE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

