mktempコマンドでシェルスクリプトの一時ファイルを安全に作成する方法|並列処理の衝突防止と自動削除も

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)Linuxtips, シェルスクリプト > mktempコマンドでシェルスクリプトの一時ファイルを安全に作成する方法|並列処理の衝突防止と自動削除も
「シェルスクリプトで一時ファイルを /tmp/tmp_file.txt と決め打ちしていたら、別のプロセスと衝突してデータが壊れた」
そんな経験はありませんか?

一時ファイルの名前を固定していると、並列実行時の上書き・競合リスクがあります。
mktemp コマンドを使えば、重複しないユニークなファイル名を自動生成できます。

この記事では、mktemp コマンドの基本的な使い方から、シェルスクリプトでの安全な一時ファイル管理、自動削除(trap との組み合わせ)まで解説します。
RHEL 9.4 / Ubuntu 24.04 LTS で動作確認済みです。

この記事のポイント

・mktemp でユニークな一時ファイルを自動生成できる
・-d オプションで一時ディレクトリも作れる
・trap と組み合わせてスクリプト終了時に自動削除する
・並列実行時の競合・上書き事故を根本から防げる


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
図解60P/登録10秒/解除も3秒 / 詳細はこちら

なぜ一時ファイルの名前を固定してはいけないのか

シェルスクリプト初心者がよくやるのが、次のような固定ファイル名の使い方です。

# NG例:固定ファイル名は並列実行で競合する TMP=/tmp/myapp_tmp.txt echo "処理結果" > $TMP

一見問題なさそうですが、このスクリプトが2つ同時に動いた場合、どちらも同じ /tmp/myapp_tmp.txt に書き込もうとして内容が破壊されます。
cronやバッチ処理で複数起動する環境では、必ずこの問題に直面します。

さらに深刻なのがシンボリックリンク攻撃(Symlink Attack)です。
攻撃者があらかじめ /tmp/myapp_tmp.txt を重要ファイルへのシンボリックリンクとして作成しておくと、スクリプトがそのファイルに書き込んだ瞬間に重要ファイルが上書きされます。

mktemp はこれらの問題を1行で解決します。

mktempコマンドの基本的な使い方

1. 一時ファイルを作成する

mktempの最もシンプルな使い方です。

$ mktemp /tmp/tmp.abc123XYZ

実行するたびに異なる名前が生成されます。
生成されたファイルは空の状態で既に作成されているため、すぐに書き込めます。

2. テンプレートで名前のパターンを指定する

ファイル名のプレフィックスをわかりやすくしたい場合は、テンプレートを指定します。
テンプレートの末尾には必ず「X」を6文字以上並べます。

# myapp_ というプレフィックスで一時ファイルを作成する $ mktemp /tmp/myapp_XXXXXX /tmp/myapp_K7mN2p # スクリプト名を含めるとデバッグ時にわかりやすい $ mktemp /tmp/backup_XXXXXXXX /tmp/backup_4fGh8kLq

Xの部分がランダムな文字列に置き換えられます。
6文字未満だと警告が出るディストリビューションもあるため、6文字以上のXを使うのが安全です。

3. 一時ディレクトリを作成する(-d オプション)

複数の一時ファイルをまとめて扱いたい場合は、一時ディレクトリを作成します。

# -d オプションで一時ディレクトリを作成する $ mktemp -d /tmp/tmp.fQ3sBxKmNv # テンプレートを指定することもできる $ mktemp -d /tmp/work_XXXXXX /tmp/work_R2xPqM # 作成されたか確認する $ ls -la /tmp/work_R2xPqM total 0 drwx------ 2 tomohiro tomohiro 40 May 9 10:35 . drwxrwxrwt 12 root root 300 May 9 10:35 ..

作成されたディレクトリのパーミッションは 700(所有者のみアクセス可)になります。
セキュリティ上、他のユーザーからはアクセスできない状態で作成されます。

シェルスクリプトでの実践的な使い方

1. 基本パターン:変数に格納して使う

スクリプト内でmktempを使う基本的なパターンです。

#!/bin/bash # 一時ファイルを作成して変数に格納する TMPFILE=$(mktemp /tmp/myapp_XXXXXX) # 処理内容を書き込む echo "処理データ1" >> "$TMPFILE" echo "処理データ2" >> "$TMPFILE" # ファイルの内容を確認する cat "$TMPFILE" # 使い終わったら削除する rm -f "$TMPFILE"

