Linux-Workshop

Shell Scripting - Abläufe automatisieren

03.05.2013 von Thomas Steudten
Unter Linux lassen sich mit Scripts stets wiederkehrende Aufgaben erleichtern und automatisieren. In unserer Artikelserie über das Shell Scripting beginnen wir mit der grundlegenden Bedienung und den Möglichkeiten der Linux-Shells "Bourne" und dessen Nachfolger "Bash".
Shell Scripting - Abläufe automatisieren.
Foto: fotolia.com/julien tromeur; Strato

Das Betriebssystem Linux zeigt seine Stärken für den Anwender auf der so genannten Kommandozeile. Natürlich sind mittlerweile grafische Oberflächen (Graphical User Interfaces GUI) weit verbreitet und haben auch ihre Daseinsberechtigung. Viele einfache Aufgaben sind damit auch problemlos per Maus zu erledigen. Stehen aber automatisierte und komplexere Abläufe an, so bietet es sich geradezu an, die Shell als Kommandointerpreter einzusetzen.

Besonders für System-Administratoren stellt das Shell Scripting schnell eine Arbeitserleichterung dar. So lässt sich beispielsweise einfach überprüfen, wo Dateien generiert oder geändert wurden. Prozesse können per Kommando angehalten werden, um sie später bei weniger Last auf dem System weiter auszuführen.

In insgesamt drei Artikeln des Shell Scriptings beschäftigen wir uns mit alltäglichen Machenschaften des Systemadministrators in Interaktion mit der Bourne-Shell ("sh") und dessen Nachfolger Bourne-Again-Shell ("bash"). In diesem Artikel beginnen wir mit der grundlegenden Funktionalität der Shell.

10 Linux-Desktops im Vergleich
Ubuntu
Ubuntu gibt es in mehreren unterstützten Geschmacksrichtungen, hier Kubuntu.
Desktop
So sieht Kubuntu nach dem Start aus.
Netbook-Edition
In dieser Variante ist Unity bereits im Einsatz.
Büro-Software
Ubuntu hat natürlich OpenOffice.org an Bord.
Netzwerk
Heterogene Netzwerke sind kein Problem.
Linux Mint
Seit Linux Mint 10 ist das ganze System nicht mehr so extrem grün.
Mint-Menu
Das Menü in Linux Mint gestaltet sich sehr übersichtlich.
Software-Manager
Da sich in Mint Anwendungen bewerten lassen, können Nutzer Programme bereits vor der Installation einschätzen.
Backup-Tool
Mit Mint Backup können Sie auch die Liste der installierten Programme sichern.
Alles im Griff
Mit dem Mint Kontrollzentrum können Sie das System Finetunen.
Red Hat Enterprise Linux
Während der Installation gibt Ihnen RHEL diese Auswahlmöglichkeit.
GNOME
Red Hat Enterprise Linux verwendet GNOME per Standard.
Eclipse
Entwicklern muss man diese Software nicht weiter vorstellen.
Qt Designer
Plattformübergreifendes Framework.
Java
Bestimmte Java-Tools sind ebenfalls vorinstalliert.
Fedora
Fedora 14 ist erst vor kurzer Zeit erschienen.
Software
Weitere Pakete lassen sich bequem über den Software-Manager einspielen.
Anderer Desktop
So sieht die KDE-Ausgabe von Fedora 14 aus.
Mit LXDE
Fedora gibt es in verschiedenen Geschmacksrichtungen.
Thunar
Der Dateimanager und Geany in der Xfce-Variante.
Macpup
Nach dem Start lässt sich das System anpassen.
Midori
Auch der Browser ist klein und schnell.
Alles dabei
Macpup hat eigentlich alles an Bord, nur eben minimalistischer und unbekannter.
Weitere Software
Mittels Quickpet können Sie bequem weitere Pakete installieren.
Lucid Lynx
Da die aktuelle Macpup-Version mit Ubuntu 10.04 binärkompatibel ist, lassen sich die entsprechenden Repositories aktivieren.
Ultimate Gamers
Bei dieser Linux-Distribution dreht sich alles ums Spiel. Hier ist der Lemmings-Klon Pingus im Einsatz.
Voll
Das DVD-Abbild ist bis oben hin voll mit kostenfreien Games.
Frozen Bubble
Das Vorbild Puzzle Bobble war ein echter Renner auf den Spielautomaten.
PlayOnLinux
Dieses GUI für Wine hilft bei der richtigen Konfiguration und ermöglicht das Laufenlassen vieler Windows-Spiele und Aplikationen.
Urban Terror
Von freien Shootern bis zu Denkspielen ist alles vorhanden.
PCLinuxOS
PCLinuxOS ist eine Anfänger-freundliche Linux-Distribution.
Die Quelle
Am Installer Draklive merkt man den Ursprung von PCLinuxOS - Mandriva.
Sieht anders aus
Die beliebte Open-Source-Software lässt sich mittels nur einem Klick und der Eingabe des root-Passworts installieren.
OpenOffice.org
Die beliebte Open-Source-Software lässt sich mittels nur einem Klick und der Eingabe des root-Passworts installieren.
Konfiguration
Auch das Kontrollzentrum von PCLinuxOS ist schön und übersichtlich.
openSUSE 11.3
Die GNOME-Version der beliebten Linux-Distribution.
Menü
GNOME-unüblich startet sich das Menü in openSUSE von unten links.
Yet another Setup Tool
YaST ist openSUSEs Allzweckwaffe in Sachen Systemeinstellungen.
Übersichtlich
Alle Anwendungen im Überblick.
Software-Verwalter
Weitere Programm lassen sich auf einfache Weise nachträglich installieren.
Sabayon Linux
Sabayon Linux basiert auf Gentoo.
XBMC
Sabayon lässt sich als Multimedia-Station einsetzen.
Repository-Update mit Sulfur
Die Paketlisten auf den aktuellen Stand bringen.
Repository-Update mit Sulfur
Die Paketlisten auf den aktuellen Stand bringen.
Software mit Entropy
Sabayon bringt einen grafischen Paketverwalter mit sich.
Debian
Während der Installation können Sie schon vorgeben, wo es hinführen soll.
Desktop
So sieht die aktuelle Debian-Variante aus.
Konservativ
OpenOffice.org 2.4 ist etwas angestaubt im stabilen Debian-Zweig.
Netzwerk
Mit heterogenen Netzwerken klappt alles gut.
GParted
Der Partitions-Manager GParted ist per Standard installiert.

