Whiptail

Commande

Whiptail est un programme Unix qui s'exécute en ligne de commande. Il est conçu pour être lancé à partir de scripts. Il propose d'afficher des boites de dialogue, des menus, des formulaires de saisie, et d'autres contenus qui permettent d'interagir avec le script.

La commande whiptail est très largement utilisée par les éditeurs de logiciels pour permettre de les configurer et la Fondation Raspberry l'utilise abondamment dans l'outil de configuration de son système d'exploitation Raspberry Pi OS avec la commande 'raspi-config'.

La commande whiptail doit être accompagnée d'une action qui détermine ce que la commande doit faire, comme afficher une information, un menu ou une liste d'options. L'action est suivie d'un texte qui s'affichera dans la boîte de dialogue pour donner le sens de cette action, comme le message d'information ou la liste des options du menu.

La taille d'affichage de la boîte de dialogue doit être également précisée. Elle se place à la fin de la commande sous la forme de deux nombres indiquant la hauteur et la largeur de la boite de dialogue. Ils sont exprimés en nombre de caractères. Par exemple, 10 60 indiquera que la boîte de dialogue fera 10 caractères de haut sur 60 caractères de large.

La commande whiptail peut avoir d'autres paramètres obligatoires en fonction de l'action choisie comme, pour un menu, le nombre d'options maximum à afficher en même temps dans la boite de dialogue. Elle peut aussi être accompagnée de paramètres optionnels comme le titre de la boîte de dialogue. Cette option bien que facultative est très couramment utilisée.

Les actions et options sont toutes précédées de deux signes '-' à l'exception des indicateurs de taille. En voici un exemple avec la commande...

whiptail --infobox "Mon message" --title "Mon titre" 10 60

…qui affichera une boîte de dialogue de 10 caractères de haut sur 60 caractères de large dont le titre sera "Mon titre" et le texte du message "Mon message" comme ci-dessous.

whiptail_demo1

Intégration de la commande dans un script

Dans ce blog nous utiliserons les scripts de type Bash qui sont les plus répandus dans le monde Unix.

Pour exécuter un script Bash il faut d'abord l'éditer. J'utilise dans ce blog l'éditeur nano. C'est un éditeur disponible avec quasiment tous les systèmes Unix qu'ils aient ou non une interface graphique. Il existe aussi l'éditeur vi ou vim qui est plus puissant mais aussi plus complexe à manipuler ou encore gedit qui est très facile à utiliser mais nécessite de disposer de l'interface graphique Gnome.

La création du script s'effectue avec la commande suivie du nom du fichier à éditer...

nano whiptail_demo.sh

On indique d'abord que le script est écrit en Bash puis l'on écrit la commande whitptail...

#!/bin/bash
whiptail --infobox "Mon message" --title "Mon titre" 10 60

Une fois que l'on a écrit le script et que l'on est sorti de l'éditeur il faut autoriser le script à pouvoir être exécuté. Cela se fait avec la commande...

chmod +x whiptail_demo.sh

On peut alors exécuter le script avec la commande...

./whiptail_demo.h

Gestion du code retour de la commande Whiptail.

La commande whiptail a été conçue pour gérer des interactions avec les scripts. Cela veut dire que l'on peut prendre des décisions avec cette commande et que ces décisions pourront être prises en compte plus tard dans le script.

Avant d'aller plus en avant, il faut d'abord savoir gérer dans un script le code retour d'exécution d'une commande Unix.

Prenons l'exemple du script...

#!/bin/bash
whiptail --yesno "Êtes-vous d’accord ?" 10 60
echo "Je continue"

...qui affichera la boîte de dialogue suivante...

whiptail_demo

Cette boîte de dialogue nous permet de choisir Oui ou Non. Mais une fois que l'on a pris cette décision il ne se passe rien. Le script ne sait pas quelle décision a été prise.

Une première chose à savoir est que lors de l'exécution d'une commande Unix, un compte rendu d'exécution de la commande est automatiquement enregistré dans une variable du système nommé '$?' que l'on appelle plus communément 'exitstatus' ou statuts de sortie. Pour exploiter ce statut de sortie d'exécution d'une commande il est impératif de l'utiliser immédiatement après l'exécution de la commande sinon sa valeur sera remplacée par le statut d'exécution de la nouvelle commande et ainsi de suite.

En affichant le résultat de l'exécution de la commande dans le script...

#!/bin/bash
whiptail --infobox "Mon message" --title "Mon titre" 10 60
echo $?
echo "Je continue"

On a la réponse...

  • 0 qui veut dire Oui ou Vrai (true).
  • 1 qui veut dire Non ou faux (false).

