コンテンツにスキップ

プロセスと systemd

各プロセスの実行ユーザーと、使用する設定・作業ディレクトリ・環境変数を確認する。コード中のユーザー指定だけで判断せず、実際の起動方法も調べる。

待ち受けと socket の見つけ方はネットワークと IPC。unit が示す資格情報は資格情報と設定。

追加確認例:

ターミナルウィンドウ
ps auxf
ps -eo user,pid,ppid,group,cmd --forest
systemctl --type=service --state=running
systemctl status <service>
systemctl cat <service>
systemctl show <service>
cat /proc/<PID>/status
tr '\0' '\n' < /proc/<PID>/environ
tr '\0' ' ' < /proc/<PID>/cmdline
readlink -f /proc/<PID>/exe
ls -l /proc/<PID>/fd
  • 目的: 実行ユーザー、起動コマンド、親子関係、unit の実設定、開いている FD を確認する。
  • 前提条件: systemd があるとは限らない。/proc/<PID>/environ や fd は、同一ユーザーまたは高権限でないと読めないことがある。
  • 何を確認しているか: User=, Group=, ExecStart=, Environment=, EnvironmentFile=, WorkingDirectory=、PID 1、開いたままの FD。
  • 期待される出力: root ... php -S 127.0.0.1:<port> -t /var/www/<app>、ExecStart=/usr/local/bin/<service>、User=root の oneshot service。
  • 出力の解釈: root で動く service が user-controlled input を読む場合は権限境界。似た設定ファイルが複数ある場合は、systemctl cat と /proc/<PID>/cmdline で実際の起動元を確定する。
  • 失敗した場合の切り分け: systemctl がない、container 内、権限不足、service 名の違い、プロセスが短命、hidepid mount option を疑う。
  • 代替コマンド: service --status-all, initctl, pgrep -a <name>, strings /proc/<PID>/environ 2>/dev/null。
  • 状態変更: 読み取り専用。systemctl status は pager が起動する場合があるため、SYSTEMD_PAGER=cat や --no-pager を使う。
  • コードだけでは実行ユーザーが分からない。root で動くと影響範囲が変わる処理がある。
  • /proc/<PID>/fd は、パスの permission を迂回する FD の手掛かりになる。詳しくはUnix socket とファイルディスクリプタ。
  • EnvironmentFile に credential や管理パスワードが残ることがある。読める場合は対象を絞って確認する。
  • /proc/<PID>/environ や fd が読めないこと自体も境界情報になる。

systemctl cat で実 ExecStart と unit ファイルの位置を確定し、サンプル設定と本番設定を分ける。localhost の管理 UI と root の timer は、同じアプリでも別 unit のことがある。開発用の組み込み HTTP サーバは、/proc/<PID>/cmdline の document root がそのプロセスのファイル範囲を示す。言語ランタイムの debug port を見つけたら、所有 PID、cmdline、UID をセットで残す。

ExecStart, User, Group, EnvironmentFile, WorkingDirectory は、次に読むファイルと次の権限境界を示す。timer との対応は定期実行で見る。