Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

Bash & the POSIX Shell  Module 12 – Processes, jobs and signals

Job control: Ctrl-Z, fg, bg, jobs, disown

Stop a running command with Ctrl-Z, move it with bg and fg, name jobs with %1 and %name, and see what disown does to a job when the terminal hangs up.

  • Beginner
  • 10 minutes
  • Examples run with Bash 5.3.20, dash 0.5.13.5, shellcheck 0.11.0 and Python 3.14.8
  • By MySmartCoPilot
Free lesson, Pro answers: 10 minutes
Free: the whole lesson. With a pass: the model answers to its 2 interview questions.

What you will learn

  • Use Ctrl-Z, bg, fg and jobs to stop a command and move it between the foreground and the background
  • Find a job by number, by the + and - markers, and by name with a job spec such as %name or %?string
  • Explain why fg and bg fail in a script and what a process group has to do with it
  • Distinguish disown, disown -h and nohup by what each does to a job when the terminal hangs up

Before you start

What you’ll learn · Before you start

What you will learn

  • Use Ctrl-Z, bg, fg and jobs to stop a command and move it between the foreground and the background
  • Find a job by number, by the + and - markers, and by name with a job spec such as %name or %?string
  • Explain why fg and bg fail in a script and what a process group has to do with it
  • Distinguish disown, disown -h and nohup by what each does to a job when the terminal hangs up

Before you start

On this page

A test run that takes 12 minutes holds your terminal, and you want the prompt back after 20 seconds. Bash can pause the run, move it behind the prompt and bring it forward again, because an interactive shell: The program that reads command lines, expands them and starts the programs they name, then waits for them to finish. Bash, dash and zsh are shells. More in “Shells, terminals and which Bash you have” keeps a numbered table of jobs and hands the keyboard to one of them at a time.

You will stop a command with Ctrl-Z, resume it with bg and fg, name jobs with %1, %- and %name, see why a script cannot use these commands, and learn what disown changes when a terminal hangs up.

Ctrl-Z stops the foreground job, and bg and fg move it

job control: The shell's ability to stop a running command, continue it in the foreground or the background, and list what it tracks. It is on in interactive shells and off in scripts unless set -m turns it on. is the shell’s ability to stop a command and continue it later. The Bash manual says it is supplied jointly by the terminal driver and the shell: the driver turns a key into a signal: A short message the kernel delivers to a process, with a name, a number and a default action such as ending it. A program can handle or ignore most signals; KILL and STOP cannot be caught. More in “Signals, kill and timeout”, and Bash keeps track of what happened to each command. Bash treats one pipeline as one job and numbers jobs from 1.

Three keys matter. The terminal sends the signal to the job that currently owns the keyboard, called the foreground job:

Key stty name Signal Effect on the foreground job
Ctrl-C intr SIGINT ends it, unless the program handles it
Ctrl-Z susp SIGTSTP pauses it, so the shell gets the prompt back
Ctrl-\ quit SIGQUIT ends it, usually with a core dump

The POSIX stty page names the three characters INTR, QUIT and SUSP, and the session below starts by asking stty which keys they are on this terminal. worker.sh is a stand-in for a long job: it announces itself and then waits until a file called release exists.

worker.sh: a stand-in for a long job that ends when a file appears Shell · worker.sh
#!/bin/bash
# worker.sh: a stand-in for a long job. It says it started, waits until the file "release" exists,
# then says it finished.
echo 'worker: running'
until [ -e release ]; do
  sleep 0.2
done
echo 'worker: finished'

The session runs Bash 5.3.20 under a pseudo-terminal, so the keys are real. Look for the Stopped line after Ctrl-Z, the different text bg and fg print, and what jobs lists each time:

Ctrl-Z, jobs, bg and fg on one job, then Ctrl-C on a new one Python · keys_session.py
from session import run, files

files("worker.sh")

