すべてのプロセスはログインシェルの設定(/etc/profile)を経由しますか?

投稿者: Anonymous

ubuntu についてです。

特定サーバーの、すべてのプロセスで反映されていてほしい独自環境変数があったとします。これを実現するにあたって、/etc/profile に記述しておくと、プロセスの fork 木の中で少なくとも1回はその環境変数が反映された状態を実現できるのでは、と思いました。(そこから、例えば環境変数をクリアする処理が入っていたのならば、おそらく相応の理由があるのだとみなして今回は考えないことにします)

この自分の理解は正しいでしょうか。(で、もし正しい場合は、「正しい」だけだと回答としてアレなので、サーバー初期化の際の fork 木がどうなっていてどこにログインシェルがいるのかなど教えていただきたく。。)

解決

/etc/profile に記述しておくと、プロセスの fork 木の中で少なくとも1回はその環境変数が反映された状態を実現できる

プロセスツリーにおいて、全てのプロセスの共通部分というと、木のルートである初期プロセス、いわゆる initプロセスしかありません。
initプロセスを/etc/profileを読んで子プロセスに引き継ぐような物にしてしまえば、答は 「Yes」 です。
通常はそうなっていないので、答は 「No」 です。

例えば環境変数をクリアする処理が入っていたのならば、おそらく相応の理由があるのだとみなして今回は考えないことにします

Initプロセスから起動されるようなプログラムは、結構な割合で環境変数をクリアします。


以下、少し細かいです。

カーネルのブート時には最初のプロセスとして「initプロセス」が起動される

Initプロセスは通常は/sbin/initです。カーネルパラメータ(起動時にブートローダによって設定される物)のinitで変更出来ます。
プロセス番号1で実行され、全てのプロセスの共通の祖先になります。
pstreeコマンドで見るとプロセスツリーのルートになっているのが分かります。

このプロセスは環境変数を引き継ぐ親プロセスを持ちませんが、自動で作られるものがいくつかあります。
カーネルパラメータで初期の環境変数を追加する事も出来ますが、この機能はあまり使われません。

Ubuntu の init は/etc/profileを読んで子プロセスに引き継ぐような事はしない

Ubuntu では Systemd が /sbin/init を提供します。
init が/etc/profileを読んで、さらに環境変数を子プロセスに引き継げば、質問で想定している動作になるでしょうが、Systemdは(恐らく他のinit系プログラムも)そのような動作になっていません。

まず、/etc/profileを読んでいる様子が無さそうです。
Systemd はシェルスクリプトではありませんから、当然かもしれません。
また、子プロセスに継承させる環境変数は、制限していると思われます。

Systemd の DefaultEnvironment

/etc/systemd/system.confDefaultEnvironmentを設定すると、Systemd はこれらを子プロセスに環境変数として引き継ぎます。

例:

DefaultEnvironment="MY_SYSTEMD_ENV=123" "MY_SYSTEMD_ENV2=456"

しかし、子プロセスが引き継いだ環境変数をそのまま、さらに自分の子プロセスに引き継ぐという保証はありません。
sshdなどは全て消し去っているようです。
ですから、sshのログインシェルなどでは、この環境変数は影も形もありません。
こういった感じで、プロセスツリーの末端では Systemd が設定した環境変数はかなりの確率で消えていると思われます。


参考

strings /proc/プロセスID/environ

でプロセスの起動時の環境変数を確認出来ます(今現在の状態ではありません)。

回答者: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *