Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

Linux & Mac & Bash Command Dictionary

  1. Home
  2. Linux & Mac & Bash Command Dictionary
  3. wait / trap

wait / trap

Since: All Linux
macOS(2001 Cheetah)
Bash 1.0(1989)

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 / SignalDescription
waitWaits until all background jobs have completed.
wait $PIDWaits until the process with the given PID exits, then returns its exit status.
trap 'command' EXITRuns when the script exits, whether normally or due to an error. Useful for deleting temporary files.
trap 'command' INTRuns when the user presses Ctrl+C.
trap 'command' TERMRuns when the script receives SIGTERM.
trap 'command' ERRRuns when a command returns a non-zero exit status.
trap 'command' HUPRuns when SIGHUP is received (terminal disconnect or config reload).
trap '' INTIgnores 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.

sample_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"

Run the following command:

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.

sample_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"

Run the following command:

bash safe_exit.sh
Press Ctrl+C to exit (auto-exits in 3 seconds)
Normal exit

The following is an advanced example. It combines arrays, background execution, and the RANDOM variable together.

This example combines wait and trap for parallel processing. Multiple workers run in the background, and their exit statuses are checked individually.

sample_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"

Run the following command:

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

Common Mistakes

Common Mistake 1: Placing trap after the code it should protect

trap only catches signals and exits that occur after the trap is registered. Any code that runs before the trap line is unprotected. Always declare trap at the top of the script.

sample_trap_late.sh
#!/bin/bash
tmp=$(mktemp)
echo "working..." > "$tmp"

trap 'rm -f "$tmp"; echo "cleaned up"' EXIT

If the script is interrupted before reaching the trap line, the temporary file is not cleaned up. Move the trap to immediately after mktemp.

sample_trap_early.sh
#!/bin/bash
tmp=$(mktemp)
trap 'rm -f "$tmp"; echo "cleaned up"' EXIT
echo "working..." > "$tmp"

Common Mistake 2: Checking exit status without wait — the status is always 0

Without wait, the background process has not finished yet when you check $?, so it reflects the exit status of the last foreground command, not the background job.

sample_wait_mistake.sh
#!/bin/bash
false &
echo "exit status: $?"

Run the following command:

bash wait_mistake.sh
exit status: 0
($? reflects echo's status, not false's)

Use wait $pid to capture the background job's exit status correctly.

sample_wait_correct.sh
#!/bin/bash
false &
pid=$!
wait "$pid"
echo "exit status: $?"

Run the following command:

bash wait_correct.sh
exit status: 1

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 update it later.

For more on background execution, see & (background execution).

If you find any errors or copyright issues, please .