run("""
stty -a | tr ';' '\\n' | grep -E ' (intr|quit|susp) '
> bash worker.sh
wait: worker: running
^Z
jobs
bg
jobs
> fg
fg: bash worker.sh
release: worker: finished
rm release
> bash worker.sh
wait: worker: running
^C
jobs
""")

Output

$ stty -a | tr ';' '\n' | grep -E ' (intr|quit|susp) '
 intr = ^C
 quit = ^\
 susp = ^Z
$ bash worker.sh
worker: running
^Z
[1]+  Stopped                    bash worker.sh
$ jobs
[1]+  Stopped                    bash worker.sh
$ bg
[1]+ bash worker.sh &
$ jobs
[1]+  Running                    bash worker.sh &
$ fg
bash worker.sh
worker: finished
$ rm release
$ bash worker.sh
worker: running
^C
$ jobs

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 keys_session.py

After Ctrl-Z, Bash printed [1]+ Stopped and gave the prompt back. The 1 is the job number and the + marks the current job. The job did not end: jobs still lists it, paused. bg then printed the job’s line with an &, which is exactly the form of a job started in the background, and jobs showed it as Running. fg printed the command line and the shell went quiet again, because the job owned the keyboard once more. Here it ended on its own when the release file appeared, which is why the transcript reaches worker: finished without a key. The second run shows the other end: Ctrl-C ended a fresh foreground job, and jobs listed nothing.

Step through the same life as four places a job can be:

Interactive · step by step Where a job can be, and what moves it Step through worker.sh in the recorded session. Watch which key or command moves it from one place to the next.
Where a job can be, and what moves it, step 5 of 5. Showing Foreground, Stopped, Background, Gone. In focus: Gone.Ctrl-ZbgfgCtrl-C or exitkill or exitForegroundowns the keyboardStoppedpaused, still listedBackgroundruns, no keyboardGonefinished or killed

The drawing shows the whole scene; its 5 steps are listed below.

Every step as text
  1. The job starts in the foreground. bash worker.sh was typed without an ampersand, so it owns the terminal and printed "worker: running". The shell waits for it and cannot take another command.
  2. Ctrl-Z stops it. The terminal turns Ctrl-Z into SIGTSTP for the foreground group. The job pauses and the shell prints "[1]+ Stopped" and a prompt. Number 1 is its job number.
  3. bg lets it run behind the prompt. bg sent SIGCONT and the job runs again, but without the keyboard. jobs now lists it as Running, and the shell accepts commands while it works.
  4. fg brings it back. fg gave the keyboard back to the job. The shell printed its command line and waits again, so a key now goes to the job, not to the shell.
  5. Ctrl-C ends it. Ctrl-C sent SIGINT to the foreground group. The job ended, jobs printed nothing afterwards, and the shell took the keyboard back. A job in the background ends with kill or when it finishes.

A job is in the foreground, stopped, in the background, or gone, and each key or command moves it along one arrow. Only the foreground job receives keystrokes.

Key idea

Ctrl-Z pauses the foreground job, bg resumes it behind the prompt, fg resumes it in front, and jobs lists what the shell is tracking. Paused is not finished: a stopped job is still in the table.

The pause has a cost that is easy to forget, because a stopped job is quiet.

Stopped jobs and leaving the shell

If you try to exit while jobs are stopped, Bash prints a warning instead, and a second exit straight away ends the stopped jobs (Bash manual, Job Control Basics). Run jobs, then fg or kill them, before you leave.

Checkpoint

Check: Stopping a job with Ctrl-Z and moving it with bg and fg

  1. Question 1 of 2 You press Ctrl-Z while a command runs in the foreground. What happens to the command?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: It is paused and stays in the shell job table, and the prompt returns

    Ctrl-Z turns into SIGTSTP for the foreground process group: the job pauses, the shell takes the keyboard back and the job waits in the table.

  2. Question 2 of 2 A job is stopped. What is the difference between bg and fg?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: Both continue it; bg leaves the prompt available for commands, fg gives the job the terminal and the shell waits

    Both send SIGCONT. The difference is who owns the keyboard afterwards: with bg the shell does, with fg the job does.

