Secure Temporary Files in Bash with mktemp

Secure temporary file and directory workflow with automatic cleanup in a Bash script

What You’ll Learn

In this lesson, you will learn how to use Bash’s mktemp command to create temporary files and directories safely. You will use these resources for intermediate backup and deployment data, then remove them automatically when the script finishes.

  • Create a unique temporary file with mktemp.
  • Create a temporary directory with mktemp -d.
  • Understand why predictable temporary filenames can be unsafe.
  • Clean up temporary resources with an exit trap.

The Concept

A temporary file is a file that a script uses for a short time. For example, a backup script might create a manifest listing files before packaging them. A deployment script might prepare configuration files in a staging directory before copying them into place.

A tempting approach is to choose a fixed filename such as /tmp/backup-list.txt. This is unsafe because another process may create or replace that file before your script uses it. This problem is called a race condition: the result depends on the timing of multiple processes.

The mktemp command creates a new temporary file with a unique, unpredictable name. It also creates the file before returning its path, which helps prevent another process from claiming the same name first. Use mktemp -d when you need a temporary directory instead.

Always save the path returned by mktemp. Then arrange for the temporary resource to be removed when the script exits, including when the script stops because of an error.

Basic Example

This backup preparation script creates a temporary manifest, writes a list of files into it, and displays the manifest as a stand-in for a later backup step.

#!/usr/bin/env bash
set -e

manifest_file=$(mktemp "${TMPDIR:-/tmp}/backup-manifest.XXXXXX")

cleanup() {
    rm -f "$manifest_file"
}
trap cleanup EXIT

printf 'Creating backup manifest at: %s\n' "$manifest_file"

printf '%s\n' \
    "/srv/website/index.html" \
    "/srv/website/assets/app.css" \
    "/srv/website/assets/app.js" \
    > "$manifest_file"

printf '\nFiles selected for backup:\n'
cat "$manifest_file"

printf '\nThe manifest will be removed when the script exits.\n'

Expected Output

The random part of the filename will be different each time. The temporary file is removed after the script exits, so it will not remain at the displayed path.

Creating backup manifest at: /tmp/backup-manifest.K8v2Qx

Files selected for backup:
/srv/website/index.html
/srv/website/assets/app.css
/srv/website/assets/app.js

The manifest will be removed when the script exits.

How the Code Works

A sequential Bash workflow: the script creates a unique temporary file or directory with mktemp, registers an EXIT trap, uses the temporary resource for backup or deployment data, then exits normally or because of an error. The trap removes the resource before the script ends.
Bash uses mktemp to create a unique temporary resource, then an EXIT trap removes it automatically after normal completion or an error.
  • set -e makes the script stop when a command fails. This helps prevent later commands from using incomplete backup data.
  • manifest_file=$(mktemp "${TMPDIR:-/tmp}/backup-manifest.XXXXXX") runs mktemp and stores its returned path in the manifest_file variable.
  • XXXXXX is a template suffix that mktemp replaces with random characters. The resulting filename is unique for this creation attempt.
  • ${TMPDIR:-/tmp} uses the directory in the TMPDIR variable when it is set. Otherwise, it uses /tmp.
  • The redirection operator writes the selected paths into the temporary file. The file already exists because mktemp created it.
  • The cleanup function removes the file with rm -f. The -f option avoids an error if the file is already gone.
  • trap cleanup EXIT tells Bash to run the cleanup function whenever the script exits normally or because of an error.

Notice that every use of the temporary path is quoted. Quoting variables protects paths that may contain spaces or other special characters.

Another Example

Deployment scripts often need a temporary staging directory instead of one temporary file. This example creates a private staging directory, prepares a configuration file inside it, and checks that the staged file exists.

#!/usr/bin/env bash
set -e

staging_dir=$(mktemp -d "${TMPDIR:-/tmp}/release-staging.XXXXXX")

cleanup() {
    rm -rf -- "$staging_dir"
}
trap cleanup EXIT

mkdir "$staging_dir/config"

cat > "$staging_dir/config/app.conf" <<'EOF'
APP_ENV=production
LOG_LEVEL=info
EOF

printf 'Prepared deployment files in: %s\n' "$staging_dir"

if [[ -f "$staging_dir/config/app.conf" ]]; then
    echo "Configuration is ready for deployment."
fi

printf 'Staging directory will be removed when the script exits.\n'

The -d option makes mktemp create a directory. The directory name is still unique, and the directory is created before the script uses it. The cleanup command uses rm -rf -- because the temporary directory contains files and subdirectories.

Common Mistakes

  • Using a predictable filename: Avoid building a temporary path from a fixed name and assuming it is available. Let mktemp create the resource.
  • Forgetting cleanup: Temporary files can accumulate and may contain sensitive backup or deployment information. Install an exit trap soon after creating the resource.
  • Using the wrong option: Use mktemp for a file and mktemp -d for a directory. A directory is needed before placing several temporary files inside it.
  • Failing to quote the variable: Use quoted paths such as "$manifest_file" and "$staging_dir" when passing them to commands.
  • Deleting the wrong path: Only remove the path returned by mktemp. Do not replace it with a broad path such as /tmp/*.

Try It Yourself

Write a Bash script that creates a temporary file for a backup status report. The script should:

  • Create the file with a name beginning with backup-status..
  • Register cleanup before writing the report.
  • Write two status lines into the file.
  • Display the report with cat.
  • Remove the file automatically when the script exits.

Use the examples above as a guide, but choose your own status messages.

Challenge

Create a small backup preparation script that safely creates a temporary directory and uses it to hold two intermediate files:

  • A manifest containing two backup paths.
  • A status file containing the message Backup preparation complete..

The script must use mktemp -d, register an exit cleanup trap, display both files, and leave no staging directory behind after it exits.

Solution

#!/usr/bin/env bash
set -e

backup_dir=$(mktemp -d "${TMPDIR:-/tmp}/backup-work.XXXXXX")

cleanup() {
    rm -rf -- "$backup_dir"
}
trap cleanup EXIT

printf '%s\n' \
    "/srv/website/index.html" \
    "/srv/website/assets/app.js" \
    > "$backup_dir/manifest.txt"

printf '%s\n' \
    "Backup preparation complete." \
    > "$backup_dir/status.txt"

printf 'Manifest:\n'
cat "$backup_dir/manifest.txt"

printf '\nStatus:\n'
cat "$backup_dir/status.txt"

printf '\nTemporary backup directory will be removed on exit.\n'

The directory is created safely with a unique name, and both intermediate files are placed inside it. The exit trap removes the directory and everything inside it after the final message is printed, including if a command fails after the trap is installed.

Key Takeaways

  • Use mktemp to create a unique temporary file instead of choosing a predictable filename.
  • Use mktemp -d when a script needs a temporary directory.
  • Save the generated path in a variable and quote that variable whenever you use it.
  • Register an EXIT trap to remove temporary resources automatically.
  • Temporary backup manifests and deployment staging files should not be left behind after a script finishes.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top