Aus Linux-Magazin 11/2011

Shellskripte aus der Stümper-Liga – Folge 17: Frage und Antwort

Soll ein Shellskript mit seinen Benutzern interagieren, braucht der zuständige Bash-Programmierer auf den Spatz nicht gleich mit der GUI-Toolkit-Kanone samt zusätzlicher Programmiersprache zu schießen. Wie das Kleinkaliber funktioniert, beschreibt dieser Artikel.

Unter [1] findet sich ein praktisches Skript für Wartungsarbeiten an WordPress-Datenbanken, seine ersten Zeilen zeigt Listing 1. Für den Datenbankzugriff braucht das Skript das zugehörige Passwort – der Programmierer hat sich offenbar der Einfachheit halber dazu entschlossen, dass der Benutzer es dem Skript als Parameter übergibt.

Mal abgesehen davon, dass das ganze Parameter-Handling nicht besonders robust gelöst ist, stellt die Übergabe von Passwörtern auf der Kommandozeile ein Sicherheitsrisiko dar. Denn jeder Benutzer kann die Prozessliste mit allen Parametern auslesen. Um diesen Designfehler zu vermeiden, muss das Skript selbst den Benutzer nach dem Datenbank-Passwort fragen, dessen Antwort entgegennehmen und verarbeiten.

Listing 1

wordpress-cleanup

01 #! /bin/bash
02
03 # Korrekte Parameteranzahl überprüfen
04 if [ $# -ne 4 ];
05 then
06    echo "Usage: wordpress-cleanup <Database> <Table-Prefix> <Username> <Password>"
07    exit 0
08 fi
09
10 # Variablen deklarieren
11 DATABASE=$1
12 WPPREFIX=$2
13 USERNAME=$3
14 PASSWORD=$4
15
16 # MySQL-Queries ausführen
17 mysql -u$USERNAME -p$PASSWORD $DATABASE <<EOF
18 [...]

Es kann kaum überraschen, dass die Bash auch für dieses Problem eine Lösung parat hält. Die Passwortabfrage ist aber nur ein Spezialfall für die Benutzereingabe einzeiliger Texte. Die Bash hat dafür den Befehl »read« und neuerdings »readarray« eingebaut. In Listing 2 verhindert die »read« -Option »-r« (für raw), dass ein Backslash als Escape-Zeichen wirkt. Die Option »-e« weist den Befehl an, die Readline-Bibliothek zu nutzen – der Anwender darf Bash-typisch in der Zeile navigieren.

Die Zeile 2 im Listing ist die klassische Passwortabfrage mit der »-s« -Option (für silent). Bei der letzten Variante führt »”-N 1″« dazu, dass der Anwender nur einen Buchstaben eingeben muss. Aus GUI-Sicht handelt es eher um eine Messagebox als um ein Eingabefeld.

Die Beispiele haben jeweils als letztes Argument nur eine Variable. Fehlt sie, schreibt Read den eingegebenen Wert in die Variable »REPLY« . Bei mehr als einer Variablen parst der Read-Befehl die Antwort. Read kennt noch ein paar Optionen mehr, die Manpage zur Bash gibt darüber ausreichend Auskunft.

Listing 2

Eingabefeld mit Bash-Mitteln

01 read -r -e -p "Bitte Wert eingeben: " zeile
02 read -p "Passwort: " -s passw
03 read -p "Sind Sie sicher? J/N: " -N 1 antwort

Längere Texte erfassen

Im manchen Fällen ist eine Zeile Eingabetext aber zu wenig. Wer längere Texte abfragen will, startet einfach einen Editor. Per Konvention steht der bevorzugte Editor in der Variablen »EDITOR« . Ist diese nicht gesetzt, dann ist der Vi die sicherste Wahl. Mit Bash-Mitteln gelingt es aber auch:

echo "Eingabe mit Strg-D beenden:"
textFeld="$(</dev/stdin)"

Die Anführungszeichen sind wichtig, ansonsten ersetzt die Bash die Zeilenumbrüche durch Leerzeichen. Diese Form ist sehr einfach und kompakt, verschafft dem Anwender aber keine Gelegenheit, im geschriebenen Text zu navigieren und Korrekturen durchzuführen.

Menüs und Auswahllisten

Menüs und Auswahllisten zaubert der Bash-Befehl »select« auf den Bildschirm. Ein Beispiel zeigt Listing 3. Es beschreibt einen einfachen Logfile-Browser, bei dem der Benutzer die gewünschte Datei nicht erst über »ls« suchen muss, sondern das Skript bietet ihm eine Liste zum Auswählen an. Der Befehl »select name in …« führt alle Wörter in der »in« -Liste als einzelne Listenpunkte auf und gibt daraufhin den PS3-Prompt aus. Das Beispiel setzt den Prompt in Zeile 3. Jetzt kann der Benutzer eine der vordefinierten Nummern eingeben, aber auch andere Antworten sind möglich.

Nur im ersten Fall landet der Wert der ausgewählten Nummer in der »select« -Variablen. Bei falscher Eingabe ist die Variable leer. Die eigentliche Eingabe des Anwenders, also die Nummer oder sonstiger eingegebener Text, landet immer in der Shellvariablen »REPLY« . Mit einem Dateiende-Zeichen ([Strg]+[D]) beendet der Benutzer die Auswahl.

Listing 3

Auswahlliste per select

01 #!/bin/bash
02
03 PS3="Auswahl der Log-Datei: "
04 select logfile in /var/log/messages* quit; do
05   echo -e "Log-Datei: $logfile\nAuswahl: $REPLY"
06   if [ -n "$logfile" ]; then
07     case "$logfile" in
08       quit) exit 0;;
09       *) less "$logfile";;
10     esac
11   elif [ "$REPLY" = "quit" -o "$REPLY" = "q" ]; then
12     exit 0
13   else
14     echo "Fehlerhafte Eingabe!" >&2
15   fi
16 done

