systemd の PrivateTmp の動作について
とあるサーバーで一般ユーザーであるサービスのステータス状態を確認して、その結果を「/var/tmp/status.log」とかに出力して、その内容をphpで読み取ってWebページで表示するようにしたら、下記のようなエラーでファイルが開けないです
cannot open ‘/var/tmp/status.txt’ for reading: No such file or directory
ファイル自体は存在していますが、何故だろうと調べてみたら、RedHat 7以降 のサービス管理は systemdで管理しており、起動するサービスで「PrivateTmp=yes」となっていると、php-fom からは /var/tmp が 独自の一時ディレクトリに分離されて見えるため、別ユーザーが作成した /var/tmp/status.txt は見えません。
実行するサービスのPrivateTmpが有効になっているか確認する。「yes」となっていれば有効になっています
$ systemctl cat php-fpm.service | grep PrivateTmp PrivateTmp=true
動作の仕組み
- systemd が tmpfs(仮想ファイルシステム)を使って、
サービス専用の/tmp・/var/tmpディレクトリをマウントします。 - サービスから見える
/tmpや/var/tmpは、実際のシステムのものとは別物 になります。
具体的な挙動
| 状況 | 結果 |
|---|---|
PrivateTmp=yes の場合 | サービスは 独立した /tmp, /var/tmp を使用。他ユーザー・他プロセスが作成したファイル・ディレクトリは見えない。 |
PrivateTmp=no の場合 | システム共通の /tmp, /var/tmp を使用。他ユーザーや他プロセスが作成したファイルも見える。 |
PrivateTmpをnoにする方法
実行サービスの「php-fpm.service」等のファイルを変更します
# 起動ユニット確認 $ systemctl status php-fpm.service | grep Loaded Loaded: loaded (/usr/lib/systemd/system/php-fpm.service; disabled; vendor preset: disabled) # 上記のコマンドのloaded の行で起動スクリプトのファイル名がわかるので編集 $ sudo vim /usr/lib/systemd/system/php-fpm.service # → PrivateTmp=yes を PrivateTmp=no に変更 # 再読込と再起動 $ sudo systemctl daemon-reload $ sudo systemctl restart munin-node
但し、この方法だとOSアップデートで上書きされるリスクがあります。その場合は「オーバーライドファイル」で設定する方法です。
$ sudo systemctl edit php-fpm
systemctl edit コマンドが開いた nano エディタ の画面が起動します。
画面に何も書かれていない状態なので、ここに以下を入力します:
[Service]
PrivateTmp=no
キーボードで「Ctrl + O」と入力して保存し、「Ctrl + X」で終了します
[Service] PrivateTmp=no ^G Get Help ^O Write Out ^W Where Is ^K Cut Text ^J Justify ^C Cur Pos ^X Exit ^R Read File ^\ Replace ^U Uncut Text^T To Spell ^_ Go To Line
編集が終わったら、再読込と再起動をおこないます
$ sudo systemctl daemon-reload $ sudo systemctl restart php-fpm


