2026年11月14日
2026年11月14日
Linux Job Control: Using bg, fg, jobs and Ctrl+Z to Switch Jobs
This article is a localized edition of the Japanese original. Read the Japanese original
When you run a long command in a terminal, you cannot type the next command until it finishes. With the job control feature of shells such as bash, you can keep a command running in the background while you do other work, or resume a command you paused partway through.
The output examples in this article were checked with bash 5.2 on Debian 13 as of October 2026. zsh works in much the same way.
Jobs, foreground and background
A command started from the shell (including a series of commands joined by pipes) is called a job. A job is in one of these states:
| State | Meaning |
|---|---|
| Foreground | Running and holding the terminal. It can receive keyboard input. Only one at a time |
| Background (Running) | Running without holding the terminal. You get the prompt back and can type other commands |
| Stopped | Paused. It does not run until you resume it with fg or bg |
These are the operations you use:
| Operation | What it does |
|---|---|
command & |
Start a command in the background |
Ctrl+Z |
Pause the foreground job |
jobs |
List jobs |
fg |
Move a job to the foreground (resuming it if stopped) |
bg |
Resume a stopped job in the background |
kill %number |
Send a signal to a job (terminate by default) |
Run a command in the background (&)
Add & to the end of a command to start it in the background and return to the prompt right away.
$ sleep 300 &
[1] 7
$ echo $!
7
[1] is the job number and 7 is the process ID. $! gives you the process ID of the most recent background process.
Messages printed by background jobs appear directly in the terminal. To keep your screen tidy, send the output to a file.
./backup.sh > backup.log 2>&1 &
Pause a running command (Ctrl+Z)
You can pause a command running in the foreground with Ctrl+Z.
$ vim memo.txt
(press Ctrl+Z in vim)
[1]+ Stopped vim memo.txt
$
A stopped job is simply frozen in place; it has not exited. For example, you can drop back to the shell with your editor still open, run a command to check something, and then return to the editor.
Ctrl+C does not pause; it interrupts (terminates) the foreground job.
List jobs (jobs)
$ sleep 300 &
[1] 7
$ sleep 200 &
[2] 8
$ jobs
[1]- Running sleep 300 &
[2]+ Running sleep 200 &
The symbol after the number means:
+: the current job. It is the target when you runfgorbgwithout a number-: the job before that
Commonly used options:
| Command | Shows |
|---|---|
jobs -l |
Process IDs as well |
jobs -p |
Process IDs only |
jobs -r |
Running jobs only |
jobs -s |
Stopped jobs only |
$ jobs -l
[1]- 7 Running sleep 300 &
[2]+ 8 Running sleep 200 &
jobs shows only jobs started from that shell. Anything started in another terminal or another SSH session does not appear. Find those with ps or pgrep.
Refer to a job (%)
With fg, bg, kill and similar commands, you refer to a job with %.
| Syntax | Target |
|---|---|
%1 |
Job number 1 |
%+ or %% |
The current job (marked +) |
%- |
The previous job (marked -) |
%sleep |
The job whose command name starts with sleep |
%?log |
The job whose command line contains log |
When you refer to a job by name, as in %sleep, and more than one job matches, you get an error. In that case, use the number.
Bring a job back to the foreground (fg)
$ fg %1
vim memo.txt
fg brings the specified job back to the front of the terminal, resuming it if it was stopped. Without a number, it acts on the current job (+).
Resume a stopped job in the background (bg)
If you forgot the & and started a long task, pause it with Ctrl+Z and then move it to the background with bg.
$ tar czf site.tar.gz /var/www/html
(press Ctrl+Z)
[1]+ Stopped tar czf site.tar.gz /var/www/html
$ bg %1
[1]+ tar czf site.tar.gz /var/www/html &
$ jobs
[1]+ Running tar czf site.tar.gz /var/www/html &
bg acts on stopped jobs. It has no effect on a job that is already running.
If a background job tries to read keyboard input, that job is stopped (jobs shows it as Stopped). For commands that ask for input such as a password, bring them to the front with fg and type there.
Terminate a job (kill)
You can give kill a job instead of a process ID.
$ kill %2
$ jobs
[1]- Running sleep 300 &
[2]+ Terminated sleep 200
By default kill sends SIGTERM (a request to exit). Only if the job does not respond, force it with kill -KILL %2 (kill -9). You can also terminate stopped jobs with kill.
When a job ends, a notice such as Done (normal exit) or Terminated (ended by a signal) appears the next time the prompt is shown, and the job is removed from the list.
What happens to jobs when the shell closes
Jobs are child processes of the shell, so take care when closing it.
- If you run
exitwhile there are stopped jobs, the shell printsThere are stopped jobs.and does not exit. If you runexitagain right away, the stopped jobs are terminated. - When an SSH connection drops or you close the terminal window, the shell receives
SIGHUPand also sendsSIGHUPto running and stopped jobs. Most commands exit when they get it.
To keep work running after you log out, use one of the following.
disown: detach a job that is already running
$ ./import.sh > import.log 2>&1 &
[1] 1234
$ disown %1
$ jobs
$
disown removes the job from the shell's job list so that the shell does not send it SIGHUP when it exits. To keep it in the list, use disown -h %1. For a stopped job, resume it first with bg and then run disown.
nohup: make it survive disconnects from the start
nohup ./import.sh > import.log 2>&1 &
nohup starts the command so that it ignores SIGHUP. If you do not redirect the output, it is written to nohup.out in the current directory.
For longer and more reliable runs
If you want your whole working session to survive an SSH disconnect, use tmux or screen. For processes that should always run on a server, registering them as systemd services instead of using job control also takes care of starting them after a reboot and managing their logs.
Using it in shell scripts
In scripts, the common pattern is to start several tasks at once with & and wait for them to finish with wait.
#!/bin/bash
gzip -k access.log &
gzip -k error.log &
wait
echo "All compression jobs are done"
wait waits until every background process started by that shell has finished. Give it a process ID, as in wait $!, to wait for just that process. Job control is normally disabled in scripts, so build them with & and wait rather than fg and bg.
Summary
- Start a command in the background with
command &; get its process ID with$! - Pause with
Ctrl+Z, bring to the front withfg, resume in the background withbg - List jobs with
jobs(-ladds PIDs) and refer to them with%1,%+,%-or%name - Terminate with
kill %number; the default signal isSIGTERM - For work that must continue after logout, use
disownornohup; for long-term use,tmuxor systemd
Related articles:
Questions about WordPress? The publisher of this site is based in Japan and replies in Japanese. Contact (Japanese)