Home Bash scripting How To Create GUI Dialog Boxes In Bash Scripts With Whiptail In Linux

How To Create GUI Dialog Boxes In Bash Scripts With Whiptail In Linux

By Karthick
Published: Updated: 19.2K views

A while ago, we briefly discussed about Zenity, a simple program that allows you to create graphical (GTK+) dialog boxes in command-line and shell scripts. In this article, we are going to discuss yet another GUI utility called Whiptail that can be used to create GUI dialog boxes in Bash scripts in Linux.

Not every script that you write needs a frontend graphical interface. But sometimes it would be better if you create a graphical interface instead of relying on interacting with the command line. In my case, if there is a long list of responses needed in the script I would choose to go with a graphical interface.

Whiptail is a friendly GUI utility that uses a newt programming library. Whiptail offers different dialog boxes for different purposes. Depending upon your use case you can use these dialog boxes to make your script more interactive.

Install Whiptail in Linux

Whiptail comes pre-installed with many distributions but if your distribution has no whiptail installed follow the below instructions to install it.

To check if whiptail is already installed run the following command.

$ which whiptail

To install Whiptail on Debian/Ubuntu and its derivative distributions, run the following command:

$ sudo apt install whiptail -y

Fedora/RHEL/CnetOS/AlmaLinux/Rocky Linux:

$ sudo dnf install newt

Arch Linux, EndeavourOS, Manjaro Linux:

$ sudo pacman -S whiptail

Alpine Linux:

$ apk add newt

Help Option

You can use --help flag which will display the list of supported dialog boxes and other options you can use. In total, there are 10 dialog box supported with various functionality and we will look at them about all in the upcoming sections.

$ whiptail -help
Box options: 
    --msgbox <text> <height> <width>
    --yesno  <text> <height> <width>
    --infobox <text> <height> <width>
    --inputbox <text> <height> <width> [init] 
    --passwordbox <text> <height> <width> [init] 
    --textbox <file> <height> <width>
    --menu <text> <height> <width> <listheight> [tag item] ...
    --checklist <text> <height> <width> <listheight> [tag item status]...
    --radiolist <text> <height> <width> <listheight> [tag item status]...
    --gauge <text> <height> <width> <percent>

1. Message Box

Message box will display messages to the user and wait till the user presses <ok> or <ESC> key. When you press <ok> it will throw a return code 0 and if you press <ESC> it will throw return code 255.

$ whiptail --title "Welcome Message" --msgbox "Howdy, Welcome to OSTechnix.." 8 78
Message Box
Message Box

Let's decode the above command.

--title This will add title to the window  
--msgbox  This will print the message you provide within the quotes.  
8 78  This set Height(8) and Width(78) of the window. 

You can open a new terminal and check for the whiptail process. It will be in a sleep state. Meaning - it is waiting for you to press <ok> or <ESC>.

$ ps -ef | grep -i whiptail 
karthick   20023    9251  0 22:41 pts/0    00:00:00 whiptail --title Welcome Message --msgbox Howdy, Welcome to OSTechnix.. 8 78 
karthick   20071   19379  0 22:41 pts/1    00:00:00 grep --color=auto -i whiptail 
$ ps -q 20023 -o state --no-headers 
S 

NOTE: State (S) -> interruptible sleep (waiting for an event to complete).

2. Info Box

Info is similar to the message box but the difference is unlike the message box info box will not wait for the user input. Use –-infobox flag and pass a string as an argument which will be displayed in the info box.

In some shells, info box will run but will not display any result. You have to change the terminal emulation and run it as I did in the below snippet.

$ TERM=ansi whiptail --title "Welcome Message" --infobox "Howdy, Welcome to OSTechnix.." 8 78 
Info Box
Info Box

3. Yes/No Box

Yes/No Box will display a dialog box with YES or NO option where if you choose <Yes> it will throw return code 0 and when you press <No> it will throw return code 1.

