Was machen wir heute?


1) 	Einleitung - Grundlagen

	- Was ist eine Shell?
	- Batch-Verarbeitung vs. Ablaufsteuerung
	- Variablen
		- freie 
		- reservierte (builtin)
		- Environment

2) 	Kontrollstrukturen + Funktionen
	
	- Grundlagen
	- if 
	- case
	- while/until ... break/continue
	- for

3)	File Descriptors - Streams

	- Grundlagen
	- STDIN / STDOUT /STDERR
	- Redirection
	- Pipe

4)	Tools - The Power of Unix

	- builtin: echo, ls, export, trap ...
	- externe Programme: 	cat, grep, awk, sed, sort, expr
				logger, mail, tr, cut ...

5)	Ressourcen


Grundlagen: Was ist eine Shell?

- 	Shell ist ein Interpreter, der Kommandos entsprechend
	seiner eigenen Syntax interaktiv oder selbstndig ausfhrt.

- 	Shell ist eine Umgebung ("Muschel"), in der Programme ablaufen.
	Jede Shell hat ihren eigenen Satz Variablen, File-Descriptoren usw.

-	Shell ist die Schnittstelle zwischen Benutzer und Betriebssystem.

-	Es gibt viele verschiedene Shells, von denen jede ihre eigene
	Syntax hat. Einige Beispiele:

	- sh:	Bourne Shell  	Die Mutter aller Shells
	- csh:	C-Shell 	Shell mit C-hnlicher Syntax
	- ksh:	Korn Shell 	Mchtige, C-orientierte Shell. Solaris!
	- tcsh: Ext. C-Shell 	Erweiterte, komfortable C-Shell
	- bash:	Bourne Again SH Erweiterte, komfortable Bourne Shell

-	Eine Shell ist immer ein guter Anlass fr einen Glaubenskrieg!

-	Und MERKE: Ein Shell-Script muss immer ausfhrbar sein!

	# chmod a+x <scriptname>


Grundlagen: Batch-Verarbeitung vs. Ablaufsteuerung

BATCH

-	Batch(Stapel)-Programme fhren einfach eine Reihe von Programmen
	in fester, unvernderbarer Reihenfolge aus. 
	
	# command1
	# command2
	# command3
	usw.

-	Es erfolgt keine Steuerung des Ablaufes.

-	Es werden einfachste Interpreter verwendet (command.com),
	im einfachsten Fall reicht ein Loader.	

ABLAUF

-	Es wird immer noch eine Reihe von Programmen ausgefhrt.

-	Der Ablauf ist aber von einer Reihe von Ereignissen abhngig,
	und nicht jedes Programm kommt notwendigerweise zur
	Ausfhrung.

	# if (command1 was successful)
	# then run command2
	# else run command3

-	Es knnen Benutzer-Interaktionen ausgewertet werden.

-	Es kommen komplexe Interpreter zum Einsatz.

Shell-Scripts knnen sowohl als Batch- wie auch als ablaufgesteuerte
Programme vorkommen.


Grundlagen: VARIABLEN

-	Variablen sind Platzhalter fr Werte.

	Man kann ihnen also Werte zuweisen, und diese spter wieder abfragen.
	Dazu wird unterschieden:
	VAR:    Name der Variablen
	$VAR:   Wert der Variablen

	# VAR1=1
	# VAR2=2
	# /wir/tun/irgendwas/anderes
	# echo \$VAR1: $VAR1 '$VAR2:' $VAR2
	$VAR1: 1 $VAR2: 2
	
	Der Wert kann aber auch aus einem andern Programm kommen:
	(Hier z.B. 'echo')
	# VAR3=`echo ${VAR1}${VAR2}`
	# echo \$VAR3: $VAR3
	$VAR3: 12

	(Hier z.B. 'hostname')
	# HOSTNAME=`hostname`
	# echo $HOSTNAME
	purely


	Der Shell muss mitgeteilt werden, dass sie zuerst den Teil rechts vom "=" ausfhren soll.
	Dies geschieht mit "Backquotes": `command`.

	# HOSTNAME=hostname
	# echo $HOSTNAME
	hostname

