Section 1 of 10

1 Before you start

Before you begin, take a few minutes to check what you already know and how confident you feel. You will see the same questions again at the end of the module — this helps both you and us measure what you have learned. Click an option for every question and confidence rating, then click Next to continue.

Pre-test

What does adding & to the end of a command do?

Pre-test

You press Ctrl-Z on a running foreground job. What happens?

Pre-test

A job is suspended. Which command makes it continue running in the background?

Pre-test

What is the difference between kill %1 and kill -9 %1?

Pre-test

Which command lets a job keep running after you close the terminal?

Pre-test

After running a command with & the shell prints [1] 20345. What are these two numbers?

Pre-test

What does the jobs command list, and how do you refer to job number 1?

Pre-test

A background script keeps printing over your prompt. What do you add to send its output to a log file?

Pre-confidence

I can start a command in the background and get my prompt back.

Not at all confident
Fully confident
Pre-confidence

I can suspend a foreground job with Ctrl-Z and resume it with bg or fg.

Not at all confident
Fully confident
Pre-confidence

I can list jobs and stop one with kill, and I know when -9 is a last resort.

Not at all confident
Fully confident
Section 2 of 10

2 Introduction

Imagine you kick off a cohort analysis that will take ten minutes, and your terminal freezes. The prompt won't return until the job finishes.

Job control is the set of shell features that fixes this. It lets you push a running command into the background, reclaim your prompt, and check on, pause, resume, or stop the job at will.

Mastering these skills allows long-running jobs to keep executing even after you close your terminal.

Here, we will cover some of the topics below:

  • Foreground and background: one terminal, several jobs.
  • Starting in the background with &, suspending with Ctrl-Z.
  • jobs, fg, and bg to list and move jobs around.
  • Signals and kill; keeping jobs alive with nohup and disown.
Section 3 of 10

3 Foreground and Background

By default, every command runs in the foreground. It "owns" the terminal until it finishes, meaning your prompt is completely unavailable. While this is fine for instant commands like ls, it is incredibly frustrating for a ten-minute analysis.

Conversely, a background job runs concurrently while handing the prompt straight back to you. A single terminal window can host many background jobs at once.

A foreground command keeps the one prompt busy until it finishes, so adding & runs the job in the background and returns the prompt immediately, letting one terminal drive many jobs at once.
A foreground command keeps the one prompt busy until it finishes, so adding & runs the job in the background and returns the prompt immediately, letting one terminal drive many jobs at once.
Section 4 of 10

4 Starting a Job in the Background - &

To launch a command directly into the background, simply add an ampersand (&) to the very end of your command:

Try it out

Try this snippet in the Bash Scratchpad on the right.

Try this snippet
$ ./cohort_summary.sh big_cohort.csv out.tsv &

The shell will immediately return two numbers:

  • [1] (Job Number): A small, terminal-specific counter used with job control commands.
  • 20345 (PID): The system-wide Process ID.

The prompt returns instantly, and your job runs quietly in the background.

Appending & runs a command in the background so the shell prompt returns immediately, and the shell reports two identifiers for it: a terminal-local job number ([1], used with fg/bg/kill %1) and a system-wide process ID (20345, used with ps/kill/top).
Appending & runs a command in the background so the shell prompt returns immediately, and the shell reports two identifiers for it: a terminal-local job number ([1], used with fg/bg/kill %1) and a system-wide process ID (20345, used with ps/kill/top).

A background job will still print its output directly to your terminal screen, scribbling over whatever else you are trying to do. For any "chatty" script, redirect its output to a log file by adding &> run.log before the final &:

Try it out

Try this snippet in the Bash Scratchpad on the right.

Try this snippet
$ ./cohort_summary.sh big_cohort.csv out.tsv &> run.log &
A backgrounded command keeps writing to your terminal at the cursor, so its output runs straight onto whatever you are typing; appending &> run.log before the & diverts both stdout and stderr into a file, leaving your screen readable while the job's output is saved.
A backgrounded command keeps writing to your terminal at the cursor, so its output runs straight onto whatever you are typing; appending &> run.log before the & diverts both stdout and stderr into a file, leaving your screen readable while the job's output is saved.
Section 5 of 10

5 Suspend and Resume - Ctrl-Z, bg, fg

