web-dev-qa-db-ja.com

Unixの別のプロセスの環境変数を変更する方法はありますか?

Unixでは、あるプロセスが別のプロセスの環境変数を変更できる方法はありますか(それらがすべて同じユーザーによって実行されていると仮定)。一般的な解決策が最善ですが、そうでない場合は、一方が他方の子である特定のケースについてはどうですか?

編集:GDB経由ではどうですか?

90
raldi

Gdb経由:

(gdb) attach process_id

(gdb) call putenv ("env_var_name=env_var_value")

(gdb) detach

これは非常に厄介なハックであり、もちろんデバッグシナリオのコンテキストでのみ実行する必要があります。

126
An̲̳̳drew

あなたはおそらく技術的にそれを行うことができます(他の回答を参照)が、それはあなたを助けないかもしれません。

ほとんどのプログラムは、起動後に外部からenv変数を変更できないことを期待するため、ほとんどの場合、起動時に関心のある変数を読み取り、それに基づいて初期化するだけです。したがって、プログラムがそれらを再読み取りすることはないため、後でそれらを変更しても違いはありません。

これを具体的な問題として投稿した場合は、おそらく別のアプローチを取る必要があります。好奇心からだけだった場合:いい質問:-)。

22
sleske

実質的にはありません。十分な特権(ルート、またはその周辺)があり、/ dev/kmem(カーネルメモリ)の周りを突いて、プロセスの環境に変更を加え、その後プロセスが実際に環境変数を再参照した場合(つまり、プロセスenv varのコピーをまだ取得しておらず、そのコピーだけを使用していませんでした)、その後、幸運で賢く、風が正しい方向に吹いていて、月の位相が正しい場合は、あなたは何かを達成するかもしれません。

13

ジェリーピークの引用:

老犬に新しいトリックを教えることはできません。

できることは、子プロセスの環境変数を変更することだけですbefore開始:親環境のコピーを取得します、申し訳ありません。

詳細については、 http://www.unix.com.ua/orelly/unix/upt/ch06_02.htm を参照してください。

/ procの使用に関する回答についてのコメントのみ。 Linuxでは/ procがサポートされていますが、機能しません。cannot/proc/${pid}/environファイル、rootであっても:absolutely読み取り専用です。

7
Davide

私はそれを行うためにかなり工夫された方法を考えることができ、それは任意のプロセスでは機能しません。

「char * getenv」を実装する独自の共有ライブラリを作成するとします。次に、「LD_PRELOAD」または「LD_LIBRARY_PATH」環境を設定します。 varsを使用すると、両方のプロセスが共有ライブラリがプリロードされた状態で実行されます。

このように、本質的に 'getenv'関数のコードを制御できます。その後、あらゆる種類の厄介なトリックを行うことができます。 「getenv」は、env varの代替値について外部設定ファイルまたはSHMセグメントを参照できます。または、要求された値で正規表現検索/置換を実行できます。または...

動的リンカー(ld-linux.so)を書き換える以外に、任意の実行中のプロセス(rootであっても)に対してこれを行う簡単な方法は考えられません。

7
ADEpt

または、プロセスを取得して、新しいプロセスの構成ファイルを更新し、次のいずれかを実行します。

  • 新しいプロセスでkill -HUPを実行して、更新された構成ファイルを再読み取りするか、または
  • プロセスが時々設定ファイルの更新をチェックするようにします。変更が見つかった場合、構成ファイルを再読み取りします。
3
Rob Wells

私の知る限りではありません。本当に、1つのプロセスからIPCメソッド(共有メモリ、セマフォ、ソケットなど)のいずれかを呼び出す別のプロセスに通信しようとしています。これらのメソッドのいずれかでデータを受信した場合環境変数を設定したり、他のアクションをより直接実行したりできます。

2

UNIXが/ procファイルシステムをサポートしている場合、envを読むことは簡単です。環境、コマンドライン、およびそのように所有するプロセスの多くの他の属性を読むことができます。それを変える...さて、私は方法を考えることができますが、それは悪い考えです。

もっと一般的な場合...わかりませんが、移植可能な答えがあるとは思いません。

(編集:私の元の答えは、OPが環境を変更するのではなく、環境を読むことを望んでいると仮定した)

1
Mike G.

UNIXはプロセス間通信でいっぱいです。ターゲットインスタンスにいくつかがあるかどうかを確認します。 Dbusは「デスクトップ」IPCの標準になりつつあります。

awesome-clientを使用してAwesomeウィンドウマネージャー内の環境変数を変更します。withはluaコードのDbus「送信者」です。

1
dvd

直接的な答えではありませんが... レイモンド・チェンは、先日だけ[Windowsベースの]理論的根拠を持っていました :-

...確かにサポートされていない方法、またはデバッガの助けを借りて機能する方法はありますが、別のプロセスのコマンドラインへのプログラムによるアクセスはサポートされていません。少なくともカーネルによって提供されているものはありません。 ...

存在しないということは、必要のない情報を追跡しないという原則の結果です。カーネルは、別のプロセスのコマンドラインを取得する必要はありません。 CreateProcess関数に渡されたコマンドラインを受け取り、GetCommandLine関数が取得できる場所で、起動中のプロセスのアドレス空間にコピーします。プロセスが独自のコマンドラインにアクセスできるようになると、カーネルの責任が完了します。

コマンドラインはプロセスのアドレススペースにコピーされるため、プロセスはコマンドラインを保持しているメモリに書き込み、変更することもあります。その場合、元のコマンドラインは永久に失われます。唯一の既知のコピーが上書きされました。

言い換えれば、そのようなカーネル機能は

  • 実装が難しい
  • 潜在的にセキュリティ上の懸念

ただし、最も可能性の高い理由は、単純にそのような施設の使用例が限られていることです。

1
Ruben Bartelink