Thư viện tri thức trực tuyến
Kho tài liệu với 50,000+ tài liệu học thuật
© 2023 Siêu thị PDF - Kho tài liệu học thuật hàng đầu Việt Nam

UNIX UNLEASHED PHẦN 2 doc
Nội dung xem thử
Mô tả chi tiết
Part II — Hunt for Shells
What Is a Shell?
Bourne Shell
Korn Shell
C Shell
Which Shell Is Right for You? Shell Comparison
10
o What Is a Shell?
By Rick Rummel
Introduction
The Kernel and the Shell
The Functions of a Shell
Command Line Interpretation
Program Initiation
Input-output Redirection
Pipeline Connection
Substitution of Filenames
Maintenance of Variables
Environment Control
Shell Programming
Summary
10
What Is a Shell?
By Rick Rummel
Introduction
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
What a shell is
What a shell does for you
How a shell relates to the overall system
The Kernel and the Shell
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 port—usually referred to as a tty—the 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.
Figure 10.1. An active system with no users.
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.
Figure 10.2. A user logs in.
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.
Figure 10.3. An active system.
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 login—and a shell is simply a program—it 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.
The Functions of a Shell
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:
Command line interpretation
Program initiation
Input-output redirection
Pipeline connection
Substitution of filenames
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. The 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 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.
Program Initiation
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.
Input-output Redirection
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:
$ wc -l fivelines
5 fivelines
$ wc -l <fivelines
5
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.
Pipeline Connection
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
5
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.
Substitution of Filenames
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.
Maintenance of Variables
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.
$ 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
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.
Environment Control
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
vt100
$ TERM=ansi
$ echo $TERM
ansi
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.
Shell Programming
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.
Summary
The shell provides an interface between the user and the heart of UNIX—the 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.
11
o Bourne Shell
By Richard E. Rummel
Shell Basics
How the Shell Interprets Commands
Entering Simple Commands
Redirection of Input and Output
Entering Multiple Commands on One Line
Entering Commands Too Long for One Line
Filename Substitutions on the Command Line
Substitution of Variable Data
Substituting the Results of Commands in a Command Line
Escaping from the Special Characters
Entering Data from the Shell
Shell Options
The Restricted Shell
Changing Shell Options with set
Variables
Defining Your Own (User-Defined) Variables
Conditional Variable Substitution
Substituting Default Values for Variables
Conditional Variable Substitution with Error Checking
Positional Variables or Parameters
Special Variables in the Bourne Shell
Environment Variables
Preventing Variables from Being Changed
Making Variables Available to Subshells with export
Shell Programming
What Is a Program?
A Simple Program
The Shell as a Language
Using Data Variables in Shell Programs
Entering Comments in Shell Programs
Doing Arithmetic on Shell Variables
Passing Arguments to Shell Programs
Decision Making in Shell Programs
The if-then Statement
Data Output from Shell Programs
The if-then-else Statement
Testing Conditions with test
Testing Character Data
Testing Numeric Data
Testing for Files
Combining and Negating test Conditions
A Shorthand Method of Doing Tests
The Null Command
Displaying the Program Name
Nested if Statements and the elif Construct
Reading Data into a Program Interactively
The case Statement
Building Repetitions into a Program
Repeating Within a while Loop
Repeating Within an until Loop
Processing an Arbitrary Number of Parameters with shift
Repeating Within a for Loop
Getting Out of a Loop from the Middle
Structured Shell Programming Using Functions
Handling the Unexpected with trap
Conditional Command Execution with the And/Or Constructs
Reading UNIX-Style Options
Customizing the Shell
Customizing the Shell with Environment Variables
Changing Your Command-Line Prompt with PS
Adding Command-Line Separators with IFS
Checking Multiple Mailboxes with MAILPATH
Automating Environment Changes
Adding Your Own Commands and Functions
Specialized Topics
Debugging Shell Programs
Grouping Commands
Using the Shell Layer Manager shl
Summary
11
Bourne Shell
By Richard E. Rummel
In this chapter, you learn how to get the most out of the Bourne shell, one of the most used of
the UNIX shells. You also learn how to store data in your own variables, how to customize your
environment with environment variables, and how to group commands together to form shell
programs.
Shell Basics
The Bourne shell was written by Stephen Bourne at Bell Laboratories, where UNIX was
originally developed. Because it is found on most UNIX systems, many software developers
work under the assumption that the Bourne shell is available on a UNIX system. This use does
not mean that it is the best shell, but simply that it is the most common. Other shells, most
notably the Korn shell, were written to enhance the Bourne shell, so shell programs written for
Bourne run under the Korn shell. In some literature, the Bourne shell is called the UNIX system
Version 7 shell.
How the Shell Interprets Commands
The first exposure most people have to the Bourne shell is as an interactive shell. After logging
on the system and seeing any messages from the system administrator, the user sees a shell
prompt. For users other than the super-user, the default prompt for the interactive Bourne shell
is a dollar sign ($). When you see the dollar sign ($), the interactive shell is ready to accept a
line of input, which it interprets. When the super-user logs in, he or she sees the pound sign (#)
as a prompt. It is a reminder that as super-user some of the built-in protections are not available
and that extra care is necessary in this mode.
NOTE: On UNIX systems the super-user, also referred to as root, is without restriction.
The super-user can write to any directory and can remove any file. File permissions do not apply
to the super-user. The password for the super-user is usually closely held by the system
administrator.
The shell sees a line of input as a string of characters terminated with a newline character, which
is usually the result of pressing Enter on your keyboard. The length of the input line has nothing
to do with the width of your computer display. When the shell sees the newline character, it
begins to interpret the line.
Entering Simple Commands
The most common form of input to the shell is the simple command, in which a command name
is followed by any number of arguments. In the example
$ ls file1 file2 file3
ls is the command and file1, file2, and file3 are the arguments. The command is any UNIX
executable. It is the responsibility of the command, not the shell, to interpret the arguments.
Many UNIX commands, but certainly not all, take the following form:
$ command -options filenames
Although the shell does not interpret the arguments of the command, the shell does make some
interpretation of the input line before passing the arguments to the command. Special characters,
when you enter them on a command line, cause the shell to redirect input and output, start a
different command, search the directories for filename patterns, substitute variable data, and
substitute the output of other commands.
Redirection of Input and Output
When the shell sees the input (<) or output (>) redirection characters, the argument following
the redirection symbol is sent to the subshell that controls the execution of the command. When
the command opens the input or output file that has been redirected, the input or output is
redirected to the file.
$ ls -l >dirfile
In this example, the only argument passed on to ls is the option -l. The filename dirfile is sent to
the subshell that controls the execution of ls. You can find more detail on input and output
redirection in Chapter 4, "Listing Files."
Entering Multiple Commands on One Line
Ordinarily, the shell interprets the first word of command input as the command name and the
rest of the input as arguments to that command. Three shell special characters—the semicolon
(;), the ampersand (&), and the vertical bar (|) or pipe—direct the shell to interpret the word
following the symbol as a new command, with the rest of the input as arguments to the new
command. For example, the command line
$ who -H; df -v; ps -e
is the equivalent of
$ who -H
$ df -v
$ ps -e
In the second case, however, the results of each command appear between the command input
lines. When you use the semicolon to separate commands on a line, the commands are executed
in sequence. The shell waits until one command is complete before executing the next.
If you separate commands on a line using the ampersand (&), the shell does not wait until one
command is run before the second is started. If the ampersand is the last character on the input
line, the last command is executed as a background job. To run the preceding series of
commands concurrently, you enter the following:
$ who -H & df -v & ps -e
Whereas the semicolon serves merely as a command separator, the pipe symbol serves a
different purpose. When the shell sees the pipe symbol, it takes the next word as a new
command and redirects the standard output of the prior command to the standard input of the
new command. For example, the command line
$ who | sort
displays an alphabetized list of all logged-in users. The command line
$ who | sort | lp
prints a hard copy of the alphabetized list of all logged-in users. You can find more information
on pipelines in Chapter 4, "Listing Files."
TIP: When you're using pipelines, sometimes the order of the commands does not
make a difference in the output, but it might make a difference in how efficiently the pipeline
executes. The two commands
sort /etc/inittab | grep bin/sh
grep bin/sh /etc/inittab | sort
accomplish the same thing, but the second pipeline operates more efficiently because it reduces
the amount of data passed to sort.
Entering Commands Too Long for One Line
Sometimes command lines get quite lengthy. On some terminals, when you reach the edge of
the display screen, the input autowraps to the next line, but depending on terminal settings,
some do not. It would be nice if you could type part of a command on one line and enter the
remainder of the command on a second line. You can accomplish by escaping the newline
character.
Remember that the shell sees a line of input as a string of characters terminated with a newline
character. But the newline character is also considered to be a white space character. If you end
a line with a backslash (\), the next character, which is the newline character, is treated literally,
meaning that the shell does not interpret the newline character as the end of the line of input. For
example,
$ echo Now is the time for all good men \_
to come to the aid of the party.
Now is the time for all good men to come to the aid of the party.
Filename Substitutions on the Command Line
Although the command separator, the pipe symbol, and the redirection symbols change the
operational effects of a command line, they did not affect the arguments that were passed to the
command. The substitution characters, on the other hand, cause a substitution to take place in
the stream of arguments passed to a command. The most common substitution is filename
substitution. When the shell's command-line interpreter sees one of the metacharacters—the
asterisk (*), the question mark (?), or square brackets ([,])—the shell searches the directories for
filenames that match a pattern indicated by the metacharacter.
The asterisk special character causes the shell to search the directory for filenames that match
any pattern. The command
$ ls f*
file1
file1a
form
creates a listing of all filenames beginning with the letter f. The important point here is that the
shell, not the ls command, did the directory search. In the following example, the ls command
sees three arguments, and the preceding command line is the equivalent of
$ ls file1 file1a form
file1
file1a
form