変数 TMPFILE にパスを格納しているため、スクリプト内のどこからでも同じファイルを参照できます。

2. trap で自動削除する(推奨パターン)

スクリプトが途中でエラー終了したときも、必ず一時ファイルを削除するのが実務の鉄則です。
trap コマンドと組み合わせることで、正常終了・異常終了どちらの場合でも自動削除できます。

#!/bin/bash set -e # 一時ファイルを作成する TMPFILE=$(mktemp /tmp/report_XXXXXX) # EXIT シグナルで必ず削除する # スクリプトが正常終了・エラー終了どちらでも実行される trap 'rm -f "$TMPFILE"' EXIT # 何らかの処理 ls -la /var/log/ > "$TMPFILE" grep "error" "$TMPFILE" || true echo "処理完了: $TMPFILE の内容を確認しました" # スクリプト終了時に trap が実行され TMPFILE が自動削除される

EXIT シグナルをtrapで捕捉すると、kill -9 以外のあらゆる終了パターンで削除処理が走ります。
「rm を書き忘れた」「エラーで途中終了した」という状況でも /tmp が汚染されません。
Linux 基本コマンドの解説でも触れていますが、/tmp の残骸は予期しないディスク不足の原因になります。

3. 一時ディレクトリを使った複数ファイル管理

複数の中間ファイルを使う処理では、一時ディレクトリをまとめて削除する方が安全です。

#!/bin/bash set -e # 一時ディレクトリを作成する TMPDIR=$(mktemp -d /tmp/process_XXXXXX) # EXIT 時に一時ディレクトリごと削除する trap 'rm -rf "$TMPDIR"' EXIT # 一時ディレクトリ内で複数ファイルを扱う cat /var/log/messages | grep "error" > "$TMPDIR/errors.txt" cat /var/log/messages | grep "warn" > "$TMPDIR/warnings.txt" wc -l "$TMPDIR/errors.txt" "$TMPDIR/warnings.txt" echo "エラー数と警告数を集計しました"

一時ディレクトリを使うと、中間ファイルの命名を気にしなくて済みます。
rm -rf "$TMPDIR" で一括削除できるため、ファイルごとにrmを書く必要もありません。

応用・実務Tips

4. 並列処理での安全な一時ファイル使用

cronやバッチ処理で同じスクリプトが並列実行される環境では、mktempは必須です。

#!/bin/bash # バックアップスクリプト(並列実行対応版) LOCKFILE=$(mktemp /tmp/backup_lock_XXXXXX) TMPOUT=$(mktemp /tmp/backup_out_XXXXXX) trap 'rm -f "$LOCKFILE" "$TMPOUT"' EXIT # /tmp は全ユーザーが書き込める領域なので # mktemp で生成したパスは他プロセスと衝突しない echo "バックアップ開始: $$" > "$LOCKFILE" tar -czf /backup/data_$(date +%Y%m%d_%H%M%S).tar.gz /var/data/ 2> "$TMPOUT" if [ -s "$TMPOUT" ]; then echo "警告が発生しました:" cat "$TMPOUT" fi

tar コマンドの実用例のように、バックアップスクリプトに組み込む場合は特にmktempが有効です。

5. mktemp のパスを安全に扱うためのポイント

ダブルクォートで囲む:スペースを含むパスでも正しく動作させるため、変数展開は必ず "$TMPFILE" と書く
TMPDIR 変数:環境変数 TMPDIR が設定されている場合、mktemp はその場所に作成する。明示的にパスを指定すれば TMPDIR に依存しない
-p オプション(GNU版):`mktemp -p /var/tmp XXXXXX` のように、作成先ディレクトリを -p オプションで指定できる
macOS との互換性:macOS の mktemp はBSD版で動作が異なる場合がある。クロスプラットフォームスクリプトでは `mktemp /tmp/XXXXXX` の形式が安全

6. 実サーバーでのデバッグ確認例

実際のサーバーで mktemp を使ったスクリプトのデバッグをしたときの出力例です。