A job spec picks a job by number, marker or name

Once there is more than one job, you need a way to say which one. A job spec: A word starting with % that names a job to commands such as fg, bg, kill and wait: %1 by number, %+ and %- by marker, %name by command prefix, %?text by a substring of the command line. is a word that starts with % and that fg, bg, kill, wait, disown and jobs all accept in place of a process id:

Job spec Picks
%1 job number 1
%+, %% or a lone % the current job, marked + in jobs
%- the previous job, marked -
%name the job whose command line starts with name
%?text the job whose command line contains text

The next session starts three jobs and then picks them in different ways. Watch which job carries the + and the -, the one job spec that fails, and how the markers move after a job ends:

Three jobs picked by prefix, by marker and by text Python · specs_session.py
from session import run, files

files("wait.sh")

run("""
sleep 61 &
bash wait.sh &
sleep 62 &
jobs
! fg %sleep
> fg %bash
fg: bash wait.sh
release:
jobs
kill %-; wait %-; echo "status $?"
kill %?62; wait %?62; echo "status $?"
jobs
""")

Output

$ sleep 61 &
[1] (pid)
$ bash wait.sh &
[2] (pid)
$ sleep 62 &
[3] (pid)
$ jobs
[1]   Running                    sleep 61 &
[2]-  Running                    bash wait.sh &
[3]+  Running                    sleep 62 &
$ fg %sleep
bash: fg: sleep: ambiguous job spec
$ fg %bash
bash wait.sh
$ jobs
[1]-  Running                    sleep 61 &
[3]+  Running                    sleep 62 &
$ kill %-; wait %-; echo "status $?"
[1]-  Terminated: 15             sleep 61
status 143
$ kill %?62; wait %?62; echo "status $?"
[3]+  Terminated: 15             sleep 62
status 143
$ jobs

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 specs_session.py

The newest job, number 3, got the + and number 2 got the -. fg %sleep failed with ambiguous job spec, because two commands begin with sleep; the manual says Bash reports an error when a prefix matches more than one job. fg %bash matched exactly one, so it ran in the foreground until it ended. Afterwards jobs showed job 1 as the previous job and job 3 still as the current one, so kill %- reached sleep 61. The wait %- that followed returned 143, which is 128 plus 15, the exit status of a process ended by SIGTERM (the exit status lesson has the table). The last job was picked by text: %?62 found sleep 62 by the 62 inside its command line.

Shortcuts for the two commands you use most

A job spec on its own is a command: %1 means fg %1, and %1 & means bg %1 (Bash manual, Job Control Basics). With no argument, fg, bg and kill %+ act on the current job.

The shortcut only helps when the spec names one job, and a prefix is where that goes wrong.

A prefix that matches two jobs

Wrong: typing kill %sleep when two sleep jobs exist; Bash refuses with an ambiguity error and nothing is killed. Right: use the job number, or a longer prefix or text that appears in one command line only, such as %?62.

Checkpoint

Check: Picking a job with %1, %+, %-, %name and %?text

  1. Question 1 of 2 Two jobs are running: sleep 61 and sleep 62. What does fg %sleep do?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: It reports an ambiguous job spec and changes nothing

    A %name spec must match exactly one job. Use the number, or text that appears in one command line only.

  2. Question 2 of 2 In the jobs output, which job carries the + marker?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: The current job, the one %+ and %% pick

    Exactly one job is current (+) and at most one is previous (-). %+ and %- pick them without a number.

Scripts run with job control off, and process groups explain why

To let a key reach one job and not the others, the shell puts each job in its own process group: A set of processes the system can signal together. A shell with job control puts each job in its own group, and the terminal sends keyboard signals such as Ctrl-C only to the foreground group., a set of processes that the system can signal together. The terminal has exactly one foreground process group at a time. The manual describes the rule: members of the foreground group receive keyboard-generated signals such as SIGINT, and processes in other groups are immune to them.

