Thursday, August 28, 2008

What Is a Shell?


By William A. Farra

Nearly every human-usable invention has an interface point with which you interact. Whether you are in the front seat of a horse and buggy, in the cockpit of a plane, or at the keyboard of a piano, this position is where you manipulate and manage the various aspects of the invention to achieve a desired outcome. The human interface point for UNIX is the shell, which is a program layer that provides you with an environment in which to enter commands and parameters to produce a given result. As with any invention, the more knowledge and experience you have with it, the greater the accomplishment you make with it.

To meet varying needs, UNIX has provided different shells. Discussed in Chapters 9 through 13 are Bourne, Bourne Again, Korn, and C shells. Each of these offers features and ways to interact with UNIX. Topics discussed in this chapter are the following:

  • How shells works with you and UNIX
  • The features of a shell
  • Manipulating the shell environment

How the Kernel and the Shell Interact

When a UNIX system is brought online, the program unix (the Kernel) is loaded into the computer's main memory, where it remains until the computer is shut down. During the bootup process, the program init runs as a background task and remains running until shutdown. This program scans the file /etc/inittab, which lists what ports have terminals and their characteristics. When an active, open terminal is found, init calls the program getty, which issues a login: prompt to the terminal's monitor. With these processes in place and running, the user is ready to start interacting with the system.

UNIX Calls the Shell at Login

Figure 8.1 shows the process flow from the kernel through the login process. At this point the user is in an active shell, ready to give command to the system.

Figure 8.1.
How a shell is started from login.

During login, when you type your user name, getty issues a password: prompt to the monitor. After you type your password, getty calls login, which scans for a matching entry in the file /etc/passwd. If a match is made, login proceeds to take you to your home directory and then passes control to a session startup program; both the user name and password are specified by the entry in /etc/passwd. Although this might be a specific application program, such as a menu program, normally the session startup program is a shell program such as /bin/sh, the Bourne shell.

From here, the shell program reads the files /etc/profile and .profile, which set up the system-wide and user-specific environment criteria. At this point, the shell issues a command prompt such as $.

When the shell is terminated, the kernel returns control to the init program, which restarts the login process. Termination can happen in one of two ways: with the exit command or when the kernel issues a kill command to the shell process. At termination, the kernel recovers all resources used by the user and the shell program.

The Shell and Child Processes

In the Unix system, there are many layers of programs starting from the kernel through a given application program or command. The relationship of these layers is represented in Figure 8.2.

Figure 8.2.
UNIX system layers.

After you finish logging on, the shell program layer is in direct contact with the kernel, as shown in Figure 8.2. As you type a command such as $ ls, the shell locates the actual program file, /bin/ls, and passes it to the kernel to execute. The kernel creates a new child process area, loads the program, and executes the instructions in /bin/ls. After program completion, the kernel recovers the process area and returns control to the parent shell program. To see an example of this, type the following command:

$ps

This lists the processes you are currently running. You will see the shell program and the ps program. Now type the following:

$sleep 10 &
$ps

The first command creates a sleep child process to run in background, which you see listed with the ps command. Whenever you enter a command, a child process is created and independently executes from the parent process or shell. This leaves the parent intact to continue other work.

Auto-Execution of the Shell

Some UNIX resources, such as cron, can execute a shell program without human interaction. When using this feature, the user needs to specify which shell to run in the first line of the shell program, like this:

#! /bin/sh

This specifies the Bourne shell.

You should also redirect any output, because no terminal is associated with auto-execution. This is described in the "File Handling: Input/Output Redirection and Pipes" section later in this chapter.

The Functions and Features of a Shell

It doesn't matter which of the standard shells you choose, because they all have the same purpose: to provide a user interface to UNIX. To provide this interface, all the shells offer the same basic characteristics:

  • Command-line interpretation
  • Reserved words
  • Shell meta-characters (wild cards)
  • Access to and handling of program commands
  • File handling: input/output redirection and pipes
  • Maintenance of variables
  • Environment control
  • Shell programming

Command-Line Interpretation

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 arguments

command is an executable UNIX command, program, utility, or shell program. arguments are passed to the executable. Most UNIX utility programs expect arguments to take the following form:

options filenames

For example, in the command line

$ ls -l file1 file2

there are three arguments to ls; the first is an option, and the last two are filenames.

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 space characters, horizontal tabs, and newline characters. 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 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.

Reserved Words

