How to integrate dialog boxes in shell scripts with Whiptail

The ability to create secure shell scripts is essential not only for system administrators, but also for users who wants to automate repetitive tasks. Sometimes, from our shell scripts, we need to provide the user with some kind of information, ask him/her to provide some input, choose from a set of alternatives, or just ask for his/her confirmation before performing a potentially dangerous operation. All those actions, can be performed from the command line, of course, but to make our scripts more user-friendly, we can use of Whiptail to customize and display textual widgets.

In this article we see how can we make our scripts more user-friendly by using textual widgets created with Whiptail.

In this tutorial you will learn:

  • How to install whiptail and the newt library in some of the most used Linux distributions
  • How to use whiptail to produce textual user interface widgets from our shell scripts
  • How to use the messagebox widget to display a simple message
  • How to use the yesno widget to let the user perform a binary choice
  • How to get user input with the inputbox and passwordbox widgets
  • How to create menus with the menu and checklist widgets
How to integrate dialog boxes in shell scripts with Whiptail
How to integrate dialog boxes in shell scripts with Whiptail
 
Software requirements and conventions used
Category Requirements, Conventions or Software Version Used
System Distribution independent
Software Whiptail
Other Administrative privileges to install Whiptail
Conventions # – requires given linux-commands to be executed with root privileges either directly as a root user or by use of sudo command $ – requires given linux-commands to be executed as a regular non-privileged user

Installation

Whiptail and the “newt” library are free and open source software. Similarly to dialog and the ncurses library, they can be used display textual widgets from shell scripts. Whiptail is available in the repositories of all the most used Linux distributions. To install it on Fedora, we can run:

$ sudo dnf install newt

On Debian and other Debian-based Linux distributions, instead, we install the whiptail package directly. We can do it by using apt:

$ sudo apt install whiptail

On Archlinux, instead, to obtain Whiptail we need to install the libnewt package which is part of the “Community” repository. We perform the installation using the pacman package manager:

$ sudo pacman -Sy libnewt

How to use whiptail to display widgets

We can use Whiptail to make our interactive shell scripts more user-friendly. Let’s see some example of its usage.

Displaying a simple message

In our first example, we demonstrate how to use Whiptail to display a simple message to the user. In order to do that, we launch the command with the --msbox option. As arguments to the command, we provide:

  1. The text to be displayed to the user
  2. The height of the widget (expressed in rows)
  3. The width of the widget  (expressed in columns)
$ whiptail --msgbox "This is a simple message!" 10 30



Here is the widget produced by the command:

A simple message box created with Whiptail
A simple message box created with Whiptail

Displaying a yes/no dialog

To display some kind of message to a user and let him perform a simple “binary” choice, we can launch whiptail with the --yesno flag. The arguments we need to provide are the same we used in the previous example. Here we create a dialog we can use to ask for user confirmation:

$ whiptail --yesno "Are you sure you want to perform the action?" 10 30

Here is the output produced by the command:

A yes/no choice dialog created with Whiptail
A yes/no choice dialog created with Whiptail



We can determine the choice selected by the user by checking the exit code of the command stored in the $? shell variable: it will be 0 if the affirmative answer is selected, 1 otherwise.

Asking for input

In the previous example we used the “yesno” widget to ask the user to perform a binary choice. In certain situations, we may need to ask the user to provide a more generic input in the form of a string. Suppose, for example, we want to ask the user to provide an “username”. To accomplish this task we launch Whiptail with the --inputbox option. The arguments we need to provide are the same we saw in the previous examples, plus an optional one, [init]: we can use it to specify  a “placeholder” for the input. Here is an example:

$ whiptail --inputbox "What is your username?" 10 30 "root"

The command produces the following dialog:

An input box widget created with Whiptail
An input box widget created with Whiptail

How to retrieve or store the user input? If the user presses “Ok”, the input it provided is printed to standard error. Supposing we want to “store” the input in a variable, we would run:

