2030666

Crashkurs: Scripten mit Bash in Linux

09.01.2015 | 13:03 Uhr |

Die Bash-Shell ist unter Linux ein unverzichtbares interaktives Werkzeug. Darüber hinaus kann sie durch Shell-Scripts Aufgaben lösen und Abläufe automatisieren. Dieser Beitrag will die Möglichkeiten andeuten und zur Eigeninitiative motivieren.

Der folgende kleine Crash-Kurs fängt nicht bei null an, sondern setzt grundlegende Kenntnis der interaktiven Shell-Benutzung bereits voraus. Er zeigt Regeln und Kniffe bei der direkten interaktiven Arbeit im Terminal und legt nachfolgend die Basis für komplexere Shell-Scripts.

Interne und externe Befehle

Die Shell muss bei jedem Befehl unterscheiden, ob es sich um ein externes Programm oder einen internen Befehl der Bash-Shell handelt. So ist „gedit“, also der Texteditor, ebenso ein externes Programm wie „ls“, das Programm zum Auflisten von Dateien. „cd“ hingegen, zuständig für den Verzeichniswechsel, werden Sie auf der Festplatte nicht finden, da es sich um einen internen Bash-Befehl handelt. Solange externe Programme in den Standardpfaden wie „/bin“ und „/usr/bin“ liegen, findet sie die Shell automatisch, so dass Sie sich um die Unterscheidung intern – extern nicht groß kümmern müssen. Dennoch ist es wichtig zu wissen, dass externe Programme eventuell eine komplette Pfadangabe oder den vorherigen Wechsel in ihr Verzeichnis benötigen, um fehlerfrei zu starten.

Einfache Stoppuhr: Die Funktion „timer“ speichert die Startzeit. Nach beliebigem Tastendruck errechnet sie die exakte Differenz zur Endzeit und zeigt das Ergebnis an.
Vergrößern Einfache Stoppuhr: Die Funktion „timer“ speichert die Startzeit. Nach beliebigem Tastendruck errechnet sie die exakte Differenz zur Endzeit und zeigt das Ergebnis an.

Aufbau einer Kommandozeile

Eine Kommandozeile besteht aus einem oder mehreren Wörtern, die durch Leerzeichen getrennt sind. Das erste Wort ist immer das maßgebliche interne oder externe Programm. Im simpelsten Fall genügt dieses eine Wort – etwa „firefox“ oder „ls“. Häufig folgen aber weitere Argumente wie etwa Dateiangaben oder auch Optionen des jeweiligen Programms: So nutzt „firefox–safe-mode“ die eingebaute Browser-Option, im abgesicherten Modus ohne Erweiterungen zu starten. Jede derartige Programmoption muss mit genauester Kenntnis der Schreibweise eingegeben werden, andernfalls wird sie vom Programm bestenfalls ignoriert oder als fehlerhaft bemängelt. In komplexeren Beispielen kommen Befehlsverkettungen zum Einsatz:

free | awk '/Speicher:/ { print "Speicher frei (%): "int($4/$2*100)}'

Der Grundbefehl „free“ ermittelt die aktuelle Speichersituation – aber relativ unübersichtlich. Der dann folgende (mit den Tasten Alt-Gr-| erzeugte) Längstrich ist das Signal für Befehlsverkettungen. In diesem Fall wird die unübersichtliche Ausgabe von „free“ an ein zweites Programm „awk“ übergeben, das zunächst die Zeile mit „Speicher:“ herausfiltert und dort wiederum das zweite und vierte Textfeld ($2 und $4). „awk“ kann die gefundenen Angaben auch gleich verrechnen und mit erklärendem Text ausgeben.

Die Linux-Konsole im Griff

Zwischen interaktiver Nutzung und Scripting

