Fachinformatik/ Kommandozeile
Dieses Kapitel vermittelt eine Einführung in die Kommandozeile (Command Line Interface, CLI) und die Programmierung von Shell-Skripten. Weiterführende Informationen und Tutorials unterschiedlichen Umfangs finden sich z. B. im Bash-Programming-Intro-HOWTO, dem Bash-Beginners-Guide und Advanced Bash-Scripting Guide.
Kommandozeile
BearbeitenDokumentation und Hilfe
BearbeitenZu jedem Befehl/Kommando kann man unterschiedlich detailierte Informationen, Erklärungen und Beispiele abrufen. Die folgenden Beispiele verwenden exemplarisch sich selbst als Argument, normalerweise gibt man hier ein beliebiges anderes Kommando (oder auch Objekt, vergl. man interfaces
) an, für das man sich interessiert. Man beachte insbesondere man
, die „manual pages“. Die GNU Info Seiten müssen oft extra installiert werden (apt install info
), um verfügbar zu sein.
whatis whatis # durchsucht die Indexdatenbank nach Kurzbeschreibungen
man man # ein Interface für die System-Referenzhandbücher
help help # Information über Kommandos, die innerhalb der Shell selbst implementiert sind
info info # GNU Info Seiten
apropos apropos # suche in Handbuchseiten und deren Kurzbeschreibungen
whatis --usage ; man --help ; info -h
Dateibaum, Verzeichnisse und Dateien
Bearbeitenls -l → liste Inhalt eines Verzeichnisses auf
|
cd → wechsele Verzeichnis
|
tree → Dateibaum
|
touch → lege Datei an bzw. ändere Zeistempel
|
rm → lösche Datei
|
rm -r → lösche rekursiv Verzeichnis und Dateien
|
cp → Datei kopieren
|
cp -r → rekursiv kopieren
|
mv → umbenennen, verschieben
|
mkdir → lege Verzeichnis an
|
mkdir -p → lege Verzeichnisse an
|
rmdir → lösche leeres Verzeichnis
|
cat → Datei über stdout ausgeben
|
more → Datei stückweise betrachten
|
less → less is more!
|
chown → Besitzer („user“) einer Datei ändern
|
chgrp → Gruppe („group“) einer Datei ändern
|
chmod → Zugriffsrechte bearbeiten
|
stat → Meta-Daten einer Datei
|
ln , ln -s → Hard- bzw. Softlink
|
Ressourcen
Bearbeitenfree -h → Arbeitsspeicher anzeigen
|
df -h → Plattenplatz anzeigen
|
top → Auslastung live!
|
uptime → der Name ist Programm!
|
uname -a → Info über Kernel
|
fdisk , gdisk → Partitionen anzeigen
|
lscpu → Info über CPU(s)
|
/proc/cpuinfo → Info über CPU(s)
|
lspci → Info über PCI-Bus und -Geräte
|
lsusb → Info über USB-Bus und -Geräte
|
lsmod → Kernelmodule auflisten
|
journalctl -b → System Log Messages
|
systemctl status → System Status (systemd)
|
ps → Prozesse auflisten
|
pstree → Prozess-Baum
|
kill → Signale an Prozess senden
|
du → disk usage (Plattenplatz)
|
dmidecode → BIOS- und Harware-Info
|
Netzwerk
BearbeitenWerkzeuge
Bearbeitenfind → Dateisystem durchsuchen
|
grep → Datei nach Muster durchsuchen
|
kill → Signale an Prozess senden
|
sort → sortieren
|
cut → „zerschneiden“
|
tar → Archivierung
|
hexdump , xxd → binärer Dateiinhalt
|
sed → stream editor, Filter
|
wc → word count
|
head → Datei-Anfang
|
tail → Datei-Ende
|
tr → translate (or delete)
|
Ein-/Ausgabe Umlenkung
Bearbeiten|
Pipe-Symbol: Ausgabe (stdout) wird an weiteres Programm weitergeleitet: cmd1 | cmd2
cmd < datei
stdin wir aus datei
gelesen
cmd > datei
stdout wird in datei
geschrieben
cmd >> datei
stdout wird an datei
angehängt
cmd 2> datei
stderr wird in datei
geschrieben
cmd 2>&1
stderr wird an die gleiche Stelle wie stdout geschrieben
Shell-Skripte
BearbeitenAllgemeiner Aufbau
BearbeitenEin Skript im allgemeinen bzw. ein Shell-Skript im speziellen bezeichnet ein in einer Skriptsprache verfasstes Programm. Skriptsprachen werden meist durch einen Interpreter ausgeführt und finden hauptsächlich Verwendung beim Prototyping sowie in der Systemadministration (Konfiguration, Automatisierung, Orchestrierung, ….)
- Programm-Header
Wir betrachten hier nur die unter GNU/Linux und anderen unixoiden Betriebssystemen üblichen Skripte. Die erste Zeile eines Skripts, genannt Shebang, definiert den zur Ausführung benötigten Interpreter und hat den folgenden Aufbau: #!/usr/bin/sh
. Nach dem #!
, interpretierbar als Magic Number (vergleiche echo '#!' | xxd
), folgt der Pfad des Interpreterprogramms: /usr/bin/sh
. Beispiele sind:
#!/usr/bin/sh
Standard-Shell des Systems, meist ein Link auf die jeweilige Shell, vergl.ls -l /usr/bin/sh
#!/usr/bin/bash
Bourne-again Shell#!/usr/bin/zsh
Z Shell#!/usr/bin/perl
Perl Interpreter#!/usr/bin/python3
Python Interpreter
Nach dem Shebang folgt üblicherweise der (nur) menschenlesbare Teil des Programms: Urheber, Lizenz- und anderweitige Informationen von Interesse. Diese Zeilen fangen mit einem Kommentarzeichen #
an. Grundsätzlich wird alles in einer Zeile nach dem #
vom Interpreter ignoriert, wobei die erste Zeile mit dem Shebang eine Ausnahme bildet.
Speziell bei Shellskripten empfiehlt sich gleich zu Beginn des eigentlichen Programm-Codes noch die Anweisung set -eu
.
Mit set -e
bricht das Shellskript ab, wenn ein Fehler auftritt (Rückgabewert einer Anweisung ≠0). Mit set -u
werden unbelegte Variablen als Fehler reklamiert. Beides hilft bei der Entwicklung, Fehlern auf die Spur zu kommen. Details und weitere Informationen findet man z. B. mit man bash
im Absatz SHELL BUILTIN COMMANDS
.
Im einfachsten Fall ist ein Shell-Skript einfach eine Reihe von Befehlen, die nacheinander ausgeführt werden. Mit Variablen und den ebenfalls weiter unten behandelten Kontrollstrukturen kann man aber beliebige Programme schreiben. Die Shell-Programmierung reiht sich damit in die stetig wachsende Menge der verschiedenen Programmiersprachen ein, wobei jede ihre Vor- und Nachteile, gut oder weniger gut geeignete Problemstellungen und Anwendungsbereiche hat.
Um ein Shell-Skript letztlich ausführen zu können, muss es ausführbar (executable) gemacht werden:
Man führt es dann mit Pfadangabe aus:
|
Durch die Ausführung mit Pfadangabe wird verhindert, dass ein im Arbeitsverzeichnis liegendes, möglicherweise gar nicht bemerktes Skript anstelle des erwarteten Programms im Pfad (vergleiche echo $PATH
) ausgeführt wird.
Variablen
BearbeitenIn Shell-Skripten spielen selbst definierte genauso wie automatisch vorhandene Variablen eine große Rolle. Man definiert und arbeitet mit Variablen folgendermaßen:
#!/usr/bin/sh
# Demonstriert die einfache Verwendung von Variablen
set -eu
GRUSS="Hallo"
FRAGE="wie geht es Dir?"
ZAHL=10
echo "Ein Gruß: $GRUSS"
echo 'Kein Gruß: $GRUSS' # Zwischen "" werden Variablen referenziert, zwischen '' nicht!
echo "${GRUSS}le, $FRAGE" # mit {} kann ein Variablenname abgegrenzt werden.
echo "$ZAHL + 5 ist $((ZAHL + 5))"
- Vordefinierte Variablen
Eine Reihe von Variablen ist vordefiniert und kann nicht gesetzt werden:
#!/usr/bin/bash
# Demonstriert vordefinierte Variablen. Aufruf mit mindestens zwei beliebigen Parametern.
set -eu
echo "Der erste Parameter des Programms: '$1', und der zweite: '$2', usw …"
echo "Alle übergebenen Parameter des Programms: '$@' oder auch '$*'."
echo -e "Wie man sieht wurden $# Parameter übergeben.\n"
echo "Dieses Programm wurde als '$0' aufgerufen und läuft unter der Prozess-ID $$."
sleep 10 & # das &-Zeichen führt den Befehl im Hintergrund aus.
echo "Die Prozess-ID des 'sleep'-Befehls ist $!."
ps
echo -e "Stimmt's?\nRückgabewert des letzten Programms bzw. Kommandos: '$?'.\n"
set +e # damit kein Abbruch erfolgt
kommandogibtsnicht
echo -e "Rückgabewert des letzten Programms bzw. Kommandos: '$?'.\n"
set -e # Abbruch bei Fehler wieder eingeschaltet.
echo "Gib jetzt in der Shell ein: 'echo \$?'. Woher kommt die Zahl?"
exit 123
Kontrollstrukturen
BearbeitenBedingungen und Kontroll-Operatoren
BearbeitenDas Durchlaufen von Kontrollstrukturen erfolgt abhängig von Bedingungen (Tests). Bedingungen sind entweder wahr (Rückgabewert = 0) oder falsch (Rückgabewert ≠ 0). Statt test AUSDRUCK
kann man auch [ AUSDRUCK ]
schreiben. In vielen Shells gibt es eine erweiterte und verbesserte Variante (siehe man bash
), die statt [ AUSDRUCK ]
zwei Klammern verwendet: [[ AUSDRUCK ]]
. Hier ein paar wenige Beispiele, für weitere konsultiere man man test
:
[[ $STRING1 = $STRING2 ]]
[[ $INTEGER1 -eq $INTEGER2 ]]
[[ -e $FILE ]]
Die Kontroll-Operatoren &&
und ||
erlauben die Ausführung eines Ausdrucks abhängig vom Rückgabewert des zuvor ausgeführten:
AUSDRUCK1 && AUSDRUCK2 ## AUSDRUCK2 wird nur ausgeführt, wenn AUSDRUCK1 „wahr“=0 zurückgibt
AUSDRUCK1 || AUSDRUCK2 ## AUSDRUCK2 wird nur ausgeführt, wenn AUSDRUCK1 „falsch“≠0 zurückgibt
## Der Rückgabewert eines Ausrucks wird in der Variable $? gespeichert:
/usr/bin/true; echo $?
/usr/bin/false; echo $?
Verzweigung
Bearbeitenecho -n "Input a Number: "
read N
if [ $N -gt 0 ] ; then
echo "$N is greater than 0, a positive number."
elif [ $N -lt 0 ] ; then
echo "$N is less than 0, negative number."
else
echo "$N must be exactly zero."
fi
Fallunterscheidung[1]
BearbeitenSPACE=$(df -h | awk '{print $5}' | grep % | grep -v Use | sort -n | tail -1 | cut -d "%" -f1 -)
case $SPACE in
[1-6]*)
MESSAGE="All is quiet."
;;
[7-8]*)
MESSAGE="Start thinking about cleaning out some stuff. There's a partition that is $SPACE % full."
;;
9[1-8])
MESSAGE="Better hurry with that new disk … One partition is $SPACE % full."
;;
99)
MESSAGE="I'm drowning here! There's a partition at $SPACE %!"
;;
*)
MESSAGE="I seem to be running with an nonexistent amount of disk space …."
;;
esac
echo "$MESSAGE"
while
-Schleife
Bearbeiten
N=0
while [ $N -lt 10 ] ; do
echo "$N"
N=$((N+1))
done
until
-Schleife
Bearbeiten
N=0
until [ $N -gt 10 ] ; do
echo "$N"
N=$((N+1))
done
for
-Schleife
Bearbeiten
LIST="a b c"
for ITEM in $LIST ; do echo "$ITEM" ; done
for N in {-5..10} ; do
echo "\$N hat den Wert: $N"
done
LIST=$(seq 0 10 50)
for ITEM in $LIST ; do
echo "$ITEM"
done
Sonstige Hilfen und Werkzeuge
BearbeitenDas Programm shellcheck
eignet sich zum Prüfen von Shell-Code und gibt viele Hinweise und Verbesserungsvorschläge.
The Linux Documentation Project (LDP): Advanced Bash-Scripting Guide
- ↑ In Anlehnung an ein Beispiel aus dem Bash-Beginners-Guide