Use --yesno flag to prompt for the choice. Run the following snippet which combines the yes/no box and the message box. At first, it will display the Yes/No option, and depending upon your choice it will throw the return code.

Create a shell script, copy the below snippet, and run it.

#!/usr/bin/env bash

whiptail --title "CONFIRMATION" --yesno "Should I proceed" 8 78 
if [[ $? -eq 0 ]]; then 
  whiptail --title "MESSAGE" --msgbox "Process completed successfully." 8 78 
elif [[ $? -eq 1 ]]; then 
  whiptail --title "MESSAGE" --msgbox "Cancelling Process since user pressed <NO>." 8 78 
elif [[ $? -eq 255 ]]; then 
  whiptail --title "MESSAGE" --msgbox "User pressed ESC. Exiting the script" 8 78 
fi 
Yes/No Dialog Box
Yes/No Dialog Box

If you have no idea about bash conditional statements, take a look at our brief article on the same using the link below.

4. Text Box

Text box will read and print the file. In the below snippet I am reading the ostechnix.txt file. The flag –scrolltext allows you to use the mouse wheel to scroll vertically when you have long pages of text that do not fit into the current window.

$ whiptail --textbox --scrolltext ostechnix.txt 10 80
Text Box
Text Box

5. Redirections

The dialog boxes that you are going to see in the upcoming section require output to be stored in a variable and later use for processing. The return value from the widget is sent to stderr instead of stdout. So you have to swap stdout and stderr so that the result is stored in the variable.

You have to use the following expression to swap stdout and stderr.

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

Let’s try to understand the above expression. You know FD1 is the standard output and FD2 is the standard error.

  • 3>&1 - Anything that is redirected to file descriptor 3 is redirected to file descriptor 1.
  • 1>&2 - Anything that is sent to file descriptor 1(Stdout) is redirected to file descriptor 2.
  • 2>&3 - Anything that is sent to file descriptor 2(stderr) is redirected to file descriptor 3.

This way we are swapping stdout and stderr so the variable can store the return value from dialog boxes.

6. Password Box

Using the password dialog box you can type passwords that will not be displayed as plain text as you type. Use --passwordbox to prompt to enter the password.

$ whiptail --title "SET PASSWORD" --passwordbox "Choose a strong password"
Password DialogBox
Password DialogBox

When you press <ok>, it will throw the return code 0 and will return the password you typed to the console (stderr) if you are running from the terminal.

Output In Terminal
Output In Terminal

You need to capture the password into a variable then later use it in the script. As discussed in the Redirection section you have to redirect the result.

$ PASSWORD=$(whiptail --title "SET PASSWORD" --passwordbox "Choose a strong password" 8 78 3>&1 1>&2 2>&3)
$ echo "The password entered by the user is $PASSWORD"
Store Output In Variable
Store Output In Variable

7. Input Box

Input dialog box will prompt the user to provide the input. As with the password dialog box, the input given by you will be printed to the terminal if you are running it from the terminal. You have to use the redirections and store the value to a variable then later use for processing according to your program logic.

NEW_USER=$(whiptail --title "Create New User" --inputbox "Username to be created" 8 40 3>&1 1>&2 2>&3)
Input Box
Input Box
Store Output To Variable
Store Output To Variable

You can also set default input text. All you have to do is add the text after height and width. Below is the syntax where instead of [init] you will place the default text.

--inputbox <text> <height> <width> [init]

Example:

whiptail --title "Create New User" --inputbox "Username to be created" 8 40 noname
Default Text
Default Text

Now let’s combine the input box, password box, Yes/No Box and Text Box and write a simple user creation program to see how these dialog boxes can be coupled together.

8. Checklist Dialog Box

Checklist allows you to create a list of options that a user can select from.

--checklist <text> <height> <width> <listheight> [tag item status]...

Above is the syntax for creating a checklist dialog box. You have to use the --checklist flag followed by setting up the height and width of the dialog box.

The option <listheight> specifies how many lists are you going to create. Each list will be tagged with <status> which is set to ON or OFF. On points to list selected and Off points to no selection of list.