All shell versions have words that have special meaning. In shell programming, words such as do, done, for, and while provide loop control--and if, then, else, and fi provide conditional control. Each shell version has different reserved word pertaining to its specific features.

Shell Meta-Character (Wild Cards)

All shell versions have meta-characters, which allow the user to specify filenames. The following are wild cards:

Wild Card Description
* Matches any portion
? Matches any single character
[] Matches a range or list of characters

Wild cards can be useful when processing a number of specific files. The following are some examples:

$ls t*

This lists all files starting with t.

$ls test?5.dat

This lists all files starting with test, any single character and ends with 5.dat.

$ls [a-c]*

This lists all files starting with a through c.

$ls [e,m,t]*

This lists all files starting with e, m, or t.

Program Commands

When a command is typed, the shell reads the environment variable $path, which contains a list of directories containing program files. The shell looks through this set of directories to find the program file for the command. The shell then passes the true filename to the kernel.

File Handling: Input/Output Redirection and Pipes

In previous chapters, you learned about standard input and output. Unless otherwise specified with arguments, most UNIX commands take input from the terminal keyboard and send output to the terminal monitor. To redirect output to a file, use the > symbol. For example,

$ls > myfiles

lists the files in your current directory and places them in a file called myfiles. Likewise, you can redirect input with the < symbol. For example,

$wc -l < myfiles

feeds the command wc with input from the file myfiles. Although you could obtain the same output by having the filename as an argument, the need for input redirection becomes more apparent in shell programming.

To string the output from one command to the input of the next command, you can use the | (pipe) symbol. For example,

$ls -s | sort -nr | pg

This lists the files in the current directory with blocksize and then pipes the output to the sort, which sorts the files in numeric descending order and pipes that output to the paging command pg for final display on the terminal's monitor. The pipe command is one of the most useful tools when creating command constructs.

Command Substitution

Command substitution is similar to redirection except that is used to provide arguments to a command from the output of another. For example,

$grep 'wc -l myfiles' *

takes the number of lines in the file myfiles from the wc command and places the number as an argument to the grep command to search all files in the current directory for that number.

Maintenance of Variables

The shell is capable of maintaining variables. Variables are places you can store data for later use. You assign a value to a variable with an equal (=) sign:

$ LOOKUP=/usr/mydir

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
/usr/mydir
$ echo LOOKUP
LOOKUP

To make a variable available to child processes, you can use the export command--for example:

$ LOOKUP=/usr/mydir
$export LOOKUP


NOTE: Assigning values to variables in the C shell differs from doing so in 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.

Shell Startup--Environment Control

When a user begins a session with UNIX and the shell is executed, the shell creates a specified environment for the user. The following sections describe these processes.

Shell Environment Variables When the login program invokes your shell, it sets up your environment variables, which are read from the shell initialization files /etc/profile and .profile. These files normally set the type of terminal in the variable $TERM and the default path that is searched for executable files in the variable $PATH. Try these examples:

$ echo $TERM
$ echo $PATH

You can easily change the variables the same way you assign values to any shell variable.


NOTE: C shell assigns values to environment variables using the setenv command:

% setenv TERM vt100


Shell Startup Files The file .profile is the local startup file for the Bourne shell. The Korn shell uses .kshrc, and the C shell uses .cshrc. You can edit these files to manipulate your startup environment. You can add additional variables as the need arises. You also can add shell programming to have conditional environment settings, if necessary.

Shell Startup Options When invoking the shell either from /etc/passwd or the command line, you can set several options as arguments to the shell program. For example, the Bourne shell has a -x option that displays commands and their arguments before they are executed. This is useful for debugging a shell program. These options are described in detail in the following chapters.

Shell Programming

You've seen that the shell is used to interpret command lines, maintain variables, and execute programs. The shell is also a programming language. You can store a set of shell commands in file. This is known as a shell script or shell programming. 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 build and manipulate your own data files. The remaining chapters in Part II discuss shell programming in more detail.

Summary

The shell provides an interface between the user and the heart of UNIX--the kernel. The shell interprets command lines as input, makes filename and variable substitution, redirects input and output, locates the executable file, and initiates and interfaces programs. The shell creates child processes and can manage their execution. The shell maintains each user's environment variables. The shell is also a powerful programming language.

While this chapter gives an overview of the UNIX shell, Chapters 9 through 13 describe in detail the various shells, their features, and language specifics. Also described are the fundamentals of shell programming and execution. Continued reading is highly recommended.

No comments:

Search

My Blog List