Der Übergang zwischen interaktiver Nutzung und Scripting ist fließend. Sobald Sie beginnen, in der automatisch eingelesenen Standarddatei „.bashrc“ (im Home-Verzeichnis) Änderungen vorzunehmen, sind Sie auf dem Weg zum Scripten. Typische erste Anpassungen in der „.bashrc“ sind Befehlsabkürzungen in Form von Alias-Definitionen. Beachten Sie, dass Änderungen der Datei „bashrc“ immer erst für Terminals gelten, die nach der Änderung gestartet werden. So verhilft dieses Alias

alias d='cd $HOME/Desktop'

dazu, mit der Eingabe „d“ zum Desktop zu wechseln. Achtung: Der Desktop-Ordner heißt bei einigen Distributionen auch „Schreibtisch“ oder „Arbeitsfläche“. Folgendes Alias

alias 2d='cp --targetdirectory=$HOME/Desktop $1'

dient einer schnellen Kopie zum Desktop: Nach der Eingabe „2d“ sollte ein Dateiname folgen, den das Alias mit der Variablen „$1“ verarbeitet und die jeweilige Datei zum Desktop kopiert. Unentbehrlich ist mittelfristig sicher ein Alias, das die „bashrc“-Datei in einen Editor lädt:

alias ini='gedit ~/.bashrc & disown'

„& disown“ ist nicht notwendig, sorgt aber dafür, dass der Editor unabhängig vom Terminal gestartet wird. Ein ähnliches einfaches Beispiel ist der Aufruf des grafischen Dateimanagers im aktuellen Verzeichnis:

alias x='nautilus $PWD & disown'

Ein Alias kann aber mehr als nur ein einzeiliges Kommando aufnehmen, wobei Sie die Befehle mit einem Semikolon trennen:

alias env='env | sort;echo "";echo -e ${PATH//:/\\n}'

Nach der Eingabe „env“ werden hier die Umgebungsvariablen sortiert angezeigt und nach einer Leerzeile noch einmal der Systempfad in gut lesbarer Form mit je einem Eintrag pro Zeile ausgegeben.

Verzeichniswechsel auch bei Dateien: Die Funktion „xd“ nimmt beim Ordnerwechsel zu einer Datei einfach dessen Pfad. „If“ klärt vorab, ob ein Directory (-d) übergeben wurde.
Vergrößern Verzeichniswechsel auch bei Dateien: Die Funktion „xd“ nimmt beim Ordnerwechsel zu einer Datei einfach dessen Pfad. „If“ klärt vorab, ob ein Directory (-d) übergeben wurde.

Ein weiteres Beispiel ermittelt mit „extip“ die externe IP-Adresse, wobei es einen beliebten Internetdienst befragt. Das ebenfalls benutzte Tool Curl ist meist Systemstandard, und ist – wo nicht – schnell nachinstalliert:

alias extip='echo -n "Externe IP = ";curl http://ifconfig.me'

Sobald Aliases mehr als drei, vier Kommandos enthalten und mit den trennenden Strichpunkten schwer lesbar werden, lohnt sich eine andere Form, nämlich die einer Funktion. Auch Funktionen, jedenfalls die allerwichtigsten, können Sie in der „.bashrc“ unterbringen. Die Syntaxbasis einer Funktion sieht wie folgt aus:

function Name() { [Befehle…] }

Auch Funktionen sind im einfachsten Fall simple Befehlsstapel, so etwa, um einige Systeminfos abzufragen:

function ver() { echo -n "System: "; uname -o echo -n "Kernel: "; uname -r echo -n "CPU : "; uname -p echo -n "Name : "; uname -n gnome-shell --version}

Ein etwas komplexeres Beispiel zeigt die Timer-Funktion in der Abbildung am Anfang dieses Artikels: Die Funktion löst eine Stoppuhr aus, welche mit beliebiger Taste beendet wird. Die gemessene Zeitdauer wird dann am Prompt exakt angezeigt.

