Unixで、あるプロセスが別のプロセスの環境変数を変更できる方法はありますか(それらがすべて同じユーザーによって実行されていると想定)。一般的な解決策が最善ですが、そうでない場合、一方が他方の子である特定のケースについてはどうでしょうか?
編集:gdbはどうですか?
Unixで、あるプロセスが別のプロセスの環境変数を変更できる方法はありますか(それらがすべて同じユーザーによって実行されていると想定)。一般的な解決策が最善ですが、そうでない場合、一方が他方の子である特定のケースについてはどうでしょうか?
編集:gdbはどうですか?
回答:
gdb経由:
(gdb) attach process_id
(gdb) call putenv ("env_var_name=env_var_value")
(gdb) detach
これは非常に厄介なハックであり、もちろんデバッグシナリオのコンテキストでのみ実行する必要があります。
ptrace: Operation not permitted
あなたはおそらく技術的にそれを行うことができますが(他の回答を参照)、それはあなたを助けにはしないかもしれません。
ほとんどのプログラムは、起動後にenv変数を外部から変更できないことを想定しているため、起動時に関心のある変数を読み取り、それに基づいて初期化するだけです。したがって、後で変更しても、プログラムがそれらを再度読み取ることはないため、違いはありません。
これを具体的な問題として投稿した場合は、おそらく別のアプローチを取る必要があります。それが好奇心から外れた場合:いい質問:-)。
実質的にはありません。十分な権限(rootまたはその周辺)があり、/ dev / kmem(カーネルメモリ)を突っ込んで、プロセスの環境に変更を加えた場合、およびプロセスが後で実際に環境変数を再参照した場合(つまり、プロセスenv varのコピーをまだ取得しておらず、そのコピーだけを使用していなかった場合)、おそらく、運がよくて賢く、風が正しい方向に吹いていて、月の位相が正しかった場合、あなたは何かを達成するかもしれません。
gdb
は親プロセスで起動し、スクリプトを実行して変更を行い、親プロセスをクラッシュさせることなく機能します。OK —おそらくそれは可能ですが、日常的に行うことではありません。したがって、実際的な目的では、答えはNoのままです。残りの答えは、理論的には可能で、やや非現実的に実行可能な代替策をカバーしています。
ジェリー・ピークの引用:
古い犬に新しいトリックを教えることはできません。
あなたができる唯一のことは、それを開始する前に子プロセスの環境変数を変更することです:親環境のコピーを取得します、申し訳ありません。
詳細については、http://www.unix.com.ua/orelly/unix/upt/ch06_02.htmを参照してください。
/ procの使用に関する回答についてのコメント。Linuxでは/ procがサポートされていますが、rootであってもファイルは変更できません/proc/${pid}/environ
。これは完全に読み取り専用です。
私はそれを行うためにかなり工夫された方法を考えることができ、それは任意のプロセスでは機能しません。
'char * getenv'を実装する独自の共有ライブラリを作成するとします。次に、「LD_PRELOAD」または「LD_LIBRARY_PATH」環境を設定します。両方のプロセスが共有ライブラリをプリロードして実行されるように、vars。
このようにして、基本的に「getenv」関数のコードを制御できます。次に、あらゆる種類の厄介なトリックを実行できます。「getenv」は、環境変数の代替値について外部設定ファイルまたはSHMセグメントを調べることができます。または、要求された値に対して正規表現検索/置換を行うことができます。または...
動的リンカー(ld-linux.so)を書き直さない限り、(rootであっても)任意の実行中のプロセスに対してこれを行う簡単な方法は考えられません。
私の知る限りではありません。実際には、IPCメソッド(共有メモリ、セマフォ、ソケットなど)の1つを呼び出すプロセス間で通信しようとしています。これらの方法のいずれかでデータを受け取ったら、環境変数を設定したり、他のアクションをより直接的に実行したりできます。
unixが/ procファイルシステムをサポートしている場合は、envを読み取るのは簡単です。所有しているプロセスの環境、コマンドライン、およびその他の多くの属性を読み取ることができます。それを変える...まあ、私は方法を考えることができますが、それは悪い考えです。
より一般的なケース...わかりませんが、移植性のある答えがあるとは思えません。
(編集:私の元の答えは、OPが環境を変更するのではなく、読み取りたいと想定していた)
直接的な回答ではありませんが... Raymond Chenはこれについて[Windowsベースの]理論的根拠がありました:-
...確かに、サポートされていない方法やデバッガーの助けを借りて機能する方法はありますが、別のプロセスのコマンドラインへのプログラムによるアクセスについてサポートされているものはなく、少なくともカーネルによって提供されているものはありません。...
ないということは、必要のない情報を追跡しないという原則の結果です。カーネルは別のプロセスのコマンドラインを取得する必要はありません。
CreateProcess
関数に渡されたコマンドラインGetCommandLine
を取得し、関数が取得できる場所にある起動中のプロセスのアドレススペースにコピーします。プロセスが独自のコマンドラインにアクセスできるようになると、カーネルの役割が完了します。コマンドラインはプロセスのアドレス空間にコピーされるため、プロセスはコマンドラインを保持しているメモリに書き込み、それを変更することもできます。その場合、元のコマンドラインは永久に失われます。既知の唯一のコピーが上書きされました。
つまり、そのようなカーネル機能は
ただし、最も可能性が高い理由は、そのような機能の使用例が限られていることです。
putenvは現在動作していないようですが、setenvは動作しています。私は現在のシェルで変数を設定しようとしている間に成功した答えをテストしていました
$] sudo gdb -p $$
(gdb) call putenv("TEST=1234")
$1 = 0
(gdb) call (char*) getenv("TEST")
$2 = 0x0
(gdb) detach
(gdb) quit
$] echo "TEST=$TEST"
TEST=
バリアントの仕組み:
$] sudo gdb -p $$
(gdb) call (int) setenv("TEST", "1234", 1)
$1 = 0
(gdb) call (char*) getenv("TEST")
$2 = 0x55f19ff5edc0 "1234"
(gdb) detach
(gdb) quit
$] echo "TEST=$TEST"
TEST=1234