That arrangement is switched on by the monitor option, which set -m toggles. POSIX ties job control to that option and turns it on by default only in a shell that runs interactively. A script is not interactive, so it starts with the option off. The session asks Bash directly, then tries fg in a script, then runs a small script with and without the option:

groups.sh: does a background job get a process group of its own? Shell · groups.sh
#!/bin/bash
# groups.sh: start a background job, then ask whether it has a process group of its own.
sleep 30 &
if kill -0 -- "-$!" 2> /dev/null; then
  echo 'the job has its own process group'
else
  echo 'the job shares the script process group'
fi
kill "$!"
The monitor option, fg in a script, and one job in its own group Python · scripts_session.py
from session import run, files

files("groups.sh")

run("""
set -o | grep monitor
bash -c 'set -o | grep monitor'
bash -c 'sleep 30 & fg; kill $!'
bash -c 'sleep 30 & jobs; kill %1 && echo "kill %1 worked"; wait'
bash groups.sh
bash -m groups.sh
""")

Output

$ set -o | grep monitor
monitor        	on
$ bash -c 'set -o | grep monitor'
monitor        	off
$ bash -c 'sleep 30 & fg; kill $!'
bash: line 1: fg: no job control
$ bash -c 'sleep 30 & jobs; kill %1 && echo "kill %1 worked"; wait'
[1]+  Running                    sleep 30 &
kill %1 worked
$ bash groups.sh
the job shares the script process group
$ bash -m groups.sh
the job has its own process group

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 scripts_session.py

The interactive shell printed monitor on and the bash -c one printed monitor off. With the option off, fg stopped with fg: no job control, and bg fails the same way. groups.sh asks whether the job it started has a process group of its own with kill -0 -- "-$!": a minus sign before the number means the group with that id, and signal 0 sends nothing and only reports whether the target exists. Run as bash groups.sh, the job shared the script’s group; run as bash -m groups.sh, it had a group of its own.

Interactive shell Script
monitor option on off
fg and bg work fail with no job control
Background job’s process group its own the script’s
Keys such as Ctrl-C reach the foreground job only reach the script and what it started

Job specs are less certain in a script

The manual says kill and wait need process ids when job control is off. Yet in the session, jobs listed a job and kill %1 ended it inside bash -c, with the option off. Treat job specs as an interactive habit: in a script, store $! when you start a job and use that.

Checkpoint

Check: Why job control is off in scripts, and process groups

  1. Question 1 of 2 A script starts a job with sleep 30 & and then runs fg. What happens?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: fg fails with the message no job control, because the monitor option is off in a script

    The monitor option is on in interactive shells and off in scripts. Without it, fg and bg have nothing to move.

  2. Question 2 of 2 groups.sh starts sleep 30 & and tests it with kill -0 -- "-$!". When does the test succeed?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: When the job has a process group of its own, as with bash -m groups.sh

    Job control gives each job a process group named by the job leader pid. kill -0 with a negative number asks whether such a group exists.

disown and nohup decide whether a job survives a hang-up

Closing a terminal window, or losing the connection behind it, makes the terminal send SIGHUP to the shell. The Bash manual says an interactive shell that receives SIGHUP exits, and before that it resends the SIGHUP to every job in its table, running or stopped; it sends SIGCONT first to stopped jobs so that they can receive it. A job ends only if it does not handle or ignore the signal, and most commands do not.

Two builtins take a job out of that handover. Plain disown %2 removes the job from the table, so the shell no longer knows it. disown -h %2 keeps the job in the table but marks it, so the shell does not send it SIGHUP. The session starts an inner shell, starts three sleep jobs, treats them differently, and sends the inner shell a SIGHUP as a closing terminal would; alive.sh then looks for each sleep:

alive.sh: is a given sleep still running? Shell · alive.sh
#!/bin/bash
# alive.sh N: say whether "sleep N" is still running. It looks a few times, because a process that
# got SIGHUP needs a moment to disappear.
for _ in 1 2 3 4 5 6 7 8 9 10; do
  pgrep -f "sleep $1" > /dev/null || break
  sleep 0.2