-	Variablen haben einen Typ.

	Shell-Variablen sind grundstzlich vom Typ "String".

	# VAR1=1
	# VAR2=$VAR1+1
	# echo \$VAR1: $VAR1 '$VAR2:' $VAR2
	$VAR1: 1 $VAR2: 1+1
	#


	Mathematische Operationen mssen von speziellen Programmen bernommen werden:
	(Achtung Backquotes!)

	# VAR1=1
	# VAR2=`expr $VAR1 + 1`
	# echo \$VAR1: $VAR1 '$VAR2:' $VAR2
	$VAR1: 1 $VAR2: 2
	#


-	Variablen-Namen sind grundstzlich frei (mit ein paar Ausnahmen)

	# MEINE_VIEL_ZU_LANGE_UND_UNUEBERSICHTLICHE_VARIABLE=1
	# A="Endlich eine kurze Variable"	

-	Quotes: Die Shell interpretiert verschiedene Quote-Zeichen anders:

	# VAR1="Variable"
	# echo "$VAR1" '$VAR1' `$VAR1`
	bash: Variable: command not found
	Variable $VAR1


-	Reservierte Variablen (Shell-abhngig)

	$0 - Name des laufenden Programms
	$1 - 1. Argument (argv[1])
	$2 - 2. Argument (argv[2])
	... $n
	$$ - Prozessnummer (PID) des laufenden Programms
	$@ - Alle bergebenen Argumente (Command Line)
	$* -          -"-
	$# - Anzahl der Argumente
	$? - Exit-Status (Rckgabewert) des zuletzt ausgefhrten
	     Kommandos
	
-	Ein erstes Beispiel-Script: Ausgabe reservierter Variablen

	
	#!/bin/bash		<-- Sagt dem Betriebssystem, was es mit dem File machen soll

	# builtin.sh		<-- Kommentar
	
	# display some builtin variables
	echo
	echo "\$0: $0"
	echo "\$1: $1"
	echo "\$2: $2"
	echo "\$@: $@"
	echo "\$*: $*"
	echo "\$#: $#"
	echo
	echo "shift"
	shift
	echo "\$1: $1"
	echo "\$2: $2"
	echo "\$@: $@"
	echo "\$*: $*"
	echo "\$#: $#"
	echo "\$$: $$"
	echo
	echo "\$?: $?"
	bla
	echo "\$?: $?"
	echo

-	Das Betriebssystem (oder eine andere aufrufende Instanz, z.B. Webserver) stellt
	spezielle Variablen zur Verfgung, auf die immer zugegriffen werden kann:
	die Umgebungsvariablen (Environment)

	z.B.:	

	$HOME	 /home/lugbe

	$PATH	 /home/lugbe/bin:/usr/local/bin:/usr/bin:/usr/X11R6/bin:/bin:/usr/lib/java/bin:
		 /usr/games/bin:/usr/games:/opt/gnome/bin:/opt/kde2/bin:/opt/kde/bin:/opt/office52/program:
	
	$SHELL 	 /bin/bash
	$DISPLAY :0
	$USER: 	 lugbe

	Das Kommando "env" gibt alle gerade vorhandenen Environment-Variablen aus.

	Das Kommando "export" fgt eine Variable dem Environment hinzu.

		# export MYVAR="meine Variable ist sehr schn!"


-	Das Kommando "eval" (bei Zuweisungen) wertet zuerst den Teil links vom "=" aus,
	und fhrt dann das ganze Kommando noch einmal aus.

		# var=VAR
		# eval $var=12
		# echo '$VAR': $VAR
		$VAR: 12

		Script: eval.sh


Kontrollstrukturen: GRUNDLAGEN

-	Kontrollstrukturen steuern wie gesagt den Ablauf eines Programms.

	Sie kommen in jeder Programmiersprache vor und machen den eigentlichen
	Kern der meisten Algorithmen aus.

	Sie prfen eine Bedingung und fhren aufgrund des Ergebnisses
	eine Aktion aus.

	Die wichtigsten Arten sind die "konditionalen" und "iterativen"
	Kontrollstrukturen.


	Beispiele:
	
	- konditional:
	# if
	# case

	- iterativ:
	# while
	# for

	
	Scripts:

	if.sh
	case.sh
	while.sh
	for.sh


Kontrollstrukturen: Funktionen

-	Funktionen sind Code-Blcke, die einmal geschrieben, aber beliebig oft ausgefhrt
	werden. Sie mssen der Shell explizit als solche bekannt gemacht werden.

