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.
Table of Contents
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
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
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
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
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"
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.
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"
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)
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
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.
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)
$ 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)
$ 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.
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:
Bash scripting guides:
- How To Use Date Command In Bash Scripting In Linux
- How To Debug Bash Scripts In Linux And Unix
- Bash Scripting – Parse Arguments In Bash Scripts Using getopts
- How To Create GUI Dialog Boxes In Bash Scripts With Zenity In Linux And Unix
- Bash Scripting – Case Statement
- Bash Scripting – Conditional Statements
- Bash Scripting – String Manipulation
- Bash Scripting – Printf Command Explained With Examples
- Bash Scripting – Indexed Array Explained With Examples
- Bash Scripting – Associative Array Explained With Examples
- Bash Scripting – For Loop Explained With Examples
- Bash Scripting – While And Until Loop Explained With Examples
- Bash Redirection Explained With Examples
- Bash Scripting – Variables Explained With Examples
- Bash Scripting – Functions Explained With Examples
- Bash Echo Command Explained With Examples In Linux
- Bash Heredoc Tutorial For Beginners