The catch-all cleanup
trap 'echo cleaning up; rm -f "$lock"' EXITtrap CMD SIGNAL... runs CMD when the script receives the named signal. EXIT is the special pseudo-signal that fires regardless of how the script ends — normal exit, error, Ctrl+C, kill. The single most reliable cleanup hook in shell.
Common patterns
tmpdir=$(mktemp -d)
trap 'rm -rf "$tmpdir"' EXIT
# ... use $tmpdir freely; it's auto-cleaned
# Lock file
lock=/tmp/myjob.lock
[[ -e "$lock" ]] && { echo 'already running'; exit 1; }
echo $$ > "$lock"
trap 'rm -f "$lock"' EXITMultiple signals
# Same handler for several signals
trap 'cleanup' EXIT INT TERM HUP
# Different handlers
trap 'echo "caught Ctrl+C"' INT
trap 'echo "normal exit"' EXITReset / clear
trap - INT restores the default INT handler (terminate). trap '' INT ignores the signal entirely.
Variables in trap
Quote carefully: trap "rm -f $tmpdir" EXIT expands $tmpdir now, when the trap is set. trap 'rm -f "$tmpdir"' EXIT with single quotes expands later, when the trap fires — usually what you want, especially if the variable might change.