Temporary Files and Directories with mktemp
Temporary files are useful for staging and validation, but predictable names in shared directories create races. `mktemp` and disciplined cleanup give temporary state a safe lifecycle.
Learning objectives
By the end of this lesson
- Create temporary files and directories safely.
- Register cleanup traps immediately.
- Preserve exit status during cleanup.
- Protect temporary secret material.
- Choose between streaming and temporary artifacts.
1. Predictable temporary names create races
# Avoid:
tmp="/tmp/my-script.$$"
printf 'data\n' > "$tmp"A predictable path can already exist or be replaced by another process before your script uses it.
Let a dedicated temporary-file utility create a unique path safely.
2. mktemp creates a temporary file
tmp=$(mktemp) || {
printf 'could not create temporary file\n' >&2
exit 1
}
printf 'tmp=%s\n' "$tmp"3. mktemp -d creates a private temporary workspace
tmpdir=$(mktemp -d) || exit 1
printf 'payload\n' > "$tmpdir/input.txt"4. Register cleanup immediately
tmpdir=$(mktemp -d) || exit 1
cleanup() {
rm -rf -- "$tmpdir"
}
trap cleanup EXITEarly registration makes cleanup cover more failure paths.
5. Preserve the original exit status during cleanup
tmpdir=$(mktemp -d) || exit 1
cleanup() {
local status=$?
rm -rf -- "$tmpdir"
exit "$status"
}
trap cleanup EXITOtherwise the cleanup command can replace the status that actually caused the script to exit.
6. mktemp syntax differs across systems
GNU and BSD/macOS mktemp differ in template and option details. The simple mktemp and mktemp -d forms are often easiest to keep portable, but test your supported platforms.
7. Temporary files may contain sensitive data
tmp=$(mktemp) || exit 1
chmod 600 -- "$tmp"
printf '%s\n' "$API_TOKEN" > "$tmp"Avoid writing credentials to disk when possible. If unavoidable, restrict permissions and remove them promptly.
8. Do not create a temporary file when streaming is enough
generate_config |
validate_config |
deploy_configUse a temp file when you need validation of a complete artifact, repeated reads, multiple consumers, retries, or preserved evidence.
9. Temp files help with validated replacement
tmp=$(mktemp) || exit 1
if render_config >"$tmp" &&
validate_config "$tmp"; then
mv -- "$tmp" app.conf
tmp=""
else
status=$?
rm -f -- "$tmp"
exit "$status"
fiUpdate cleanup state after promotion so later cleanup cannot remove the live artifact.
10. Hands-on lab: temporary render workspace
mkdir -p "$HOME/devops-academy/bash/chapter09/lesson04"
cd "$HOME/devops-academy/bash/chapter09/lesson04"
tmpdir=$(mktemp -d) || exit 1
cleanup() {
local status=$?
rm -rf -- "$tmpdir"
exit "$status"
}
trap cleanup EXIT
printf 'SERVICE=api\n' > "$tmpdir/base.env"
printf 'ENVIRONMENT=staging\n' >> "$tmpdir/base.env"
cp -- "$tmpdir/base.env" rendered.env
cat rendered.envVerification checklist
11. Knowledge check
Question 1. Why is /tmp/script.$$ weak?
Question 2. When should cleanup be registered?
Question 3. Why save $? in cleanup?
Question 4. When is streaming preferable?
12. Summary
Temporary state should be unique, short-lived, and cleaned up predictably. Use mktemp, traps, restrictive permissions where needed, and streaming when no durable intermediate state is required.
13. Further reading
- GNU Coreutils manual — mktemp.
- BSD/macOS mktemp manual pages.
- GNU Bash Reference Manual — Traps.
- OWASP temporary-file security guidance.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this address.