ディスク容量不足の衝撃とsystemd-tmpfilesの登場
以前、本番サーバーが突然ダウンし、冷や汗をかいたことがあります。ログには No space left on device というエラーが出ていましたが、数日前までは200GBもの空き容量があったはずでした。
du -sh で調査したところ、/tmp ディレクトリに1,000万個を超える微細なセッションファイルが溜まっており、合計で80GBにも達していました。その時は「力技」で解決しようと、rm -rf を実行するBashスクリプトを書いて crontab に登録しました。しかし、スクリプトが強力すぎて稼働中のデータベースのソケットまで削除してしまい、さらに30分間のダウンタイムを招く結果となりました。
もしあなたも同じように手動でゴミ掃除に苦労しているなら、systemd-tmpfiles を使いましょう。これは systemd に深く統合された標準ツールです。一時ファイルやディレクトリのライフサイクルを、科学的かつ安全、そして完全に自動で管理してくれます。
このツールは単に削除するだけではありません。起動時に必要なディレクトリを自動作成したり、ソケットファイルに適切な権限(permission)を付与したり、アプリケーションの要求に応じてシンボリックリンクを作成したりもできます。バラバラで管理しにくいスクリプトではなく、宣言的な設定ファイルにすべてをまとめることができます。
システム上のsystemd-tmpfilesを確認する
Ubuntu、CentOS/AlmaLinux、Fedoraなどの主要なディストリビューションでは、この機能がデフォルトで有効になっています。システムが保護されているかどうかを確認するには、以下のコマンドを入力します:
systemctl status systemd-tmpfiles-setup.service systemd-tmpfiles-clean.timer
これら2つのコンポーネントが重要な役割を果たします:
- systemd-tmpfiles-setup.service: 起動時に実行され、一時ファイルやディレクトリを初期化します。
- systemd-tmpfiles-clean.timer: 通常24時間ごとに実行され、期限切れ(expired)のファイルをスキャンしてクリーンアップします。
設定:システムエラーを避けるためのルールを理解する
systemd は明確な優先順位に基づいて設定を管理します。/usr/lib 内のファイルを直接編集しないでください。OSのアップデート時に上書きされてしまうからです。
設定ファイルの配置場所
/usr/lib/tmpfiles.d/: ソフトウェアパッケージのデフォルト設定。変更禁止。/run/tmpfiles.d/: 実行中に生成される一時的な設定。/etc/tmpfiles.d/: ここがあなたの出番です。 独自のカスタマイズを行うには、ここに.confファイルを作成します。
構文の解説
標準的な設定行は以下のようになります:
# Type Path Mode User Group Age Argument
d /run/my_app 0755 nginx nginx - -
各項目の詳細:
- Type: 実行するアクション。
dはディレクトリ作成、fはファイル作成、eは中身のみ削除、Xは削除対象外。 - Path: 絶対パス。
- Mode: 権限(例: 0755)。
- User/Group: 所有者。
- Age: ファイルの保持期間。例:
7d(7日間)、12h(12時間)。-を指定すると、自動削除されません。 - Argument: 通常、シンボリックリンクのリンク先などを指定します。
実践例:1週間後に50GBのキャッシュを削除する
アプリケーションが /var/cache/my-app/ にファイルを生成し続けているとします。ディスクがいっぱいになるのを防ぐため、7日を過ぎた古いファイルを自動削除したい場合を考えます。
まず、設定ファイルを作成します:
sudo nano /etc/tmpfiles.d/my-app-cleanup.conf
以下の内容を追加します:
# メインディレクトリは残し、中身のみをクリーンアップ
e /var/cache/my-app 0750 webapp webapp 7d -
なぜ e を使うのでしょうか? d に Age を指定すると、親ディレクトリである my-app 自体が7日間変更されていない場合に削除されてしまう可能性があるからです。e (empty) を使う方が安全で、中身のゴミだけを掃除してくれます。
もう一つのヒント:RAM上のRedis用ソケットディレクトリを作成する場合(/run は再起動時に消去されます)、以下のように記述します:
d /run/redis 0755 redis redis - -
安全な運用:運任せにしない
設定を書いて終わりではありません。予期せぬミスを避けるために、すぐに確認を行いましょう。
1. ドライラン(実行シミュレーション)
このコマンドは非常に重要です。実際に削除や作成を行わずに、systemd が何をしようとしているかを確認できます:
systemd-tmpfiles --create --dry-run /etc/tmpfiles.d/my-app-cleanup.conf
2. 即時実行の強制
すぐにディレクトリを作成したい場合:
sudo systemd-tmpfiles --create
または、期限切れのファイルを今すぐクリーンアップしたい場合:
sudo systemd-tmpfiles --clean
警告: --clean の使用には注意してください。もし重要なディレクトリの Age を誤って 1s(1秒)に設定していた場合、Enterキーひとつでデータがすべて消え去ります。
Age(保持期間)の計算に関する実戦的な知識
多くの人が Age はファイルの修正時間だけで計算されると誤解しています。実際には、systemd-tmpfiles は atime(アクセス)、mtime(内容修正)、ctime(メタデータ変更)の3つのタイムスタンプをすべてチェックします。デフォルトでは、これら3つすべてが設定時間を超えた場合にのみ削除されます。これにより、プロセスによって読み取られているが修正はされていないファイルが保護されます。
一時ファイルの管理は細かい作業に思えるかもしれませんが、Linuxの一般ユーザーとプロのDevOpsエンジニアを分ける重要なスキルです。この記事が、古いBashスクリプトを卒業し、より標準的で洗練された systemd-tmpfiles へ移行する助けになれば幸いです。