-	Funktionen knnen Parameter bergeben werden - genau wie unabhngigen Shell-Scripts.

	#! /bin/bash

	### function code
	myadd() {
		tmp=0
		args=$@

		for i in $args
		do
			tmp=`expr $tmp + $i`
		done
		
		return $tmp
	}

	### main code
	myadd 1 2 3 $VAR
	RES=$?

	myadd $RES 5 6 $VAR2
	RES=$?

	usw()
	

FILEDESCRIPTORS: I/O

-	Jedes von einem Programm geffnete Objekt (Datei, Stream, Socket usw.) bekommt
	vom Betriebssystem eine eindeutige Nummer ("Handle").
	Drei spezielle Handles sind genormt:

	- Standard Input: 	 STDIN 	(0)
	- Standard Output:	 STDOUT	(1)
	- Standard Error Output: STDERR (2)

	Bei interaktiv ablaufenden Programmen entspricht STDIN der Tastatur, STDOUT und 
	STDERR dem Bildschirm (Terminal, tty).

	Bei nicht-interaktiven Programmen (d.h. kein tty), wird STDIN geffnet, ohne an
	ein bestimmtes Terminal gebunden zu sein. Jedes andere Programm kann jetzt auf
	STDIN schreiben.
	So ist es mglich, einem Programm beliebigen Input zu liefern.

	Die hufigsten Anwendungen fr diese Funktion sind

	- Pipes
	- Redirects


FILEDESCRIPTORS: Pipes

-	Pipes ("Pfeifen") sind Verbindungsstcke zwischen zwei Programmen. Die Programme
	tauschen ber sie Daten aus. Pipes werden vom Betriebssystem zur Verfgung gestellt
	als Mechanismus der Kommunikation zwischen Prozessen (Inter-process communication IPC).

	# PIPE	|

	# VAR="Hello World"
	# echo $VAR | sed -e s/"World"/"LugBE"/g
	Hello LugBE
	#

	Was luft hier genau ab?

	- Das Programm "echo" gibt "Hello World" auf seinen STDOUT aus.
	- Dort wartet aber gemeinerweise eine Pipe, die den Output entgegennimmt und
	  an den STDIN des Programmes "sed" weiterleitet.
	- "sed" nimmt die Daten entgegen und verarbeitet sie entsprechend unseren
	  Angaben -e s/"World"/"LugBE"/g (d.h. ersetze alle Vorkommen von 'World' durch
	  'LugBE')
	- Das Ergebnis schickt "sed" an seinen STDOUT weiter.


-	Dieser Mechanismus kann beliebig oft hintereinander angewendet werden ... und
	das wird er auch.

	# cat input.txt \
	  | sort -r +1  \
	  | tr -d ":" 	\
	  | awk '{print $4": " $3 " " $2 " " $1}' \
	  | tr [:upper:] [:lower:] 		  \
	  | cat -	


FILEDESCRIPTORS: Redirection

-	STDIN, STDOUT und STDERR knnen aber auch beliebig umgelenkt werden.
	Dies geschieht mittel Redirections:

	# STDOUT  >
	# STDIN   <

	z.B.

	# echo "Hello LugBE" > hello.txt		<-- STDOUT umlenken
	# sed -e s/"LugBE"/"World"/g < hello.txt	<-- STDIN umlenken
		(identisch mit cat hello.txt | sed -e s/"LugBE"/"World"/g)
	# cat hallo.ttx 2> /dev/null			<-- STDERR umlenken


	Es geht aber auch noch:

	# ping -c5 some.host.ch 2> ping-error.txt 1> ping-success.txt
	
	STDERR (Fehlermeldungen) geht nach ping-error.txt, normaler Programm-
	Output (STDOUT) nach ping-success.txt. Was dabei auf welchen Handle
	geschickt wird, entscheidet das Programm selbst (hier ping).

        
	# ping -c5 some.host.ch > ping-kombi.txt 2>&1

	Das letzte Beispiel leitet STDERR an die Adresse von STDOUT ("&1")
	um, das wiederum in die Datei ping-kombi.txt umgeleitet wird.
	Am hufigsten sieht man:

	# /irgendein/kommando > /dev/null 2>&1		<-- who cares for errors?
	

TOOLS: Uebersicht