Je m'étale un peu sur la signification des valeurs car l'on retrouve ici les principes de la logique binaire qui régit tout programme informatique. Oui/Non -> Yes/no -> True/False -> 0/1

Et si l'on a décidé de sortir de la boîte de dialogue avec la touche 'ESC' on aura quand même un résultat...

  • 255

A savoir. Ce chiffre a également un sens d'un point de vue de la logique binaire car il s'agit de la valeur 2 à la puissance 8 (2^8) qui est la correspondance en décimale d'un octet de données dont les 8 bits de données sont à 1. Le bit et l'octet de données sont deux des piliers de l'informatique. Mais fermons cette parenthèse.

On peut alors affecter le résultat à une variable pour ensuite l'afficher...

#!/bin/bash
whiptail --infobox "Mon message" --title "Mon titre" 10 60
exitstatus=$?
echo $exitstatus
echo "Je continue"

On peut enfin tester la variable avec la commande 'if' et afficher un résultat différent en fonction du résultat de ce test...

#!/bin/bash
whiptail --infobox "Mon message" --title "Mon titre" 10 60
exitstatus=$?
if [[ $exitstatus = 0 ]]; then
    echo "Je continue."
else
    echo "Je m'arrête".
fi

On peut aussi tester le fait d'être sorti anormalement de la boîte de dialogue...

#!/bin/bash
whiptail --infobox "Mon message" --title "Mon titre" 10 60
exitstatus=$?
case $exitstatus in
    "0")
        echo "Je continue."
        ;;
    "1")
        echo "Je m'arrête".
        ;;
    *)
        echo "j'ai quitté anormalement la boîte de dialogue."
        ;;
esac

On aurait pu indiquer pour le troisième test la valeur '255' mais en indiquant la valeur '*' on indique que l'on traitera toutes les valeurs qui n'ont pas été traitées précédemment ce qui inclut la valeur '255'.

Gestion de la valeur de retour de la commande Whiptail.

Pour comprendre la commande whiptail et la manière dont il faut l'utiliser dans un script, Il faut faire la distinction entre le code retour d'exécution d'une commande Unix et la valeur que renvoie cette même commande.

Le code retour est purement technique. Il permet de s'assurer que la commande s'est exécutée correctement ou non. C'est ce que l'on a vue dans le chapitre précédent.

La valeur de retour est le résultat de l'exécution de la commande Unix ce qui dépend totalement de la commande. Dans le cas de la commande whiptail cela pourrait être une valeur saisie ou un choix dans un menu.

En général pour récupérer le résultat de l'exécution d'une commande Unix on l'écrit dans un script de la manière suivante...

mavariable=$(Commande Unix)

Mais pour la commande whiptail c'est plus compliqué. Elle "dessine" sa boite de dialogue dans le flux de sortie standard stdout. C'est à dire dans le terminal en fonction du réglage de la variable d'environnement TERM. Par conséquent, vous ne pouvez pas utiliser le flux de sortie standard de whiptail pour définir une variable puisque qu'elle récupérera dans ce cas la boîte de dialogue et non la valeur saisie.

D'autre part, whiptail écrit la valeur saisie par l'utilisateur provenant du flux d'entrée standard stdin dans le flux d'erreur standard stderr. Donc, encore une fois, vous ne pouvez pas utiliser le flux de sortie standard pour définir une variable.

Il faut donc pour que cela fonctionne intervertir les flux de données stdout et stderr pour que la saisie soit renvoyée à la variable. Cela se fait grâce à l'enchainement de commandes suivant...

3>&1 1>&2 2>&3

Pour comprendre cet enchainement il faut comprendre que les chiffres représentent les flux de données standards dans Unix :

  • 1 = stdout
  • 2 = stderr
  • 3 = nouveau flux de données temporaire pour la commande.

Ensuite le signe '>' indique que le flux est renvoyé vers le flux spécifié. Par exemple '1>2' indique que le flux de données stdout est renvoyé vers le flux de données stderr.

Enfin le symbole '&' indique que le flux renvoyé est ajouté au flux spécifié et ne le remplace pas. Donc '1>&2' indique que le flux stdout s'ajoute au flux stderr.

Ici l'ordre des commandes est important. On écrit tout d'abord que le résultat de la commande est écrit dans un nouveau flux de données '3' et que l'on ajoute se flux de données au flux de données '1' stdout. On indique ensuite que le flux 1 stdout est ajouté au flux 2 stderr. Et enfin que le flux 2 stderr est ajouté au flux 3. Par conséquent les sorties stdout et stderr sont inversées et notre commande va donc récupérer le contenu du flux stderr qui contient la valeur saisie... Et voilà.

