BASH dialog howto

Dialog - Utility für interaktive Shell Skripte

Das Shell Utility DIALOG
Dialog - Funktionen
Das Skript: test_dialog - the Tutoral Script
Rückgabewerte ohne Umweg über Datei

Das Shell Utility DIALOG

Dialog-Image
Main Menü des Tutorial Skripts - © 2007 - Bernd Holzhauer

Dialog ist ein einfacher Weg um BASH oder andere Shell Skripts interaktiv zu gestalten. Bei den meisten Linux Distributionen ist Dialog im Lieferumfang enthalten oder lässt sich sehr leicht mit Bordmitteln nachinstallieren.

Dialog ist ein super Utility. Es lässt sich relativ einfach in Shell Skripts einbinden. Leider gibt es nur wenig Beispiele im Netz. Dieses kleine HowTo mit einem ausführlichen Tutorial Skript weiter unten, soll die Verwendung von Dialog erleichtern.

Wozu überhaupt auf der Shell skripten oder programmieren? Dialog funktioniert auch mit Skripten auf UNIX/Linux-Rechnern, zu denen nur eine Telnet- oder SSH-Verbindng besteht.

zum Seitenanfang

Dialog - Funktionen (Parameter)

Die einzelnen Funktionen von Dialog werden über Parameter beim Aufrufen von Dialog übergeben. Eine kurze Übersicht der Möglichkeiten erhält man, wenn man Dialog ohne Parameter aufruft. Auf die Verwendung eines Dialog RC-Files wird im Beispiel bewusst verzichtet. Jedem Dialog Fenster muss die Höhe und Breite in Zeilen bzw. Zeichen mitgegeben werden. Dies ist leider etwas inkonsistent ... lässt sich jedoch durch Probieren sehr schnell ermitteln.

Ich habe im Tutorial, die für mich wichtigsten Funktionen eingebaut/getestet.

Allen Funktionen ist gemeinsam, dass die Dialog-Ausgabe auf den Standard Output geroutet ist. Funktionen die Parameter zurück liefern, übergeben diese defaultmäßig an Error Out und werden daher entsprechend mit 2>datei umgeleitet und anschließend aus der Datei gelesen. Im Fehlerfall muss man diese Datei lesen, da auch die Error-Meldungen dort landen.

Viele Dialoge können auch über eine Abbrechen-Funktion verlassen werden. Ob nun zuletzt [ok] oder [abbrechen] gewählt wurde, kann man über den RETURN-Code $? abfragen.

--calendar

dialog --calendar "Datum auswählen" 2 1 01 11 2007

Zeigt einen Monatskalender mit Datum vom 1.11.2007, in dem mit Tabulator und Cursor Tasten geblättert und ein bestimmtes Datum ausgewählt werden kann.

--checklist

dialog --checklist "tag item(s) to choose" 15 50 8 \
       01 "Erste Auswahl" off\
       02 "Zweite Auswahl" on\
       ...

Bietet die Möglichkeit per Checkboxen einen Multiselect durchzuführen. Je Auswahlmöglichkeit müssen 3 Parameter übergeben werden. Der 3te Parameter bestimmt per on/off die Vorselektion der Auswahl.

--fselect

dialog --fselect /home/bernd/ 10 60

Directory und File Auswahl. Wichtig ist der Slash am Ende der Pfadangabe. Dadurch wird das Verzeichnis gelesen und dargestellt. Mir gefällt diese File Auswahl nicht besonders gut, da die Navigation und Auswahl mir recht umständlich erscheint.

--gauge

dialog --gauge "Fertig zu:" 6 60 50

Stellt einen statischen semigrafischen Progress Balken dar. Die letzte Ziffer (hier 50) gibt die Fertigstellung in Prozent an. Ein komplettes Beispiel mit laufendem Balken siehe Skript Listing gauge() Funktion

--inputbox

Einfache Box zur Eingabeaufforderung.

--menu

Erlaubt den Aufbau von Menüs.

--msgbox

Dient der Augabe von Informationen, die mit [ok] bestätigt werden müssen.

--radiolist

dialog --radiolist "tag item(s) to choose" 15 50 8 \
       01 "Erste Auswahl" off\
       02 "Zweite Auswahl" on\
       ...

Entspricht --checklist, jedoch ist nur eine Selektion erlaubt. Das "Anklicken" einer Auswahl disabled automatisch die anderen Möglichkeiten.