done
if pgrep -f "sleep $1" > /dev/null; then echo "sleep $1: still running"; else echo "sleep $1: gone"; fi
A hang-up reaches the plain job; the marked and the forgotten job survive Python · hangup_session.py
from session import run, files

files("alive.sh")

run("""
# An inner shell stands in for a terminal window that is about to be closed.
bash --norc --noprofile -i
sleep 7101 &
sleep 7102 &
sleep 7103 &
disown -h %2
disown %3
jobs
kill -HUP $$
""")

run("""
alive.sh 7101
alive.sh 7102
alive.sh 7103
pkill -f 'sleep 710[23]'
""")

Output

$ bash --norc --noprofile -i
$ sleep 7101 &
[1] (pid)
$ sleep 7102 &
[2] (pid)
$ sleep 7103 &
[3] (pid)
$ disown -h %2
$ disown %3
$ jobs
[1]-  Running                    sleep 7101 &
[2]+  Running                    sleep 7102 &
$ kill -HUP $$
Hangup: 1                  bash --norc --noprofile -i
$ alive.sh 7101
sleep 7101: gone
$ alive.sh 7102
sleep 7102: still running
$ alive.sh 7103
sleep 7103: still running
$ pkill -f 'sleep 710[23]'

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 hangup_session.py

jobs listed jobs 1 and 2 only, because disown %3 had removed the third, while disown -h %2 kept job 2 listed. After the hang-up, the outer shell reported Hangup: 1 for the inner shell, sleep 7101 was gone, and both sleep 7102 and sleep 7103 were still running. Step through the same hang-up:

Interactive · message by message What a hang-up does to three jobs Step through a hang-up sent to a shell that holds three jobs. Watch which job the shell still knows about.
What a hang-up does to three jobs, step 4 of 4. Messages so far: Terminal to Shell: SIGHUP; Shell to The jobs: SIGHUP to job 1.Terminalthe window or loginShelltable holds jobs 1 and 2The jobs1 gone, 2 and 3 runSIGHUPSIGHUP to job 1

The drawing shows the whole scene; its 4 steps are listed below.

Every step as text
  1. Three jobs, three treatments. The shell started sleep 7101, 7102 and 7103. It ran disown -h %2 and then disown %3, so job 1 is untouched, job 2 is marked and job 3 has left the shell's table.
  2. The terminal hangs up. Closing a terminal window or dropping a connection makes the terminal send SIGHUP to the shell. The session sent kill -HUP to its inner shell to do the same.
  3. The shell passes the hang-up on. An interactive shell that gets SIGHUP resends it to every job in its table, except those marked by disown -h. Job 1 gets it. Job 2 is skipped. Job 3 is not in the table at all.
  4. Only job 1 is gone. sleep 7101 died of SIGHUP. sleep 7102 and sleep 7103 were still running when the session looked, so a marked job and a forgotten job both survive the hang-up.

Command What it changes
disown %n the shell forgets the job: no SIGHUP, and jobs no longer lists it
disown -h %n the job stays listed, but the shell does not send it SIGHUP
nohup cmd starts a new command that ignores SIGHUP from the first instant

nohup is the third route and acts on a job before it starts; the background jobs lesson shows its redirections. Both disown forms act on a job that already runs. A separate shell option, huponexit, makes a login shell send SIGHUP to all its jobs when it exits normally; it is off by default.

jobs and finished jobs in Bash 5.3

The Bash 5.3 NEWS says it implements the POSIX requirement that running the jobs builtin removes jobs from the jobs list. This lesson’s sessions were recorded on 5.3.20; an older Bash may keep a reported job in the list for longer.

Checkpoint

