Learning_the_bash_Shell_Third_Edition 16/n

CHAPTER 8

 Process Handling

Process IDs and Job Numbers

UNIX gives all processes numbers, called process IDs, when they are created.

Job Control

Foreground and Background

If you have only one background job running, you can use fg without arguments, and the shell will bring that job into the foreground. But if you have several jobs running in the background, the shell will pick the one that you put into the background most recently. If you want some other job put into the foreground, you need to use the job’s command name, preceded by a percent sign (%), or you can use its job number, also preceded by %, or its process ID without a percent sign. If you don’t remember which jobs are running, you can use the command jobs to list them.

jobs has a few interesting options. jobs -l also lists process IDs:

[1] 93 Running alice &

[2]- 102 Running duchess &

[3]+ 104 Running hatter &

If you type fg without an argument, the shell will put hatter in the foreground,because it was put in the background most recently. But if you type fg %duchess (or fg %2), duchess will go in the foreground.

You can also refer to the job most recently put in the background by %+. Similarly, %-refers to the next-most-recently backgrounded job (duchess in this case). That explains the plus and minus signs in the above: the plus sign shows the most recent job whose status has changed; the minus sign shows the next-most-recently invoked job

 Suspending a Job

 To suspend a job, type CTRL-Z while it is running

You will probably also find it useful to suspend a job and resume it in the background instead of the foreground. You may start a command in the foreground (i.e.,normally) and find that it takes much longer than you expected—for example, a grep, sort, or database query. You need the command to finish, but you would also like control of your terminal back so that you can do other work. If you type CTRL-Z followed by bg, you will move the job to the background.

You can also suspend a job with CTRL-Y. This is slightly different from CTRL-Z in that the process is only stopped when it attempts to read input from the terminal.

 Signals

A signal is a message that one process sends to another when some abnormal event takes place or when it wants the other process to do something. Most of the time, a process sends a signal to a subprocess it created. You’re undoubtedly already comfortable with the idea that one process can communicate with another through an I/O pipeline; think of a signal as another way for processes to communicate with each other. (In fact, any textbook on operating systems will tell you that both are examples of the general concept of interprocess communication, or IPC. * )

Depending on the version of UNIX, there are two or three dozen types of signals,including a few that can be used for whatever purpose a programmer wishes. Signals have numbers (from 1 to the number of signals the system supports) and names;we’ll use the latter. You can get a list of all the signals on your system, by name and number, by typing kill -l. Bear in mind, when you write shell code involving signals,that signal names are more portable to other versions of UNIX than signal numbers.

 Control-Key Signals

When you type CTRL-C, you tell the shell to send the INT (for “interrupt”) signal to the current job; CTRL-Z sends TSTP (on most systems, for “terminal stop”). You can also send the current job a QUIT signal by typing CTRL- (control-backslash);this is sort of like a “stronger” version of CTRL-C. You would normally use CTRL- when (and only when) CTRL-C doesn’t work.

 kill

Task 8-1

Write a script called killalljobs that kills all background jobs.
kill "$@" $(jobs -p)

  

You may be tempted to use the KILL signal immediately, instead of trying TERM(the default) and QUIT first. Don’t do this. TERM and QUIT are designed to give a process the chance to “clean up” before exiting, whereas KILL will stop the process, wherever it may be in its computation. Use KILL only as a last resort!

You can use the kill command with any process you create, not just jobs in the background of your current shell. For example, if you use a windowing system, then you may have several terminal windows, each of which runs its own shell. If one shell is running a process that you want to stop, you can kill it from another window—but you can’t refer to it with a job number because it’s running under a different shell.You must instead use its process ID.

 ps

trap 

 Process ID Variables and Temporary Files

The only thing new about this script is $$ in the filename expression. This is a special shell variable whose value is the process ID of the current shell.

To see how $$ works, type ps and note the process ID of your shell process (bash).Then type echo “$$”; the shell will respond with that same number. Now type bash to start a subshell, and when you get a prompt, repeat the process. You should see a different number, probably slightly higher than the last one.A related built-in shell variable is ! (i.e., its value is $!), which contains the process ID of the most recently invoked background job. To see how this works, invoke any job

Ignoring Signals

Sometimes a signal comes in that you don’t want to do anything about. If you give the null string (“” or ‘’) as the command argument to trap, then the shell will effectively ignore that signal. The classic example of a signal you may want to ignore is HUP (hangup). This can occur on some UNIX systems when a hangup (disconnection while using a modem—literally “hanging up”) or some other network outage takes place.

HUP has the usual default behavior: it will kill the process that receives it. But there are bound to be times when you don’t want a background job to terminate when it receives a hangup signal.

 Coroutines

Subshells

Subshell Inheritance 

Nested Subshells

Process Substitution

 

A unique but rarely used feature of bash is process substitution. Let’s say that you had two versions of a program that produced large quantities of output. You want to see the differences between the output from each version. You could run the two programs, redirecting their output to files, and then use the cmp utility to see what the differences were.

Another way would be to use process substitution. There are two forms of this substitution. One is for input to a process: >(list); the other is for output from a process: <(list). list is a process that has its input or output connected to something via a 

named pipe. A named pipe is simply a temporary file that acts like a pipe with a name.

In our case, we could connect the outputs of the two programs to the input of cmp via named pipes:

cmp <(prog1) <(prog2)

  

This chapter has covered a lot of territory. Here are some exercises that should help you make sure you have a firm grasp on the material. Don’t worry if you have trouble with the last one; it’s especially difficult.

1. Write a shell script called pinfo that combines the jobs and ps commands by printing a list of jobs with their job numbers, corresponding process IDs, running times, and full commands.

2. Take a non-trivial shell script and “bullet-proof” it with signal traps.

3. Take a non-trivial shell script and parallelize it as much as possible.

4. Write the code that checks for duplicate arguments to the mcp script. Bear in mind that different pathnames can point to the same file. (Hint: if $i is “1”, then eval ‘echo ${$i}’ prints the first command-line argument. Make sure you understand why.)

原文地址:https://www.cnblogs.com/winditsway/p/14537880.html