Die weitere Beispielfunktion „xd“ eignet sich ebenfalls für die Datei „bashrc“, weil sie den interaktiven Komfort der Kommandozeile erhöht: Sie macht bereits von einfachen Kontrollstrukturen Gebrauch, in diesem Fall von einer einfachen Fallunterscheidung mit If – Then – Else. Beim Verzeichniswechsel mit „xd“ spielt es keine Rolle, ob ein Ordnerpfad oder ein Dateipfad nachfolgt, denn im zweiten Fall zieht sich die Funktion einfach den Ordner aus dem Dateipfad. Das ist etwa praktisch, wenn Sie Dateiobjekte aus dem Dateimanager in das Terminal ziehen und dann in dessen Ordner wechseln wollen. Das der Funktion nachgestellte Alias „cd='xd'“ macht das intelligentere „xd“ zum Standard.

Drei Tricks für die Linux-Shell

Selbständige Shell-Scripts

Die bisher genannten Aliases der Datei „bashrc“ oder auch Funktionen innerhalb dieser Datei bedeuten zwar bereits Scripting, waren aber immer noch auf den interaktiven Einsatz am Terminal-Prompt ausgerichtet. Es gibt aber gute Gründe, ein Bash-Script als unabhängige und selbständige Datei abzulegen: Nur so ist es möglich, ein Script per Mausklick aus der grafischen Oberfläche zu starten oder automatisch beim Log-on sowie als periodischen Cron-Job auszuführen.

Suchbegriff und aktuellen Pfad an das grafische Gnome-Search-Tool übergeben: Wird das Script ohne Parameter aufgerufen, setzt das Script lediglich den Standardpfad „/home“.
Vergrößern Suchbegriff und aktuellen Pfad an das grafische Gnome-Search-Tool übergeben: Wird das Script ohne Parameter aufgerufen, setzt das Script lediglich den Standardpfad „/home“.

Außerdem ist es nicht sinnvoll, umfangreiche, aber nur gelegentlich genutzte Scripts allesamt in der „bashrc“-Datei mitzuschleppen.

Bash-Scripts sind wie die bereits genutzte „bashrc“ einfache Textdateien, die Sie mit einem Editor Ihrer Wahl erstellen und bearbeiten. Der Editor sollte aber Fähigkeiten wie Syntax-Highlighting mitbringen, was die Übersicht wesentlich verbessert. Der empfehlenswerte Editor gedit zeigt unter „Ansicht -> Hervorhebungsmodus -> Skripte“ die Option „sh“, die Sie für Shell-Scripts wählen sollten. Auch die Farbschemata unter „Bearbeiten -> Einstellungen -> Schrift und Farben“ sind beim Scripten wichtiger als beim Tippen von Text.

Ein Bash-Script beginnt immer mit dieser Zeile:

#!/bin/bash

Das Zeichen „#“ leitet eigentlich einen Kommentar ein, also eine Zeile, die die Shell ignorieren soll. In der Kombination „#!“ gibt sie jedoch die zu verwendende Shell an. Da nicht auf allen Systemen die Bash-Shell Standard sein muss, erfährt das System hier, welches Programm es starten soll. Das setzt natürlich voraus, dass „/bin/bash“ tatsächlich existiert, was aber in aller Regel der Fall ist.

Für einen ersten Versuch erstellen Sie ein ganz kurzes Script „test.sh“ mit folgendem Inhalt:

#!/bin/bash for i in *.* do mv $i $(echo $i | tr ':' '-') done

Das Beispiel-Script ersetzt bei allen Dateien des aktuellen Verzeichnisses eventuelle Doppelpunkte im Namen durch Bindestriche. Das ist eine nützliche Hilfe, wenn Sie Dateien von Linux nach Windows kopieren wollen. Für eine vollständigere Ersetzung problematischer Zeichen müssen Sie nur die dritte Script-Zeile für weitere erforderliche Zeichen wiederholen.

Shell-Scripts starten standardmäßig nur aus dem Terminal. Der Dateimanager kann aber veranlasst werden, auch den Start per Mausklick zu erlauben.
Vergrößern Shell-Scripts starten standardmäßig nur aus dem Terminal. Der Dateimanager kann aber veranlasst werden, auch den Start per Mausklick zu erlauben.