Grundlegenden Systemstatus abrufen

CTRL-X und CTRL-V präsentieren die Version und ein "echo $SHELL" den Pfad der Shell. Der Standard-Prompt wird über die Variable "PS1", die weiteren über "PS2" und "PS3" gesetzt. Ein "echo $USER $UID $EUID" zeigt uns den Usernamen und die (effektive) User-ID (UID) unter der wir angemeldet sind.

Mit "uname -a" ermitteln wir die Kernel-Version und die Architektur. Ist das /proc Dateisystem gemounted, so lassen sich mit "cat /proc/cpuinfo" Daten über die vorhandenen Prozessoren anzeigen. Welche letzten 10 Benutzer auf einem Multiuser-System angemeldet waren, zeigt uns "last -10" und die 3 letzten System-Reboots mit "last -3 reboot".

Traditionell steht der Runlevel S für Single-, 3 für Multiuser und 5 für Start des Grafiksystems. Diese Definition lockert sich je nach Distribution. "who -r" zeigt uns den aktuellen Runlevel und "uptime" die Zeit, seit dem das System "up", also eingeschaltet ist.

Der Befehle "mount", "df -h", und "du -sh" listet die aktiven Dateisysteme inklusive Type, Dimensionen und freien Platz in einer verständlichen Form ("-h") auf.

Ob unsere Shell eine interactive Shell ist, zeigt uns das Flag "i" in der Variablen "$-", nämlich "echo $- | grep -q i && echo interactive".

Shell-Skript

Der Grundaufbau eines Shell-Skripts sollte bei Meldungen den Namen den Skripts mit ausgeben und vor allem einen gültigen Exit-Wert:

> ME=$(basename $0); echo "$ME: Problem .."

Wie uns

> true ; echo $? ; false ; echo $?