--tailbox

Entspricht dem Aufruf von tail -f datei. Wird entsprechend in einem Fenster dargestellt.

--textbox

Ist ein Viewer für ASCII-Dateien mit der Möglichkeit zum Blättern.

--yesno

Einfach Dialogbox mit Ja/Nein Antwortmöglichkeit.

zum Seitenanfang

Das Beispiel Skript: test_dialog - the Tutoral Script

Das Skript Sample test_dialog fasst die wesentlichen Funktion von Dialog in einem Hauptmenü zusammen. Das eigentliche Programm besteht aus der while true Schleife am Ende des Skriptes. In ihr wird das Main Menu immer wieder aufgerufen.

Das Beispiel Skript selbst erfüllt keinen Zweck, sondern dient nur dem Testen und Präsentieren von Dialog Funktionen.

#!/bin/bash

#######################################################################
# Title      :    test_dialog
# Author     :    Bernd Holzhauer {bholz@cc-c.de}
# Date       :    2007-11-02
# Requires   :    dialog
# Category   :    Shell menu tools
#######################################################################
# Description
#   DIALOG test & demo
#   Sample Script without functionality - just to test and demonstrate
#   the usage of the dialog features
# Note:
#   - it draws a small main menu to try different dialog options
#######################################################################

_temp="/tmp/answer.$$"
PN=`basename "$0"`
VER='0.31'
dialog 2>$_temp
DVER=`cat $_temp | head -1`

### gauge demo ###
gauge() {
    { for I in $(seq 1 100) ; do
        echo $I
        sleep 0.01
      done
    echo 100; } | dialog --backtitle "Dialog - Progress sample" \
                         --gauge "Progress" 6 60 0
}

### File or Directory selection menu with dialog
file_menu() {
    fileroot=$HOME
    IFS_BAK=$IFS
    IFS=$'\n' # wegen Filenamen mit Blanks
    array=( $(ls $fileroot) )
    n=0
    for item in ${array[@]}
    do
        menuitems="$menuitems $n ${item// /_}" # subst. Blanks with "_"  
        let n+=1
    done
    IFS=$IFS_BAK
    dialog --backtitle "Dialog - Sample menu with variable items" \
           --title "Select a file" --menu \
           "Choose one of the menu points" 16 40 8 $menuitems 2> $_temp
    if [ $? -eq 0 ]; then
        item=`cat $_temp`
        selection=${array[$(cat $_temp)]}
        dialog --msgbox "You choose:\nNo. $item --> $selection" 6 42
    fi
}

### File Select sample 
file_select() {
    dialog --backtitle "Dialog - fselect sample"\
           --begin 3 10 --title " use [blank] key to select "\
           --fselect "$HOME/" 10 60 2>$_temp

    result=`cat $_temp`
    dialog --msgbox "\nYou selected:\n$result" 9 52
}

### create Today's calendar ###
calendar() {
    today=date +"%d %m %Y"
    echo "heute=$today"
    dialog --backtitle "Dialog - Calendar sample" \
           --calendar "choose a date" 2 1 $today 2>$_temp
    datum=`cat $_temp`
    dialog --title " Date selected " --msgbox "\nYour date: $datum" 6 30
}    

### Check List - multi select sample ###
checklist() {
    dialog --backtitle "Dialog - CheckList (multi select) sample" \
           --checklist "tag item(s) to choose" 15 50 8 \
           01 "first item to select" off\
           02 "second item - on by default" on\
           03 "third item" off\
           04 "more items ..." off 2>$_temp
    result=`cat $_temp`
    dialog --title " Item(s) selected " --msgbox "\nYou choose item(s): $result" 6 44
}    

### Radio List - single select sample ###
radiolist() {
    dialog --backtitle "Dialog - RadioList (single select) sample" \
           --radiolist "tag item to choose" 15 50 8 \
           01 "first item to select" off\
           02 "second item - on by default" on\
           03 "third item" off\
           04 "more items ..." off 2>$_temp
    result=`cat $_temp`
    dialog --title " Item(s) selected " --msgbox "\nYou choose item: $result" 6 44
}    

### Input Box sample 
inputbox() {
    dialog --backtitle "Dialog - InputBox sample"\
           --inputbox "Enter a line, please" 8 52 2>$_temp

    result=`cat $_temp`
    dialog --msgbox "\nYou entered:\n$result" 9 52
}