L'exemple suivant à bout but de renvoyer la valeur saisie dans une boite de dialogue générée par la commande whiptail dans la variable myanswer. Il s'assure également que la commande whiptail s'est correctement exécutée en testant le code retour de la dernière commande exécutée...

#!/bin/bash
myanswer=$(whiptail --inputbox "Saisissez votre donnée" 10 60 3>&1 1>&2 2>&3)
exitstatus=$?
if ! [[ $exitstatus = 0 ]]; then
        echo "J'ai quitté anormalement la boite de dialogue"
        exit
fi
echo "Ma donnée = " $myanswer

Ce script introduit également la commande exit qui force l'arrêt du script. Dans cet exemple le script s'arrête si le code retour d'exécution de la commande whitpail n'est pas normal. Remarquez le '!' devant le test qui indique une négation et implique que le test ne soit pas réussi pour que les commandes qu'il englobe s'exécutent.

Les actions possibles avec la commande Whitpail.

La commande whiptail permet de réaliser les actions suivantes :

  • yesno : Afficher une boîte de dialogue avec deux boutons permettant de valider ou non le message affiché.
  • msgbox : Afficher un message qui doit être validé pour que le script Unix se poursuive.
  • infobox : Afficher un message tout en laissant l'exécution du script Unix se poursuivre.
  • inputbox : Afficher une boîte de saisie. La valeur saisie est retournée au script Unix pour qu'il puisse l'utiliser.
  • passwordbox : Afficher une boîte de saisie masquée. Les caractères saisis sont remplacés par des "*". La valeur saisie est retournée en clair au script Unix pour qu'il puisse l'utiliser.
  • textbox : Afficher le contenu d'un texte en provenance d'un fichier. Si le texte est plus grand que la zone d'affichage, on peut naviguer dans le texte avec les touches Haut, Bas, Gauche, Droite et revenir en haut du texte avec la touche Home.
  • menu : Afficher une liste de choix et retourner au script le choix qui a été fait.
  • checklist : Afficher une liste de choix et permettre d'en sélectionner plusieurs. Les choix sélectionnés sont renvoyés au script.
  • radiolist : Afficher une liste de choix et permettre d'en sélectionner une seule. Le choix sélectionné est renvoyé au script.
  • gauge : Afficher une barre de progression sous forme de pourcentage.

Les descriptions rédigées dans ce blog qui accompagnent chacune des actions de la commande whitpail proviennent de ma traduction personnelle et sans doute approximative du manuel Unix de la commande whiptail.

yesno

whiptail --yesno text height width

L'action yesno affiche une boîte de dialogue oui/non de hauteur height et de largeur width. La chaîne spécifiée par text s'affiche dans la boîte de dialogue. Si cette chaîne est trop longue pour tenir sur une seule ligne, elle sera automatiquement divisée en plusieurs lignes aux endroits appropriés. La chaîne de texte peut également contenir des caractères de saut de ligne "\n" pour contrôler explicitement les sauts de ligne. Cette boîte de dialogue est utile pour poser des questions auxquelles l'utilisateur doit répondre par oui ou par non. La boîte de dialogue comporte un bouton Oui et un bouton Non, dans lesquels l'utilisateur peut basculer entre les deux en appuyant sur la touche TAB.

Dans le script ci-dessous, l'action yesno de la commande whiptail est directement interprétée par un test du résultat de cette commande.

Le script...

#!/bin/bash
if (whiptail --yesno "Est-ce que ça marche" 10 60) then
    echo "Vous avez choisi 'OUI'"
else
    echo "Vous avez choisi 'NON'"
fi

… affichera ...

whiptail_yesno_01

L'appuie sur la touche TAB permet de passer d'une option à l'autre. L'appuie sur la flèche droite permet de sélectionner l'option NO. L'appuie sur la flèche gauche permet de sélectionner l'option YES. L'appuie sur la touche "Entrée" permet de valider le choix et de sortir de la boîte de dialogue. L'appuie sur la touche ESC sélectionne l'option NO et sort de la boîte de dialogue.

Les options suivantes peuvent être ajoutées à la commande :

  • --yes-button text : La valeur de text qui remplace le texte du bouton OK.
  • --no-button text = La valeur de text qui remplace le texte du bouton OK.

Le script...

#!/bin/bash
if (whiptail --yesno "Est-ce que ça marche" 10 60 --yes-button "OUI" --no-button "NON") then
    echo "Vous avez choisi 'OUI'"
else
    echo "Vous avez choisi 'NON'"
