Job Control Basics
GNU Screen & Linux Job Control
Chapter 5 ยท Shell Job Control Basics
Screen gives you many terminals. Job control lets one terminal run several things at once: starting commands in the background, pausing them, and moving them between the background and the foreground. It's built into the shell. This chapter uses bash, but zsh and most other modern shells behave the same way. It's also the foundation for Chapter 8, where you move an already-running job into screen.
Foreground and Background
A command normally runs in the foreground: it owns the terminal, receives what you type, and
you get your prompt back only when it finishes. Add & to the end of a command and it runs in the
background instead, and the prompt comes back straight away.
The shell prints two numbers: [1] is the job number, and 48213 is the
process ID (PID). They are different things, and Chapter 6 is all about the difference. When the
job finishes, the shell tells you the next time it shows a prompt:
Pausing a Job: Ctrl-Z
If a command is already running in the foreground, Ctrl-Z suspends it. The shell sends
the job the SIGTSTP signal: the job stops where it is — not ended, just frozen — and you
get your prompt back.
Ctrl-C sends SIGINT, which normally ends the program. Ctrl-Z only pauses it.
A stopped job does no work at all until you resume it — a paused backup isn't making progress in the
background.
Listing Jobs
Each line shows the job number, a marker, the state (Running, Stopped, Done), and the command. The
+ marks the current job, the one commands act on by default; the - marks
the previous job. jobs -r lists only running jobs, and jobs -s only
stopped ones.
Moving Jobs Around: fg and bg
| Command | What it does |
|---|---|
fg | Bring the current job to the foreground (resuming it if stopped) |
fg %2 | Bring job 2 to the foreground |
bg | Resume the current stopped job in the background |
bg %1 | Resume job 1 in the background |
kill %1 | Send job 1 the SIGTERM signal, asking it to end |
wait | Wait until all background jobs have finished |
Ctrl-Z, then type
bg. The job carries on in the background, and you can keep working. This is also the first step in
Chapter 8's rescue technique.
Referring to Jobs: Job Specs
| Spec | Refers to |
|---|---|
%1 | Job number 1 |
%% or %+ | The current job (marked +) |
%- | The previous job (marked -) |
%tar | The job whose command starts with tar |
%?backup | The job whose command contains backup |
kill %1 means "job number 1 in this shell." kill 1 means "process ID 1" — on most
systems that's the init process, and an ordinary user isn't allowed to signal it. Forgetting the
% is a common and potentially confusing mistake.
Background Jobs and the Terminal
- Output still appears. A background job's output is printed to your terminal, mixed in with whatever you're doing. Redirect it to a file to avoid this:
long-command > out.log 2>&1 &. - Input stops the job. If a background job tries to read from the terminal, it's sent the
SIGTTINsignal and stops, waiting for you to bring it to the foreground. - Leaving with stopped jobs. If you try to exit the shell while jobs are stopped, bash warns you. Exiting again anyway usually ends them.
Hands-On Exercises
Start sleep 600 in the foreground, suspend it, resume it in the background, start a second sleep 900 &, then use jobs to identify the current and previous jobs. Finally, end both using job specs.
Run read -p "Name? " name &. What does jobs show, and why? How do you finish the command?
Start ping localhost in the foreground. Without stopping it permanently, get your prompt back so that it keeps running but stops cluttering your screen. What problem remains, and how would you have started it differently?
Chapter 5 Quick Reference
command &runs in the background and prints[job] PIDCtrl-Zsuspends the foreground job (SIGTSTP);Ctrl-Cends it (SIGINT)jobslists jobs (-rrunning,-sstopped);+is the current job,-the previousfg/bgmove jobs to the foreground/background;kill %nends one;waitwaits for all- Job specs:
%n,%%/%+,%-,%string,%?string— never forget the% - Background jobs still print to the terminal, and stop (
SIGTTIN) if they try to read from it - Job numbers belong to one shell and disappear with it