Linuxの/proc/<pid>/environ
は更新されません(私が理解しているように、ファイルにはプロセスの初期環境が含まれています)。
プロセスのcurrent環境を読み取るにはどうすればよいですか?
/proc/$pid/environ
は、プロセスが独自の環境を変更すると更新されます。しかし、多くのプログラムは独自の環境を変更する必要がありません。それは少し無意味だからです。プログラムの環境は、通常のチャネルからは見えず、/proc
とps
からしか見えません。この種の機能なので、アプリケーションはそれに依存しません。
カーネルに関する限り、環境はプログラムを起動する execve
システムコールの引数としてのみ表示されます。 Linuxは/proc
を介してメモリ内の領域を公開し、一部のプログラムはこの領域を更新しますが、他のプログラムは更新しません。特に、シェルがこの領域を更新することはないと思います。領域のサイズは固定されているため、新しい変数を追加したり、値の長さを変更したりすることはできません。
プロセスのinitial環境は_/proc/<pid>/environ
_から読み取ることができます。
プロセスchangesその環境の場合、環境を読み取るには、プロセスのシンボルテーブルがあり、ptrace
システムコールを使用して(たとえば、gdb
を使用して)グローバルから環境を読み取る必要があります。 _char **__environ
_変数。実行中のLinuxプロセスから変数の値を取得する方法は他にありません。
それが答えです。次に、いくつかの注意事項について説明します。
上記は、プロセスがPOSIX準拠であることを前提としています。つまり、プロセスは Ref Spec で指定されているグローバル変数_char **__environ
_を使用して環境を管理します。
プロセスの初期環境は、プロセスのスタック上の固定長バッファーでプロセスに渡されます。 (これを行う通常のメカニズムはlinux//fs/exec.c:do_execve_common(...)
です。)バッファーのサイズは初期環境に必要なサイズ以下になるように計算されるため、既存の変数を消去せずに新しい変数を追加したり、スタックを壊します。したがって、プロセスの環境での変更を許可するための適切なスキームはヒープを使用します。ここで、任意のサイズのメモリを割り当てて解放できます。これは、GNU libc
(glibc
)が行うこととまったく同じです。
プロセスがglibc
を使用する場合、それはPOSIXに準拠しており、___environ
_は_glibc//posix/environ.c
_で宣言されています。Glibcは、プロセスのヒープからmalloc
sを指すメモリへのポインタで___environ
_を初期化し、初期スタックからこのヒープ領域への環境。プロセスが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
_規約はuser-space規約です。 Linuxカーネルには何の関係もありません。 glibc
を使用せず、___environ
_グローバルを使用せずにユーザー空間プログラムを作成し、環境変数を好きなように管理できます。これを行ったことで誰もあなたを逮捕することはありませんが、独自の環境管理関数(setenv
/getenv
)と_sys_exec
_の独自のラッパーを作成する必要があり、どこにどこに置くか推測できない可能性があります環境の変化。
プロセスがその環境変数を取得/削除したときに更新されます。/procファイルシステムの下のプロセスディレクトリで、プロセスのenviron
ファイルが更新されていないことを示すリファレンスがありますか?
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
ファイルにも反映されます。
[centos@centos t]$ printenv | grep MASK
[centos@centos t]$ export MASK=NIKHIL
[centos@centos t]$ printenv | grep MASK
MASK=NIKHIL
[centos@centos t]$ xargs --null --max-args=1 echo < /proc/self/environ | grep MASK
MASK=NIKHIL
[centos@centos t]$ unset MASK
[centos@centos t]$ printenv | grep MASK
[centos@centos t]$ xargs --null --max-args=1 echo < /proc/self/environ | grep MASK
[centos@centos t]$
ターミナル/セッションが環境変数が設定されているシェルの子プロセスではない他のセッションからそれをチェックします。
同じホスト上の別の端末/セッションから確認する:
terminal1::printenvはforkされ、bashの子プロセスであるため、独自の環境ファイルを読み取ることに注意してください。
[centos@centos t]$ echo $$
2610
[centos@centos t]$ export SPIDEY=NIKHIL
[centos@centos t]$ printenv | grep SPIDEY
SPIDEY=NIKHIL
[centos@centos t]$
terminal2:同じホストで-上記の変数が設定された同じシェルで起動しないでください。ターミナルを個別に起動します。
[centos@centos ~]$ echo $$
4436
[centos@centos ~]$ xargs --null --max-args=1 echo < /proc/self/environ | grep -i spidey
[centos@centos ~]$ strings -f /proc/2610/environ | grep -i spidey
[centos@centos ~]$ xargs --null --max-args=1 echo < /proc/2610/environ | grep -i spidey
[centos@centos ~]$
さて、以下は作者の本当の意図とは関係ありませんが、本当に「読みたい」場合は/proc/<pid>/environ
、お試しください
strings /proc/<pid>/environ
cat
より良いです。