Many simple day-to-day system administration tasks can be accomplished by the numerous Linux command-line tools available to administrators. However, tasks with greater complexity often require the chaining together of multiple commands. In these situations, Linux command-line tools can be combined with the offerings of the Bash shell to create powerful shell scripts to solve real-world problems.
In its simplest form, a Bash shell script is simply an executable file composed of a list of commands. However, when well-written, a shell script can itself become a powerful command-line tool when executed on its own, and can even be further leveraged by other scripts.
Proficiency in shell scripting is essential to the success of Linux system administrators in all operational environments. Working knowledge of shell scripting is especially crucial in enterprise environments, where its use can translate to improved efficiency and accuracy of routine task completion.
Creating and Executing Bash Shell Scripts
A Bash shell script can be created by opening a new empty file in a text editor. While any text editor can be used, advanced editors, such as vim or emacs, understand Bash shell syntax and can provide color-coded highlighting. This highlighting can be a tremendous help for spotting syntactical errors, such as unpaired quotes, unclosed brackets, and other common blunders.
The command interpreter
The first line of a Bash shell script begins with ‘#!’, also commonly referred to as a sharp-bang, or the abbreviated version, sha-bang. This two-byte notation is technically referred to as the magic pattern. It indicates that the file is an executable shell script. The pathname that follows is the command interpreter, the program that should be used to execute the script. Since Bash shell scripts are to be interpreted by the Bash shell, they begin with the following first line.
Executing a Bash shell script
After a Bash shell script is written, its file permissions and ownership need to be modified so that it is executable. Execute permission is modified with the chmod command, possibly in conjunction with the chown command to change the file ownership of the script accordingly. Execute permission should only be granted to the users that the script is intended for.
Once a Bash shell script is executable, it can be invoked by entering its name on the command line. If only the base name of the script file is entered, Bash will search through the directories specified in the shell’s PATH environmental variable, looking for the first instance of an executable file matching that name. Administrators should avoid script names that match other executable files and should also ensure that the PATH variable is correctly configured on their system so that the script will be the first match found by the shell. The which command, followed by the file-name of the executable script displays in which directory the script resides that is executed when the script name is invoked as a command resides.
$ which hello ~/bin/hello $ echo $PATH /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/user01/.local/bin:/home/user01/bin
The echo command can be used to display arbitrary text by passing the text as an argument to the command. By default, the text is directed to standard out (STDOUT), but can also be directed to standard error (STDERR) using output redirection. In the following simple Bash script, the echo command displays the message “Hello, world” to STDOUT.
$ cat ~/bin/hello #!/bin/bash echo "Hello, world"
$ hello Hello, world
While seemingly simple in its function, the echo command is widely used in shell scripts due to its usefulness for various purposes. It is commonly used to display informational or error messages during the script execution. These messages can be a helpful indicator of the progress of a script and can be directed either to standard out, standard error or be redirected to a log file for archiving. When displaying error messages, it is good practice to direct them to STDERR to make it easier to differentiate error messages from normal status messages.
$ cat ~/bin/hello #!/bin/bash echo "Hello, world" echo "ERROR: Houston, we have a problem." >&2
$ hello 2> hello.log Hello, world
$ cat hello.log ERROR: Houston, we have a problem.
The echo command can also be beneficial when trying to debug a problematic shell script. The addition of echo statements to the portion of the script that is not behaving as expected can help clarify the commands being executed, as well as the values of variables being invoked.
Quoting special characters
A number of characters or words have special meanings to the Bash shell in a specific context. There are situations when the literal values, rather than the special meanings, of these characters or words, are desired. For example, the # character is interpreted by Bash as the beginning of comment and is therefore ignored, along with everything following it on the same line. If this special meaning is not desired, then Bash needs to be informed that the # character is to be treated as a literal value. The meanings of special characters or words can be disabled through the use of the escape character, \, single quotes, ”, or double quotes, “”.
The escape character, \, removes the special meaning of the single character immediately following it. For example, to display the literal string # test with the echo command, the # character must not be interpreted by Bash with special meaning. The escape character can be placed in front of the # character to disable its special meaning.
$ echo # not a comment
$ echo \# not a comment # not a comment
The escape character, \, only removes the special meaning of a single character. When more than one character in a text string needs to be escaped, users can either use the escape character multiple times or employ single quotes, ”. Single quotes preserve the literal meaning of all characters they enclose. The following example demonstrates how single quotes can be used when multiple characters need to be escaped.
$ echo # not a comment #
$ echo \# not a comment # # not a comment
$ echo \# not a comment \# # not a comment #
$ echo '# not a comment #' # not a comment #
While single quotes preserve the literal value of all characters they enclose, double quotes differ in that they do not preserve the literal value of the dollar sign, $, the back-ticks, “, and the backslash, \. When enclosed with double quotes, the dollar sign and back-ticks preserve their special meaning, and the special meaning of the backslash character is only retained when it precedes a dollar sign, back-tick, double quote, backslash, or newline.
$ echo '$HOME' $HOME $ echo '`pwd`' `pwd` $ echo '"Hello, world"' "Hello, world" $ echo "$HOME" /home/user01 $ echo "`pwd`" /home/user01 $ echo ""Hello, world"" Hello, world $ echo "\$HOME" $HOME $ echo "\`pwd\`" `pwd` $ echo "\"Hello, world\"" "Hello, world"