$ username="$(whiptail --inputbox "What is your username?" 10 30 "root" 3>&1 1>&2 2>&3)"

What are all those redirections at the end of the command? As we know there are three file descriptors used by the shell: standard input (0), standard output (1) and standard error (2). Whiptail uses the standard output file descriptor to display widgets, and, as we already said, prints the input of the user to standard error. When we use the command substitution mechanism, a command is substituted by its output, which is what we usually store in a variable.  In this case, however, what we want to store in the variable is the standard error produced by the command, therefore we need to swap standard output and standard error to achieve our goal. How can we do this?

When we perform a redirection, we duplicate a file descriptor into another. For, example, if we write:

1>&2

What we are saying is: “use a duplicate of the standard error file descriptor (2) for standard output”. To swap the standard output and standard error file descriptors, therefore we can write:

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

With those redirections we:

  1. Duplicate file descriptor 1 (standard output) to file descriptor 3
  2. Duplicate file descriptor 2 (standard error) to file descriptor 1 (standard output)
  3. Duplicate file descriptor 3 (which, in the first step we made a duplicate of the original standard output) to file descriptor 2 (standard error)

In other words, we just swapped standard error and standard output. We used an extra file descriptor (3) as a “temporary place” to store the original standard output, which otherwise would be lost. At this point the string entered as input by the user is printed to standard output and, since we used command substitution, is “stored” in the “username” variable:

$ echo $username
root

Prompting the user to enter a password

The “password” dialog works similarly to the “input” one: the only difference is that the characters entered by the user are not displayed as he/she types, for security reasons. To create a password dialog we launch Whiptail with the --passwordbox option. Here, just as we did in the previous example, we store the input in a variable:

$ password="$(whiptail --passwordbox "Please enter your password:" 10 30 3>&1 1>&2 2>&3)"

The widget generated by the command:

The password input widget
The password input widget

Displaying a menu

The menu box is created by launching whiptail with the --menu option, and can be used to present the user to choose an entry among a list of alternatives. As arguments to the option we provide the usual arguments plus the menu-height and a tag/ item pair for each choice we want to include in the menu. The “tag” represents the name of the choice, the “item” is a description of it. Here is an example:

$ whiptail \
  --menu "What is your favorite shell?" 10 35 2 \
  "Bash" "(Bourne Again shell)" \
  "Zsh"  "(Z-Shell)"

Here is the result of the command:

A "menu" widget generated with Whiptail
A “menu” widget generated with Whiptail – The user can select only one entry.



The user can navigate the menu by using the UP and DOWN keys. The entry he selects is printed to the standard error descriptor, once he/she presses <Ok>.

Letting the user select more than one choice

When the “menu” widget is used, the user is allowed to select only one entry of those we provide. If we want to allow multiple selections, we have to use the “checklist” widget. We can generate it by launching Whiptail with the --checklist option. The syntax we need to use is similar to that of the --menu, except that for each choice we have to specify the checkbox status, as you can see in the following example:

$ whiptail \
  --checklist "What are your favorite shells?" 10 40 3 \
  "Bash" "(Bourne Again shell)" 1 \
  "Zsh"  "(Z-Shell)" 0 \
  "Dash" "(Dash shell)" 0

As you can see, for each menu entry we provided:

  1. A tag
  2. A description
  3. The checkbox status: here 0 and 1 means checked and unchecked, respectively
A checklist widget generated with Whiptail
A checklist widget generated with Whiptail – The user can select more than one entry.

The user can navigate with the UP and DOWN keys through the menu, and select/unselect entries with the SPACE key. The selected choices are printed, space-separated, to standard error, as usual.

Conclusions

In this tutorial we saw how to install Whiptail on some of the most used Linux distribution, and we learned how to use it to display textual user interface widgets from our shell scripts. We created some input widgets, and we learned how to retrieve and store the user choices. Here we just scratched the surface of what we can do with Whiptail; you can learn more by reading the manual.



Comments and Discussions
Linux Forum