CIT052 Index > Notes 1

Notes 1

Chapter 1

Summary of Section 1.5.3

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,

  1. The shell does a fork call to create a new child process that is an exact copy of the shell.
  2. The original shell (the parent) then does a wait for the child process to finish.
  3. The child process does an exec of the command you wanted. The command is read in from disk, replaces the copy of the shell, and starts executing.
  4. When the command finishes, it calls 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.

Section 1.6.2 and 1.6.3

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...

Section 1.6.5

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

Section 1.6

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.

Chapter 2

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.

Section 2.6.1

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.

Chapter 13

Section 13.8

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.”

Section 13.17.1

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.