GNU/Linux >> Linux の 問題 >  >> Linux

プロセスの環境変数を読み取る方法

イニシャルを読むことができます /proc/<pid>/environ からのプロセスの環境 .

プロセスが変更された場合 その環境を読み取るには、プロセスのシンボル テーブルを取得し、ptrace を使用する必要があります。 システムコール (たとえば gdb を使用) ) グローバル char **__environ から環境を読み取る 変数。実行中の Linux プロセスから変数の値を取得する方法は他にありません。

それが答えです。では、いくつかメモを取りましょう。

上記は、プロセスが POSIX 準拠であることを前提としています。つまり、プロセスはグローバル変数 char **__environ を使用して環境を管理します。 参照仕様で指定されているとおり。

プロセスの初期環境は、プロセスのスタック上の固定長バッファーでプロセスに渡されます。 (これを行う通常のメカニズムは linux//fs/exec.c:do_execve_common(...) です .) バッファーのサイズは、初期環境に必要なサイズを超えないように計算されるため、既存の変数を消去するか、スタックを壊さない限り、新しい変数を追加することはできません。したがって、プロセスの環境の変更を許可する合理的なスキームは、任意のサイズのメモリを割り当てて解放できるヒープを使用します。これは、GNU libc とまったく同じです。 (glibc ) はあなたのために行います。

プロセスが glibc を使用する場合 の場合、__environ で POSIX に準拠しています。 glibc//posix/environ.c で宣言されている glibc は __environ を初期化します malloc であるメモリへのポインタ プロセスのヒープから、初期環境をスタックからこのヒープ領域にコピーします。プロセスが setenv を使用するたびに 関数、glibc realloc を実行します __environ の領域のサイズを調整するには 新しい値または変数を格納するために を指します。 (git clone git://sourceware.org/git/glibc.git glibc で glibc のソース コードをダウンロードできます。 )。メカニズムを本当に理解するには、hurd//init/init.c:frob_kernel_process() の Hurd コードも読む必要があります。 (git clone git://git.sv.gnu.org/hurd/hurd.git hurd).

新しいプロセスが fork のみの場合 ed、後続の exec なし スタックを上書きし、引数と環境コピーの魔法が linux//kernel/fork.c:do_fork(...) で行われます 、ここで copy_process ルーチン呼び出し dup_task_struct alloc_thread_info_node を呼び出して新しいプロセスのスタックを割り当てます 、これは setup_thread_stack を呼び出します (linux//include/linux/sched.h ) alloc_thread_info_node を使用した新しいプロセス .

最後に、POSIX __environ 規約はユーザー空間です 大会。 Linux カーネルとは何の関係もありません。 glibc を使用せずにユーザー空間プログラムを作成できます __environ なし グローバルで、環境変数を好きなように管理します。これを行ったとして誰もあなたを逮捕することはありませんが、独自の環境管理機能を作成する必要があります (setenv /getenv ) と sys_exec の独自のラッパー また、環境のどこに変更を加えたかを誰も推測できない可能性があります。


/proc/$pid/environ プロセスが独自の環境を変更した場合、更新されます。しかし、多くのプログラムは自分自身の環境をわざわざ変更することはありません。それは少し無意味だからです:プログラムの環境は通常のチャンネルでは見えず、/proc を通してしか見えません。 と ps であり、すべての UNIX バリアントにこの種の機能があるわけではないため、アプリケーションはそれに依存しません。

カーネルに関する限り、環境は execve の引数としてのみ表示されます プログラムを起動するシステムコール。 Linux は /proc を介してメモリ内の領域を公開します 、一部のプログラムはこの領域を更新しますが、他のプログラムは更新しません。特に、この領域を更新するシェルはないと思います。領域は固定サイズであるため、新しい変数を追加したり、値の長さを変更したりすることはできません。


プロセスがその環境変数を取得/削除すると更新されます。 environ と記載されているリファレンスはありますか ファイルは、/proc ファイルシステムの下のプロセス ディレクトリにあるプロセス用に更新されていませんか?

xargs --null --max-args=1 echo < /proc/self/environ

または

xargs --null --max-args=1 echo < /proc/<pid>/environ

または

ps e -p <pid>

上記は、プロセスの環境変数を ps に出力します 環境変数をリストとして表示するには、テキスト処理 (解析/フィルタリング) が必要です。

Solaris (聞かれませんが、参考までにここに投稿します):

/usr/ucb/ps -wwwe <pid>

または

pargs -e <pid> 

編集: /proc/pid/environ が更新されていません!私は訂正します。検証プロセスは以下のとおりです。ただし、プロセスがフォークされた子はプロセス環境変数を継承し、それぞれの /proc/self/environ ファイルに表示されます。 (文字列を使用)

シェル内:ここで xargs は子プロセスであるため、環境変数を継承し、その /proc/self/environ にも反映されます ファイル。

[[email protected] t]$ printenv  | grep MASK
[[email protected] t]$ export MASK=NIKHIL
[[email protected] t]$ printenv  | grep MASK
MASK=NIKHIL
[[email protected] t]$ xargs --null --max-args=1 echo < /proc/self/environ  | grep MASK
MASK=NIKHIL
[[email protected] t]$ unset MASK
[[email protected] t]$ printenv  | grep MASK
[[email protected] t]$ xargs --null --max-args=1 echo < /proc/self/environ  | grep MASK
[[email protected] t]$

端末/セッションが、環境変数が設定されているシェルの子プロセスではない、他のセッションからチェックしています。

同じホスト上の別の端末/セッションから検証:

ターミナル1: :printenv は fork され、bash の子プロセスであるため、独自の環境ファイルを読み取ることに注意してください。

[[email protected] t]$ echo $$
2610
[[email protected] t]$ export SPIDEY=NIKHIL
[[email protected] t]$ printenv | grep SPIDEY
SPIDEY=NIKHIL
[[email protected] t]$ 

ターミナル2: 同じホスト上で -- 上記の変数が設定されたのと同じシェルで起動しないでください。ターミナルを個別に起動してください。

[[email protected] ~]$ echo $$
4436
[[email protected] ~]$ xargs --null --max-args=1 echo < /proc/self/environ | grep -i spidey
[[email protected] ~]$ strings -f /proc/2610/environ | grep -i spidey
[[email protected] ~]$ xargs --null --max-args=1 echo < /proc/2610/environ | grep -i spidey
[[email protected] ~]$ 

Linux
  1. Linux で環境変数を設定、一覧表示、および削除する方法

  2. su に現在のユーザー環境変数を与える方法

  3. 多くの環境変数の設定を解除する方法

  1. Linux環境変数:LinuxVPSでの読み取りと設定の方法

  2. 環境変数をDockerコンテナに渡す方法

  3. 環境変数は Linux で非特権ユーザーに表示されますか?

  1. R に環境変数を読み取らせるにはどうすればよいですか?

  2. Ansible で Linux 環境変数を設定する方法

  3. 明らかに隠された環境変数を出力するには?