You can do many things without having an extensive knowledge of how they actually work. For example, you can drive a car without understanding the physics of the internal combustion engine. A lack of knowledge of electronics doesn't prevent you from
enjoying music from a CD player. You can use a UNIX computer without knowing what the shell is and how it works. However, you will get a lot more out of UNIX if you do.
Three shells are typically available on a UNIX system: Bourne, Korn, and C shells. They are discussed in Chapters 11, 12, and 13. In this chapter, you'll learn
As the shell of a nut provides a protective covering for the kernel inside, a UNIX shell provides a protective outer covering. When you turn on, or "boot up," a UNIX-based computer, the program unix is loaded into the computer's main memory,
where it remains until you shut down the computer. This program, called the kernel, performs many low-level and system-level functions. The kernel is responsible for interpreting and sending basic instructions to the computer's processor. The kernel is
also responsible for running and scheduling processes and for carrying out all input and output. The kernel is the heart of a UNIX system. There is one and only one kernel.
As you might suspect from the critical nature of the kernel's responsibilities, the instructions to the kernel are complex and highly technical. To protect the user from the complexity of the kernel, and to protect the kernel from the shortcomings of
the user, a protective shell is built around the kernel. The user makes requests to a shell, which interprets them, and passes them on to the kernel. The remainder of this section explains how this outer layer is built.
Once the kernel is loaded to memory, it is ready to carry out user requests. First, though, a user must log in and make a request. For a user to log in, however, the kernel must know who the user is and how to communicate with him. To do this, the
kernel invokes two special programs, getty and login. For every user portusually referred to as a ttythe kernel invokes the getty program. This process is called spawning. The getty program displays a login prompt and continuously monitors the
communication port for any type of input that it assumes is a user name. Figure 10.1 shows a freshly booted UNIX system with six user ports.
When getty receives any input, it calls the login program, as shown in Figure 10.2. The login program establishes the identity of the user and validates his right to log in. The login program checks the password file. If the user fails to enter a valid
password, the port is returned to the control of a getty. If the user enters a valid password, login passes control by invoking the program name found in the user's entry in the password file. This program might be a word processor or a spreadsheet, but it
usually is a more generic program called a shell.
In the system shown in Figure 10.3, four users have logged in. Likewise, one user is in the process of logging in, and one port has no activity. Of the four active users, two are using the Bourne shell, one is using the Korn shell, and one has logged
into a spreadsheet. Each user has received a copy of the shell to service his requests, but there is only one kernel. Using a shell does not prevent a user from using a spreadsheet or another program, but those programs run under the active shell. A shell
is a program dedicated to a single user, and it provides an interface between the user and the UNIX kernel.
You don't have to use a shell to access UNIX. In Figure 10.3, one of the users has been given a spreadsheet instead of a shell. When this user logs in, the spreadsheet program starts. When he exits the spreadsheet, he is logged out. This technique is
useful in situations where security is a major concern, or when it is desirable to shield the user from any interface with UNIX. The drawback is that the user cannot use mail or the other UNIX utilities.
Because any program can be executed from the loginand a shell is simply a programit is possible for you to write your own shell. In fact, three shells, developed independently, have become a standard part of UNIX. They are
The Bourne shell, developed by Stephen Bourne
The Korn shell, developed by David Korn
The C shell, developed by Bill Joy
This variety of shells enables you to select the interface that best suits your needs or the one with which you are most familiar.
It doesn't matter which of the standard shells you choose, for all three have the same purpose: to provide a user interface to UNIX. To provide this interface, all three offer the same basic functions:
When you log in, starting a special version of a shell called an interactive shell, you see a shell prompt, usually in the form of a dollar sign ($), a percent sign (%), or a pound sign (#). When you type a line of input at a shell prompt, the shell
tries to interpret it. Input to a shell prompt is sometimes called a command line. The basic format of a command line is
command is an executable UNIX command, program, utility, or shell program. The arguments are passed to the executable. Most UNIX utility programs expect arguments to take the following form:
For example, in the command line
$ ls -l file1 file2
there are three arguments to ls, the first of which is an option, while the last two are file names.
One of the things the shell does for the kernel is to eliminate unnecessary information. For a computer, one type of unnecessary information is whitespace; therefore, it is important to know what the shell does when it sees whitespace. Whitespace
consists of the space character, the horizontal tab, and the new line character. Consider this example:
$ echo part A part B part C
part A part B part C
Here, the shell has interpreted the command line as the echo command with six arguments and has removed the whitespace between the arguments. For example, if you were printing headings for a report and you wanted to keep the whitespace, you would have
to enclose the data in quotation marks, as in
$ echo 'part A part B part C'
part A part B part C
The single quotation mark prevents the shell from looking inside the quotes. Now the shell interprets this line as the echo command with a single argument, which happens to be a string of characters including whitespace.
When the shell finishes interpreting a command line, it initiates the execution of the requested program. The kernel actually executes it. To initiate program execution, the shell searches for the executable file in the directories specified in the PATH
environment variable. When it finds the executable file, a subshell is started for the program to run. You should understand that the subshell can establish and manipulate its own environment without affecting the environment of its parent shell. For
example, a subshell can change its working directory, but the working directory of the parent shell remains unchanged when the subshell is finished.
Chapter 4, "Listing Files," introduced input-output redirection. It is the responsibility of the shell to make this happen. The shell does the redirection before it executes the program. Consider these two examples, which use the wc word count
utility on a data file with 5 lines:
This is a subtle difference. In the first example, wc understands that it is to go out and find a file named fivelines and operate on it. Since wc knows the name of the file it displays it for the user. In the second example, wc sees only data, and does
not know where it came from because the shell has done the work of locating and redirecting the data to wc, so wc cannot display the file name.
Since pipeline connections are actually a special case of input-output redirection in which the standard output of one command is piped directly to the standard input of the next command, it follows that pipelining also happens before the program call
is made. Consider this command line:
$ who | wc -l
In the second example, rather than displaying its output on your screen, the shell has directed the output of who directly to the input of wc. Pipes are discussed in Chapter 4.
Chapter 4 explained how metacharacters can be used to reference more than one file in a command line. It is the responsibility of the shell to make this substitution. The shell makes this substitution before it executes the program. For example,
$ echo *
file1 file2 file3 file3x file4
Here, the asterisk is expanded to the five filenames, and it is passed to echo as five arguments. If you wanted to echo an asterisk, we would enclose it in quotation marks.
The shell is capable of maintaining variables. Variables are places where you can store data for later use. You assign a value to a variable with an equal (=) sign.
Here, the shell establishes LOOKUP as a variable, and assigns it the value /usr/mydir. Later, you can use the value stored in LOOKUP in a command line by prefacing the variable name with a dollar sign ($). Consider these examples:
$ echo $LOOKUP
$ echo LOOKUP
Note for C-shell users. Assigning values to variables in the C-shell differs from the Bourne and Korn shells. To assign a variable in the C-shell use the set command.
% set LOOKUP = /usr/mydir
Notice that spaces precede and follow the equal sign.
Like filename substitution, variable name substitution happens before the program call is made. The second example omits the dollar sign ($). Therefore, the shell simply passes the string to echo as an argument. In variable name substitution, the value
of the variable replaces the variable name.
For example, in
$ ls $LOOKUP/filename
the ls program is called with the single argument /usr/mydir/filename.
When the login program invokes your shell, it sets up your environment, which includes your home directory, the type of terminal you are using, and the path that will be searched for executable files. The environment is stored in variables called
environmental variables. To change the environment, you simply change a value stored in an environmental variable. For example, to change the terminal type, you change the value in the TERM variable, as in
$ echo $TERM
$ echo $TERM
Note for C-shell users. C-shell assigns values to environment variables using the setenv command.
% setenv TERM vt100
Chapter 11, "Bourne Shell," Chapter 12, "Korn Shell," and Chapter 13, "C Shell," contain more information on customizing your environment.
You've seen that the shell is used to interpret command lines, maintain variables, and execute programs. The shell also is a programming language. By combining commands and variable assignments with flow control and decision making, you have a powerful
programming tool. Using the shell as a programming language, you can automate recurring tasks, write reports and you can even build and manipulate your own data files. The next three chapters discuss shell programming in more detail.
The shell provides an interface between the user and the heart of UNIXthe kernel. The shell takes command lines as input, makes filename and variable substitution, redirects input and output, locates the executable file, and initiates programs.
The shell maintains each user's environment variables. The shell also is a powerful programming language.