プロセスが環境変数をもつ

勘違いしていたのだがプロセスが環境変数を保持している。ユーザが持っているわけではない。

supervisodをrootユーザで実行し、その子プロセスが実行するアプリケーションは別ユーザで実行するようにsupervisor.confを設定( http://supervisord.org/configuration.html#program-x-section-valuesuserを参照)するようにした。そして、アプリケーションで使用する環境変数を実行ユーザの.bash_profileexport XXX=xxxのように記載して設定するようにしていた。しかし、アプリケーションのログを見ると、設定した環境変数が読み込まれていないようであった。最終的には/proc/{pid}/environを確認し、所望の環境変数が設定されていないことがわかった。

なぜ環境変数が設定されなかったかというと、冒頭に戻るが、そもそもユーザではなくプロセスが環境変数を保持しているためである。この場合だと、supervisordを実行したrootユーザ(のbashプロセス)の環境変数が子プロセスであるアプリケーションのプロセスにそのまま引き継がれる。このため、supervisorのドキュメントにも記載されている(以下、引用)が、実行ユーザを変更するときにはsetuidしているだけで実行ユーザの.bash_profileなどは実行されない。このため、実行ユーザの.bash_profile環境変数を設定してもアプリケーションのプロセスが保持する環境変数に設定が反映されない。

The user will be changed using setuid only. This does not start a login shell and does not change environment variables like USER or HOME. See Subprocess Environment for details.

いつも環境変数を設定するときはそのユーザのホームディレクトリにある.bash_profile.bashrcに設定を記載しており、なんとなくユーザが環境変数をもっていると誤解したため、このような間違いをやってしまったのではないかと思う。

ここで正しく環境変数を設定する方法とは、rootユーザに環境変数を設定してsupervisordを実行し直すか、supervisor.confのenvironment環境変数を設定するか、のどちらかである。

なお、Advanced Programming in the UNIX Environmentを確認したが、環境変数はstackやheapと同様にプロセスのメモリに格納される。

the environment strings are typically stored at the top of a process’s memory space, above the stack.