Automation With Bash Scripts: Initialization and sanity testing





Last Updated on 11/25/2023 by dboth

In the first article in this series we created our first, very small, one-line Bash script. We also explored the reasons for creating shell scripts and why they are the most efficient option for the system administrator, rather than compiled programs. In the second article, we began the task of creating a fairly simple template that we can use as a starting point for other Bash programs. We learned how to create and use a simple help function. In order to create our help facility we also learned about using functions and how to handle command line options such as -h.

In this installment we learn more about variables and initializing them as well as how to do a bit of sanity testing to help ensure the program is run under the proper conditions. Remember, our objective is to build working code that will be used for a template for future Bash programming projects. The idea is to make getting started on new programming projects easy by already having common elements available in the template.

Variables

Like all programming languages, the Bash shell can deal with variables. A variable is a symbolic name that refers to a specific location in memory that contains a value of some sort. The value of a variable is changeable, i.e., it is variable. We looked at using variables in my article, Programming Bash: Getting Started, so if you are not familiar with using variables you can read that before we go any farther.

Done? Great! Let’s now look at some good practices when using variables.

I always set initial values for every variable used in my scripts. I do this in our template script immediately after the procedures as the first part of the main program body, before processing the options. Initializing each variable with an appropriate value can prevent errors that might occur with uninitialized variables when used in comparison or math operations. Placing this list of variables in one place allows me to see all of the variables that are supposed to be in the script and their initial values.

Our little script so far has only a single variable, $option, so let’s set that. Insert the following lines as shown.

################################################################################
################################################################################
# Main program                                                                 #
################################################################################
################################################################################
# Initialize variables
option=""
################################################################################
# Process the input options. Add options as needed.                            #
################################################################################

Test this to ensure that everything works as it should and that nothing has broken as the result of this change.

Constants

Constants are variables, too – at least they should be. Use variables wherever possible in CLI programs instead of hard-coded values. Even if you think you will only use a particular value once, such as a directory name, a file name, or a text string, create a variable and use the variable where you would have placed the hard-coded name.

For example, the message we print as part of the main body of the program is a string literal, echo “Hello world!”. Let’s change that to a variable. First, add the following statement to the variable initialization section. I like to keep the variable assignments in alphanumeric sorted order to make them easier to find as the list grows longer.

Msg="Hello world!"

And now change the last line of the program from:

echo "Hello world!"

to:

echo "$Msg"

Test the results.

Sanity checks

Sanity checks are simply tests for conditions that need to be true in order for the program to work correctly. For example, the program must be run as the root user or it must run on a particular distribution and release of that distro.

Let’s add a check for root as the running user to our simple program template. Testing for root as the user running the program is easy. When a program runs, it is run as the user that launches it. This is a security strategy designed to prevent users from escalating their privilege level to that of root. The id command can be used to determine the numeric user ID that the program is running under. The id command provides us with several bits of information when used without any options.

[dboth@testvm1 testdir6]$ id
uid=1000(dboth) gid=1000(dboth) groups=1000(dboth),10(wheel)
[dboth@testvm1 testdir6]$ 

Using the -u option just returns the UID of the user. This number is easily usable in our Bash program.

[dboth@testvm1 testdir6]$ id -u
1000
[dboth@testvm1 testdir6]$

Add the following function to the program. I added it after the help procedure but you can place it anywhere in the procedures section. The logic is that if the UID is not zero, which is always the root user’s UID, the program exits.

################################################################################
# Check for root.                                                              #
################################################################################
CheckRoot()
{
   if [ `id -u` != 0 ] 
   then
      echo "ERROR: You must be root user to run this program"
      exit
   fi  
}

Now add a call to the CheckRoot procedure just before the variable initialization. Test this, first running the program as the student user…

[dboth@testvm1 testdir6]$ ./BashTemplate.sh
ERROR: You must be root user to run this program

… and as the root user.

[root@testvm1 testdir6]# ./BashTemplate.sh
Hello world!