It is incredibly common to start a job in the foreground, only to realize seconds later that it’s going to take a long time. You don't have to kill it and start over. Instead, press Ctrl-Z to suspend it.

Try it out

Try this snippet in the Bash Scratchpad on the right.

Try this snippet
$ ./cohort_summary.sh big_cohort.csv out.tsv
Ctrl-Z does not kill a foreground job, it pauses it and hands your prompt back, so you can then use bg to let the same job keep running in the background while you work.
Ctrl-Z does not kill a foreground job, it pauses it and hands your prompt back, so you can then use bg to let the same job keep running in the background while you work.

Suspending a job freezes it completely; it stops consuming CPU cycles, and your prompt returns. From here, you have two choices to resume it:

  • bg: Resumes the job, but keeps it running in the background.
  • fg: Pulls the job back into the foreground so it owns the terminal again.
Try it out

Try this snippet in the Bash Scratchpad on the right.

Try this snippet
$ bg
A suspended job is frozen (0% CPU) but still alive, and you choose where it resumes, bg keeps it running while freeing your prompt, fg hands the terminal back to it.
A suspended job is frozen (0% CPU) but still alive, and you choose where it resumes, bg keeps it running while freeing your prompt, fg hands the terminal back to it.

If you accidentally start a long job in the foreground, the magic rescue workflow takes just a few keystrokes:

  • Press Ctrl-Z to pause it.
  • Type bg and hit Enter to push it to the background.

Your job safely carries on, and your prompt is free for your next task.

Ctrl-Z only pauses a foreground job (freezing it while freeing your prompt); it takes bg to actually resume that job in the background, so it keeps running while you carry on working.
Ctrl-Z only pauses a foreground job (freezing it while freeing your prompt); it takes bg to actually resume that job in the background, so it keeps running while you carry on working.
Section 6 of 10

6 Listing and Naming Jobs - jobs and %

The jobs command lists all processes currently running or suspended in your current terminal session.

Try it out

Try this snippet in the Bash Scratchpad on the right.

Try this snippet
$ ./cohort_summary.sh big_cohort.csv out.tsv &
$ ./convert_ecg_all.sh &
$ jobs
The jobs command prints the shell's private list of background tasks for the current terminal, where appending & adds an entry, and each line reports that task's job number, its current (+) or previous (-) marker, and its run state.
The jobs command prints the shell's private list of background tasks for the current terminal, where appending & adds an entry, and each line reports that task's job number, its current (+) or previous (-) marker, and its run state.

To interact with a specific job, refer to it using a percent sign (%) followed by its job number or symbol:

  • %1 - job number 1.
  • %+ or %% - the most recent job (the one marked + in jobs).
  • %- - the previous job (marked -).
  • fg %1 - brings job 1 into the foreground (interative mode).
  • bg %2 - resumes job 2 in the background.
A % job specifier is just a pointer into the shell's job table, where a number selects a job directly and the + (current) and - (previous) markers give you %+/%% and %- as shortcuts to the two jobs you most often want.
A % job specifier is just a pointer into the shell's job table, where a number selects a job directly and the + (current) and - (previous) markers give you %+/%% and %- as shortcuts to the two jobs you most often want.

With a single job you can drop the number entirely - plain fg and bg act on the most recent.

Section 7 of 10

7 Stopping a Job - Signals and kill

Managing a process involves sending it a SIGNAL—a lightweight notification delivered by the operating system kernel. You likely already use two signals daily via keyboard shortcuts:

  • Ctrl-C sends SIGINT - "interrupt and stop". The polite stop for a foreground job.
  • Ctrl-Z sends SIGTSTP - "suspend". The pause you just used.
Pressing Ctrl-C or Ctrl-Z does not act on a process directly; it tells the OS kernel to deliver a specific named signal, and the signal's identity (SIGINT vs SIGTSTP) is what decides whether the process is terminated or merely suspended.
Pressing Ctrl-C or Ctrl-Z does not act on a process directly; it tells the OS kernel to deliver a specific named signal, and the signal's identity (SIGINT vs SIGTSTP) is what decides whether the process is terminated or merely suspended.

Because you cannot use keyboard shortcuts on background jobs, you must use the kill command. Despite its aggressive name, kill simply sends a signal to a job:

  • kill %1 - sends SIGTERM, the polite "please terminate". The program is given time to save progress and clean up temporary files first.
  • kill -9 %1 - sends SIGKILL, the forceful stop handled directly by the kernel. The program cannot ignore it and dies instantly with no cleanup.