$ whiptail --title "SELECT PACKAGES TO INSTALL" --checklist \
"List of packages" 20 100 10 \
"chrome" "browser" OFF \
"pip3" "Python package manager" OFF \
"ksnip" "Screenshot tool" OFF \
"virtualbox" "virtualization software" ON

To select a list press space bar and use up and down arrows to move between the list. Once done press enter.

CheckList Dialog Box
CheckList Dialog Box

You can store the output to an array and later use it. The tag (“Chrome, pip3, ksnip, virtualbox”) names will be printed as output to stderr based on the selection.

SELECTED=($(whiptail --title "SELECT PACKAGES TO INSTALL" --checklist \
"List of packages" 20 100 10 \
"chrome" "browser" OFF \
"pip3" "Python package manager" OFF \
"ksnip" "Screenshot tool" OFF \
"virtualbox" "virtualization software" ON 3>&1 1>&2 2>&3))
$ echo ${SELECTED[@]} # Array of values

Sample output:

"pip3" "ksnip" "virtualbox"

If you have no idea about bash arrays, we have a detailed article about bash array. I suggest you take a look at the link below.

9. Radio List Dialog Box

Radio list dialog box is similar to the checklist dialog box but the only difference is you can only choose one option from the list. Syntactically both the radio list and checklist are the same.

--radiolist <text> <height> <width> <listheight> [tag item status]...

Example:

SELECTED=$(whiptail --title "Choose Only One Package" --radiolist \
"List of packages" 20 100 10 \
"chrome" "browser" OFF \
"pip3" "Python package manager" OFF \
"ksnip" "Screenshot tool" OFF \
"virtualbox" "virtualization software" OFF 3>&1 1>&2 2>&3)
Radio Button
Radio Button
$ echo $SELECTED
virtualbox

10. Menu Dialog Box

Menu dialog box is similar to the radio button dialog box. The only difference I feel is, in the radio button dialog box you have to press <space-bar> to select an item from the list then press enter. But in the menu dialog box, all you have to do is just press enter which will return the tag name to stderr.

The syntax is similar to the checklist and radio button but the only difference is there is no need for the "status" option to set ON/OFF in the menu dialog box.

--menu <text> <height> <width> <listheight> [tag item]

Example:

TO_RUN=$(whiptail --title "Menu example" --menu "Choose an option" 25 78 5 \
"backup" "Start taking defined backup" \
"restore" "restore from last backup" \
"Schedule" "Display active backup schedules" 3>&1 1>&2 2>&3)
Menu Dialog Box
Menu Dialog Box
$ echo $TO_RUN 
backup

11. Progress Bar

To create a progress bar you have to use the following syntax. First, you will pass a text which will be printed when the progress bar is running and set the height and width of the window followed by the percentage of the progress.

--gauge <text> <height> <width> <percent>

The progress percentage will be controlled by our logic. Take a look at the below snippet. I am redirecting the while loop to the progress bar and incrementing the COUNTER variable in 10 counts which will be used as the percentage of progress.

#!/usr/bin/env bash

COUNTER=0
while [[ ${COUNTER} -le 100 ]]; do
  sleep 1
  COUNTER=$(($COUNTER+10))
  echo ${COUNTER} 
done | whiptail --gauge "Running Data Loader" 6 50 ${COUNTER}

The progress bar will increment in the count of 10’s.

Progress Bar Dialog Box
Progress Bar Dialog Box

Conclusion

We have reached the end of this article. Here, we have briefly seen how to use Whiptail to create various dialog boxes in bash scripts. If you have already used whiptail and have any trick under the slave, share it with us through the comment box.

Resource:

You May Also Like

Leave a Comment

* By using this form you agree with the storage and handling of your data by this website.

This site uses Akismet to reduce spam. Learn how your comment data is processed.

This website uses cookies to improve your experience. By using this site, we will assume that you're OK with it. Accept Read More