Ein guter Ort für solche speziellere Scripts ist etwa ein Ordner „/Scripts“ im Home-Verzeichnis. Öffnen Sie dann ein Terminal-Fenster, und geben Sie

chmod u+x ~/Scripts/test.sh

ein, um das Script für den aktuellen Benutzer „Ausführbar“ zu machen. Alternativ geht das auch im Dateimanager über „Eigenschaften -> Zugriffsrechte -> Datei als Programm ausführen“. Gehen Sie dann mit „cd“ in einen Ordner, der Dateien mit problematischen Zeichen enthält, und starten Sie mit dem Befehl

sh ~/Scripts/test.sh

das Script. Die Variable „$i“ nimmt innerhalb der do-Schleife nacheinander jeweils den Wert des nächsten Dateinamens im aktuellen Verzeichnis an. „echo $i“ übergibt den Namen an das Translate-Tool „tr“.

Ein weiteres einfaches Script verbessert die Benutzung des gnome-searchtools, indem es einen übergebenen Suchbegriff und das aktuelle Verzeichnis direkt an das Tool weitergibt. Wird das Script an der grafischen Oberfläche oder auch im Terminal ohne Suchbegriff gestartet (also ohne Parameter $1), dann lädt das Tool ganz normal mit dem Home-Verzeichnis als Vorgabe. Eine typische Eingabe am Prompt wäre dann:

sh ~/Scripts/search Shakespeare

Den Aufrufkomfort externer Shell- Scripts sollten Sie bei allen wichtigeren Exemplaren durch Aliases weiter und deutlich verbessern. Mit einem Alias „alias search=sh ~/Scripts/search‘‘ verkürzt sich die Eingabe auf

search Shakespeare
Basis-Script für eine Textdatei-Auswertung: Die While-Schleife liest Zeile für Zeile einer übergebenen Datei ein und zeigt sie in diesem Fall lediglich mit Zeilenummer an.
Vergrößern Basis-Script für eine Textdatei-Auswertung: Die While-Schleife liest Zeile für Zeile einer übergebenen Datei ein und zeigt sie in diesem Fall lediglich mit Zeilenummer an.

Script-Start per GUI: Wenn Sie Shell-Scripts über die grafische Oberfläche per Doppelklick starten wollen, genügt es nicht, den Scripts das Attribut „Ausführbar“ zuzuweisen. Zusätzlich müssen Sie diese Startoption im Dconf-Editor oder – meist einfacher – im Dateimanager erlauben. Bei Nautilus (Ubuntu) und Nemo (Mint) finden Sie die Option unter „Bearbeiten -> Einstellungen -> Verhalten -> Ausführbare Textdateien“.

Linux zu Befehl - pfiffige Shell-Tricks

Tipps zur Ablaufkontrolle

Einige kleinere If-Entscheidungen kamen bereits zu Wort. Es gibt zahlreiche Parameter und Operatoren für If-Fallunterscheidungen. Ein wichtiger Parameter „-e“

if [ -e ~/Schreibtisch ]; then cd ~/Schreibtisch fi

überprüft die Existenz eines Dateiobjekts. Der Parameter „-n“ stellt fest, ob die nachfolgend genannte Variable existiert („not empty“ ist):

if [ -n "$var" ]; then echo "Existiert"; fi

Dies ist auch von besonderer Bedeutung, wenn Sie die Übergabeparameter an ein Script („$1“, „$2“ etc.) auswerten müssen. Viele weitere Vergleichoperatoren müssen Sie bei Bedarf im Web recherchieren. Wichtig zu wissen ist es, dass die Operatoren „-eq“ (gleich), „-ne“ (ungleich) nur bei Integer-Zahlen funktionieren, während Sie für den Textvergleich „=“ (gleich) und „!=“ (ungleich) verwenden müssen:

if [ "X" = "Y" ]…

