← Back to Bash Course | Chapter 11: Process Management | Lesson 1 of 12

Running Commands in the Background (&) and $!

Adding an ampersand after a command tells Bash to start it running in the background and immediately move on to the next line without waiting.

Starting a Background Job

Appending & after a command launches it asynchronously; the shell does not wait for it and immediately continues to the next line. This lets independent tasks run concurrently.

Example: Starting a Background Job

bash
#!/bin/bash
sleep 0.2 &
echo "this prints immediately, before the sleep finishes"
wait
echo "the background sleep has now finished"

Capturing the Background PID with $!

$! expands to the process ID of the most recently started background job, which lets a script track, wait for, or send signals to that specific process later.

Example: Capturing the Background PID with $!

bash
#!/bin/bash
sleep 0.2 &
pid=$!
echo "started background job with PID $pid"
wait "$pid"
echo "job $pid has completed"

Running Several Jobs Concurrently

Multiple commands can be backgrounded one after another; each keeps its own PID in $! at the moment it starts, so PIDs must be saved into separate variables (or an array) if you want to reference them individually later.

Example: Running Several Jobs Concurrently

bash
#!/bin/bash
sleep 0.1 &
pid1=$!
sleep 0.1 &
pid2=$!
echo "started jobs $pid1 and $pid2"
wait "$pid1" "$pid2"
echo "both jobs finished"
Common Mistakes
  1. Assuming a backgrounded command's output won't interleave with the rest of the script's output; both run concurrently and can print at overlapping times.
  2. Forgetting $! must be captured immediately after the & command, since it always refers to the most recently backgrounded job's PID.
  3. Not waiting for background jobs before the script ends, which in an interactive shell is fine but can mean a non-interactive script exits before the job's work (like a file write) is actually done.
Chapter Summary
  • Appending & to a command starts it in the background and returns control immediately.
  • $! holds the process ID (PID) of the most recently started background job.
  • Multiple & jobs can run concurrently; use wait to block until they finish.
  • Non-interactive scripts have job control disabled, so interactive builtins like fg/bg/jobs are unreliable there; $! and wait are the portable way to manage background work.

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.