fi

… affichera...

whiptail_yesno_02

msgbox

whiptail --msgbox text height width

Une boîte de message est très similaire à une boîte oui/non. La seule différence entre une boîte de message et une boîte oui/non est qu'une boîte de message n'a qu'un seul bouton OK. Vous pouvez utiliser cette boîte de dialogue pour afficher n'importe quel message de votre choix. Après avoir lu le message, l'utilisateur peut appuyer sur la touche ENTREE pour que whiptail se ferme et que le script Bash appelant puisse continuer son opération.

Le script...

#!/bin/bash
whiptail --msgbox "Ceci est mon message" 10 60

… affichera ...

whiptail_msgbox

L'appuie sur la touche "Entrée" ou la touche ESC permet de sortir de la boîte de dialogue.

infobox

whiptail --infobox text height width

Une boîte d'information est essentiellement une boîte de message. Cependant, dans ce cas, whiptail se fermera immédiatement après avoir affiché le message à l'utilisateur. L'écran n'est pas effacé à la sortie de whiptail, de sorte que le message reste à l'écran jusqu'à ce que le script Bash appelant l'efface ultérieurement. Ceci est utile lorsque vous souhaitez informer l'utilisateur que certaines opérations en cours peuvent nécessiter un certain temps pour se terminer.

#!/bin/bash
whiptail --infobox "Ceci est un message d'information" 10 60

… affichera ...

whiptail_infobox

inputbox

whiptail --inputbox text height width [init]

Une zone de saisie est utile lorsque vous souhaitez poser des questions nécessitant que l'utilisateur saisisse une chaîne comme réponse. Si init est fourni, il est utilisé pour initialiser la chaîne d'entrée. Lors de la saisie de la chaîne, la touche RETOUR ARRIÈRE peut être utilisée pour corriger les erreurs de frappe. Si la chaîne d'entrée est plus longue que la largeur de la boîte de dialogue, le champ d'entrée défile. En quittant, la chaîne d'entrée sera imprimée sur stderr.

Le script...

#!/bin/bash
myAnswer=$(whiptail --yesno "Est-ce que ça marche ?" 10 60 3>&1 1>&2 2>&3)
echo $myAnswer

… affichera ...

whiptail_input_01

… et renverra la valeur saisie dans la variable de script myAnswer.

La commande peut être suivie d'un texte qui s'affichera comme valeur de saisie par défaut dans la boîte de dialogue.

Le script...

#!/bin/bash
myAnswer=$(whiptail --yesno "Est-ce que ça marche ?" 10 60 "OUI" 3>&1 1>&2 2>&3)
echo $myAnswer

… affichera ...

whiptail_input_02

On peut aussi ajouter un contrôle sur le statut de sortie afin de s'assurer que l'on n'a pas quitter la commande avec la touche ESC.

Le script...

#!/bin/bash
myAnswer=$(whiptail --yesno "Est-ce que ça marche ?" 10 60 3>&1 1>&2 2>&3)
existatus = $?
if [ $exitstatus = 0 ]; then
   echo $myAnswer
else
   echo "La saisie a été annulée.
fi

S'assurer que l'on est sorti normalement du script est très utile et l'ajout d'un test de contrôle doit toujours être pris en considération lors de la rédaction d'un script faisant appel à la commande whiptail.

passwordbox

whiptail --passwordbox text height width [init]

Une zone de mot de passe est similaire à une zone de saisie, mais le texte saisi par l'utilisateur n'est pas affiché en clair. Ceci est utile lorsque vous demandez des mots de passe ou d'autres informations sensibles. Sachez que si quelque chose est passé dans "init", il sera visible dans la table de processus du système pour les espions occasionnels. De plus, il est très déroutant pour l'utilisateur de lui fournir un mot de passe par défaut qu'il ne peut pas voir. Pour ces raisons, l'utilisation de "init" est fortement déconseillée.

Le script...

#!/bin/bash
myAnswer=$(whiptail --passwordbox "Saisissez votre mot de passe" 10 60 3>&1 1>&2 2>&3)
echo $myAnswer

… affichera ...

whiptail_passwordbox

textbox

whiptail --textbox file height width

Une zone de texte permet d'afficher le contenu d'un fichier texte dans une boîte de dialogue. C'est comme une simple visionneuse de fichiers texte. L'utilisateur peut se déplacer dans le fichier en utilisant les touches UP/DOWN, PGUP/PGDN et HOME/END disponibles sur la plupart des claviers. Si les lignes sont trop longues pour être affichées dans la boîte, les touches GAUCHE/DROITE peuvent être utilisées pour faire défiler la zone de texte horizontalement. Pour plus de commodité, des fonctions de recherche vers l'avant et vers l'arrière sont également fournies.