-	"The Power of Unix" basiert auf einer Unzahl kleiner Helfer und
	Programme/Kommandos, die frei kombiniert werden knnen, um ein
	bestimmtes Problem zu lsen.
	Den Anwendungsgebieten sind dabei keine Grenzen gesetzt.


	Einige der hufigsten Tools haben wir bereits kennengelernt:

	- echo		gibt einen String auf STDOUT aus
	- cat		gibt eine Datei auf STDOUT aus
	- expr		fhrt mathematische Operationen aus
	- sed		verarbeitet Input-Streams nach dynamischen Regeln
	- sort		sortiert Input-Streams zeilenweise
	- test		prft eine Bedingung
	- tr		ersetzt einzelne Zeichen durch andere


	Einige andere sind z.B.

	- grep		durchsucht Input-Streams nach bestimmten Zeichen (Regular Expressions)
	- cut		zerlegt Input-Streams in Einzelteile
	- diff		zeigt Unterschiede zwischen 2 Dateien an
	- find		sucht Dateien mit bestimmten Merkmalen
	- logger	loggt eine Nachricht via Syslog
	- sleep		hlt das Programm fr eine bestimmte Zeit an
	- strings	zeigt alle druckbaren Zeichen in einerd Datei an
	- touch		"berhrt"/erzeugt eine Datei
	- uniq		filtert mehrfach vorkommende Zeilen (oft mit sort)
	- wc		zhlt Zeichen, Worte, Zeilen im Input
	
	- awk, perl	MegaMonsterAllesknner (TM) 


TOOLS im einzelnen

-	grep

	Durchsucht Input-Streams nach bestimmten Zeichen (Regular Expressions)

	# ifconfig | grep eth0
	# grep -i FIVE input.txt

-	cut

	Zerlegt Input-Streams in ihre Einzelteile, gibt nur bestimmte Teile aus.

	# echo "Hello LugBE" | cut -d "g" -f2
	# PID=`ps ax | grep -v "grep" | grep inetd | tr -s " " | cut -d " " -f2

- 	diff

	Zeigt Unterschiede zwischen 2 Dateien an

	# if diff file1 file2 >/dev/null 2>&1; then
	#	echo "Dateien sind unterschiedlich"
	#	shutdown -h now
	# fi

-	find

	Sucht Dateien nach bestimmten Kriterien

	# find /home/lugbe -type f -name einleitung\* -exec touch {} \;

-	logger

	Loggt eine Nachricht via Syslog

	# logger -p warn -t "manual logging" "Wie sag ich's bloss dem Sysadmin?"

-	sleep

	Hlt das laufende Programm fr eine bestimmte Zeit an

	# CNT=1
	# while [ $CNT -le 5 ]
	# do
	#	echo -n "$CNT "
	#	CNT=`expr $CNT + 1"
	#	sleep 1
	# done

- 	touch

	"Berhrt" eine Datei - d.h. setzt ihre Access Time und Modified Time -
	oder erzeugt sie.

	# LOCKFILE=/var/run/myprog.lck
	# [ -f $LOCKFILE ] && exit 1
	# touch $LOCKFILE

-	sort

	Sortiert Input-Streams zeilenweise lexikalisch oder numerisch

	# tail -20 /var/log/messages | sort -r -g -k1,2

-	uniq

	Fasst identische Zeilen in Input-Streams zu einer zusammen.
	
	# cat file1 file2 file3 | sort | uniq


RESSOURCEN

-	Es gibt unendlich viele Bcher zum Thema Shell-Scripting.
	Ich empfehle Grundlegendes:

	- UNIX Power Tools 
	  Jerry D. Peek, Tim O'Reilly, Mike Loukides
	  O'Reilly

	- Linux in a Nutshell
	  Ellen Siever, Stephen Spainhour, Stephen Figgins, Jessica Hekman
	  O'Reilly


	Diese beiden enthalten Kapitel zu den wichtigsten Tools/Kommandos/Scriptsprachen.


-	Dein bester Freund: die Manpage (RTFM)

	# man bash
	# man <command>


-	Dein zweitbester Freund: dein bester Freund

	Finde jemanden, von dem du glaubst, er kennt sich aus (besser noch: der das selber
	von sich meint). Ziehe am besten bei ihm ein.


- 	Die Welt ist voll von Gurus. Man muss sie nur finden. 
	z.B. lugbe@lugbe.ch, linux@lugs.ch 


HAPPY SCRIPTING

-	Na dann noch viel Spass beim Hacken.

	Happy trails.