Diese Zeile ist ebenso korrekt wie folgende:

if [ "21" –eq "5" ]…

Schleifenkonstruktionen mit While, Until (meist entbehrlich) und For haben entweder eine genau bezifferbare Anzahl der Durchläufe oder warten auf ein bestimmtes Ereignis (etwa Textinhalt, Dateiname), das die Schleife beendet. Eindeutig bezifferbar, ohne dass Sie das selbst absehen oder programmieren müssten, ist etwa die Anzahl der Dateien in folgender Schleife:

for dat in `find /home –name "*.png" -type f` do echo $dat done

Dasselbe gilt für das Einlesen und Analysieren einer Textdatei mit

while read line; …

bis zum Ende der Datei. In eher selteneren Fällen sind genau bezifferbare Schleifendurchläufe folgender Sorte die richtige Wahl:

for i in {1..255}; do ping –c1 192.168.0.$i; done

Viel häufiger ist es erforderlich, in der Schleife bei jedem Durchlauf eine Variable zu neu aktualisieren, die dann bei einem bestimmten Wert die Schleife stoppt:

while [ "$name" != "LinuxWelt" ]; …

Noch pragmatischer kann es sein, eine Schleife etwa mit „while :“ ohne Bedingung endlos laufen zu lassen und beim entscheidenden Ereignis direkt im Schleifencode mit dem Schlüsselwort „break“ abzuspringen.

Quellen für Bash und Scripting

GNU-Shell Bash (deutsch):
www-user.tu-chemnitz.de/~hot/unix_linux_werkzeugkasten/bash.html

Shell-Programmierung (deutsch):
http://openbook.galileocomputing.de/shell_programmierung/

Advanced Bash-Scripting Guide (englisch):
http://tldp.org/LDP/abs/html/index.html

Informativer und schicker Prompt

Manche fundamentale Info müssen Sie gar nicht erst explizit erfragen, sondern können sich diese standardmäßig am Terminal-Prompt anzeigen lassen. Möglich ist hier im Prinzip alles, weil die Bash-Shell mit dem „PROMPT_COMMAND“ eine interne Funktion vorsieht, die vor jeder Prompt-Darstellung aufgerufen wird.

Informativer und schicker Prompt
Vergrößern Informativer und schicker Prompt

Daher können Sie in einer selbstgestrickten Funktion „promptcmd“ alles abfragen, was Sie echtzeitaktuell am Prompt angezeigt haben wollen. Die Abbildung zeigt den passenden Abschnitt in der Datei „bashrc“ und darunter das Ergebnis, wie es sich im Terminal auswirkt.

Grafische Dialoge für Bash-Scripts 

In Distributionen wie Ubuntu und Linux Mint ist ein Programm für grafische Dialoge in der Regel vorinstalliert. Geben Sie am Terminal den Befehl dialog ein, um sich dieser Tatsache zu versichern. Sie erhalten eine Reihe von Unterfunktionen angezeigt wie „inputbox“, „msgbox“ oder „yesno“. Den ganz großen Charme versprühen diese Dialoge nicht, aber gelegentlich ist der Mausklick doch angenehmer als eine Texteingabe (mit „read“). Das gilt vor allem, wenn Sie Scripts für andere User möglichst komfortabel gestalten wollen.

Grafische Dialoge für Bash-Scripts
Vergrößern Grafische Dialoge für Bash-Scripts

Das in diesem Kasten abgebildete Beispiel soll einige Möglichkeiten andeuten: In der Inputbox wird ein Name abgefragt, danach folgt eine Yes-No-Entscheidung, deren Ergebnis schließlich mit einer Notify-Meldung quittiert wird.

Dieser Artikel stammt aus der LinuxWelt 6/2014

10 Jahrgänge auf DVD, im Heft: Linux retten & reparieren, Server selbst gebaut - das und mehr erwartet Sie in der neuen LinuxtWelt 6/2014 !

0 Kommentare zu diesem Artikel
2030666