This chapter describes Unix's facilities for running more than one command
With the X Window System, the simplest way of running another command
is to start a new
and do it there.
This makes these facilities less useful than they were
back in the days when Unix was used via a simple VDU.
However, X and Unix only work so well together because Unix was designed to
run more than one simultaneous command per user.
Also, some of the
editor's most powerful features depend on this.
The execution of a command is known as a process. All multi-user operating systems have to run more than one process at once but Unix was the first to let each user have more than one process. We call this: user multi-processing. In fact, we have already seen Unix running more than process; that's what happens when we execute a pipeline. Something remarkable about this:
$ ls | tee tout | wc -l $
is that Unix automatically synchronises the execution of the three processes so that each stage only produces output when the next is ready to consume it.
Being able to multi-process can save us much waiting. Suppose we wish to sort a huge file, we might type this:
$ sort -o gigantic gigantic <----- a long delay $
We would have to wait while
finished before we could give our next command.
If we add an ampersand
&) to the end of the command, Unix does not wait for the
process to finish before it gives us a prompt:
$ sort -o gigantic gigantic & 26970 $
The number is the unique process identity (PID) of the new process. If we don't dawdle, we can see what processes we have running:
$ ps PID TTY TIME CMD 26970 pts/45 0:01 sort 26914 pts/45 0:00 sh $
does not show itself.
It does however, show
and the shell.
name for the Bourne shell.)
shows that the sorting is over:
$ ps PID TTY TIME CMD 26914 pts/45 0:00 sh $
indicates the input/output connection between the
process appears in the list
because, by default,
only shows processes associated with a terminal.
The PID can be used to stop a process:
$ kill 26970 $ kill -9 26970 $
The second form of the command gets rid of stubborn processes.
Commands such as
start a new window.
If we issue the command without an ampersand,
we can't use the old window until the new one disappears.
That is why we should use this form of command:
$ xman & 26991 $ xedit file & 26993 $
for programs that run in their own windows.
Unix has several commands for running other commands later,
is one of them:
$ at -m 0730 tomorrow sort -o gigantic gigantic ^D $
Notice how the command
will execute is read from standard input.
stops, the processes it started are stopped automatically.
The following command lets users leave processes running after the
$ nohup xman & 26997 $ Sending output to nohup.out
Processes can even be left running after we log off:
$ nohup sort -o gigantic gigantic & 27001 $ Sending output to nohup.out
nohup's output obscures shell's prompt.
This next section is very complicated; we tackle it now because it will help us to understand Unix's means of executing shell scripts when we cover them in Chapter ??.
Unix lets us start extra shells in the same window. Now that we know the name of the Bourne shell, we can easily do so. To clarify what follows, we will make a set of directories to play with:
$ mkdir level1 level1/level2 level1/level2/level3 $
We then start a new shell process and change to another directory:
$ sh $ cd level1 $
We do that twice more and display our current directory and list of processes:
$ sh $ cd level2 $ sh $ cd level3 $ pwd /homedir/cms/ps/book.unix/level1/level2/level3 $ ps PID TTY TIME CMD 26914 pts/45 0:00 sh 27009 pts/45 0:00 sh 27010 pts/45 0:00 sh 27015 pts/45 0:00 sh $
is the original shell in the original directory and is waiting for
which is in
is the last shell that prompted us; it is in
If we now stop the three extra processes we will be back where we started. On the way we can confirm that the waiting shells were in the predicted directories:
$ ^D $ pwd /homedir/cms/ps/book.unix/level1/level2 $ ^D $ pwd /homedir/cms/ps/book.unix/level1 $ ^D $ pwd /homedir/cms/ps/book.unix $ ps PID TTY TIME CMD 26914 pts/45 0:00 sh $
When we were in
level3, we had a stack of four shell processes running.
Programmers will realise the importance of this: it is the mechanism that allows local variables and recursion in shell scripts. It also explains why shell scripts cannot easily leave the user in another directory!
The power of processes makes it possible for the user of interactive
commands, such as mailers and editors, to escape from them temporarily
to execute other commands.
For example if we were using the
editor, we could execute the
command like this:
...(vi) :!date Thu Mar 20 14:50:23 GMT 1997 [Hit return to continue] (vi)...
that asks us to hit the return key after the execution of
Of course, we can run any command - even the shell:
...(vi) :!sh $ cp file1 file1.bu $ cp file2 file2.bu $ cp file3 file3.bu $ ^D [Hit return to continue] (vi) ...
Running the shell means we can do lots of commands before returning to the editor.
An even more powerful facility is that
can take text from the screen, feed it through any Unix command
and replace the text on the screen with the output from the command.
Here we sort all the lines in the file without leaving
...(vi) :1,$!sort (vi)...
Here we format all the text being edited:
...(vi) :1,$!fmt (vi)...
We could easily use this facility to put a C program through a pretty-printer.
We can even execute Unix commands that we are editing:
...(vi) :1,$!sh (vi)...
without leaving the window!
None of these powerful facilities would be possible without Unix's user multi-processing.