verdeutlicht, steht der Wert "0" für eine erfolgreiche Ausführung, jeder andere Wert wäre nicht erfolgreich. Für die Shell steht "$? " für den letzten Exit-Wert eines Kommandos.

Wenn das erste Skript bei der Eingabe des Namens von der Shell nicht ausgeführt wird, kann dies mittels "bash myscript.sh" erreichen, oder man gibt dem Skript die für eine Ausführung nötigen Rechte per "chmod u+x myscript.sh". Als Superuser/ ROOT (UID=0) scheint die Shell das Script nocht oft nicht zu finden, obwohl dieses im aktuellen Verzeichnis vorliegt. Der Grund dafür ist, daß das aktuelle Verzeichnis nicht im Suchpfad der Shell vorhanden ist - für ROOT übrigens aus Sicherheitsgründen. Zwei Wege führen einfach zum Ziel:

# ./myscript.sh

oder:

# export PATH=.:$PATH; myscript.sh

Welche Zeilen im Script wie ausgeführt werden, ermöglicht der Aufruf der Shell mit dem Argument "-x", also "bash -x myscript.sh".

Pipe - Prozesse verknüpfen

Jeder gestartete Prozess hat im Minimum drei Datei-Handles (Filedescriptoren) offen:

  1. Standard-In (stdout): Eingabe Handle ID 0

  2. Standard-Out (stdin): Ausgabe Handle ID 1

  3. Standard-Err (stderr): Fehlerausgabe Handle ID 2

Die Ausgabe des einen Prozesses kann mit der Eingabe eines anderen Prozesses verknüpft werden. Hier liegen gerade die Stärken von Linux. Der Shell teilt man dies mittels der so genannten Pipe "|" mit. Damit wird die Shell angewiesen, beide Prozesse auszuführen und die Dateihandles miteinander zu verbinden.

Beispielsweise zeigt die Folge "cat /etc/passwd | grep --color root" alle Zeilen in /etc/passwd, die die Zeichenfolge "root" enthalten. "cat" gibt alle Zeilen auf stdout aus, "grep" liest von stdin. Bei einem so einfachen Bespiel liese sich dies natürlich zu "grep -color root /etc/passwd" optimieren.

Eine ganze Kette von Filtern kann so aufgebaut werden:

cmd1 | cmd2 | cmd3 | .. | cmdn

Möchte man stderr und stdout jeweils in eine andere Datei umleiten, dann geht dies per "cmd 2> error.txt > out.txt". Eine kombinierte Version in nur eine Datei wäre "cmd > errout.txt 2>&1". Die Syntax dabei ist folgende:

  1. Verknüpfe stdout von cmd mit der Datei "errout.txt"

  2. Leite stderr dahin um, wohin stdout zeigt

Prozess-Steuerung über die Tastatur

Die Shell nimmt interaktiv ihre Befehle über die Tastatur vom Benutzer entgegen und führt diese nacheinander aus. Wir können aber der Shell auch mitteilen, dass diese in den Hintergrund geschickt werden soll und so die Tastatur wieder für andere Aufgaben verfügbar ist.

Ein "find / -type f -name date" würde bei Eingabe die aktuelle Shell beschäftigen bis das Kommando sich beendet hat, was unter Umständen sehr lange dauern kann. Also ab damit in den Hintergrund mit "find / -type f -name date &".

Das "&" - auch bekannt als "Ampersand" - teilt der Shell mit, die Folge im Hintergrund auszuführen. Dies können wir verifizieren und uns den Status der Hintergrundprozessgruppe anschauen mit "jobs" - dort sollte "Running" und "find" erscheinen. Die Job-ID steht in eckigen Klammern.

Möchte man den zuletzt in den Hintergrund geschickten Aufruf wieder in den Vordergrund holen, um diesen beispielsweise zu beenden, dann genügt ein "fg" oder "fg <jobid>", wobei "<jobid>" die ID kennzeichnet.

Abarbeitung stoppen und wiederaufnehmen

Nun läuft der Aufruf zwar im Vordergrund, aber möchten wir dies wirklich? Falls nicht, halten wir die Prozesskette mittels "CTRL-Z" einfach an. "jobs" zeigt uns ebenfalls nach Stunden den Status "Stopped" an und wir entscheiden uns, für eine Abarbeitung im Hintergrund, nachdem das System nicht mehr so unter Last steht: "bg" oder "bg <jobid>".