Check: What disown, disown -h and nohup do at a hang-up

  1. One question A shell gets SIGHUP and holds job 2, marked with disown -h, and job 3 after disown with no option. What does each do?

    Choose one answer.

    Show the answer: One question

    Answer: Neither receives SIGHUP from the shell; job 2 is still listed by jobs and job 3 is not

    disown forgets a job and disown -h marks it; either way the shell does not pass the hang-up on.

Practise: take a job through every state

In your own terminal, start sleep 300. Press Ctrl-Z, run jobs, then bg, then jobs again, and finish with fg followed by Ctrl-C. The two jobs lines should read Stopped and then Running, and the shell should have no job left at the end. Next start sleep 301 & and sleep 302 &, then end the older one with a job spec built from the - marker, and the newer one with a spec built from the text 302. Check that wait on each returns 143 and that a last jobs prints nothing. If a spec is refused, read the ambiguity message and choose a longer one.

Practice that adapts to you

Practise this lesson

9 questions about 4 ideas of this lesson. Each answer is explained at once, and what you get right is kept in this browser.

  1. Question 1 of 9 Which key sends SIGINT to the foreground job?

    Choose one answer.

    Show the answer: Question 1 of 9

    Answer: Ctrl-C

    The terminal maps intr to SIGINT, susp to SIGTSTP and quit to SIGQUIT; the keys can be changed with stty.

  2. Question 2 of 9 You stop a job with Ctrl-Z and run bg. What does jobs show next?

    Choose one answer.

    Show the answer: Question 2 of 9

    Answer: The job as Running, with an & at the end of its command line

    bg turns a Stopped job into a Running background job, shown with a trailing &.

  3. Question 3 of 9 You try to exit a shell that still holds a stopped job. What does Bash do?

    Choose one answer.

    Show the answer: Question 3 of 9

    Answer: It warns once, and a second exit straight after ends the stopped jobs

    The warning is a safety net against leaving paused work behind; a second exit confirms that you mean it.

  4. Question 4 of 9 Jobs: [1] sleep 61 &, [2] bash wait.sh &, [3] sleep 62 &. Which spec picks job 3 and no other?

    Choose one answer.

    Show the answer: Question 4 of 9

    Answer: %?62

    Use %?text for a part of the command line, a longer prefix, or the job number, so that the spec fits one job.

  5. Question 5 of 9 At the prompt you type %2 and press Enter, with job 2 stopped. What runs?

    Choose one answer.

    Show the answer: Question 5 of 9

    Answer: fg %2: job 2 continues in the foreground

    %n means fg %n and %n & means bg %n; both are shortcuts for the two commands used most.

  6. Question 6 of 9 Why does an interactive shell give each job its own process group?

    Choose one answer.

    Show the answer: Question 6 of 9

    Answer: So the terminal can send a key signal to the foreground job only

    A process group is the unit a signal can address; the terminal names one foreground group and keys go there.

  7. Question 7 of 9 How does a script with no job control tell you that you used fg?

    Choose one answer.

    Show the answer: Question 7 of 9

    Answer: It prints fg: no job control and fg returns a non-zero status

    fg and bg are job control commands, so they refuse to run when the monitor option is off.

  8. Question 8 of 9 Which statement about nohup and disown -h is true?

    Choose one answer.

    Show the answer: Question 8 of 9

    Answer: nohup starts a new command that ignores SIGHUP; disown -h marks a job that already runs so the shell skips it

    nohup changes how a command reacts to SIGHUP; disown -h changes whether the shell sends it.

  9. Question 9 of 9 When a terminal hangs up, who sends SIGHUP to the shell, and what does the shell do with it?

    Choose one answer.

    Show the answer: Question 9 of 9

    Answer: The terminal sends it; an interactive shell resends it to the jobs in its table and exits

    SIGHUP travels from the terminal to the shell, and from the shell to the jobs it tracks.

Interview questions

Warm-up (fresher to 2–5 years): what does Ctrl-Z send, and what do bg, fg and jobs do next?

