Umlenkungszeichen *
> Ausgabeumlenkung auf etwas, z.B. Datei *
Pipes *
Kommandoverkettung *
»geshiftete Hochkommas« *
Bedingte Kommandoausführung *
Entwertung von Metazeichen (maskieren) *
Tee *
Prozesse *
Variablen *
Gültigkeit von Variablen *
Reale und effektive User- und Group- Rechte *
setzen von SUID und Stickybit: 4. Stelle bei Rechten vergeben. *
Shellscripte (Kommandoprozeduren) *
Shellscriptnamen *
Ausführung von Shellscripten *
Positionsparameter *
Positionsparameter mit SET setzen *
SHIFT Kommando *
flusr (first last user) *
FOR- Schleife *
anmeld *
NEWUSER *
Test- Kommando *
IF- Anweisung *
newdir *
susr *
Geschachtelte if if *
if mit Mehrfachverzweigung *
testdf *
Die Mehrfachauswahl mir case *
zahlcase [ZIFFER] *
expr *
Readbefehl *
alusr *
alusr Musterlösung: *
While Schleife *
minmax *
minmax Musterlösung: *
Until Schleife *
Endlosschleifen *
break Kommando *
continue Kommando *
usrda & *
listsize *
sleep Befehl *
Metazeichen sind Sonderzeichen die für die Shell eine besondere Bedeutung haben. Zu diesen zählen z.B. Wildcards * ? [] [! ]
Umlenkungszeichen (pipes)
Wildcards werden für Dateinamensubstitution benutzt.
z.B. unter unix Verz anlegen: wilddir
Dateien anlegen: dat1, dat2, batx, caty, datei1. Datei2, .datei, data, dat, dot
* ersetzt eine beliebige Folge von Zeichen, auch kein Zeichen, aber nicht den »Punkt«
z.B.: ls d* alle Dateien, die mit d anfangen
ls * alle außer ».Datei«
? steht stellvertretend für ein beliebiges Zeichen, aber nicht für den »Punkt«
z.B.: ls ?at ein Zeichen gefolgt von at
ls d?t dat, dot
ls ??? 3 beliebige Zeichen, sonst nix
ls ?at? 4 Stellen, in mitte at
[ ] In Eckige Klammern werden Zeichen eingetragen. Anschließend werden die Dateinamen geliefert, die anstelle der Eckigen Klammer eines der Zeichen aus der EK haben
z.B.: ls d[ao]t bringt: dat, dot
ls d[ao]* alle, die mit do oder da anfangen
ls [a-z][0-9]* alle, die mit kl. Buchstab., gefolgt von 1 Ziffer beginnen
ls [A-z]* alle in ASCI- Tab., zwischen A und z, gefolgt von bel.
[! ] nicht!- ALLES außer die Zeichen in der Klammer!!
z.B.: ls [!ie]t alles außer dit und det
0 - stdin (Tastatur)
1 - stdout (Bildschirm)
2 - stderr (Bildschirm)
Es gibt 3 Zeichen: > >> <
z.B.: ls 1> »Dateiname« - Datei wird erstellt oder überschrieben,
- Kanal 1 wird mit der Datei verbunden,
- ls wird ausgeführt,
- Ausgabe wird in Datei geschrieben
ls schreibt immer auf Kanal 1, die Umlenkung passiert immer hinterher, d.h. man nimmt keinen anderen Kanal, sondern lenkt die Ausgabe , die in Kanal 1 erfolgt, in etwas anderes um.
ls 2> »Dateiname« - Fehlermeldung wird in Datei umgelenkt
ls 1> dateiname 2> dateiname2 - beides zusammen
>> Hängt an Datei an, d.h. Datei wird nicht überschrieben
(Fehlermedungen stehen hintereinander darin) (»zweimal umlenken«
< holt Daten von woher, z.B Dateien
cprog < dateiname - erwartet Dateneingabe nicht von Tastatur, sondern aus Datei
prog < datein >> dataus 2>> daterr - nimmt Daten aus datein,
- schreibt Ausgabe in dataus, - schreibt Fehler in daterr.
Mit pipes kann man Programme verketten, d.h. einzelne Programme zu komplexen Aufgaben zusammenketten
| Kommando1 | Kommando2
ls | more
; anstatt ls, who, pwd einzeln einzugeben: --> ls;who;pwd
z.B.: who am i ; pwd > dat who am i wird ausgeführt
pwd wird ausgeführt und in dat umgelenkt
(who am i gibt es als Befehl !!!!!!!!!!!!!)
(;) (Kommando1 ; Kommando2) > datei - Ausgabe von Kommando1 wird gemacht
- Ausgabe von Kommando 2 wird gemacht
beide werden in Datei umgelenkt
Kommando1 > datei ; Kommando2 >> datei ist dasselbe!!!!
` `
soll die Ausgabe eines Befehls als Argument einem anderem Kommando übergeben werden, so muß dieses in geshiftete Hochkommas geschrieben werden.z.B.: echo pwd auf dem BS wird der Text »pwd« angezeigt
echo `pwd` pwd wird ausgeführt
Ausgabe von pwd wird auf dem BS angezeigt
echo Aktuelles Verzeichnis: `pwd` Anzeige BS: Aktuelles Verzeichnis:
»Verz«
&& kommando1 && Kommando2
wenn k1 erfolgreich dann wird k2 ausgeführt
|| kommando1 && Kommando2
wenn k1 nicht erfolgreich, dann wird k2
ausgeführt
\ " " ' '
\ setzt das nachfolgende Metazeichen außer Kraft
ls dat\* macht datei dat*
" " partielles Quoting entwertet alle Metazeichen außer $, \ und ''
z.B.: echo "*** Aktuelles Verz: `pwd` ***"
` ` vollständiges Quoting entwertet alle Metazeichen
Wird in Verbindung mit pipes verwendet
z.B.: ls -lisapd | tee "dateiname" | more
Option d: wenn Eintrag ein Verzeichnis ist, dann bringe nur den Namen, nicht den Inhalt
- schreibt in Datei und gibt's am Bildschirm seitenweise aus
Ein aktives Programm ist ein Prozeß. Jeder Prozeß besitzt mehrere Atttribute, die vom Unix- kernel benötigt werden, um den Prozessablauf zu kontrollieren. Diese Attribute gehören zum Environment des jeweiligen Prozesses.
z.B.: PID, PPID (parent), UID (reale User- id), GID ( reale Group- id), EUID, EGID u.s.w.
Damit ein Prozess entstehen kann und bis hin zu dessen Beendigung, verwendet ein Kernel u.a. folgende Systemaufrufe: fork,
wait, exec, exit (nicht verwechseln mit den unix kommandos)
Fork -veranlasst den Kernel einen neuen Prozess zu erzeugen, der eine exakte Kopie des aufrufenden Prozesses ist.
Exec -der aufrufende Prozess wird überlagert durch den neuen Prozess.
Wait -veranlasst den aufrufenden Prozess auf die Beendigung des Kindprozesses zu warten
Exit -führt zur Beendigung des aufrufenden Prozesses
z.B.: was passiert wenn auf Shellebene das Programm ls aufgerufen wird?
Shell
fork
pid =6 shell shell pid =6
wait exec ls ppid =
5
pid =5 shell lspid =6
exit exit ppid=5
1. Standartvariablen sind Variablen, die für die Shell eine feste Bedeutung haben und haben festgelegte Namen. Diesen Variablen können Werte zugewiesen werden. (werden immer großgeschrieben) Um deren Inhalt anzuzeigen, bzw. auf deren Inhalt zuzugreifen muß immer ein $ vorangeschrieben werden
$ "VARIABLENNAME"
PATH ---> $PATH z.B.: echo $PATH
HOME ---> $HOME
LOGNAME ---> etc.
2. Benutzerdefinierte sind Variablen, die sich der Benutzer selber setzt.
Variablen
- Will man Variablen einen Wert zuweisen, so muß der Variablenname eingegeben werden, gefolgt vom "=" Zeichen und dem Inhalt.
- Will man den Inhalt einer Variable einer Anderen zuweisen, so schreibt man: VAR1=$VAR2
- Soll der Variableninhalt "BLANKS" enthalten, dann muß dieser zw. " " geschrieben werden
- Soll einer Variable der Inhalt einer anderen zugewiesen und etwas neues angehängt werden, so
muß der Name der ersten Variable in { } gesetzt werden --> VAR2=${VAR1}blah
3. Automatisch gesetzte der Inhalt kann nicht verändert werden
Variablen wird automatisch bei bestimmten Aktionen verändert.
z.B.: #, * u.s.w.
Allgemein: lokal global
wird eine Variable neu definiert, so gilt diese zuerst mal nur im aktuellen Prozess. Weder
Elternprozess noch Kindprozess kann auf diese
Variable zugreifen. Soll eine Variable in allen Kindprozessen (auch
Kindeskinder) Gültigkeit haben, dann muß diese einmal Exportiert
werden, anschließend ist diese Variable keine lokale, sondern eine
globale
Variable. Man spricht hier auch von einem Vererben
von Variablen. Variablen können nie auf Elternprozesse
übertragen werden. D.h. diese Exportierung geht immer nur in
eine Richtung. Variablennamen müssen immer mit einem Buchstaben beginnen,
ansonsten gehen alle Ziffern und der Unterstrich. Postionsparameter können
nicht exportiert werden.
Variablen anzeigen set [RETURN]
Exportierte Variablen anzeigen env [RETURN]
einzige Variable anzeigen echo $[VARIABLENNAME]
USER1 UID GID
U1 G1
PROGRAMM UX GX neue datei UID GID
EUID EGID U1 G1
PROZESS U1 G1 U1 G1
Vergleich Zugriff auf bestehende Datei
DATEI UID GID
Beispiel: UY GY
Hans UID=5 GID=100
CPROG1 UID=5 GID=100 UID=5 GID=100 EUID=5 EGID=100
CPROG2 UID=6 GID=200
DAT1 UID=5 GID=100
DAT2 UID=6 GID=300
Zugriff auf DAT1
vergleicht EUID mit UID von DAT1 ist gleich, also hans Besitzer, also USER- Rechte
Zugriff auf DAT2
vergleicht EUID mit UID von DAT2 ist nicht gleich, also Hans nicht Besizer also gelten other- Rechte
...die ein oder mehrere Kommandos enthalten. (Textdateien) Wird ein Shellscript aktiviert, wird dieses von der Shell Zeile für Zeile gelesen, interpretiert und durchgeführt. Neben Kommandos können Shellscripte auch Kontrollstrukturen enthalten (if, for, while, until) Außerdem können in Shellscripten auch Variableninhalte eingegeben werden um den Shellscriptablauf zu steuern.
Allgemeine Regeln von UNIX- Dateinamen sind gültig.
1. $sh [scriptname] [RETURN] alle Var. Die festgelegt wurden gelten nach Beendigung nicht mehr (wird selten genutzt)
Subshell wird erzeugt, die script abarbeitet
2. $[scriptname] [RETURN] vorher muß dem Script das x- Recht erteilt werden
Ablauf ist gleich, wie oben
3. $. [scriptname] . ---> "Punktkomando"
Es entsteht keine Kindshell!
Die in diesem Script abgearbeiteten Variablen bleiben
auch hinterher gültig
Es gibt kein EXIT mehr (sonst wäre man ja ausgeloggt)
Bsp.: profile und .profile werden von der Loginshell abgearbeitet und sind hinterher immer noch vorhanden
Jedem Programm können beim Aufruf Argumente übergeben werden. (um die Programmsteuerung zu beeinflussen)
- Genauso geht es bei einem Shellscript und diese Argumente können in dem Shellscript über Positionsparameter angesprochen werden (werden dem Positionsparameter übergeben)
- Es gibt nur 9 Parameter
- Außerdem gibt es noch den Parameter 0, darin wird noch der Scriptname eingetragen
zugegriffen wird auf die parameterinhalte mit $
- Positionsparameter sind im Grunde genommen Variablen.
- Es gibt noch 2 Positionsparameter, nämlich $# und $*
$# -beinhaltet eine Zahl = die Zahl der beim Aufruf übergebenen Argumente, auch wenn es mehr wie 9 sind
-$0 wird nicht mitgezählt
$* -beinhaltet alle Argumente, auch wenn es mehr wie 9 sind
$0 ist nicht enthalten.
Bsp.: postest Hallo du da
echo $0 postest
echo $1 Hallo
echo $2 du
echo $3 da
echo $# 3
echo $* Hallo du da
Das set- Kommando kann unter anderem verwendet werden, um den Positionsparametern $1- $9 Werte zuzuweisen. Dementsprechend werden auch $# und $* neu belegt.
Shellscript anmeld
set `who am i `
echo "Anmeldename: $1"
echo "Anmeldedatum: $3"
echo "Anmeldeuhrzeit: $3"
Wenn man ein Script mit Punkt- Kommando aufruft, können keine Argumente übergeben werden. (nicht LINUX). Werden trotzden welche übergeben werden sie einfach ignoriert.
Unter UNIX kennt die Shell insgesamt 10 Poitionsparameter ($0- $9), wobei nur 9 davon für Argumente verwendet werden können. Sollen mehr, wie 9 Argumente einem Shellscript übergeben werden, können diese über das SHIFT- Kommando ansprechbar gemacht werden. Das SHIFT- Kommando verschiebt die Positionsparameterinhalte unwiederruflich um eine Stelle nach links, wobei das ganz links stehende Argument (ehemaliger $1 Inhalt) verloren geht. Versucht man über das letzte Argument hinauszushiften, erhält man eine Fehlermeldung.
Aufgabe: Shellscript schreiben, name:
bei Aufruf soll der erste und letzte angemeldete user angezeigt werden. (Bezogen auf die Uhrzeit)Erster angemeldeter User (Uhrzeit): Name
Letzter angemeldeter User (Uhrzeit): Name
man braucht set, who, sort, echo und Kenntnisse über Positionsparameter
Lösung:
set `who | sort +4`
echo "Erster angemeldeter User: $1 $5"
set `who | sort -r +4`
echo "Letzter angemeldeter User: $1 $5"
For "VARIABLE" in "LISTE"
do
Kommandoliste
done
Der Variablen VARIABLE wird das erste Argument, daß bei LISTE
steht, übergeben. Dann läüft die Schleife das erste Ma ab.
Danach wird VARIABLE das zweite Argument übergeben und die Schleife
läuft wieder. Das ganze so lange, bis kein Argument mehr in LISTE
steht. (im Bsp. also drei mal).
Bsp.: for USER in Hans Emil Egon
do
echo "Hallo $USER"
echo "Wie geht`s?"
done
Wo kann man das gut nutzen?
scriptname Huber Hans Emil
for USER in $*
do
echo "Hallo $USER"
done
Aufgabe: Script, das nachdem es aufgerufen wurde, soll alle angemeldeten User anzeigen, wie folgt: User: "USERNAME" ist angemeldet!
User: "USERNAME" ist angemeldet!
.......
set `who | cut -d" " -f1 | sort +0 | tr "\012" " "`
for USER in $*
do
echo User: $USER ist angemeldet!
done
Aufgabe: Befehle:
User anlegen useradd "username"
HOMEverzeichnis anlegen mkdir
HOMEverzeichnis auf User übertragen chown
HOMEverzeichnis auf User- Gruppe übertragen chgrp Gruppe: USERS
Standart- passwort vergeben passwd "user"
Lösung:Scriptname ist
do
useradd $USR
mkdir /home/$USR
chown $USR /home/$USR
chgrp USERS /home/$USR
passwd $USR
done
Test "Ausdruck" Exitstatus: 0 wahr
!0 falsch
Die Variable ? beinhaltet automatisch den Exitstatus des zuletzt ausgeführten Test- Befehls
Variableninhalte sind immer char, nie Zahlen!!!
Soll ein Shellscript abhängig von der Ausgabe eines Tests (Kommando) verschiedene Kommandos ausführen, kann das mit Hilfe der Kontrollstruktur IF realisiert werden.
Wie funktoniert das?
If kommandoliste1 (wenn das letzte Kommando 0 liefert, dann, sonst)
then
kommandoliste2
else (kann auch fehlen!)
kommandoliste3
fi
if test -d /home/$1
then
echo "Verzeochnis existiert bereits!"
else
mkdir /home/$1
echo "Verzeichnis wurde erfolgreich angelegt!"
fi
Aufruf: newdir "Verzeichnis"
Übung: shellscript, i
if who | egrep "^$1 " > /dey/null egrep- Aisgabe soll nicht angezeigt werden-
then Umleitung nach /dev/null
echo "User $1 ist angemeldet"
else
echo "User $1 ist nicht angemeldet"
fi
auch
if test "`who | egrep "^$1 "`" braucht nicht ins Nirvana umgelenkt werden, liefert nur Exitstatus wahr oder falsch.
then
if
then
else
fi
else
fi
if test $1
then
if test "`who | egrep "^$1 "`"
then
echo "User $1 ist angemeldet"
else
echo "User $1 ist nicht angemeldet"
fi
else
echo "Falscher Aufruf: isusr [USERNAME]"
fi
If kommandoliste1 wahr = weiter mit Kommandoliste2, dann fi
then falsch = weiter nach elif Kommandoliste3
Kommandoliste2
elif Kommandoliste3 wahr = weiter mit Kommandoliste4, dann fi
then Kommandoliste4 falsch = weiter mit elif Kommandoliste5
elif Kommandoliste5 wahr = weiter mit Kommandoliste6, dann fi
then Kommandoliste6 falsch = weiter mit else Kommandoliste7, dann fi
else
Kommandoliste7
fi
übung:
testdf [pfad/]datei
if test "$1"
then
if test -d "$1"
then
echo "$1 is a directory"
elif test -f "$1"
then
echo "$1 is a ordinary file"
else
echo "Argument ist weder VERZEICHNIS noch DATEI!"
fi
else
echo "Falscher Aufruf:-- testdf [verz/]datei"
fi
Case text in
muster1) kommando 1 text wird mit muster 1 verglichen
kommando 2 gleich = kommandoliste, dann esac, sonst
kommando n;;
muster 2) kommando 1 text mit muster 2 veglichen
kommando 2 gleich = kommandoliste, dann esac, sonst
kommando n;;
*) (optional) kommando 1 text wird mit allem anderen(*) verglichen
kommando 2 gleich = kommandoliste, dann esac
kommando n;;
esac
wenn 0-9, dann Zahl in Text, sonst Fehlercase $1 in
0 ) echo "Null"
1 ) echo "Eins"
2 ) echo "Zwei"
etc.
Bsp.: expr 3 + 2
VAR = `expr 3 + 2`
read VAR ---einlesen einer Zeile aus der Standarteingabe
read VAR1 VAR2 .... Hallo du eingeben
VAR1 = hallo
VAR2 = du
read kann man als pause- Befehl benutzen
shellscript will eingabe haben durch readbefehl
Übung: shellscript, mit hilfe dessen man neueUser anlegen, oder alte löschen kann
Frage: anlegen oder löschen
Eingabe: a oder l
bei anlegen Meldung: "bite Username(n) eingeben
Eingabe: username
"bitte usergruppe(n) eingeben
Eingabe: gruppe
bei anlegen: homeverzeichnis anlegen
homeverzeichnis user schenken
passwort
bei löschen Ausgabe aller User, die es gibt (optional)
User löschen (userdel username)
homeverzeichnis löschen egal ob leer oder
nicht
lösung:
echo "Programm zur Benutzerverwaltung: User anlegen oder löschen"
echo "bitte wählen Sie: anlegen (a) löschen (l)"
read OPTION
case $OPTION in
a) echo "Bitte Username(n) eingeben"
read USR
#echo "Bitte Gruppe(n) eingeben"
#read GRUSR
#useradd $USR
#groupadd $GRUSR
mkdir /home/$USR
chown $USR /home/$USR
chgrp USERS /home/$USR
passwd $USR
b) echo "Bitte User auswählen"
cut -d: -f1 /etc/passwd | tr "\012" " "
read USR
userdel $USR
rmdir /home/$USR
*) echo "Bitte nur klein, oder Großbuchstaben eingeben!"
read AUSW
if test "$AUSW" = "a" -o "A"
then
echo -e "Bitte User (anlegen) eingeben:\c"
read NEWUSER
echo "Gruppen:"
read GRP
for USER in $NEWUSER
do
if test "`cat /etc/passwd | egrep ^$USER:`" test wartet auf string, dann: wahr oder falsch
then
echo "User $USER war bereits angelegt!"
else
useradd $USER
mkdir /home/$USER
chown $USER /home/$USER
chgrp $GRP /home/$USER
echo "Erstes Passwort für User $USER: Start"
passwd $USER
fi
done
elif test "$AUSW" = "l" -o "L"
then
echo -e "Bitte User (lööschen) eingeeben: \c"
read DELUSER
for USER in $DELUSER
do
if test "`cat /etc/passwd | egrep ^$USER:`"
then
userdel $USER
rm -fr /home/$USER
echo "User $USER wurde gelöscht!"
else
echo "User nicht vorhanden!"
fi
done
else
echo "Falsche Option!-- Bitte (a) oder (l) eingeben!"
fi
while Kommandoliste 1 wenn
Kommandoliste wahr
do
Kommandoliste 2 wenn k1 =0
done
Aufgabe: scipt, daß eine Zahl verlangt, sooft soll dann Hallo Hans angezeigt werden
echo -e "Gib eine Zahl ein: \c"
read ZAHL
Z = 0
while test "$Z -lt $ZAHL"
do
Z = `expr $Z +1`
echo "Hallo Hans"
done
Übung: Script, Aufforderung, mehrere zahlen einzugeben. Die größte und Kleinste der Zahlen soll angezeigt werden. Zusatz: gleich mit der k.zeile übergeben
echo -e "Gib ein paar Zahlen ein: \c"
read ZAHLEN
GZ = 0
KZ = 0
for ZAHL in $ZAHLEN
do
if test "$ZAHL -gt $GZ"
then
GZ=$ZAHL`
elif test "$ZAHL -lt $KZ"
then
KZ= $ZAHL`
fi
done
echo -e "Größte Zahl: $GZ \c"
echo -e "Kleinste Zahl: $KZ \c"
if test $# -eq 0
then
echo -e "Bitte zahlen eingeben: \c"
read ZAHLEN
else
ZAHLEN = $*
fi
set ` echo $ZAHLEN`
MIN=$1
shift
while test $# -gt 0
do
if test $1 -lt $MIN
then
MIN=$1
fi
shift
done
echo "kleinste Zahl ist: $MIN"
set `echo $ZAHLEN`
MAX=$1
shft
while test $# -gt 0
do
if test $1 -gt $MAX
then
MAX=$1
fi
shift
done
echo "kleinste Zahl ist: $MAX"
until kommandoliste 1 wenn Kommandoliste falsch!
do
konnandoliste 2
done
möchte man eine Endlosschleife mit while,
oder until erzeugen, so kann man das ganz einfach mit hilfe der kommandos
true
und false machen.
Daskommando true setzt den Exitstatus immer auf null, das kommando false
immer auf !=0.
Mit Hilfe des Break kommandos können
while und until. Schleifen abgebrochen werden, d. h. nach break wird mit
dem ersten Kommando nach der Schleife weitergemacht. Nach dem Break kann
noch eine Zahl angegeben (Standart =1), über die bei geschachtelten
Schleifen die Anzahl der Schleifen, die abgebrochen werden sollen
VAR=0
while true
do
if test VAR -ne 0
then
break
else
read var
fi
done
Continue wird auch in Verbindung mit while
und until verwendet und führt nur dazu, daß der aktuelle Schleifendurchlauf
abgebrochen wird. D. h. Es wird zurück zur Kommandoliste 1 zurückgekehrt
bzw. zur Bedingung der Schleife, die wird neu abgearbeitet und dementsprechend
wieder in die Schleife rein, oder nicht. Auch hier kann eine Zahl angegeben
(Standart =1), über die bei geschachtelten Schleifen die Anzahl der
Schleifen, die abgebrochen werden sollen
Unterschied: break schickt ihn hinter done, damit ist er fertig
continue schickt ihn auf done, done schickt ihn wiedernachoben
Übung: Script, will username, das solange läuft, bis user angameldet ist, mit Meldung.
hintergrundprozess
while true
do
if test "`who | egrep "^$1 "`"
then
echo "User $1 ist angemeldet"
break 2
fi
done
Nicht benutzt werden darf der Befehl do.
Tip.: ls | cut tr
max 600