Dies ist eine alte Version des Dokuments!
Shellscripts
Eine Sammlung eigener und fremder Shellskripte.
Grundsätzlich macht man ein Shellsripte ausführbar (chmod +x DATEI).
Für den Debugmodus ändert man einfach die erste Zeile, der sog. Shebang, in
#!/bin/sh -x
Links
Piepton auf Shell ausschalten
- dauerhaft
- Systemweit:
echo "set bell-style none" >> /etc/inputrc
- für den aktuellen Benutzer:
echo "set bell-style none" >> ~/.inputrc
- sofort
- Console:
- Disable: setterm -blength 0
- Enable: setterm -blength 200
- X11:
- Disable: xset b off
- Enable: xset b on
Umleitungen der Eingabe- und Ausgabe
Umleitungsschema | Wirkung |
---|---|
Befehl > ausgabe.log
(auch: Befehl 1> ausgabe.log | Die (Standard-)Ausgabe (STDOUT) wird in die Datei ausgabe.log geschrieben (diese Datei wird, falls vorhanden, komplett durch die Ausgabe von cmd überschrieben. |
Befehl > ausgabe.log
| Die (Standard-)Ausgabe (STDOUT) wird an die Datei ausgabe.log angehängt |
Befehl 2> ausgabe.log | Die (Standard-)Fehlerausgabe (STDERR) wird in die Datei ausgabe.log geschrieben |
Befehl 2>> ausgabe.log | Die (Standard-)Fehlerausgabe (STDERR) wird an die Datei ausgabe.log angehangen |
BefehlA | BefehlB
| Ausgabe des BefehlA an BefehlB übergeben (pipen) |
Befehl < eingabe.txt
| Die (Standard-)Eingabe wird aus der Datei eingabe.log genommen (nicht von der Tastatur). |
Befehl << EOT eingabe.log
| Die (Standard-)Eingabe wird aus der Datei eingabe.log genommen (nicht von der Tastatur). Aber nur bis zur (frei wählbaren!) Zeichenfolge EOT. Es handelt sich um ein HERE-Dokument. |
Numeric handles: | |
---|---|
Name | Bedeutung |
STDIN = 0 | Keyboard input |
STDOUT = 1 | Text output |
STDERR = 2 | Error text output |
UNDEFINED = 3-9 |
Umleitung nach /dev/null (Fehlermeldungen verbergen): |
|
---|---|
Befehl 2> /dev/null | Fehlermeldungen an /dev/null umleiten |
Befehl >/dev/null 2>&1 | Fehlermeldungen und Ausgaben an /dev/null umleiten |
Befehl >Dateiname 2> /dev/null | Fehlermeldungen an /dev/null , die Ausgaben jedoch an „Dateiname“ umleiten |
Kombinationen
- STDERR und STDOUT an ausgabe.log anhängen:
die echo ausgabe.log >> test.txt 2>&1
- die Eingabe aus eingabe.txt holen, STDOUT auf ausgabe.log und STDERR auf fehler.log leiten
cmd < eingabe.txt > ausgabe.log 2> fehler.log
- die Eingabe aus eingabe.log holen und STDERR auf STDOUT (2>&1) umlenken:
cmd < eingabe.txt > ausgabe.log 2>&1
wobei das ganze auch einfacher als
cmd < eingabe.txt &> ausgabe.log
geschrieben werden kann.
- Fehlermeldungen und Ausgaben an „Dateiname“ anhängen:
Befehl > Dateiname 2>&1
- Ausgaben und Fehlermeldungen an „Dateiname“ anhängen:
Befehl > Dateiname 2<&1
Kommandoverkettungen
Den Begriff Returncode bzw. Exitlevel vorher: Rückgabe von „0“ an das Betriebssystem heißt Erfolg, alles andere (Returncode ≠ 0) sind Fehler.
Schema | Wirkung |
---|---|
cmd1 | cmd2 | Pipe: Die Standardausgabe des ersten Befehls (cmd1) ist die Eingabe des zweiten Befehls. |
cmd1; cmd 2 | Einfache Verküpfung: cmd2 wird gestartet wenn cmd1 beendet ist (egal ob erfolgreich oder nicht). |
cmd1 & cmd2 | cmd1 wird im Hintergrund ausgeführt, während dessen wir schon cmd2 ausgeführt |
cmd1 && cmd2 | cmd2 wird nur ausgeführt wenn cmd1 fehlerfrei beendet wurde (Returncode = 0) |
cmd1 || cmd2 | cmd2 wird nur ausgeführt wenn cmd1 fehlerhaft beendet wurde (Returncode ≠ 0) |
Argumente für den Befehl test
Der Befehl test (oft nur über die Aliase der eckigen Klammern [ ] benutzt) prüft verschiedene Bedingungen ab und liefert einen Boolean-Rückgabewert (true oder false) zurück.
Beispiel:
if [ zeichenkette1 == zeichenkette2 ] then echo "Zeichenketten sind gleich." else echo "Zeichenketten sind ungleich." fi
Auch reguläre Ausdrücke sind möglich:
[[ "string" =~ pattern ]]
Tests für Dateien | |
---|---|
Syntax (name = Dateiname) | testet was? |
-d name | name ist ein Verzeichnis |
if [ ! "`ls -A $verz`" ] then echo "leer!" fi | Verzeichnis leer? |
-e name | name ist eine Datei |
-f name | name ist eine reguläre Datei |
-L name | name ist ein symbolischer Link |
-r name | name existiert und ist lesbar |
-w name | name existiert und ist schreibbar |
-x name | name existiert und ist ausführbar |
-s name | name existiert und hat eine von Null unterschiedliche Größe |
name1 -nt name2 | name1 ist jünger als name2 |
name1 -ot name2 | name1 ist älter als name2 |
Tests für Zeichenketten (Strings) | |
---|---|
Syntax | testet was? |
s1 == s2 | s1 und s2 sind gleich |
s1 != s2 | s1 und s2 sind ungleich |
-z s1 | s1 hat Länge Null |
-n s1 | s1 hat Länge ungleich Null |
nummerische Tests, für ganzzahlige (Integer) | |
---|---|
Syntax | testet was? |
a -eq b | a und b sind gleich |
a -ne b | a und b sind ungleich |
a -gt b | a größer als b |
a -ge b | a größer-gleich als b |
a -lt b | a kleiner als b |
a -le b | a kleiner-gleich b |
Kombinationen und Negationen (Umkehrungen) | |
---|---|
Syntax | Wirkung |
test1 -a test2 | test1 und test2 sind wahr |
test1 -o test2 | test1 oder test2 sind wahr |
! Bedingung | Testnegationen: Bedingung ist falsch |
\( Bedingung \) | Verkettung bzw. Gruppieren von Bedingungen: Backslash \ schützt die Klammern |
häufig benutzter Code
Die Ausgabe von Programmen in einer Variable speichern:
Datum=`date`
oder besser (weil verschachtelbar!):
Datum=$(date)
Parameter leer?
if [ -z $1 ]; then echo "empty parameter!" echo "usage: $0 [Parameter]" exit fi Code
oder leicht einfacher (und umgedreht):
if [ $1 ]; then CODE else echo "empty parameter!" echo "Usage: $0 [Parameter]" fi
Fehler aufgetreten (Exit-Code ungleich 0)
if [ $? -ne 0 ] then echo Fehler aufgetreten exit 1 else Code fi
als root aufgerufen?
if [ "`id -u`" -eq 0 ]; then echo you are root! else echo you are not root! fi
interaktive Abfragen
Posix-kompatibel:
echo -n "Is this a good question (y/n)? " read answer if [ "$answer" != "${answer#[Yy]}" ] ;then echo Yes else echo No fi
Bash:
echo "Do you wish to install this program?" select yn in "Yes" "No"; do case $yn in Yes ) make install; break;; No ) exit;; esac done
How do I prompt for Yes/No/Cancel input in a Linux shell script?
Datei erzeugen
Einfache Dateien können mit „echo Inhalt > Datei“ erzeugt werden, was aber wenn komplexe Konfigurationsdateien erzeugt werden müssen?
cat > "Dateiname" << EOF <Directory /> AllowOverride AuthConfig FileInfo Limit Indexes Order allow,deny allow from all </Directory> EOF
Zählschleife (kopfgesteuert)
von 1.. bis 10 zählen:
#!/bin/bash i=1 while [ $i -le 10 ] do echo $i let i=$i+1 #nur bash # i=`expr $i + 1` # universal done
Datei zeilenweise auslesen
for zeile in $(cat listendatei.txt); do echo $zeile done
bzw. diese Alternativlösung wenn die Zeilen auch Leerzeichen enthalten könnten:
while read -r zeile ; do echo "$zeile" done < listendatei.txt
Leerzeichen entfernen
sed:
- vorne:
sed 's/^[[:blank:]]*//'
- hinten:
sed 's/[[:blank:]]*$//'
- vorne+hinten:
sed 's/^[[:blank:]]*//;s/[[:blank:]]*$//'
tr (mehr als ein Leerzeichen):
tr -s ' '
bash-only-Lösung:
- vorne:
shopt -s extglob echo ${text##+([[:space:]])}
- hinten:
shopt -s extglob echo ${text%%+([[:space:]])}
- alle Leerzeichen entfernen:
echo ${text//[[:space:]]}
Fehlerbehandlung
#!/bin/bash set -e -o pipefail function cleanup { EXIT_CODE=$? set +e # disable termination on error rm "$tempfile" exit $EXIT_CODE } trap cleanup EXIT
Dateinamen beschneiden
Aus einem Pfad bekommt man mit basename
den Dateinamen heraus. Andere Möglichkeiten
- nur den Dateinamen:
echo "$DATEINAME" | cut -d. -f1
- nur die Erweiterung:
echo $DATEINAME | awk -F . '{print $NF}'
- pro Aufruf eine Ebene wegnehmen (bei mehreren Punkten im Dateinamen):
- 1 Ebene:
echo "$DATEINAME" | sed s/\.[^\.]*$//
- 2 Ebenen (usw.):
echo "$DATEINAME" | sed s/\.[^\.]*$// | sed s/\.[^\.]*$//
Anwendungsbeispiel: Vor der Erweiterung etwas einfügen.
a="Dateiname.ext" xclude_ext=`echo "$DATEINAME" | cut -d. -f1` ext=`echo $DATEINAME | awk -F . '{print $NF}'` mv "$a" "$xclude_ext"-Zwischentext."$ext"
Dialog-boxen
In einigen Fällen ist es nötig den Benutzer eine Auswahl treffen zu lassen. Dazu bieten sich einige Programme an, zenity ist sicherlich eine der besseren Programmen; es basiert auf dem GTK+-Toolkit und zeigt die Texte lokalisiert an (siehe Screenshot).
Anzeigebeispiel (Siehe auch: A complete zenity dialog examples #1 und #2 und das Zenity-Handbuch z.B. zum Thema Fortschrittsanzeige-Dialog):
Die Auswertung der Antwort(en) ist relativ simpel:
- ausgewählte Optionen werden komplette als Text zurückgegeben, wenn Mehrfachauswahlen zugelassen sind, dann sind diese durch ein „|“-Symbol getrennt. Um in diesem Fall die Antworten besser auswerten zu können, könnte man durch anfügen von
--separator=„\n“
als Trenner einen Zeilenumbruch nehmen und dann eine for-Schleife über alle Antworten laufen lassen:for dev in $answer do echo "answer is $dev" done
- OK ist Errorlevel 0 (Variable $? prüfen)
- Cancel ist Errorlevel 1 (Variable $? prüfen)
answer=`zenity --title="main menu" --width=300 --height=200 --list --radiolist --column "select" --column "choice" TRUE choice1 FALSE choice2 FALSE "choice3 with more text"` if [ $? -eq 1 ]; then echo "cancel pressed" exit else echo "OK pressed" case "$answer" in choice1) echo "choice1" ;; choice2) echo "choice2" ;; choice3) echo "choice3" ;; *) echo "case $answer not implemented yet." ;; esac fi
konkrete Programme
Systemadministration
Dateioperationen
- Checkmd5: md5-Summen von vielen Dateien mit einzelnen md5-Prüfsummendateien
- Rename (Wahrscheinlich das meist-vermisste bei Umsteigern)
- Rename2 noch ein Rename, sollte ich vielleicht in Par2 check+unpack einbauen um die vol-Dateien automatisch umzubenennen!
binäre Newsgroups
alt.bin.repair - umfangreiches Shellscript zum Prüfen und entpacken von .par2-sets aus dem usenet.