First, a quick refresher of what you may have covered in your first UNIX course: In the diagrams in this section, you see this small table at the bottom:
| 0 stdin terminal |
| 1 stdout terminal |
| 2 stderr terminal |
These are the first three default file descriptors for the LINUX environment. Standard input, standard output, and standard error are all connected to your terminal window.
Now, on to the topic at hand.
As detailed in the explanation on page 17,
when you type a shell command that isn’t an internal command,
for example, grep,
the shell does the following steps,
fork call to create a new
child process that
is an exact copy of the shell.wait for
the child process to finish.exec of the command you wanted.
The command is read in from disk, replaces the copy of the shell, and starts
executing.exit to terminate.
This wakes up the parent process.
Why does the shell go through all these gyrations? Why doesn’t it
just do an exec of the command (which would unload the shell
and start the command) and then have the command do
an exec of the shell when it’s done? Asked and answered!
The overhead of reloading the shell after every command finishes would far
exceed the overhead of starting a new process with fork.
Why fork? It makes sense to have the command run in the same
environment as the shell and have access to any open files that the
shell has. Duplicating the shell process does this automatically.
Does exec really overwrite the duplicate child shell? You’d
better believe it. Open up a new terminal and type this at the shell
prompt:
exec ls
If you blink you’ll miss it. The ls command will
replace the shell, and your terminal window will vanish.
But see the notes for section 13.17.1
for a place where exec can be useful.
The first paragraph in this section should
say that “...the umask command is used to
remove permissions from the default permissions of
newly created files.” In this phrase, the key word
is remove. Let’s say you wanted to remove
no permissions for yourself, write permission for the group, and
read, write and execute permission for everybody else. Those permissions
work out to the numeric code 027, as described in
section 1.6.3. This is what you would use for your umask
command.
For a more complete description of the chmod command,
see this external site.
Example 1.8 at the bottom of page 21 should have a colon instead of a dot:
Usage: chown [OPTION]... [OWNER][:[GROUP]] FILE... or: chown [OPTION]... :[GROUP] FILE...
This section sets new horizons in vagueness. Chapter 2 will go into more detail
about creating variables for each of the shells. This sentence needs a bit of
explanation: “ If an environment variable is set in the child shell,
it is not passed back to the parent.” If you type
echo $PAGER in the Bash shell, it will show you the name
of the program used to display files one page at a time. The default value
is less. If you start a new child shell and ask for the value
of $PAGER, it will still be less. If you change
the value to a different program, such as more, the value changes
only for that shell and its children. As far as the
parent shell is concerned, the value of $PAGER is still
less.
> echo $PAGER less > /bin/bash #create a new child shell > echo $PAGER less > PAGER=more > echo $PAGER more > /bin/bash # create a grandchild shell > echo $PAGER # it inherits child's variables more > exit # return to child shell exit > echo $PAGER # child shell value is "more" more > exit # return to parent shell exit > echo $PAGER # parent shell's value remains unchanged less
Ignore Figure 1.8, which shows how the C and TC shells do redirection of standard error.
Redirection and Pipes are different! Redirection sends the output of a program to some file other than standard output, or receives input from some file other than the standard input. A pipe sends the output of one program to the input of another program.
In all the shells, when you create a variable, you just give its
name. When you access a variable, you precede it with a dollar
sign. Thus, in bash:
x=37 # creates the variable echo $x # accesses the variable
In the Bash shell, expansion of wildcards is “smart.” If you
just type echo How are you? without quote
marks, you will probably get How are you?. This
“works” because the shell is smart enough to figure out that
you have no file names four characters long beginning with
you, and thus it doesn’t treat the question mark as a
wildcard. However, make these three files:
touch youa touch youb touch youc
And then try echo How are you? without quote
marks. It will produce How are youa youb youc
The moral of the story: if you don’t want wildcards interpreted, use quote marks to turn them off. Please note that the history character ! in the Bash shell is not a wildcard. To get it to echo properly, you must not use quote marks.
Some of the comments on page 65 are totally wrong. Item 14 should read “If
the counter variable n is equal to the number of items in the
foods array, then we are at the end of the list.”
Item 15 should read: “The array called foods is
reassigned values. This is not necessary because, unlike the C shell script,
we have not shifted the list after each mail is sent.
The wildcard
characters do not have the same meaning in the shell as they do in
regular expressions.
If you have never used regular expressions before, you will learn
about them in chapters 3 and 4 when covering the grep
command. In that context, the ? and *
characters will work very differently. Sections 13.8 and 13.9
cover the use of the wildcards in the context of “how do I find
a match to a group of file names for a command to work with.”
When you type a command and redirect its output or input, the command takes place in a child shell. If you have to redirect output for several commands, it may be easier to simply redirect output for the current shell, do the commands, then redirect the output back to the terminal. This is what is happening in Example 13.84, starting with step 2.