LFCA 32 ๐ง Background Jobs and Job Control
A shell is a job controller. It runs commands in the foreground by default โ you type a command, it runs, and the prompt returns when it finishes. But a shell can also run commands in the background, suspend a running command, resume it later, and manage a small table of jobs that belong to the session. This is job control, and it is one of the oldest features of the Unix shell. It matters because the shell is where work happens: a long compile, a server that should keep running, a test suite that takes minutes, an editor that is already open. Without job control, the shell would be able to do one thing at a time. With it, the shell is a small supervisor of the work happening in the session. This chapter covers the job control model, the commands โ &, Ctrl+Z, jobs, fg, bg, kill %N, disown โ and the patterns that make background work manageable. It follows the previous chapter on process management and treats job control as the shell-specific layer above the kernel’s signal model.
Key point: A job is a pipeline managed by the shell. Every job has a job number (%1, %2), a PID (the process group leader), and a state (Running, Stopped, Done). The & operator starts a job in the background. Ctrl+Z suspends the foreground job. jobs lists the jobs of the current shell. fg %N brings a job to the foreground, bg %N resumes it in the background, and kill %N sends a signal to it. Jobs are per-shell: a job started in one terminal is invisible in another. When the shell exits, it sends SIGHUP to its jobs, so a job that must survive logout needs nohup, disown, or setsid.
Why job control exists
Before job control, a shell could run one command at a time. If you started a long-running process, you waited. If you wanted to do something else, you opened another terminal. Job control changed that by letting the shell track multiple jobs and switch between them.
The shell as a session manager. A login session is a shell process with a controlling terminal. The shell reads commands, runs them, and waits for the foreground job. With job control, the shell can also start background jobs, suspend a foreground job, and resume any of them. The shell is a small scheduler of the session’s work.
The distinction between a process and a job. A process is a kernel entity. A job is a shell concept โ one or more processes forming a pipeline, identified by a job number. A job like grep foo file | sort | head is three processes in one job. Killing the job kills all three; killing a process kills only one.
Why the distinction matters. A single kill PID on one process of a pipeline leaves the rest running, and the job may hang. The kill %N form signals the whole job, which is usually what is intended. The shell knows the process group and signals it.
Why the shell is the right place for this. The kernel does not know about jobs โ it knows process groups and sessions. The shell creates a process group per job and tracks the group. The job control commands are the shell’s interface to the kernel’s process-group model.
Why job control is per-shell. The jobs table lives in the shell process. A different shell โ a new terminal, a tmux pane, an SSH session โ has its own table. A job started in one is not visible in another, even if both run as the same user. This is why jobs in one terminal does not show the jobs of another.
Why the controlling terminal matters. A job that reads from the terminal must be in the foreground, because only one process group can read from the terminal at a time. A background job that reads from the terminal is stopped by the kernel with SIGTTIN, and a background job that writes to the terminal can be stopped with SIGTTOU depending on the terminal settings. This is the mechanism that prevents two jobs from interleaving input and output.
Why the shell’s prompt is the foreground process. When the shell is waiting for a command, it is the foreground process. When a command runs, the shell hands the terminal to the command’s process group and waits. Job control is the mechanism that lets the shell take the terminal back and give it to another job.
Starting a background job
The & operator at the end of a command starts the command in the background.
$ sleep 1000 &
[1] 12345
The shell prints the job number in brackets and the PID. The prompt returns immediately, and the command runs in the background.
The job number. The [1] is the job number in the current shell. It is used with %1, %2, and so on.
The PID. The 12345 is the PID of the process group leader. It is used with kill, ps, and the other process tools.
The prompt returns immediately. The shell does not wait for the command. The command continues in the background, and the shell is free to accept new commands.
Multiple background jobs. Each backgrounded command gets the next job number.
$ sleep 100 &
[1] 11111
$ sleep 200 &
[2] 22222
$ sleep 300 &
[3] 33333
The job numbers increment. The numbers are not reused until a job completes and a new job is started.
Why background is useful. A long-running command โ a compile, a download, a test suite โ runs in the background while the shell is used for other work. The shell does not block, and the command does not need a separate terminal.
Why background is not detachment. A background job is still a child of the shell. When the shell exits, it sends SIGHUP to the job, and the job terminates unless it ignores the signal. The nohup and disown are the fixes, covered later in the chapter.
Why background output is still the terminal’s. A background job’s standard output is the terminal unless redirected. The job’s output interleaves with the shell’s prompt and with other jobs’ output, which is confusing. The redirection to a file or a pipe is the standard fix.
$ long-job > job.log 2>&1 &
[1] 12345
The output goes to job.log, and the terminal stays clean.
Suspending and resuming
Ctrl+Z suspends the foreground job. The process is stopped โ not terminated โ and the prompt returns.
$ vim notes.txt
# (editing)
# press Ctrl+Z
[1]+ Stopped vim notes.txt
$
The editor is stopped, and the shell prompt is back. The editor is still in memory, and its state is preserved.
Why the process is stopped, not killed. The SIGTSTP signal stops the process. The kernel preserves its memory and its state, and SIGCONT resumes it. This is why a suspended editor comes back with its buffer intact.
Resuming in the foreground. The fg command brings a stopped or background job to the foreground.
$ fg
vim notes.txt
# (back in the editor)
The fg with no argument resumes the current job โ the most recently suspended or backgrounded. The fg %1 form resumes a specific job.
Resuming in the background. The bg command resumes a stopped job in the background.
$ bg %1
[1]+ vim notes.txt &
The job resumes, but it runs in the background. For an interactive program like an editor, this is usually wrong โ the editor expects the terminal and stops again when it tries to read input.
Why the shell stops a background job that reads the terminal. A background job that reads from the terminal receives SIGTTIN from the kernel, which stops it. This is the mechanism that prevents two jobs from competing for input. The job must be brought to the foreground to continue.
Why bg is useful for non-interactive jobs. A compile, a download, or a test suite does not need the terminal. Suspending it with Ctrl+Z and resuming with bg puts it in the background, and the shell is free.
Why the stopped state consumes resources. A stopped process still holds its memory and its file descriptors. It is not using CPU, but it is using RAM. Many stopped jobs can consume significant memory, and the kill %N is the way to release them.
Listing jobs
The jobs command lists the jobs of the current shell.
$ jobs
[1] Stopped vim notes.txt
[2]- Running sleep 1000 &
[3]+ Running sleep 2000 &
Each line shows the job number, the state, and the command. The + marks the current job (the one fg and bg act on without an argument), and the - marks the previous job.
The states. Running is a job that is executing. Stopped is a job that is suspended. Done is a job that has completed but whose status has not been reported. Done appears when the shell notices the job has exited.
The -l option. The jobs -l form adds the PID to the output.
$ jobs -l
[1]+ 12345 Stopped vim notes.txt
[2]- 12346 Running sleep 1000 &
[3] 12347 Running sleep 2000 &
The PID is the process group leader’s PID.
The -p option. The jobs -p form lists only the PIDs, one per line, which is useful for scripting.
$ jobs -p
12345
12346
12347
The -r and -s options. The jobs -r lists only running jobs, and jobs -s lists only stopped jobs. These are useful when the list is long.
Why the current and previous job markers matter. The + and - markers are the shortcuts. fg with no argument acts on the + job. fg - acts on the - job. This is the shell’s way of letting you switch between the two most recent jobs without typing the job number.
Why jobs output is sometimes empty. The command lists the jobs of the current shell. If the shell has no background or stopped jobs, the output is empty. A job that has completed and whose status has been reported is removed from the table, so it does not appear.
Why the job table is not the process table. The jobs command shows the shell’s jobs, which is a small subset of the system’s processes. The ps command shows the system’s processes. The two are different views, and the job table is the shell’s.
Signaling jobs
The kill command sends a signal to a process or a job. The %N form targets a job.
$ kill %1
[1]+ Terminated sleep 1000
The job number is prefixed with %. The shell resolves the number to the job’s process group and sends the signal.
The %N forms. The %N is the job number, %+ is the current job, %- is the previous job, and %string is a job whose command starts with the string.
kill %1 # job 1
kill %+ # current job
kill %- # previous job
kill %sleep # job whose command starts with "sleep"
The string form is convenient when the job number is unknown. It matches the beginning of the command.
Why the % prefix is required. Without the %, the number is a PID. With the %, it is a job number. The shell distinguishes the two, and kill 1 and kill %1 are different commands.
Sending a specific signal to a job.
kill -STOP %1
kill -CONT %1
kill -TERM %2
The signal is specified the same way as for a process. The job’s process group receives the signal.
Why kill %N is preferred over kill PID for jobs. The job may be a pipeline with several processes. The kill %N signals the whole process group, which terminates all of them. The kill PID signals one process, which may leave the pipeline hanging.
Why the job table updates after the signal. When a job is terminated, the shell notices the child’s exit and updates the job’s state to Done or Terminated. The next jobs command shows the new state, and the entry is removed after the status is reported.
Why the disown command removes a job from the table. The disown %N removes the job from the shell’s table without terminating it. The shell no longer tracks it, so the shell does not send SIGHUP when it exits. This is the alternative to nohup for a job that is already running.
Background jobs and the terminal
The terminal is a shared resource, and the shell mediates access to it. This mediation is what makes job control more than a convenience.
The controlling terminal. A login session has a controlling terminal โ the device the shell reads from and writes to. The terminal has a foreground process group, which is the job currently allowed to read from and write to it.
The foreground process group. When the shell runs a command in the foreground, it makes the command’s process group the foreground group of the terminal. The command reads and writes the terminal directly. When the command finishes, the shell becomes the foreground group again.
The background process group. A background job’s process group is not the foreground group. When a background job tries to read from the terminal, the kernel sends SIGTTIN, which stops the job. When it tries to write and the terminal’s TOSTOP flag is set, the kernel sends SIGTTOU.
Why reading is stopped and writing is usually allowed. Two jobs reading from the same terminal would interleave their input, which is almost never desired. So reading is stopped. Writing is usually allowed because the output is just text, and the interleaving is cosmetic rather than corrupting. The stty tostop command enables the write-stopping behavior.
Why a background job that reads is a problem. A background job that expects input โ an editor, a REPL, a password prompt โ stops when it tries to read. The job is stuck in the stopped state, and the fix is fg to bring it to the foreground.
Why a daemon detaches from the terminal. A long-running service should not depend on a terminal. It detaches from the controlling terminal, becomes a session leader with no controlling terminal, and runs in the background indefinitely. This is the setsid behavior, and it is what systemd provides for services.
Why the terminal settings affect job control. The terminal’s settings include the signals sent for Ctrl+C (SIGINT), Ctrl+Z (SIGTSTP), and Ctrl+\ (SIGQUIT). The stty command changes these. A different configuration changes the keys that suspend and interrupt.
Why the shell must be the foreground process to accept input. The shell reads commands from the terminal, which means the shell must be the foreground group. When a foreground command is running, the shell is not in the foreground and does not read. This is why the prompt returns only after the foreground command finishes or is suspended.
Surviving logout
A background job is a child of the shell, and the shell sends SIGHUP to its children when it exits. A job that should survive logout must ignore or detach from SIGHUP.
nohup. The nohup command runs a program and makes it ignore SIGHUP.
$ nohup ./long-job.sh &
[1] 12345
nohup: ignoring input and appending output to 'nohup.out'
The job runs in the background, ignores SIGHUP, and its output goes to nohup.out. The job survives the shell’s exit.
disown. The disown command removes a job from the shell’s table.
$ ./long-job.sh &
[1] 12345
$ disown %1
The shell no longer tracks the job, so it does not send SIGHUP. The job continues after the shell exits. The disown is a shell built-in, and its behavior depends on the shell.
setsid. The setsid command runs a program in a new session.
$ setsid ./long-job.sh
The program becomes a session leader with no controlling terminal. It is fully detached. This is the most complete detachment, and it is what a daemon does at startup.
Why the three are different. nohup ignores SIGHUP but the job is still a child of the shell. disown removes the job from the shell’s table but does not change the signal handling โ the job still receives SIGHUP if the shell sends it to the process group. setsid creates a new session, which fully detaches the job from the terminal and the shell’s process group.
Why systemd is the modern answer. A long-running service should be managed by systemd, which handles the daemonization, the logging, the restart policy, and the dependency management. The nohup, disown, and setsid are for one-off jobs that need to survive a logout; a service should be a systemd unit.
Why nohup.out can grow unbounded. The output file is appended to and never rotated. A long-running job that writes to it fills the disk. The fix is to redirect the output to a log file with rotation, or to use systemd‘s journal, which has its own rotation.
Why the logout behavior depends on the shell. A shell that does not send SIGHUP to its background jobs does not terminate them on exit. The behavior is not standardized, and the difference between bash, zsh, and other shells is a source of surprise. The nohup and disown are portable solutions.
Complete Example Session
# ============================================
# PART 1: START A BACKGROUND JOB
# ============================================
sleep 1000 &
# [1] 12345
# ============================================
# PART 2: LIST JOBS
# ============================================
jobs
# [1]+ Running sleep 1000 &
jobs -l
# [1]+ 12345 Running sleep 1000 &
# ============================================
# PART 3: SUSPEND AND RESUME
# ============================================
# Start a foreground job
vim notes.txt
# Press Ctrl+Z
# [1]+ Stopped vim notes.txt
jobs
# [1]+ Stopped vim notes.txt
fg %1
# (back in vim)
# Press Ctrl+Z again
# [1]+ Stopped vim notes.txt
bg %1
# [1]+ vim notes.txt &
# ============================================
# PART 4: MULTIPLE JOBS
# ============================================
sleep 100 &
# [1] 11111
sleep 200 &
# [2] 22222
sleep 300 &
# [3] 33333
jobs
# [1] Running sleep 100 &
# [2]- Running sleep 200 &
# [3]+ Running sleep 300 &
# ============================================
# PART 5: CURRENT AND PREVIOUS JOB
# ============================================
fg
# brings job 3 (the current, marked +) to the foreground
# Ctrl+Z
# [3]+ Stopped sleep 300
fg -
# brings job 2 (the previous, marked -) to the foreground
# ============================================
# PART 6: SIGNAL A JOB
# ============================================
kill %1
# [1]+ Terminated sleep 100
kill %2
# [2]+ Terminated sleep 200
# ============================================
# PART 7: JOB BY NAME
# ============================================
kill %sleep
# terminates the job whose command starts with "sleep"
# ============================================
# PART 8: DISOWN
# ============================================
./long-job.sh &
# [1] 12345
disown %1
# removes job 1 from the table; it survives logout
jobs
# (empty โ the job is no longer tracked)
# ============================================
# PART 9: NOHUP
# ============================================
nohup ./long-job.sh > job.log 2>&1 &
# [1] 12345
# nohup: ignoring input and appending output to 'job.log'
# The job ignores SIGHUP and survives logout.
# ============================================
# PART 10: BACKGROUND WITH REDIRECTED OUTPUT
# ============================================
./compile.sh > compile.log 2>&1 &
# [1] 12345
# output goes to compile.log, not the terminal
# ============================================
# PART 11: WHAT NOT TO DO
# ============================================
# Don't expect `&` to survive logout
sleep 1000 & # receives SIGHUP when the shell exits
# Don't use `bg` for an interactive program
vim & # the editor stops when it tries to read the terminal
# Don't kill a job by PID if it is a pipeline
# Use kill %N to signal the whole job.
# Don't leave stopped jobs around
# They consume memory.
# Don't forget to redirect background output
# The output interleaves with the prompt.
# Don't use nohup.out without rotation
# It grows forever.
The eleven parts cover starting, listing, suspending, resuming, multiple jobs, signaling, disown, nohup, redirection, and the anti-patterns.
Quick Reference
Job Control Commands
| Command | Purpose |
|---|---|
cmd & | Start in background |
Ctrl+Z | Suspend foreground |
jobs | List jobs |
jobs -l | List with PIDs |
fg %N | Foreground job N |
bg %N | Background job N |
kill %N | Signal job N |
disown %N | Remove from table |
nohup cmd & | Ignore SIGHUP |
setsid cmd | New session |
Job Specifications
| Form | Meaning |
|---|---|
%N | Job number N |
%% or %+ | Current job |
%- | Previous job |
%string | Job starting with string |
%?string | Job containing string |
Job States
| State | Meaning |
|---|---|
Running | Executing |
Stopped | Suspended |
Done | Completed, status not reported |
Terminated | Killed by signal |
Detachment
| Level | Command | Survives logout |
|---|---|---|
| Background | cmd & | No |
| Ignore SIGHUP | nohup cmd & | Yes |
| Remove from table | disown %N | Yes |
| New session | setsid cmd | Yes |
| Managed service | systemd | Yes |
Signals for Job Control
| Signal | Key | Effect |
|---|---|---|
SIGINT | Ctrl+C | Terminate |
SIGTSTP | Ctrl+Z | Suspend |
SIGQUIT | Ctrl+\ | Quit with core |
SIGTTIN | โ | Background read, stops |
SIGTTOU | โ | Background write, stops if TOSTOP |
Best Practices
โ Do This:
# Redirect background output
./job.sh > job.log 2>&1 & # โ
# List jobs to check state
jobs -l # โ
# Use job numbers for signaling
kill %1 # โ
# Use nohup for jobs that must survive logout
nohup ./job.sh > job.log 2>&1 & # โ
# Use disown for a running job
./job.sh & disown %1 # โ
# Use systemd for services
systemctl start myservice # โ
# Bring a stopped interactive job back
fg %1 # โ
โ Don’t Do This:
# Don't expect `&` to survive logout
sleep 1000 & # terminated on logout # โ ๏ธ
# Don't run an interactive program in the background
vim & # it stops when it tries to read # โ ๏ธ
# Don't kill a pipeline by one PID
kill 12345 # only one process of the pipeline # โ ๏ธ
# Don't leave stopped jobs
# They consume memory # โ ๏ธ
# Don't forget to redirect background output
# The output interleaves with the prompt # โ ๏ธ
# Don't use nohup.out without rotation
# It grows unbounded # โ ๏ธ
Common Pitfalls
| Pitfall | Problem | Solution |
|---|---|---|
| Background job dies on logout | SIGHUP | nohup, disown, setsid |
| Interactive program in background | Stops on read | Use fg |
| Killing one PID of a pipeline | Others hang | kill %N |
| Output interleaves | Confusing terminal | Redirect to a file |
| Stopped jobs accumulate | Memory | kill %N |
nohup.out grows | Disk fills | Redirect with rotation |
| Job number and PID confused | Wrong target | %N for jobs |
| Job not in another terminal | Per-shell table | Use the same shell |
Real-World Examples
1. Background a long job
./build.sh &
2. Redirect output
./build.sh > build.log 2>&1 &
3. List jobs
jobs -l
4. Suspend and resume
# Ctrl+Z
bg %1
5. Foreground a job
fg %1
6. Kill a job
kill %1
7. Survive logout
nohup ./job.sh > job.log 2>&1 &
8. Disown
./job.sh &
disown %1
9. Fully detach
setsid ./job.sh
10. Service management
systemctl start myservice
Visual: Job Control Model
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ SHELL (controlling terminal) โ
โ โ โ
โ โโโ Job 1: vim notes.txt (Stopped) โ
โ โโโ Job 2: sleep 1000 & (Running) โ
โ โโโ Job 3: ./build.sh & (Running) โ
โ โโโ Job 4: grep foo | sort (Running) โ
โ โ
โ Each job is a process group. โ
โ The shell tracks the job numbers and states. โ
โ The foreground job is the one with terminal access. โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Visual: The Foreground/Background Switch
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ FOREGROUND โ
โ โ
โ $ vim notes.txt โ
โ (shell waits, vim has the terminal) โ
โ โ
โ Ctrl+Z โ
โ โ โ
โ โผ โ
โ [1]+ Stopped vim notes.txt โ
โ $ โ
โ (shell has the terminal again) โ
โ โ
โ fg %1 โ
โ โ โ
โ โผ โ
โ (vim has the terminal again) โ
โ โ
โ bg %1 โ
โ โ โ
โ โผ โ
โ [1]+ vim notes.txt & โ
โ (vim runs in background, shell has the terminal) โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Visual: Terminal Access
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Terminal โ
โ โ โ
โ โโโ Foreground process group: โ
โ โ Can read and write โ
โ โ โ
โ โโโ Background process group: โ
โ Reading โ SIGTTIN (stops) โ
โ Writing โ allowed (or SIGTTOU if TOSTOP) โ
โ โ
โ Only one process group can read the terminal at a time. โ
โ The shell switches the foreground group with fg and bg. โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Visual: Job vs Process
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ JOB: grep foo file | sort | head โ
โ โ
โ Process group 1234: โ
โ 1234 grep โ
โ 1235 sort โ
โ 1236 head โ
โ โ
โ kill 1235 โ
โ โ only sort receives the signal โ
โ โ grep and head may hang โ
โ โ
โ kill %1 (= kill -1234) โ
โ โ the whole group receives the signal โ
โ โ the job terminates cleanly โ
โ โ
โ The job is the pipeline; the processes are its parts. โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Visual: Surviving Logout
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ./job.sh & โ
โ Child of the shell. โ
โ Receives SIGHUP on logout. โ
โ Terminates. โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ nohup ./job.sh & โ
โ Ignores SIGHUP. โ
โ Survives logout. โ
โ Output to nohup.out. โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ ./job.sh & disown %1 โ
โ Removed from the job table. โ
โ Shell does not send SIGHUP. โ
โ Survives logout. โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ setsid ./job.sh โ
โ New session, no controlling terminal. โ
โ Fully detached. โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ systemd service โ
โ Managed by the init system. โ
โ Restart policy, logging, dependencies. โ
โ The correct answer for a service. โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Visual: Job States
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Running โ
โ Executing. โ
โ Can be suspended with Ctrl+Z. โ
โ Can be signaled with kill %N. โ
โ โ
โ Stopped โ
โ Suspended by SIGTSTP or SIGSTOP. โ
โ Not using CPU, still holding memory. โ
โ Resumed with fg or bg. โ
โ โ
โ Done โ
โ Completed. โ
โ Status not yet reported. โ
โ Removed after jobs shows it. โ
โ โ
โ Terminated โ
โ Killed by a signal. โ
โ Removed after jobs shows it. โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Summary
| Command | Purpose |
|---|---|
cmd & | Start in background |
Ctrl+Z | Suspend foreground |
jobs | List jobs |
fg %N | Foreground |
bg %N | Background |
kill %N | Signal job |
disown %N | Remove from table |
nohup cmd & | Ignore SIGHUP |
setsid cmd | New session |
| Item | Value |
|---|---|
| Job number | %1, %2 |
| Current job | %+ or %% |
| Previous job | %- |
| Job by name | %string |
| States | Running, Stopped, Done, Terminated |
| Per-shell | Yes |
| Terminal access | Foreground only |
Key takeaways:
- A job is a pipeline managed by the shell โ it has a job number, a PID, and a state, and it is a process group, not a single process
- The
&operator starts a job in the background โ the shell returns the prompt immediately, and the job runs concurrently Ctrl+Zsuspends the foreground job โ the process is stopped, not killed, and its state is preservedjobslists the jobs of the current shell โ the+and-markers identify the current and previous jobs for thefgandbgshortcutsfgandbgswitch a job between foreground and background โ the foreground job has terminal access, and the background job does notkill %Nsignals the whole job โ a pipeline has several processes, and the job form signals the process group- Jobs are per-shell โ a job started in one terminal is invisible in another, because the job table lives in the shell process
- A background job that reads the terminal is stopped โ the kernel sends
SIGTTIN, and the job must be brought to the foreground nohup,disown, andsetsiddetach a job from the shell โ a background job with&receivesSIGHUPon logout, and the detachment is what keeps it runningsystemdis the modern answer for services โnohupis for one-off jobs, and a service should be managed by the init system
Remember: Job control is the shell’s layer over the kernel’s process groups. The & starts a job in the background, Ctrl+Z suspends it, jobs lists it, fg and bg switch it between foreground and background, and kill %N signals the whole job. The foreground job has the terminal, the background job does not, and a job that must survive logout needs nohup, disown, or setsid. The job number and the PID are different identifiers, and the job form is the correct one for a pipeline.
Stop using slow, ad-bloated tool sites! ๐คฎ
๐ Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
โ
Finance (Mortgage, Interest, Inflation)
โ
Tech (Base64, JSON, Dev Suite, IP)
โ
Health (BMI, BMR, TDEE)
โ
Productivity (Timer, Workspace, QR)
โก๏ธ Fast & Private
๐ No data leaves your device
๐ 100% Free
๐ Use it now: https://tools.kandz.me
๐ Bookmark itโyouโll need it later!