29145


ubuntu についてです。

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

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


CC BY-SA 3.0
2016-09-25T15:21:41.720
29126
2016-10-08T15:24:27.927
754
question
ubuntu
すべてのプロセスはログインシェルの設定(/etc/profile)を経由しますか？


NOです。

UNIX系OSのプロセスはfork&execモデルです。これはforkにより自身のプロセスのコピーを作成することと、execにより自身のプロセスを指定したプログラムに置き換えることとの２ステップによって成り立っています。その際の環境変数はexec前のものが引き継がれます。  
その上で、fork&execはシェルだけに許されるものではなく、任意のプロセスが行えます。そのため、exec元のプロセスが環境変数を消してしまった場合は、execされたプログラムとしては消されずに残されていた環境変数しか得られません。


CC BY-SA 3.0
2016-09-26T03:03:30.463
29132
2016-09-26T03:03:30.463
4236
29126
answer


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

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

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

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

* * *

以下、少し細かいです。

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

Initプロセスは通常は`/sbin/init`です。カーネルパラメータ（[起動時にブートローダによって設定される物](https://wiki.archlinuxjp.org/index.php/%E3%82%AB%E3%83%BC%E3%83%8D%E3%83%AB%E3%83%91%E3%83%A9%E3%83%A1%E3%83%BC%E3%82%BF)）の`init`で変更出来ます。  
プロセス番号`1`で実行され、全てのプロセスの共通の祖先になります。  
`pstree`コマンドで見るとプロセスツリーのルートになっているのが分かります。

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

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

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

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

### Systemd の DefaultEnvironment

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

例:

[code]

    DefaultEnvironment="MY_SYSTEMD_ENV=123" "MY_SYSTEMD_ENV2=456"
    
[/code]

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

* * *

### 参考

[code]

    strings /proc/プロセスID/environ
    
[/code]

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


CC BY-SA 3.0
2016-09-26T10:15:29.573
29145
2016-09-26T12:50:25.923
2016-09-26T12:50:25.923
3054
3054
29126
answer


以下、ubuntu でなく archlinux での確認結果になります。

サーバの話ということなので、  
つまり、ssh で login した先でどうなのか、という話ですよね?

pstree で見たところ、systemd が sshd を起動し、  
sshd が shell を起動しているようです。  
私の場合、shell には tcsh を使っているので /etc/profile は読み込んでいません。  
systemd も sshd も /etc/profile を読んでるとは思えませんので、  
私の tcsh は /etc/profile を読み込んではいないようです。


CC BY-SA 3.0
2016-09-26T13:42:20.760
29151
2016-09-26T13:42:20.760
5288
29126
answer