/tmp 掃除の作法 - tmpfiles.d と systemd-tmpfiles

/tmp 掃除の作法 - tmpfiles.d と systemd-tmpfiles

この記事で解決できること

  • /tmp の掃除が自動で行われる仕組みを理解できる
  • tmpfiles.d のルールファイルを自作できる
  • systemd-tmpfiles コマンドを手動・自動の両方で使える

結論(実務の型)

  • /tmp の自動削除は systemd-tmpfiles-clean.timer が担う
  • カスタムクリーンアップは /etc/tmpfiles.d/ にルールファイルを置く
  • ルールの書式は タイプ パス モード UID GID 年齢 引数

前提(対象環境)

  • OS: Ubuntu / systemd 搭載 Linux
  • root 権限または sudo 実行が必要

/tmp とは何か — なぜ掃除が必要なのか?

/tmp はアプリケーションが一時ファイルを書き込む場所で、再起動後は内容が保証されない。長時間稼働するサーバでは放置するとディスクを圧迫し、PID ファイルやソケットファイルの誤参照が起きる。

  • 典型的な用途: 圧縮・解凍の中間ファイル、セッションデータ、ソケットファイル
  • Ubuntu のデフォルト: /tmp はメモリ上の tmpfs にマウントされており、再起動で自動消去
  • /var/tmp: 再起動後も消えない永続 tmp。意図的な管理が必要
$ mount | grep /tmp
tmpfs on /tmp type tmpfs (rw,nosuid,nodev)

tmpfs の場合は再起動で自動消去されるが、長時間稼働システムでは蓄積するため定期削除が必要。df -h /tmp でディスク使用量を確認しておく。

systemd-tmpfiles とは何か?

systemd-tmpfiles は、/tmp/run といった一時ディレクトリの作成・削除・パーミッション管理を設定ファイルで宣言的に制御するツール。

3 つの動作モードを持つ:

モード コマンド 動作
作成 --create ルールに従ってファイル・ディレクトリを作成
削除 --clean 年齢基準を超えた一時ファイルを削除
完全削除 --remove ルール対象のファイル・ディレクトリをすべて削除
# 手動で実行する場合
$ sudo systemd-tmpfiles --create
$ sudo systemd-tmpfiles --clean
$ sudo systemd-tmpfiles --remove

systemd の起動シーケンスに統合されており、2 つのユニットが自動動作する:

  • systemd-tmpfiles-setup.service — 起動時に --create を実行
  • systemd-tmpfiles-clean.timer — 定期的(デフォルト: 起動後 15 分 + 1 日ごと)に --clean を実行

tmpfiles.d の設定ファイルの書き方

設定ファイルは /etc/tmpfiles.d/*.conf に置く。システム提供のルールは /usr/lib/tmpfiles.d/ にある(直接編集禁止、パッケージ更新で上書きされる)。

書式

タイプ パス モード UID GID 年齢 引数

各フィールドの意味:

フィールド 説明
タイプ 操作の種類 d(ディレクトリ作成)/ f(ファイル作成)/ x(削除除外)
パス 対象パス /tmp/myapp
モード パーミッション(8進数) 0755
UID / GID 所有者(- で現状維持) root / -
年齢 この経過時間を超えたら削除(--clean 時) 7d(7日)/ 1h(1時間)/ -(削除しない)
引数 ファイルタイプの場合の初期内容(オプション) -

よく使うタイプ一覧

タイプ 意味
d ディレクトリを作成(なければ)、年齢超過ファイルを --clean で削除
D d と同じだが --remove で中身ごと削除
f ファイルを作成(なければ)
f+ ファイルを作成または上書き
x --clean / --remove の対象から除外
e 既存ファイル・ディレクトリのパーミッションを設定
z パーミッション・SELinux ラベルを設定

定期クリーンアップをどう動かすか?

systemd-tmpfiles-clean.timer が自動的に周期実行される。状態確認:

$ systemctl status systemd-tmpfiles-clean.timer
● systemd-tmpfiles-clean.timer - Daily Cleanup of Temporary Directories
     Loaded: loaded (/lib/systemd/system/systemd-tmpfiles-clean.timer; static)
     Active: active (waiting) since Mon 2024-01-01 00:00:00 UTC; 3h ago
    Trigger: Tue 2024-01-02 00:15:30 UTC; 20h left

手動でクリーンアップを即時実行:

$ sudo systemctl start systemd-tmpfiles-clean

--clean は年齢フィールドが設定されているエントリのみ削除対象とする。年齢フィールドを - にしたエントリは手動・自動いずれの削除も受けない。

カスタムルールの実践例

例 1: アプリ専用一時ディレクトリを作成・管理する

# /etc/tmpfiles.d/myapp.conf
d /tmp/myapp 0750 myapp myapp 1d

/tmp/myappmyapp:myapp 所有・0750 で作成し、1日経過したファイルを削除。

例 2: /var/tmp 配下のログを7日で削除する

# /etc/tmpfiles.d/clean-var-tmp.conf
d /var/tmp/app-logs 0755 root root 7d

例 3: /run 配下に PID ディレクトリを起動時に作成する(削除なし)

# /etc/tmpfiles.d/myapp-run.conf
d /run/myapp 0755 myapp myapp -

年齢 - なので削除されない。起動時に必ず作成される。

例 4: 特定パスを削除対象から除外する

# /etc/tmpfiles.d/exclude.conf
x /tmp/persistent-cache

--clean 時に /tmp/persistent-cache をスキップする。

設定を即時反映・確認する

# 作成ルールを即時実行(新しいディレクトリを生成)
$ sudo systemd-tmpfiles --create /etc/tmpfiles.d/myapp.conf

# ドライランで削除対象を確認
$ sudo systemd-tmpfiles --clean --dry-run /etc/tmpfiles.d/myapp.conf

--dry-run は実際には削除せず、何が削除対象になるかを出力する。本番実行前に必ず確認する。

よくあるトラブルと対処

削除が起きない

年齢フィールドが - になっていないか確認。また --clean は**ファイルの最終アクセス時刻(atime)**を基準にする。書き込みタイムスタンプ(mtime)ではない。

# ファイルの atime を確認
$ stat /tmp/myfile | grep Access

noatime マウントオプション使用時は atime が更新されず、実際より古く見える。意図的に atime を更新してテストするには touch -a /tmp/myfile を使う。

作成したルールが反映されない

設定ファイルの構文を直接検証する:

$ sudo systemd-tmpfiles --create /etc/tmpfiles.d/myapp.conf

エラーが出なければ正常。journalctl でエラーログも確認:

$ journalctl -u systemd-tmpfiles-setup

/usr/lib/tmpfiles.d/ のルールを上書きしたい

/etc/tmpfiles.d/ に同名ファイルを置くと上書きされる(優先順位: /etc > /run > /usr/lib)。

# システム提供ルールを確認
$ cat /usr/lib/tmpfiles.d/tmp.conf

# 上書き用ファイルを作成して編集
$ sudo cp /usr/lib/tmpfiles.d/tmp.conf /etc/tmpfiles.d/tmp.conf

やってはいけないこと

  • /usr/lib/tmpfiles.d/ 内のファイルを直接編集(パッケージ更新で上書きされる)
  • D タイプを重要なディレクトリ配下に対して年齢なしで設定(--remove で中身が全消去)

次に読む