Article
Fire Up your own Linux Server
Programming the Shell
The shell itself can be quite a powerful little programming language. It supports looping, branching, variables—everything that constitutes a worthwhile programming environment. These shell programs, called shell scripts, are just text files on which execute permissions are set. The text files contain commands just like those you'd type on the command line:
Example 3.1. hello_world.sh
#!/bin/sh
echo "Hello, World!"
The output of this script is exactly as you'd expect:
Hello, World!
Let's take a look at some of the shell's more programming language-like features. First, we'll create a new variable in the shell and print its value.
[kermit@swinetrek ~]$ COUNTER=0
[kermit@swinetrek ~]$ echo $COUNTER
0
Once the variable COUNTER is created, it's there until you close the terminal window. The value of the variable may change, as you'll see, but the variable itself remains until the terminal session is ended. This is true of any declared shell variable.
If we use the increment operator (++) to increment the value of COUNTER, then echo it again, you'll see that the shell does, in fact, track the values of these variables:
[kermit@swinetrek ~]$ let COUNTER++
[kermit@swinetrek ~]$ echo $COUNTER
1
Let's build a simple script, called counter_test.sh, that will keep on counting until we tell it to stop by pressing Ctrl-C.
Sorry to Interrupt...
You can abort any process on the command line by pressing Ctrl-C. This is referred to as sending the program an interrupt signal.
This same keyboard shortcut will throw away a command and start you on a new, blank prompt if you're not happy with what you've typed.
The first line of any shell script is what's commonly referred to as the shebang: a pound sign, followed by an exclamation point, followed by the path to the shell. (/bin/sh is a standard shortcut to the shell program on Linux systems. Usually, this file is just a link to the actual shell program (e.g. /bin/bash), but using the standard name ensures that you script will still work on a system that uses a different shell.)
#!/bin/sh
Every shell script must begin with this line. The next line of our script will set a value for the COUNTER variable:
COUNTER=0
In other words, we're starting the counter at zero. Next, we'll add a loop to the program. We'll make it an infinite loop, so the user will have to send an interrupt signal to quit the program.
while true;
do
# contents of loop go here
done
Now all we need to do is define just what it is that the shell is going to do as long as the condition is true: print the value of COUNTER, increment COUNTER, and wait for one second:
while true;
do
echo $COUNTER
let COUNTER++
sleep 1;
done
If you're following along closely, you'll already know what we'll see on the screen: a count up from 0. Here's the script in its entirety:
Example 3.2. counter_test.sh
#!/bin/sh
COUNTER=0
while true;
do
echo $COUNTER
let COUNTER++
sleep 1;
done
We've created a good shell script, but we still have one loose end to tie up before we can run it. For our script to execute, we need to set the appropriate permissions.
[kermit@swinetrek ~]$ chmod u+x counter_test.sh
[kermit@swinetrek ~]$
Now we can run the script:
[kermit@swinetrek ~]$ ./counter_test.sh
0
1
2
3
4
This tells the shell to execute a file named counter_test.sh within the current working directory. You should see the screen start to count from zero, pausing for a second between increments. Ctrl-C will stop the counting.
That's but a small taste of the process of writing a shell script. Remember, as well, that shell scripts can access most of the single commands you'll utilize in your day-to-day Linux use. A script that elegantly combines these tasks into a single executable file can be a thing of beauty and a real time-saver.
If you've had previous programming experience, you're likely to find the shell a bit lightweight for programming purposes. Clearly, the shell isn't a powerful development environment. If it doesn't meet your needs, you should probably begin to dig more deeply into powerful scripting languages like Perl. Shell scripts, however, have the advantage of being a good hacker's tool. They're quick, they can accomplish many of the daily administrative tasks you'll face in Linux, and many pieces of each script can be tested directly in the shell prior to being rolled into a script.
Further exploration of the possibilities of shell scripting can be found in the detailed online tutorial A Quick Guide to Writing Scripts Using the Bash Shell.
The PATH Environment Variable
Now, remember that all of the command line tools are binary files located somewhere in the filesystem: the ls command, for example, actually lives in the directory /bin. But how does the shell know to find /bin/ls when you type ls at the command prompt?
The shell looks through all the directories listed in its built-in PATH variable, in search of a file that has the same name as the command you're after. The PATH environment variable for a default Fedora Core installation will look something like this:
[kermit@swinetrek ~]$ echo $PATH
/usr/kerberos/bin:/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin
So when you type the ls command, the shell would first look for an executable file /usr/kerberos/bin/ls, without success. Is there a /usr/local/bin/ls? No. What about a /usr/bin/ls? Sorry. How about a /bin/ls? Bingo!
Remember that, when we ran our counter_test.sh script, we needed to prefix the script filename with ./ to tell the shell that the executable file was in the working directory. If we were to add this directory to the PATH variable, we could simply enter counter_test.sh to run this script regardless of the working directory.
Built-in variables such as PATH are known as environment variables. These are the variables that describe the environment in which a process is running. Examples of other environment variables are HOME, which contains the path of the user's home directory, and MAIL, which is the name of the file that stores the user's email. Environment variables work just like normal shell variables, except they can be accessed by programs that are launched from the shell too.
To set or modify an environment variable, you must use the export command:
[kermit@swinetrek ~]$ export PATH=$PATH:/home/kermit
[kermit@swinetrek ~]$ echo $PATH
/usr/kerberos/bin:/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin
:/home/kermit/bin:/home/kermit
Note how we've used the PATH environment variable's existing value ($PATH) in specifying its new value. This technique allows us to tack an additional directory onto the end of the existing PATH. You can see that the /home/kermit directory has been added to the PATH variable. You should now be able to run counter_test.sh as easily as you'd run ls.
[kermit@swinetrek ~]$ counter_test.sh
0
1
2
3
4
Setting the PATH environment variable in this way will allow you to run a shell script from any directory for the remainder of this terminal session, but the modified PATH will be lost as soon as you exit the terminal. In Chapter 4, System Administration, we'll see how to modify the default PATH used whenever a new shell is launched.
Summary
As useful as it is, the Linux command line can seem pretty cryptic when you first open a terminal. There is logic to the commands, but it will likely take a bit of experimentation before you feel comfortable with them. In order to set you on the right path, we've laid out some of the most common terminal commands, and explained their use in your Linux system, in Appendix A, Command Line Reference.
It's possible to use a Linux system without going anywhere near the command line. If you do so, however, you'll forego accessing the true power of the operating system. Linux's roots lie in the command line interface. Certainly, you can use the terminal to achieve tasks more efficiently than would be possible using the graphical interface, but, even more importantly, the command line allows you to execute tasks that would be impossible to complete via the gui.
In a discussion on the intuitiveness of interfaces in the comp.os.linux.misc newsgroup, Mark van Hoeij wrote "How do I type 'for i in *.dvi do xdvi i done' in a GUI?", and his point is a valid one; the command line lets you do things easily that the GUI does not. Mastery of the command line is a big step on the ladder to achieving status as a Linux guru.