Le script...

#!/bin/bash
whiptail --textbox file.txt 10 60

… affichera ...

whiptail_textbox_01

Dans l'exemple présenté, le texte affiché provient du fichier texte file.txt qui se trouve au même endroit que le script.

Si le texte à afficher est plus grand que la zone d'affichage, il faut rajouter l'option --scrolltext à la commande pour que vous puissiez naviguez vers le haut et le bas du texte avec les touches flèche haut et bas.

Le script...

#!/bin/bash
whiptail --textbox file.txt 10 60 --scrolltext

… affichera ...

whiptail_textbox_02

whiptail --menu text height width menu-height [ tag item ] ...

Comme son nom l'indique, une boîte de menu est une boîte de dialogue qui peut être utilisée pour présenter une liste de choix sous la forme d'un menu à choisir par l'utilisateur. Chaque entrée de menu se compose d'une chaîne de balise et d'une chaîne d'élément. La balise donne un nom à l'entrée pour la distinguer des autres entrées du menu. L'élément est une brève description de l'option représentée par l'entrée. L'utilisateur peut se déplacer entre les entrées du menu en appuyant sur les touches HAUT/BAS, la première lettre de l'étiquette servant de raccourci.

#!/bin/bash
myChoice=$(whiptail --menu "faites votre choix" 11 60 3 \
 "A" "Choix 1" \
 "B" "Choix 2" \
 "C" "Choix 3" 3>&1 1>&2 2>&3)
echo $myChoice

... affichera ...

whiptail_menu

… et renverra la valeur d'index A, B ou C dans la variable de script myChoice en fonction de l'option de menu choisie.

checklist

whiptail --checklist text height width list-height [ tag item status ] ...

Une zone de liste de contrôle est similaire à une zone de menu en ce sens qu'il existe plusieurs entrées présentées sous la forme d'un menu. Vous pouvez sélectionner et désélectionner des éléments à l'aide de la touche ESPACE.

Le script...

#!/bin/bash
myChoice=$(whiptail --checklist "faites votre sélection" 12 60 4 \
 "A" "Choix 1" OFF\
 "B" "Choix 2" ON \
 "C" "Choix 2" OFF \
 "D" "Choix 3" ON 3>&1 1>&2 2>&3)
echo $myChoice

… affichera ...

whiptail_checklist

Il renverra la liste des options sélectionnées, dans cet exemple...

"B" "D"

Les valeurs OFF et ON indiquent si l'option est sélectionnée ou non par défaut.

radiolist

whiptail --radiolist text height width list-height [ tag item status ] ...

Une boîte de liste radio est similaire à une boîte de menu. La seule différence est que vous pouvez indiquer quelle entrée est actuellement sélectionnée en définissant son statut sur activé.

Le script...

#!/bin/bash
myChoice=$(whiptail --radiolist "faites votre choix" 12 60 4 \
 "A" "Choix 1" OFF\
 "B" "Choix 2" ON \
 "C" "Choix 2" OFF \
 "D" "Choix 3" OFF 3>&1 1>&2 2>&3)
echo $myChoice

… affichera ...

whiptail_radiolist

Il renverra l'option sélectionnée, dans cet exemple...

B

gauge

whiptail --gauge text height width percent

Une jauge affiche une barre de progression au bas de la boîte. Le compteur indique un pourcentage. Les nouveaux pourcentages sont lus à partir de l'entrée standard, un entier par ligne. Le compteur est mis à jour pour refléter chaque nouveau pourcentage. Si stdin est XXX, la première ligne suivante est un pourcentage et les lignes suivantes jusqu'à ce qu'un autre XXX soit défini comme nouvelle valeur. La jauge sort lorsque EOF est atteint sur stdin.

Le script...

#!/bin/bash
{
    for ((i = 0 ; i <= 100 ; i+=20)); do
        sleep 1
        echo $i
    done
} | whiptail --gauge "Veuillez patienter" 6 60 0

… affichera tout en l'animant...

whiptail_gauge

Cet exemple utilise l'enchainement de commandes avec le symbole '|'. Quand on enchaine des commandes le résultat de la commande est envoyée dans le flux de données d'entrée stdin de la commande suivante. Dans le cas de l'action gauge de la commande whiptail le flux stdin est interprété comme étant la valeur du pourcentage à afficher. Ce flux de données stdin remplace la valeur du dernier paramètre de la commande whiptail, ici '0' qui est obligatoire mais n'est pas utilisé.

Previous Post