Ctrl-Z makes the terminal send SIGTSTP to the foreground process group, which pauses the job and returns the prompt; the shell prints a line such as [1]+ Stopped with the job number. The job is paused, not ended, and stays in the shell’s job table. jobs lists the table with each job’s number, its state and its command line, and + and - mark the current and previous jobs. bg sends the paused job SIGCONT and lets it run in the background, as if it had been started with &, so the shell takes commands again. fg also continues the job but gives it the terminal, so the shell waits for it and keyboard input and Ctrl-C go to the job. With no argument, both act on the current job; %n or %name picks another.

The two harder questions are about situations where the keyboard cannot do what you need: a job that must outlive its terminal, and a script that switched job control on. Decide what you would check first, then read the worked first step on each page:

Model answers open with any pass: ₹79 for 1 week ($2.99), one payment that never renews.

  1. Mid to senior

    A 40-minute make runs in the foreground of an SSH session, and the Wi-Fi is about to drop. You cannot restart the build. What can you do right now, what does each step protect against and what does it leave exposed, and how would you start such a job next time?

    Model answer, Pro. Model answers open with any pass; prices are in the notice on this page. First step and follow-ups

  2. Mid to senior

    A wrapper script turns on set -m so it can use kill %1. Since then, Ctrl-C ends the wrapper but leaves its workers running, and a worker that reads standard input shows as Stopped. Explain both symptoms, judge whether set -m is the right tool here and give an alternative.

    Model answer, Pro. First step and follow-ups

Flashcards · 6 cards

Recall it, then check

Say the answer to yourself before you look: recalling it is what makes it stick.

  1. What does Ctrl-Z do to the foreground job?

    The terminal sends SIGTSTP to the foreground process group, which pauses the job and gives the prompt back. The job is stopped, not finished, and stays in the shell's job table.

  2. What do bg, fg and jobs do?

    bg resumes a stopped job in the background, fg resumes it in the foreground, and jobs lists the job table with each job's number, state and command, + marking the current job and - the previous one.

  3. How do you name a job in fg, bg or kill?

    With a job spec starting with %: %1 by number, %+ and %- by marker, %name by the start of its command and %?text by text anywhere in it. Bash refuses a prefix that matches two jobs.

  4. Why do fg and bg fail inside a script?

    Job control is on in interactive shells and off in scripts, so they answer no job control. set -m turns it on, and then each job gets its own process group.

  5. Why does job control give each job its own process group?

    So the terminal can send keys such as Ctrl-C and Ctrl-Z to the foreground job alone, while background jobs keep running untouched.

  6. How can a job survive the hang-up of its terminal?

    At a hang-up an interactive shell resends SIGHUP to every job in its table. disown removes a job from the table, disown -h keeps it listed but marked so it gets no SIGHUP, and nohup starts a command that ignores SIGHUP.

Key takeaways

  • Ctrl-Z sends SIGTSTP to the foreground process group and pauses the job; bg resumes it in the background, fg resumes it in the foreground, and jobs lists the table with a number and a + or - marker.
  • A job spec starting with % picks a job: %1 by number, %+ and %- by marker, %name by command prefix and %?text by substring, and Bash refuses a prefix that matches two jobs.
  • Job control gives each job its own process group so a key reaches only the foreground one; it is on in interactive shells and off in scripts, where fg and bg fail with no job control unless set -m turns it on.
  • At a hang-up an interactive shell resends SIGHUP to every job in its table; disown removes a job from the table, disown -h keeps it listed but marked, and nohup starts a command that ignores SIGHUP.

Terms in this lesson

job control
The shell's ability to stop a running command, continue it in the foreground or the background, and list what it tracks. It is on in interactive shells and off in scripts unless set -m turns it on.
job spec
A word starting with % that names a job to commands such as fg, bg, kill and wait: %1 by number, %+ and %- by marker, %name by command prefix, %?text by a substring of the command line.
process group
A set of processes the system can signal together. A shell with job control puts each job in its own group, and the terminal sends keyboard signals such as Ctrl-C only to the foreground group.

References

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.