Tools that extend Bash scripting
#!Bash
Admins write a great deal of code in scripting languages, and one of the most popular is Bash [1]. It has many of the basic attributes needed in a scripting language, such as variables, I/O redirection, functions, loops, conditional execution, arrays, pipes, branching, string manipulation, and so on. However, there are times when Bash can't do everything you want, and that's when you can bring in some external tools to help out.
A number of articles around the web discuss cool tricks you can do in Bash and "additions" or functions that people have created. I'll pick and choose some of these to highlight in this article. However, I must admit that I feel a little funny writing about extensions to Bash. After all, the reason Bash is so popular is that it comes with every distribution of Linux and is reasonably small and useful. Adding extensions possibly means adding new software dependencies, of which you have to be careful. With that in mind, I'll talk about some of the cooler extensions.
Pop-Up Notification Windows
One of the largest groups of extensions for Bash is GUI tools – which doesn't mean Bash can be used to code GUI interfaces, but it does allow simple GUI tools to be used within in a Bash script. This can be very useful if you are deploying an interactive Bash script for production (i.e., users).
To begin, install libnotify or libnotify-bin (for my CentOS 6 and 7 systems I installed libnotify). Make sure your Bash script is executable, and enter:
notify-send "Dinner is served" -t 10000
You should see something like Figure 1 on the screen.
The option -t 10000
makes sure the notification window stays up for 10 seconds.
The notify-send
command can create all kinds of pop-up notifications. For example, to add a title, a message, and an image to the pop-up window (Figure 2), enter:
notify-send "This is the Title" \ "Check out the cool icon" \ -i /home/laytonjb/SHELL_SCRIPTING/linux-icon.png \ -t 10000
If your application produces plots or images, a simple Bash script can pop up a notification displaying the image. In applications in which you typically watch a residual to determine when the solution is "converged," you can use "notify" to display the residual plot so the user can check the progress of the solution.
TUI/GUI Tools
Bash scripts have available a number of text-based user interface (TUI)/graphical user interface (GUI) tools [2] that usually fall in the category of popping up dialog boxes for user interaction, or for information. Although I still cling to my command-line interface, sometimes it's easier to click on buttons or enter information in boxes than to memorize the options for certain command-line tools (there, I said it). They don't have to be complicated and can be very useful.
One reason TUIs can be so powerful is that you can stay on the command line to interact with them. You don't need a working X setup on the system, which is common in the admin world.
tput (TUI): Tput is part of the ncurses package supplied with most Linux distributions. At first blush, tput [3] sounds really boring, but you can do some pretty interesting things with it, such as,
- move the cursor around the screen,
- set colors (background and foreground),
- set bold mode, and
- set reverse mode.
In essence, you can use tput for creating ASCII interfaces without having to use curses [4] or another tool.
Using the tput
command is pretty darn simple. The man pages don't give you a great deal of detail, but you can find a number of examples on the Internet because it's been around since about the 1980s. Listing 1 shows a simple script that illustrates some of the things tput can do. First, make the script executable, then run it to see the output in Figure 3.
Listing 1: Tput Multiple Choice Dialog
#!/bin/bash # clear the screen tput clear # Move the cursor to screen location (x,y) = (3,5) # Note that the top left of the screen is (0,0) tput cup 3 15 # Set the foreground color using an ASCII escape tput setaf 3 # Write a "title" to the screen echo "Title of the company" tput sgr0 # Write a menu title tput cup 5 17 # Set reverse mode tput rev echo "M-A-I-N M-E-N_U" tput sgr0 # Write first line of menu tput cup 7 15 echo "1. User" # Write second line of menu tput cup 8 15 echo "2. Service" # Get the user input # Set bold mode tput bold tput cup 10 15 read -p "Enter Your Choice [1-2] " choice tput clear tput sgr0 tput rc
The tput cup
command controls the location of the cursor, the tput sgr0
entries turn off the bold and reverse attributes, and tput rc
resets the cursor to a saved position (tput sc
, not used here) or its default 0 0
location at the top left-hand corner of the screen.
dialog (TUI): Dialog was developed quite a while ago – around 1993. With this utility, you can create dialog boxes from a shell script. Whereas tput
allows you to create simple menus in the terminal, dialog
goes to the next level and allows you to create text-based interfaces, including things like simple message boxes, menu boxes, radio buttons, multiple selection boxes, and more. The really cool thing is that it is all text based, using the curses library, so X is not needed.
Creating dialog boxes from a shell script, notably Bash, is straightforward. I'll start with a simple notification box that lets you know when a job has finished (Figure 4):
#!/bin/bash dialog --title "Message" --msgbox "You job is done" 5 30
The script for a more complicated multiple-selection dialog box (Listing 2) allows users to select multiple options from a list of items using the cursor and the enter key (Figure 5):
Listing 2: Multiple Selections
#!/bin/bash dialog --checklist "Choose toppings:" 10 40 3 \ 1 Cheese on \ 2 "Tomato Sauce" on \ 3 Anchoives off
You can find a number of TUI dialog box examples online [5] and read the dialog
man page [6] for more details. Finally, you can read a history of dialog
and the other TUI commands discussed here – whiptail
, kdialog
, and zenity
– online [7].
whiptail (TUI): Whereas dialog
uses the curses library, whiptail
[8] uses the newt library. Whiptail is not too different from Dialog, as this simple yes/no script for a TUI dialog box (Figure 6) shows:
#!/bin/bash whiptail --yesno "Do you want to continue?" --yes-button "Yes" --no-button "No" 8 40
Xdialog (GUI): One downside to a TUI is that it uses the entire terminal, which means you likely need to have several terminals open at once. Moreover, if a terminal application is running in the background, it might pop up a TUI while you're using the terminal for other work (how rude). However, if Dialog looks interesting, and you're willing to use X instead of a pure terminal, you can "port" your Dialog scripts to the similar Xdialog [9].
To pop up a dialog box in Xdialog [10] is as simple as in Dialog. Listing 3 shows how to create a simple Xdialog script (Figure 7).
Listing 3: Xdialog Script
#!/bin/bash Xdialog --radiolist "Select one" 20 40 10 \ tag1 item1 off \ tag2 item2 off \ tag3 item3 on
zenity (GUI): Zenity [11] is somewhat similar to Xdialog. It is open source, and perhaps more importantly, a cross-platform toolkit for creating dialog boxes from a shell script. Listing 4 is a simple script that creates a yes/no box (Figure 8), then pops up a response box based on your selection.
Listing 4: Zenity Dialog Box
#!/bin/bash if zenity --question --text="Please press a button."; then zenity --info --text="You pressed Yes\!" else zenity --error --text="You pressed No\!" fi
kdialog (GUI): Kdialog is similar to Xdialog and Zenity, but it focuses on using the Qt toolkit, as is used in KDE. The following script creates a kdialog user input box (Figure 9):
#!/bin/bash answer=$(kdialog --title "Input Dialog" --inputbox "How many grid points would you like to use?") echo $answer
A huge range of kdialog boxes are available online [12], but remember that using kdialog means your system will need to install the Qt libraries, which could add a number of dependencies.
Text-Based Data Plotting
While I'm discussing shell scripts, at some point you might want to create a quick and dirty data graph by plotting the data within a terminal (text) window. This graph will not be a publication-quality chart, but rather something that can give you a quick overview of information and doesn't require X. Text-based plotting options range from the familiar to Bash-like.
gnuplot: Gnuplot [13] is a cross-platform command-line charting tool that allows you to plot 2D and 3D data sets. It can output the charts directly to the screen, including in a terminal, or to a file (various file types are supported), or it can create LaTeX code.
Gnuplot can be run interactively, you can enter commands that manipulate the chart, or it can be run in batch mode. They key to creating an ASCII plot with gnuplot is the command set terminal dumb
, which creates the plot in the terminal (Figure 10):
#!/bin/bash gnuplot -persist <<-EOFMarker set terminal dumb plot sin(x) EOFMarker
bashplotlib: If you code in Python, you might be familiar with matplotlib [14], a widely used charting library for Python and other languages. A similar sounding library, bashplotlib [15], creates ASCII plots.
Installing the library is pretty simple using pip install bashplotlib
. However, because the library is written in Python, you have now added dependencies to your simple Bash shell – Python and bashplotlib; however, the ability to create ASCII charts might be worth the trade.
Bashplotlib has two types of plots: (1) hist
, a histogram, and (2) scatter
, a simple (x, y) plot. Each plot type has several options that you can discover by invoking help (e.g., hist --help
). Listing 5 is a simple script from the GitHub page that downloads a sample data file and then creates a histogram (Figure 11).
Listing 5: bashplotlib Histogram
#!/bin/bash dir=$(dirname "$0") curl -L 'https://dl.dropbox.com/s/yuxlaj8okcjta9t/exp.txt?dl=1' > "${dir}/data/exp.txt" echo 'plotting a histogram with colors' hist --file "${dir}/data/exp.txt" --colour blue
System Logging
Linux handily locates all system logs in /var/log/
, where you can go to look at system messages, login messages, and more. Wouldn't it be nice to put your own messages relevant to the system in /var/log/messages
, where system messages are logged? A utility named logger
[16] allows you to send messages to the system logs. Although users don't have access to these logs, system administrators can use them to track down problems.
One of the most obvious use cases for logger is to have production scripts enter information into the system log. For example, it could be part of a cron job that finds the used disk space of all users, or it could be used to track user usage. The simple two-line script that follows shows how to use logger to add data to the system logs (Figure 12):
#!/bin/bash logger "Just finished a job by user jlayton" logger " Date: `date` "
Summary
Simple scripting using languages such as Bash are extremely common in an admin's toolkit. Bash is installed with most Linux distributions, it is small in size, and it has few dependencies. Thus, it is an ideal tool for system administrators. However, there are times when Bash doesn't have all the capabilities you want, or you might want to take a script to the next level and include interaction with users.
To achieve this, you might have to install tools that supplement Bash, while adding additional dependencies. Some people might argue that if you are going to add tools (e.g., TUI/GUI) to Bash, you might as well convert to a more complete scripting language, such as Python or Perl. However, these tools can have a much larger footprint than Bash and can create even more external package dependencies. Which way you want to go is up to you, but be aware that Bash can be a very effective scripting tool with just a few additional tools.
This blog represents my own view points and not those of my employer, Amazon Web Services.