Leider schreibt uns die Ausgabe unser Terminal voll, also brechen wir die Ausführung mit "fg" und "CTRL-C" hier ab und senden die Fehlermeldungen ins Nirwana und die Ausgabe von "find" in eine Datei:

find / -type f -name date 2>/dev/null > /tmp/findout.txt

"2>" leitet nur stderr um, "1>" oder ">" die Standardausgabe in unsere Datei. Das ganze schicken wir in den Hintergrund.

Die Shell informiert uns, wenn die Abarbeitung beendet ist, sobald diese einen Prompt (PS1) ausgibt. Möchte man über die Beendigung sofort informiert werden, muss man der Shell dies über die Option "notify" mitteilen: "set -b" zum unmittelbaren Status oder "set +b" für Nachricht beim Prompt. "set -o" zeigt den Status der Optionen.

Stop und Resume sind nur zwei hilfreiche Tastatur-Eingaben um die Ausgabe im Terminal anzuhalten und wieder zu Starten. "CTRL-s" hält dazu die Ausgabe an und "CTRL-q" startet diese wieder. Die aktuelle Tastaturbelegung für die genannten Funktionen lassen sich über die Terminaleinstellungen "stty -a" abfragen und auch setzen.

Aus dem täglichen Leben kaum noch wegzudenken ist die History-Funktion der Shell über die Tasten Cursor-UP und -DOWN. Die ganze History seit dem Start der Shell lässt sich über das integrierte "history" Kommando ausgeben. Dort enthaltene Einträge kann man beispielsweise über "!34" wieder ausführen - 34 wäre hier der Eintrag mit der Nummer 34.

Datei-Konsistenz bei Backup / Restore überprüfen

Oft möchte man verifizieren, ob Dateien nach dem Backup und Restore noch konsistend sind, oder ob es viele Dateien mit identischem Inhalt, aber verschiedenen Dateinamen und/oder Datei-/Zeitstempel im Dateisystem gibt.

Am einfachsten generiert man einen Hash-Wert, beispielsweise mit dem fast überall verfügbaren "md5sum".

Die Ausgabe sieht dabei wie folgt aus: "<hashwert> /pfad/datei"

Checksumme über Dateipfad bilden:

find /bin /sbin /usr/bin /usr/sbin -type f -exec md5sum {} \; > /tmp/MD5SUM_bin.txt

Nach dem Backup und Restore lassen sich dann diese Checksummen erneut bilden und mit den gespeicherten vergleichen:

md5sum -c /tmp/MD5SUM_bin.txt | grep -v OK

Dubletten und aktuelle Dateien aufspüren

Um mehrfach vorhandene Dateien (Dubletten) aufzuspüren, ist die Hash-Datei zu sortieren und mehrfach vorhandene und gleiche Hash-Werte auszugeben:

sort -k1,1 /tmp/MD5SUM_bin.txt | uniq -w 33 -D

Nun muss man sich entscheiden, welche Datei in welchem Pfad man behalten und welche löschen möchte. Möchte man ermitteln, welche Dateien am aktuellen Tag (seit Mitternacht) angelegt wurden, ohne auf die "-newer"-Syntax mit einer Vergleichsdatei zurückzugreifen, so bietet die Option "-d" von "date" die passende Lösung. "date -d’’ liefert den Zeitstempel für Mitternacht zurück, das heißt Stunde, Minute und Sekunde ist jeweils Null.

Unterstützt der Befehl "find" die "-newerXY" Syntax, dann sieht der Aufruf wie folgt aus:

find /var/spool -type f -newerct

Last but not least: "dmesg" gibt den Inhalt des Kernel-Ring-Buffers aus und das sind meist die Meldungen des Kernels und der Treiber, die auch über den "syslogd" nach "/var/log/messages" geschrieben werden. Unmittelbar nach dem Booten, lassen sich dort nützliche Informationen entnehmen. (cvi)

Dieser Artikel basiert auf einem Beitrag unserer Schwesterpublikation TecChannel. (ph)