We may not always need this particular sanity test, so comment out the call to CheckRoot but leave all the code in place for our template. That way all we need to do in order to use that code in a future program is to uncomment the call.

The code

After making the changes descussed in this article, our code now looks like this.

#!/bin/bash
################################################################################
#                              BashTemplate                                    #
#                                                                              #
# Use this template as the beginning of a new program. Place a short           #
# description of the script here.                                              #
#                                                                              #
# Change History                                                               #
# 11/11/2019  David Both    Original code. This is a template for creating     #
#                           new Bash shell scripts.                            #
#                           Add new history entries as needed.                 #
#                                                                              #
#                                                                              #
################################################################################
################################################################################
################################################################################
#                                                                              #
#  Copyright (C) 2007, 2019 David Both                                         #
#  LinuxGeek46@both.org                                                        #
#                                                                              #
#  This program is free software; you can redistribute it and/or modify        #
#  it under the terms of the GNU General Public License as published by        #
#  the Free Software Foundation; either version 2 of the License, or           #
#  (at your option) any later version.                                         #
#                                                                              #
#  This program is distributed in the hope that it will be useful,             #
#  but WITHOUT ANY WARRANTY; without even the implied warranty of              #
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
#  GNU General Public License for more details.                                #
#                                                                              #
#  You should have received a copy of the GNU General Public License           #
#  along with this program; if not, write to the Free Software                 #
#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA   #
#                                                                              #
################################################################################
################################################################################
################################################################################

################################################################################
# Help                                                                         #
################################################################################
Help()
{
   # Display Help
   echo "Add description of the script functions here."
   echo
   echo "Syntax: scriptTemplate [-g|h|v|V]"
   echo "options:"
   echo "g     Print the GPL license notification."
   echo "h     Print this Help."
   echo "v     Verbose mode."
   echo "V     Print software version and exit."
   echo
}
################################################################################
# Check for root.                                                              #
################################################################################
CheckRoot()
{
   if [ `id -u` != 0 ]
   then
      echo "ERROR: You must be root user to run this program"
      exit
   fi
}

################################################################################
################################################################################
# Main program                                                                 #
################################################################################
################################################################################

# CheckRoot

# Initialize variables
Msg="Hello world!"
option=""
################################################################################
# Process the input options. Add options as needed.                            #
################################################################################
# Get the options
while getopts ":h" option; do
   case $option in
      h) # display Help
         Help
         exit;;
     \?) # incorrect option
         echo "Error: Invalid option"
         exit;;
   esac
done

echo $Msg

Final exercise

You probably noticed that the Help function in our code refers to some features we have not included in this code. As a final exercise, you should add those functions to the code template we have created.

Summary

In this article we’ve created a couple functions to perform sanity tests for whether the program is running as root and which distro it is running on. Our program is getting a little more complex and so testing is becoming more important and requires more test paths in order to be complete.

By now you get the idea. In this series we have looked at a very minimal Bash program and we have seen how to build a script up a bit at a time. Our end result is a simple template that can be the starting point for other, more useful Bash scripts and which contains some useful elements that make it easy to start new scripts.

Compiled programs are necessary and fill a very important need. But for sysadmins there is always a better way. We should always use shell scripts to meet the automation needs of our jobs. Shell scripts are open; their content and purpose are knowable. They can be readily modified to meet differing requirements. Personally, I have found nothing that I have ever needed to do in my SysAdmin role that could not be accomplished with a shell script.

What we have created so far is just the beginning. As you write more Bash programs of your own, you will find more bits of code that you use frequently and that should be included in your program template.


Series Articles

This list of links contains all of the articles in this series about Bash.

  1. Learning Bash and How to Program It. An introduction to this series.
  2. Programming Bash: Getting Started
  3. Programming Bash: Logical Operators
  4. Programming Bash: Loops
  5. Automation With Bash Scripts: Getting Started
  6. Automation With Bash Scripts: Creating a template
  7. Automation With Bash Scripts: Bash Program Needs Help
  8. Automation With Bash Scripts: Initialization and sanity testing