3

環境変数を bash プロセスから設定し、別のプロセスから読み取る方法があるかどうか疑問に思っていました。

環境変数の値は(継承を除いて)プロセスに対してローカルであるため、端末で実行export FOO="bar"して別の端末から読み取ることはできません。私はそれからそれらを通過させようとしていまし/proc/environたが、これは私が得たものです:

etuardu@subranu:~$ FOO="foo" bash
etuardu@subranu:~$ strings /proc/$$/environ | grep FOO
FOO=foo
etuardu@subranu:~$ export FOO="bar"
etuardu@subranu:~$ strings /proc/$$/environ | grep FOO
FOO=foo
etuardu@subranu:~$ echo $FOO
bar

プロセスが開始されたときにその環境変数が持っていた値を取得できるようです。
現在の価値はどうですか?

4

1 に答える 1

7

これは、環境変数が機能する方法のため、一般的には不可能です。

プロセスが最初execに ed になると、カーネルは環境変数の初期セットと他のもの (主にargvベクトル、つまりコマンドライン) をプロセスに提供します。その後、このリスト (argvベクターと同様) は、プロセス内の文字ポインターの通常の C 配列にすぎません。プロセスは、必要に応じて他の用途のために文字列を保持するメモリを完全にリサイクルするなど、好きなように自由に管理できます。あるプロセスが他のプロセスのメモリ空間を覗き込んでその環境変数を見つけるのは安全ではありません。

ほとんどのタイプのプロセスは、カーネルによって提供される環境変数のリストを多かれ少なかれそのまま使用します。おそらくそれを照会し、 や などの C ライブラリ関数で変更しgetenv()ますputenv()。これらのプロセスが順番に他の実行可能ファイルを実行する場合、それらexecveは、自身の実行の開始時に受け取ったシステム コールに同じ環境ベクトルを渡します。これは、新しい実行可能ファイルが同じ環境を取得することを意味します (おそらく へのいくつかの呼び出しによって強化されますputenv()) 。 .

シェルは別の問題です。シェル スクリプトでは環境変数が非常に重要であるため、一部のシェルは提供された環境ベクトルを「開始値」としてのみ使用し、その後は無視します。それらは、独自のより機能的なデータ構造を使用して環境変数を管理します。独自の子プロセスを実行すると、それらの内部データ構造から構築された、まったく新しい環境ベクトルが新しいプロセスに渡されます。これは、上記のようにシェルのメモリ空間を覗いてその環境変数を見つけたとしても、シェルが実際に使用している環境ではなく、初期セットしか見つからないことを意味します!

できることは、プロセスの環境変数の初期セット、つまり、実行可能ファイルが開始されたときに渡されたものと同じベクトルを照会することです。しかし、これは移植性がなく、これをサポートするオペレーティング システム間でもかなりの違いがあります。たとえば、歴史的な UNIX では、プロセスのメモリ空間 (「ユーザー領域」と呼ばれるメモリの特別な領域ではありますが) をのぞき見する必要があるため、まだ少し醜いです。Linux はこれをより洗練された方法で可能にします。ベクトルは でテキスト文字列として見つけることができます/proc/<pid>/environ。この情報を取得できるほとんどのシステムでpsは、e表示できるオプションがあります。

于 2012-11-03T14:28:30.903 に答える