[tomohiro@web01 ~]$ cat test_mktemp.sh #!/bin/bash TMPFILE=$(mktemp /tmp/test_XXXXXX) trap 'echo "削除: $TMPFILE"; rm -f "$TMPFILE"' EXIT echo "作成されたファイル: $TMPFILE" ls -la "$TMPFILE" [tomohiro@web01 ~]$ bash test_mktemp.sh 作成されたファイル: /tmp/test_Kx8mNpQr -rw------- 1 tomohiro tomohiro 0 May 9 10:42 /tmp/test_Kx8mNpQr 削除: /tmp/test_Kx8mNpQr [tomohiro@web01 ~]$ ls /tmp/test_* ls: cannot access '/tmp/test_*': No such file or directory

スクリプト終了後にファイルが存在しないことが確認できました。
trap による自動削除が正しく機能しています。

トラブルシュート・エラー対処

「mktemp: too few X's in template」が出た場合

テンプレートの末尾の「X」が少ない場合に発生します。

# NG:X が 3 文字では警告が出る場合がある $ mktemp /tmp/tmp_XXX mktemp: too few X's in template '/tmp/tmp_XXX' # OK:末尾に X を 6 文字以上 $ mktemp /tmp/tmp_XXXXXX /tmp/tmp_abc123

GNU版の mktemp は X が3文字以上あれば動作しますが、移植性を考えて6文字以上にする習慣をつけましょう。

「mktemp: failed to create file」が出た場合

作成先ディレクトリが存在しない、または書き込み権限がない場合に発生します。

# 存在しないディレクトリを指定した場合 $ mktemp /tmp/nonexistent/tmp_XXXXXX mktemp: failed to create file via template '/tmp/nonexistent/tmp_XXXXXX': No such file or directory # /tmp 自体の権限を確認する $ ls -la /tmp drwxrwxrwt 12 root root 300 May 9 10:35 /tmp # ↑ スティッキービットが設定されていれば正常 # /tmp への書き込み権限がない場合(稀) $ df -h /tmp Filesystem Size Used Avail Use% Mounted on tmpfs 512M 450M 62M 88% /tmp # ディスク使用率が高い場合は不要ファイルを削除する

Linux ポート確認の全コマンドのような障害切り分けと同様に、まずは ls -la でパーミッションと存在確認から始めましょう。

スクリプトが kill -9 で強制終了されたとき

trap は kill -9(SIGKILL)では実行されません。
定期的に /tmp を掃除するために、cron で古い一時ファイルを削除する運用を組み合わせるのが実務上の対処です。

# crontab に追記:24時間以上前の /tmp/myapp_* を削除する # ファイル名のプレフィックスで絞り込んで削除する 0 3 * * * find /tmp -maxdepth 1 -name "myapp_*" -mtime +1 -delete

本記事のまとめ

mktemp コマンドの重要なポイントを一覧にまとめます。
やりたいこと コマンド
一時ファイルを作成する mktemp /tmp/myapp_XXXXXX
一時ディレクトリを作成する mktemp -d /tmp/work_XXXXXX
変数に格納して使う TMPFILE=$(mktemp /tmp/app_XXXXXX)
スクリプト終了時に自動削除する trap 'rm -f "$TMPFILE"' EXIT
一時ディレクトリを自動削除する trap 'rm -rf "$TMPDIR"' EXIT
作成先ディレクトリを指定する(GNU版) mktemp -p /var/tmp XXXXXX
シェルスクリプトで一時ファイルを扱う場合は、固定ファイル名を使わず mktemp で生成し、trap EXIT で自動削除するパターンを標準にしましょう。
この1つの習慣で、並列実行の競合・シンボリックリンク攻撃・/tmp の汚染という3つのリスクを同時に排除できます。

シェルスクリプトの知識、現場で使える形になっていますか?

mktemp や trap による安全なスクリプト設計はサーバー管理の基礎です。SSHの鍵管理、ファイアウォール設定、ユーザー権限管理——これらを体系的に理解していないと、いざというときに手が止まります。
コマンドのコピペでその場をしのぐのではなく、現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼントしています。

「独学の時間がもったいない」「プロから直接、現場の技術を最短で学びたい」という本気の方には、2日で実務レベルのスキルが身につく【初心者向けハンズオンセミナー】も開催しています。

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は1分、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

登録10秒/合わなければ解除3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として15年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。