Bash Temp File Cleanup with mktemp and trap Prompt
Generate bash scripts that create temp files and directories safely with mktemp and guarantee cleanup on every exit path — normal return, error, and signals — so scripts never leak /tmp garbage or clobber shared filenames.
- Target user
- Engineers writing bash automation that needs scratch space
- Difficulty
- Intermediate
- Tools
- Claude, ChatGPT
The prompt
You are a senior systems engineer who has debugged too many cron jobs that filled /tmp, collided on predictable filenames, or left half-written state behind after a SIGTERM.
I will provide:
- My current script (or a description of the scratch files/dirs it needs)
- Where it runs (cron, systemd timer, interactive, CI)
- Whether it must be safe to run concurrently with copies of itself
- Any cleanup that must NOT happen (e.g. keep artifacts on failure for debugging)
Your job:
1. **Replace every predictable temp path** (`/tmp/foo.$$`, `/tmp/out.txt`) with `mktemp` / `mktemp -d`, using a descriptive template like `mktemp -t myscript.XXXXXXXX`. Explain why `$$` and hardcoded names are race-prone and a symlink-attack vector.
2. **Centralize cleanup in a single trap** — one `cleanup()` function registered with `trap cleanup EXIT INT TERM HUP`. EXIT alone catches normal + most error exits; the signals ensure cleanup still runs when the script is killed.
3. **Make cleanup idempotent and safe** — guard each `rm -rf` so an unset or empty variable can never expand to `rm -rf /` or `rm -rf $HOME`. Use `[[ -n "${tmpdir:-}" && -d "$tmpdir" ]]` before removing. Quote everything.
4. **Track resources in an array** — append each temp path to a `TMP_RESOURCES=()` array as you create it, and have cleanup loop over the array. This scales when a script creates several temp files at different points.
5. **Preserve the exit code** — cleanup must not mask the original failure. Capture `local rc=$?` at the top of the trap and `exit "$rc"` at the end.
6. **Optional keep-on-failure** — support a `KEEP_TMP=1` or `--keep-tmp` switch that skips removal and prints the path so a human can inspect artifacts after a failed run. Print to stderr.
7. **Strict mode interplay** — show how this works under `set -euo pipefail`, and note that traps fire even when `set -e` aborts mid-script.
8. **Verification** — give me a one-liner that runs the script, kills it mid-flight with `kill -TERM`, and asserts the temp dir is gone.
Output: (a) the refactored script with the trap + cleanup pattern, (b) a short comment block explaining each guard, (c) the kill-test verification snippet. Bias toward defensive guards over brevity, and never leave a code path where cleanup can be skipped.