Bashing About
Any Linux administrator who wishes to remain sane relies heavily on scripting to automate routine tasks, customize jobs, and build the plumbing that connects the different utilities that make a Linux system run smoothly. The Linux world is chock-full of scripting languages: Perl, Python, PHP, Scheme, Tcl, Tk, Ruby, Forth, Smalltalk, Eiffel, and doubtless many more. To get the column started, we'll look at shell scripting with Bash, and scripting with Python and Perl.
Understanding what Bash does is fundamental to using Linux. Bash is a command interpreter, the direct interface between you and your Linux system. Python is easy-to-learn, yet capable of handling any system administration chore. Perl is endlessly flexible, which makes learning it rather vexing at times. But it can do almost anything: Complex programs are written in Perl, such as the indispensible game Frozen-Bubble.
Scripting and text-and-file processing go hand-in-hand. So we'll also incorporate regular expressions, awk, sed, find, sort, uniq, and other text-and-file processing utilities. Half of using Linux is simply learning all these odd little specialized commands. Here is where the real power of Linux/Unix lies: All these little, specialized programs can be strung together in any way you need. You're not limited by some program author's idea of what you need, so you can use these building blocks to construct your Linux house the way you like it.
The default command shell on most Linux distributions is the Bash shell. Linux/Unix gurus adore silly wordplay; Bash stands for Bourne-again Shell. Bash is based on the Bourne Shell, the original command shell for Unix SysV systems. It incorporates features of the Korn shell, the C shell, and some new stuff of its own. Some folks love to debate command shells, and wax poetic over Csh, Tcsh, Zsh, and so forth. You are welcome to go nuts and experiment with any shells you like. Meanwhile, we're going to talk about Bash. (Should there come a time when you need to run a different shell, but don't want change your system default, simply invoke it from Bash: $ exec /bin/zsh)
For admins looking to master the shell game, the book "Linux In A Nutshell," by Ellen Siever, is indispensible. It's the best Linux command reference we've seen. It separates the built-in Bash shell commands from other commands, such as system administrator and user commands. Understanding what belongs to Bash will prevent a lot of confusion. Run this command to see what built-in commands are enabled on your system:
enable -a
This command displays all of your environment variables:
set
You should have version 2 or newer:
carla@windbag:~$ echo $BASH_VERSION
2.05b.0(1)-release
Unlike many Linux programs, Bash is mature, and does not change very often, so you don't have to worry about laboring to keep up with the latest and greatest.
Saving Output in a File
Directing command output into a file is very useful. Some operations generate a lot of output; saving it in a file lets you study it at leisure. This command creates a new file, or replaces the contents of an existing file:
ls -al ~ > homefiles.txt
This creates a new file, or appends to the end of an existing file:
ls -al ~ >> homefiles.txt
This is a fast way to append lines to an existing file:
cat >> homefiles.txt
testing, testing, new line
Hit CTRL + D to finish.
I like piping the output of make to a file, so I know what files were installed, and where. And to review any error messages. In this example, I'm installing JOE, Joe's Own Editor:
make install | tee joe-makeinstall.txt
The tee command is one of those odd little specialized Unix commands that come in handy at the strangest times. It both displays the command output on the screen, and stores it in a file. Use tee -a to append, instead of overwrite.
You doubtless noticed how most of the pieces of the above examples are not Bash features at all. The only Bash bits are:
> redirection operator
| pipe
Redirection operators work both ways, for input and output. This takes the contents of file1 and directs it to the output file, file2:
cat < file1 > file2
This works great when you're feeding a list, or other data in a file, to a script:
scriptname < filelist > outputfile.txt
A Simple Backup Script
This script demonstrates a number of common ways to use Bash. A slick Bash trick is to take a script like this, and execute it one line at a time. That's a great way to build and test a script.
To run it as a script, save it as text file, with a nice name like "backup," and make it executable:
chmod +x backup
There are severals ways to run it. Change to the directory it's in, and use one of these:
$ ./backup
$ bash backup
Or, do what leet geeks do, and put it in /usr/bin. Or keep it all to yourself- create your own personal scripts directory, and put it in your path:
mkdir ~/scripts
Append to your PATH, using your own filepath, of course.
/home/carla/scripts
This allows you to run the script like any other command:
backup
And now, the script itself:
#!/bin/bash ## This is the famous "sha-bang" statement, ## that tells the shell which command ## interpreter to use. See man magic ## to learn the inner workings of sha-bang. ## this script uses the tar, mkdir, and cp commands ## plus Bash's conditional statements ## smart admins write lots of comments # test for existing backup directory # if it does not exist, create it # -e is the Bash way of asking "does this file exist" # $ means variable substitution. HOME is a builtin # Bash variable. if [ -e $HOME/1backups ] then echo "The backup directory exists." else echo "A backup directory does not exist, and will be created." mkdir $HOME/1backups echo "A backup directory has been created" fi # now we define our own variables # location of files to backup FILES=$HOME/archive-files # name of compressed archive ARCHIVENAME=backups.tgz # location of backup directory BACKUPDIR=/archive/carla/ # create compressed archive, copy to backup directory tar czf $ARCHIVENAME $FILES cp -ap $ARCHIVENAME $BACKUPDIR if [ -e $BACKUPDIR/$ARCHIVENAME ] then echo "Jolly good show, the backup worked!" else echo "Dagnabit, the backup failed. Time to debug." fi
Going through this script and understanding which parts are Bash commands, and which are Linux commands, is important for understanding how to put scripts together.
Resources
Bash home page
"Learning the Bash Shell," by Cameron Newham, Bill Rosenblatt
"Linux In A Nutshell," by Ellen Sievers
[This article originally appeared on CrossNodes, By: Carla Schroder]