wait / trap
wait waits for background processes to finish. trap catches signals and shell exit events to run custom code. Both are essential for implementing cleanup logic and safe exit handling in scripts.
Syntax
Use wait to wait for processes.
wait # Wait for all background jobs to finish wait $PID # Wait for the specified PID to finish wait %job_num # Wait for the specified job to finish
Use trap to catch signals.
trap 'command' signal_name... trap 'command' EXIT # Always runs when the script exits trap 'command' INT # Catches Ctrl+C (SIGINT) trap 'command' TERM # Catches SIGTERM trap 'command' ERR # Catches non-zero exit status from any command
Remove a trap.
trap - signal_name # Restore default behavior trap '' signal_name # Ignore the signal
Command List
| Command / Signal | Description |
|---|---|
| wait | Waits until all background jobs have completed. |
| wait $PID | Waits until the process with the given PID exits, then returns its exit status. |
| trap 'command' EXIT | Runs when the script exits, whether normally or due to an error. Useful for deleting temporary files. |
| trap 'command' INT | Runs when the user presses Ctrl+C. |
| trap 'command' TERM | Runs when the script receives SIGTERM. |
| trap 'command' ERR | Runs when a command returns a non-zero exit status. |
| trap 'command' HUP | Runs when SIGHUP is received (terminal disconnect or config reload). |
| trap '' INT | Ignores Ctrl+C, preventing accidental interruption during critical operations. |
Sample Code
Use trap ... EXIT to reliably delete a temporary file. The cleanup runs regardless of whether the script exits normally, with an error, or via Ctrl+C.
cleanup.sh
#!/bin/bash
tmpfile=$(mktemp /tmp/myapp.XXXXXX)
echo "Temp file: $tmpfile"
trap 'rm -f "$tmpfile"; echo "Cleanup complete"' EXIT
echo "Processing data" > "$tmpfile"
cat "$tmpfile"
bash cleanup.sh
Temp file: /tmp/myapp.aB3xYz
Processing data
Cleanup complete
This example catches Ctrl+C (SIGINT) and SIGTERM for a clean shutdown. Putting the cleanup logic in a function makes it easier to reuse across multiple signals.
safe_exit.sh
#!/bin/bash
cleanup() {
echo ""
echo "Interrupt detected. Exiting safely..."
exit 0
}
trap cleanup INT TERM
echo "Press Ctrl+C to exit (auto-exits in 3 seconds)"
sleep 3
echo "Normal exit"
bash safe_exit.sh
Press Ctrl+C to exit (auto-exits in 3 seconds)
Normal exit
This example combines wait and trap for parallel processing. Multiple workers run in the background, and their exit statuses are checked individually.
parallel_worker.sh
#!/bin/bash
worker() {
local id=$1
sleep $(( RANDOM % 3 + 1 ))
echo "Worker $id done"
return 0
}
pids=()
for i in {1..3}; do
worker $i &
pids+=($!)
done
echo "Waiting for all workers to finish..."
for pid in "${pids[@]}"; do
wait "$pid"
echo "PID $pid exit status: $?"
done
echo "All workers done"
bash parallel_worker.sh
Waiting for all workers to finish...
Worker 2 done
Worker 3 done
Worker 1 done
PID 12345 exit status: 0
PID 12346 exit status: 0
PID 12347 exit status: 0
All workers done
Notes
trap ... EXIT runs whenever the script exits — on normal exit, error exit, SIGTERM, or SIGINT — but not on SIGKILL. It is the standard pattern for cleanup tasks such as deleting temporary files, releasing lock files, and writing to logs. It is recommended practice to include this in every production script.
Defining the trap handler as a function lets you register the same logic for multiple signals and makes it easy to update later.
For more on background execution, see & (background execution).
If you find any errors or copyright issues, please contact us.