フックは成功を報告するのに、同じパスはシェルから見ると今も空のままです。両方の記述は同時に正しくなり得ます。systemd サービスがプライベートな一時ディレクトリを持つ独自のマウント名前空間の中で動いている場合があるからです。それが分かれば、関心は書き込みがそもそも成功したのかという問いに移ります。

二つの一時ディレクトリ、一つのパス

分離の設定は、一時ディレクトリを読み取り専用にするのではなく、ユニットにプライベートな見え方を与えます。ユニットの外のプロセスはそこに何が書かれたか見えず、ユニットが停止すると残されたものは破棄されます。したがって、フックが出力したパスとシェルから確認したパスは、同じ名前の別のオブジェクトを指している可能性があります。

これは可視性の問題であり、データ損失の問題のように見えます。実際には何も削除されていません。ファイルは単に、シェルが所属していない名前空間にあるだけです。同じコマンドもユニットの内部で実行すると挙動が変わり、その観察が通常は議論を決着させます。書き込みについて何かを結論づける前に、ユニットの設定を読んでください。

見えないものと書けないものを切り分ける

書き込みの成功とオープンの失敗は異なる証拠を残し、その違いが修復方法を決めます。フックがファイルを作成したと言うのに外部の読み手が見つけられないなら、名前空間の問題です。もしフックが権限エラーやオープンの失敗を報告するなら、ファイルは一度も書かれておらず、名前空間を変えても解決しません。

systemctl show [email protected] -p PrivateTmp -p User -p Group -p RuntimeDirectory
systemctl show [email protected] -p MainPID --value
sudo ls -l /proc/PID/root/tmp/client-state

プロセスのルート経由のパスは、サービス自身のファイルシステムの見え方を示しますが、プロセスが動作している間はそのプロセスに対する権限確認の対象になります。同じセッションでユニットのジャーナルを読んでください。誰かが原因をすでに決めつけていると、書き込みエラーとファイル欠如は混同されやすいからです。

共有データに明示的な場所を与える

サービスだけが必要とするデータは、そのプライベートな一時ディレクトリに置きます。別のプロセスが読む必要のあるデータには、双方のために定義されたパスが必要で、所有者・モード・有効期限を明示します。ユニットを編集する前に、どちらのケースなのかを決めてください。こうした障害の多くは、プライベートなファイルを共有ファイルとして扱うことから生じます。

[Service]
RuntimeDirectory=openvpn-hook-office
RuntimeDirectoryMode=0750

ランタイムディレクトリは、フォルダーをシステムのランタイム領域の下に置き、ユニットに設定されたユーザーとグループのために作成し、ユニットが停止すると削除します。パッケージのユニットをそのまま保つため drop-in で追加し、その後マネージャーを再読み込みしてそのインスタンスを再起動します。クライアントが再接続することは受け入れます。

インストール済みのユニットがすでに必要としているランタイムディレクトリは残してください。リストを追加ではなく置き換えるのは、変更と無関係な機能を壊すよくある方法です。

二つの特権層は食い違うことがある

サービスマネージャーはユニットに設定されたユーザーのためにディレクトリを作りますが、VPN デーモンは接続フックを実行する前に別途自分のアカウントへ降りる場合があります。これは別の層であり、別の身元を指すことがあります。

制限的なモードの root 所有ディレクトリは、すでに特権を手放したデーモンからは完全に見えますが、それでも書き込めません。そのときエラーは権限の問題として読まれますが、パスはまさに期待した場所に存在しています。ディレクトリの所有者と、フックが報告する身元を比べてください。両者が異なるなら、モードは最初から問いではありません。

所有権を変える前に、フックが実際にどの身元で動いているかを確認してください。ディレクトリを直すためにサービスの実行ユーザーを変えると、他の場所でデバイスへのアクセスやネットワーク特権が変わり得ます。小さな問題にしては大きな代償です。

受け渡し全体を検証する

四つのことを同時に確認します。フックが本当の身元で書き込むこと、想定した読み手がファイルを利用できること、無関係なユーザーはできないこと、ユニットの停止が設計どおりに後片付けすることです。ホストの共有一時ディレクトリにファイルが現れることは要件ではなく、たいていは受け渡しが独自のパスを得られなかった印です。再起動後に読み手を試してください。初回の実行時だけでは不十分です。後片付けの挙動は設計の一部なので、想定せずに観察してください。

永続的な状態は、寿命が合う場所に置くべきです。ランタイムディレクトリは消えるためにあるからです。場所は便利さではなく寿命で選んでください。その習慣が、同じ調査の次の版を防ぎます。

関連記事