Tải bản đầy đủ (.pdf) (202 trang)

UNIX UNLEASHED PHẦN 2 doc

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (1.3 MB, 202 trang )

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
The shell makes filename substitutions regardless of the command to be executed.
$ echo f*

file1 file1a form
The question mark metacharacter searches the directories for filenames that match the pattern
with any single character substituted for the metacharacter. Square brackets cause a match to be
made on any character appearing within the brackets. You can find more details on filename
substitution in Chapter 4, "Listing Files."
Substitution of Variable Data
The second type of substitution that can take place is variable substitution. When the shell sees
the dollar sign ($) character, the remainder of the word following the dollar sign is presumed to
be a variable name. The shell then searches for any variables that have been defined for the
current shell and substitutes the value of the variable in the command line. If the variable has
not been defined, a null string, one containing no characters, is substituted on the command line.
For example, the command
$ ls $HOME
lists the contents of the users' home directory, regardless of what the current working directory
is. HOME is an environment variable. Variables are discussed in more detail in the next major
section of this chapter. As in filename substitution, the ls command sees only the result of the
substitution, not the variable name.

You can substitute variable names anywhere in the command line, including for the command
name itself. For example,
$ dir=ls

$ $dir f*

file1

file1a

form
This example points out that the shell makes its substitutions before determining what
commands to execute.
Substituting the Results of Commands in a Command Line
Sometimes it is useful to pass the output or results of one command as arguments to another
command. You do so by using the shell special character, the back quotation mark ('). You use
the back quotation marks in pairs. When the shell sees a pair of back quotation marks, it
executes the command inside the quotation marks and substitutes the output of that command in
the original command line. You most commonly use this method to store the results of
command executions in variables. To store the five-digit Julian date in a variable, for example,
you use the following command:
$ julian='date '+%y%j''
The back quotation marks cause the date command to be executed before the variable
assignment is made. Back quotation marks can be extremely useful when you're performing
arithmetic on shell variables; see "Shell Programming" later in this chapter.
Escaping from the Special Characters
By now, it should be clear that the shell looks for special characters in the input line before
taking any other action. When it becomes necessary to use a special character in a command
line, you can override, or "escape," the special action of the character by using an escape
character. The escape characters are:

\
the backslash, which causes a single character to be escaped
'
the single quotation mark, which, used in pairs, causes a group of characters to be escaped
"
the double quotation mark, which, used in pairs, causes a group of characters to be escaped,
but allows some special characters to perform their normal function
For example, UNIX does not forbid you to use special characters in filenames.
Suppose you have a directory with the following files:
file* file1 file2 file3
You want to display the contents of the first file, the one with the asterisk in its name. Enter the
following command:
$ cat file*
You then get not only the file you want, but the rest of the files in the directory as well. Because
you now understand how the shell interprets its input, performing filename substitution
whenever it sees an asterisk, you know what the problem is but wonder how you can rectify the
problem. If you try to remove the offending file with the command
$ rm file*
you remove far more than you want. Fortunately, the Bourne shell has provided a mechanism to
get around this kind of problem.
Another special character that the shell looks for is the escape character, or backslash (\). When
the shell sees the escape character, it takes the subsequent character literally; it does not attempt
to interpret that character. In the preceding scenario, you can use the escape character to remove
or even rename the offending file:
$ mv file\* filestar
Other characters that get special treatment by the shell are the white space characters. They are
the tabs, spaces, and newlines, which make a separation between words. When more than one of
these characters appears at a time, the shell strips the redundant white space characters from the
input. For example,
$ echo This word is separated


This word is separated
Here, the result is probably not the desired effect.
Suppose you want to display a message with asterisks as attention getters, as in the following:
***** Program Error *****
To do so using escape characters would be cumbersome, as you can see in the following:
$ echo \*\*\*\*\* Program Error \*\*\*\*\*

***** Program Error *****
You may already have guessed that the shell has an easier way of displaying a message of this
type. When you enclose a string of text within single quotation marks ('), the entire string is
treated literally, as follows:
$ echo '***** Program Error *****'

***** Program Error *****
You can use this same method to retain white space:
$ echo 'This word is separated'

This word is separated
On some occasions, however, you may want part of a string to be treated literally and other parts
to be interpreted by the shell.
$ USERS='who | wc -l'

$ echo '*** There are $USERS users logged into the system'

*** There are $USERS users logged into the system
You can overcome this problem by using the double quotation marks ("). The double quotation
marks are not as restrictive as the single quotation marks. Within double quotation marks, the
dollar sign ($), the backslash (\), and the back quotation marks (`) retain their shell meaning:
$ USERS='who | wc -l'


$ echo "*** There are $USERS users logged into the system"

There are 5 users logged into the system
Because the double quotation marks still allow the shell to interpret the back quotation marks,
you can simplify the preceding example, as follows:
$ echo "*** There are `who | wc -l` users logged into the system"

There are 5 users logged into the system
Entering Data from the Shell
One of the useful features of a computer is its ability to process large volumes of data at one
time. Often this data exists in the form of disk files. You have seen how you can provide a file
name to a UNIX program in a command line, but what if the data does not exist in a file? For
instance, you can use the UNIX mail utility to send a data file to another user, but often you just
want to type in a short note to send to another user. Many UNIX programs allow data to be
supplied to the program either from a disk file or from your keyboard.
When a UNIX program needs more data from the user than is practical to get from a command
line, the program issues a read request. For most programs, a read terminates when a newline
character is processed. In other words, a read request processes one line at a time. When the
program is reading its data from a file, no response from the user is necessary for a read request,
but when the program is reading its data from the keyboard, or standard input, the program
pauses until the user enters a string of characters terminated with a newline character. Consider
the following example:
$ head -2

Line 1

Line 1

Line 2


Line 2

$
Because no filename is supplied on the command line, and no input redirection has occurred,
head is looking for its input from the standard input. After you enter the first line, head
processes the line and sends it to the output file, which in this case is the standard output,
creating the echo effect of the example. After you enter the second line, head displays that line
and terminates because the command-line option requested only two lines. The natural operation
of some programs is to process a file until it has processed the entire file. When a program looks
for a complete file, and the file comes from the standard input, the user needs some way to
indicate the end-of-data or end-of-file condition. In the Bourne shell, the end-of-file is indicated
by Ctrl+d.
The file concatenation utility cat, processes an entire file at one time. In the following example,
cat "sees" a file containing two lines.
$ cat

Line 1

Line 1

Line 2

Line 2

Ctrl+d

$
So if you wanted to send a short note to John, you might type:
$ mail John


John,

Meet me at the mall at noon.

Rick

Ctrl+d

$
Shell Options
The Bourne shell is a computer program and like most programs it has several options. You are
already familiar with the most common shell option, the interactive shell. Some options change
the way the shell interprets command lines; others put limits on the user of the shell
The Restricted Shell
The restricted shell gives more control to the system administrator and restricts the options of
the user. The restricted shell is useful in situations where security is vital or where the users lack
sophistication. The restricted shell can be a user's default login shell. On many systems, the
restricted shell is invoked by using /usr/bin/rsh, but this may vary; consult your system's
documentation. You may also invoke the restricted shell by using the -r flag when you're
invoking the shell:
$ sh -r
In a restricted shell, the user cannot change directories (cd), change the PATH variable, specify
a full pathname to a command, or redirect output.
The restricted user can execute shell programs that have access to these features. If the restricted
shell calls a shell procedure, an unrestricted shell is invoked to carry out the commands. In this
case, if the user has write permission in his or her working directory, he or she can write shell
programs and bypass the restrictions. Normally, a restricted user is placed in a directory in
which he or she has no write permission. Not having write permission in this directory does not
mean that the user has no write permission anywhere, but because he or she cannot change

directories or specify pathnames in commands, the user cannot write a shell script and later
access it if he or she cannot write in the working directory.
Changing Shell Options with set
Although the restricted shell and the interactive shell are chosen when the shell is invoked, you
can turn other options on and off using the set option. Following are some options you can set:
-e
Causes a noninteractive shell to exit if any subsequent command terminates with a nonzero
exit status
-f
Disables filename substitution
-
n
Causes the shell to read commands but not execute them
-
u
Treats unset variables as errors when substituting
-
x
Prints commands and their arguments as they are executed, showing the result of any
substitutions
You turn on options with a hyphen (-) and turned them off with a plus (+).
For example, the shell normally looks at command line input and tries to substitute filenames
when it encounters certain special characters, such as an asterisk (*). This default behavior can
be changed with the set command using the -f option.
$ set -f

$ echo *

*
You can restore the default behavior by using set with the +f option.

$ set +f

$ echo *

file1 file2
Variables
In algebra, variables are symbols which stand for some value. In computer terminology,
variables are symbolic names which stand for some value. Earlier in this chapter, you saw how
the variable HOME stood for the name of a user's home directory. If you enter the change
directory command, cd, without an argument, cd takes you to your home directory. Does a
generic program like cd know the location of every user's home directory? Of course not, it
merely knows to look for a variable, in this case HOME, which stands for the home directory.
Variables are useful in any computer language because they allow you to define what to do with
a piece of information without knowing specifically what the data is. A program to add two and
two together is not very useful, but a program that adds two variables can be, especially if the
value of the variables can be supplied at execution time by the user of the program. The Bourne
shell has four types of variables: user-defined variables, positional variables or parameters,
predefined or special variables, and environment variables.
Defining Your Own (User-Defined) Variables
As the name implies, user-defined variables are whatever you want them to be. Variable names
are made up of alphanumeric characters and the underscore character, with the provision that
variable names do not begin with one of the digits 0 through 9. (Like all UNIX names, variables
are case sensitive. Variable names take on values when they appear in a command line to the
left of an equal sign (=). For example, in the following command lines, COUNT takes on the
value of 1, and NAME takes on the value of Stephanie:
$ COUNT=1

$ NAME=Stephanie

TIP: Because most UNIX commands are lowercase words, shell programs have

traditionally used all capital letters in variable names. It is certainly not mandatory to use all
capital letters, but using them enables you to identify variables easily within a program.


To recall the value of a variable, precede the variable name by a dollar sign ($):
$ NAME=John

$ echo Hello $NAME

Hello John
You also can assign variables to other variables, as follows:
$ JOHN=John

$ NAME=$JOHN

$ echo Goodbye $NAME

Goodbye John
Sometimes it is useful to combine variable data with other characters to form new words, as in
the following example:
$ SUN=Sun

$ MON=Mon

$ TUE=Tues

$ WED=Wednes

$ THU=Thurs


$ FRI=Fri

$ SAT=Satur

$ WEEK=$SAT

$ echo Today is $WEEKday

Today is

$
What happened here? Remember that when the shell's interpreter sees a dollar sign ($), it
interprets all the characters until the next white space as the name of a variable, in this case
WEEKday. You can escape the effect of this interpretation by enclosing the variable name in
curly braces ({,}) like this:
$ echo Today is ${WEEK}day

Today is Saturday

$
You can assign more than one variable in a single line by separating the assignments with white
space, as follows:
$ X=x Y=y
The variable assignment is performed from right to left:
$ X=$Y Y=y

$ echo $X

y


$ Z=z Y=$Z

$ echo $Y

$
You may notice that when a variable that has not been defined is referenced, the shell does not
give you an error but instead gives you a null value.
You can remove the value of a variable using the unset command, as follows:
$ Z=hello

$ echo $Z

hello

$ unset Z

$ echo $Z

$
Conditional Variable Substitution
The most common way to retrieve the value of a variable is to precede the variable name with a
dollar sign ($), causing the value of the variable to be substituted at that point. With the Bourne
shell, you can cause variable substitution to take place only if certain conditions are met. This is
called conditional variable substitution. You always enclose conditional variable substitutions in
curly braces ({ }).
Substituting Default Values for Variables
As you learned earlier, when variables that have not been previously set are referenced, a null
value is substituted. The Bourne shell enables you to establish default values for variable
substitution using the form
${variable:-value}

where variable is the name of the variable and value is the default substitution. For example,
$ echo Hello $UNAME

Hello

$ echo Hello ${UNAME:-there}

Hello there

$ echo $UNAME

$

$ UNAME=John

$ echo Hello ${UNAME:-there}

Hello John

$
As you can see in the preceding example, when you use this type of variable substitution, the
default value is substituted in the command line, but the value of the variable is not changed.
Another substitution construct not only substitutes the default value but also assigns the default
value to the variable as well. This substitution has the form
${variable:=value}
which causes variable to be assigned value after the substitution has been made. For example,
$ echo Hello $UNAME

Hello


$ echo Hello ${UNAME:=there}

Hello there

$ echo $UNAME

there

$ UNAME=John

$ echo Hello ${UNAME:-there}

Hello John

$
The substitution value need not be literal; it can be a command in back quotation marks:
USERDIR={$MYDIR:-'pwd'}
A third type of variable substitution substitutes the specified value if the variable has been set,
as follows:
${variable:+value}

Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay
×