Bestenliste

Als benutzerfreundlicher erweist sich das Anwendungspattern aus Listing 3. Zusätzlich zu den Dateinamen (»/var/log/messages*« ) steht der feste Wert »quit« in der »in« -Liste. Außerdem prüft das Programm bei einer falschen Eingabe, ob der Benutzer statt der Nummer irrtümlich »quit« oder zumindest »q« eingegeben hat (siehe Abbildung 1).

Abbildung 1: Das gestartete Skript aus <link href="#article_l3" class="listing" srcset=

Listing 3 präsentiert eine Liste zum Auswählen einer Logdatei.” width=”300″ height=”102″ /> Abbildung 1: Das gestartete Skript aus Listing 3 präsentiert eine Liste zum Auswählen einer Logdatei.

Auf die Anordnung der Liste hat der Programmierer keinen Einfluss. Wer eine spezielle Anordnung will oder statt der Nummern Buchstaben, muss das Menü selbst programmieren. Im Prinzip ist das aber nicht aufwändig: Eine »while true; do … done« -Schleife erfüllt den Zweck. Zuerst gibt das Programm per »echo« das Menü aus, anschließend liest es mit »read« die Antwort.

In einem alten, inzwischen von modernerer Software überholten Projekt des Autors kam diese Lösung zum Einsatz (siehe Abbildung 2). Das Programm leitete den Benutzer durch diverse Konfigurationsschritte, jeder erledigte Menüpunkt änderte seine Farbe von Rot nach Grün. All das gelang mit reinen Bash-Mitteln, für die verschiedenen Farben einschließlich der Cursorsteuerung im Fenster sorgten Terminal-Escape-Sequenzen.

Abbildung 2: Ein Menü mit Farben dank Terminal-Escape-Sequenzen.

Abbildung 2: Ein Menü mit Farben dank Terminal-Escape-Sequenzen.

Jenseits der Bash

Zwischen reine Bash-Mittel und eigene, interaktive Programme reihen sich noch Tools wie Dialog [2] oder Xdialog [3] ein. Das erste Werkzeug fußt auf Ncurses, das andere benötigt einen laufenden X-Server. Wer auf möglichst geringe Abhängigkeiten Wert legt, verzichtet natürlich auf solche Pakete. Andererseits sind die interaktiven Widgets beider Pakete deutlich schöner und benutzerfreundlicher als reine Bash-Mittel.

Vorbildliches Checkinstall

Zusammenfassend lässt sich feststellen, dass mit dem Benutzer interagierende Bash-Skripte je nach Anspruch an die Optik mit recht geringem Aufwand implementierbar sind. Neben Eingabefeldern umfasst das Vokabular Menüs und Abfragen (“Sind Sie sicher?”).

Vorbildlich sind Skripte wie etwa Checkinstall [4]. Der Anwender kann das Programm auf Wunsch komplett oder teilweise über Kommandozeilen-Parameter steuern. Alle fehlenden Angaben fragt »checkinstall« dann über interaktive Dialoge ab, so wie es dieser Artikel beschrieben hat. Damit ist das Tool nutzbar, ohne dass der Anwender sich durch lange Hilfeseiten quälen muss. Bei regelmäßigem Gebrauch – etwa aus Makefiles – läuft das Programm aber trotzdem vollautomatisch ab. (jk)

Der Autor

Bernhard Bablok betreut bei der Allianz Shared Infrastructure Services ein großes Datawarehouse mit technischen Performance-Messdaten von Mainframes bis zu Servern. Wenn er nicht Musik hört, mit dem Radl oder zu Fuß unterwegs ist, beschäftigt er sich mit Themen rund um Linux und Objektorientierung. Er ist unter mailto:mail@bablokb.de zu erreichen.

LINUX-MAGAZIN KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Readly Logo
E-Mail Benachrichtigung
Benachrichtige mich zu:
0 Kommentare
Älteste
Neuste Beste Bewertung
Inline Feedbacks
Alle Kommentare anzeigen
Nach oben