Try it out

Try this snippet in the Bash Scratchpad on the right.

Try this snippet
$ ./cohort_summary.sh big_cohort.csv out.tsv &
$ kill %1
SIGTERM (kill %1) asks a job to stop so it can save its work and clean up, whereas SIGKILL (kill -9) forces an instant, uncatchable stop that can leave half-written scratch files behind.
SIGTERM (kill %1) asks a job to stop so it can save its work and clean up, whereas SIGKILL (kill -9) forces an instant, uncatchable stop that can leave half-written scratch files behind.

Always try kill %1 first. Only use kill -9 as a last resort if a job is completely frozen. kill -9 doesn't give the program a chance to close files properly, which can corrupt half-written data.

Section 8 of 10

8 Keeping a Job Alive After You Log Out

When you close a terminal or lose your SSH connection, the shell automatically sends a SIGHUP (Hang Up) signal to all its active jobs, causing them to terminate.

If you are running a long script (like an overnight data processing job), you need to protect it from SIGHUP using one of two methods,

Method A: Start the job with nohup

If you know ahead of time that a job will take a while, prepend it with nohup. You should also redirect its output to a log file and append & to run it in the background:

Try it out

Try this snippet in the Bash Scratchpad on the right.

Try this snippet
$ nohup ./cohort_summary.sh big_cohort.csv out.tsv &> run.log &
A job started normally is tied to your login session, so logging off sends it a hangup signal that kills it, whereas prefixing the job with nohup makes it ignore that signal so it survives and finishes after you disconnect.
A job started normally is tied to your login session, so logging off sends it a hangup signal that kills it, whereas prefixing the job with nohup makes it ignore that signal so it survives and finishes after you disconnect.

Method B: Use disown on an already running job

If a job is already running and you realize you need to log out, you can detach it from your current shell session so closing the terminal won't kill it:

Try it out

Try this snippet in the Bash Scratchpad on the right.

Try this snippet
$ ./cohort_summary.sh big_cohort.csv out.tsv &
$ disown %1
A running job is owned by your shell, so logging out hangs it up with SIGHUP; running disown first removes it from the shell's job table, leaving nothing for SIGHUP to reach, so the job keeps running after the terminal closes.
A running job is owned by your shell, so logging out hangs it up with SIGHUP; running disown first removes it from the shell's job table, leaving nothing for SIGHUP to reach, so the job keeps running after the terminal closes.

Whichever method you choose, you can monitor the progress of your background job in real-time by tracking its log file:

Try it out

Try this snippet in the Bash Scratchpad on the right.

Try this snippet
$ tail -f run.log

tail -f keeps following run.log as the job appends new lines to it; press Ctrl-C when you are done watching to get your prompt back.

Section 9 of 10

9 Check your understanding

You have reached the end of the module. Try the same questions again — your answers here, paired with your pre-test answers, are how we measure what the module taught you. Answer every question and confidence rating, then click Submit and see results to view your score.

Post-test

What does adding & to the end of a command do?

Post-test

You press Ctrl-Z on a running foreground job. What happens?

Post-test

A job is suspended. Which command makes it continue running in the background?

Post-test

What is the difference between kill %1 and kill -9 %1?

Post-test

Which command lets a job keep running after you close the terminal?

Post-test

After running a command with & the shell prints [1] 20345. What are these two numbers?

Post-test

What does the jobs command list, and how do you refer to job number 1?

Post-test

A background script keeps printing over your prompt. What do you add to send its output to a log file?

Post-confidence

I can start a command in the background and get my prompt back.

Not at all confident
Fully confident
Post-confidence

I can suspend a foreground job with Ctrl-Z and resume it with bg or fg.

Not at all confident
Fully confident
Post-confidence

I can list jobs and stop one with kill, and I know when -9 is a last resort.

Not at all confident
Fully confident
Section 10 of 10

10 Your results

Here is how your post-test answers compare with your pre-test answers. The pre/post pairing is the most reliable way to see what this module actually taught you.

Your score

Submit the post-test to see your results.

Muddiest point

What is the one thing from this module that is still unclear to you?

Rate this module

Overall, how would you rate this module?

How likely are you to recommend this module to a peer? (0 = not at all, 10 = extremely likely)