### Message Box sample - show versions 
version() {
    dialog --backtitle "Dialog - MessageBox sample" \
           --msgbox "$PN - Version $VER\na Linux dialog Tutorial\n\nusing:\n$DVER" 9 52
}

### Text Box sample - show file test.txt
textbox() {
    filename="test.txt"
    if [ -e $filename ]; then
        dialog --backtitle "Dialog - TextBox sample - use [up] [down] to scroll"\
               --begin 3 5 --title " viewing File: $filename "\
               --textbox $filename 20 70
    else
        dialog --msgbox "*** ERROR ***\n$filename does not exist" 6 42
    fi
}

### Form Sample ###
formbox () {
	dialog --backtitle "Dialog - Form sample" \
	    --form " Form Test - use [up] [down] to select input field " 21 70 18 \
	    "name" 2 4 "" 2 15 20 0\
	    "surname" 4 4 "" 4 15 20 0\
	    "city" 6 4 "" 6 15 20 0\
	    "county" 8 4 "Germany" 8 15 "-20" 0\
	    2>$_temp
	
	if [ ${?} -ne 0 ]; then return; fi   
    result=`cat $_temp`
    echo "Result=$result"
    dialog --title "Items are separated by \\n" --cr-wrap \
           --msgbox "\nYou entered:\n$result" 12 52
}

### Text Box sample - show file test.txt
tailbox() {
    dialog --backtitle "Dialog - TailBox sample"\
           --begin 3 5 --title " viewing File: /var/log/messages "\
           --tailbox /var/log/messages 18 70
}

### create main menu using dialog
main_menu() {
    dialog --backtitle "Dialog - Linux Shell Tutorial" --title " Main Menu - V. $VER "\
        --cancel-label "Quit" \
        --menu "Move using [UP] [DOWN], [Enter] to select" 17 60 10\
        Calendar "Show today's calendar "\
        Editor "Start vi editor with test.txt"\
        File "Show Dirctory & File selector"\
        Form "Show a form"\
        Home_Menu "Show files in \$HOME for selection"\
        Input "Show Box for typing a line"\
        Gauge "Progress bar"\
        Multi "Multi select list"\
        Radio "Single select list"\
        Show "Show file test.txt"\
        Tail "Watch /var/log/messages"\
        Version "Show program version info"\
        Quit "Exit demo program" 2>$_temp
        
    opt=${?}
    if [ $opt != 0 ]; then rm $_temp; exit; fi
    menuitem=`cat $_temp`
    echo "menu=$menuitem"
    case $menuitem in
        Gauge) gauge;;
        File) file_select;;
        Home_Menu) file_menu;;
        Input) inputbox;;
        Calendar) calendar;;
        Editor) vi test.txt;;
        Multi) checklist;;
        Radio) radiolist;;
        Show) textbox;;
        Tail) tailbox;;
        Version) version;;
        Form) formbox;;
        Quit) rm $_temp; exit;;
    esac
}

while true; do
  main_menu
done
zum Seitenanfang


Rückgabewerte ohne Umweg über Datei

Für ein sauberes Shell Programm ist es notwendig, die Existenz einer Rückgabe Datei zu prüfen und auch diese Datei beim Verlassen des Programms zu löschen. Das ist im Beispiel oben nicht der Fall.

Auf der Shell kann man die Ausgaben eines Programms jedoch auch einer Variablen zuweisen. Nutzt man die direkte Zuweisung, kann man sich die Rückgabe-Datei und die entsprechenden Routinen ersparen.

Liste=$(ls)
Die Variable $Liste enhält in dem Beispiel alle Namen des Directories.

Das gleiche funktioniert natürlich auch mit dialog Ausgaben. Nur dass man hier alle möglichen Rückgabewerte umleiten sollte. Dann können die Prüfungen entsprechend erfolgen.
Beispiel:

RESULT=$(dialog --inputbox "Enter a Line, please" 10 60 3>&1 1>&2 2>&3 3>&-); echo "Antwort: ${RESULT}"
In dem Beispiel wird Standard Out plus Error Out in eine Variable 3 geschrieben und von dort in die Variable RESULT übertragen. Diese kann dann leicht im Programm weiterverarbeitet werden. 3>&- löscht die Variable 3 anschließend.

Eine sehr gute Anleitung zum Rerouting auf der Shell finden Sie unter: Shells: Tutorial.