env変数をエクスポートして、すべてのサブシェルで使用可能にし、変更できるようにしますか?


22

私が持っていると仮定します

export MY_VAR=0

~/.bashrc

開いたgnomeターミナルがあり、このターミナルで$MY_VAR値をに変更します200。だから、私がやったら

echo $MY_VAR

この端末で200は、表示されます。

今、私は私のgnomeターミナルで別のタブを開いて、

echo $MY_VAR

...そして代わりに200、私は持ってい0ます。

端末が環境変数を変更し、この変更(200に設定)を後続のすべてのサブシェルなどで使用できるようにした場合、200の値を保持するにはどうすればよいですか?これは可能ですか?

回答:


23

コピーサブシェルに環境伝播するので、この作品の:

$ export MY_VAR=200
$ bash
$ echo $MY_VAR
200

しかし、それはコピーなので、少なくとも環境を変更することによってではなく、親シェルまでその値を取得することはできません。

Gnomeターミナルの新しいタブのように、親とは別に開始される「兄弟」シェルによって共有されるグローバル変数のように動作するものを作成するために、実際にさらに先に進みたいようです。

ほとんどの場合、答えは「できません。環境変数がそのように機能しないためです」。ただし、別の答えがあります。それは、何かをいつでもハックできるということです。1つのアプローチは、変数の値をのようなファイルに書き込み、~/.myvarそれをに含めることです~/.bashrc。その後、各新しいシェルは、そのファイルから読み取られた値で開始されます。

さらに一歩進ん~/.myvarで、makeをformat MYVAR=200にしてからset PROMPT_COMMAND=source ~/.myvarにすると、新しいプロンプトが表示されるたびに値が再読み取りされます。それはまだありませんかなり共有グローバル変数が、それのように行動し始めています。ただし、プロンプトが戻るまでアクティブになりません。これは、何をしようとしているかによって深刻な制限になる場合があります。

そして、もちろん、次のことはに自動的変更を書き込むこと~/.myvarです。それはもう少し複雑になりますが、実際のところ、環境変数はシェル間通信メカニズムを意図したものではなく、別の方法を見つけた方がよいため、この時点で停止します。


10
拷問の下でシェルの

ごめんなさい それが私がやめた理由です。:)
mattdm

「これは、グローバル変数のように機能するものを作成することです」-実際、それは私が達成しようとしていたことです。〜/ .myvarはきれいではありませんが、動作します。別の提案がありますか?
誰かがまだあなたを使用してMS-DOS

2
さて、少し後退しましょう。なぜグローバル変数が必要なのですか?
mattdm

1
@mattdm:従わなければならない「官僚制度」がいくつかあります。それらの1つは、コメントとともにコミットする必要があるコードの束です。これらのコードは現在、フォルダー階層(home / user / projects / projectcode / code1 / code2)にあります。code1とcode2をenv変数に抽出する関数を作成しました(したがって、アクティビティを実行する必要がある場合は、dir内の関数をコードで呼び出します)。これらの変数を読み取り、自動的にコメントを入力します。そのためにファイルを使用することが解決策になると思います。
誰かがまだあなたを使用してMS-DOS

13

私が持っていると仮定export MY_VAR=0~/.bashrcます。

それはあなたの間違いです。環境変数はで定義する必要があります。~/.profileこれはログイン時に読み込まれます。~/.bashrcシェルを起動するたびに読み込まれます。インナーシェルを起動すると、が上書きされますMY_VAR。そうしなかった場合、環境変数は下方に伝播します。

詳細については~/.bashrc、VS ~/.profile、私の見る前の 記事 この トピックを

上方への伝播(サブシェルから変更された値を親シェルに自動的に反映する)は不可能であり、完全に停止することに注意してください。



3

環境変数をまったく使用しないでください。ファイルを使用します。

ファイルの更新/読み取り時にプロセスが互いに踏まないようにするには、ロックされていない場合に$ 1でファイルを更新するだけの目的のロックファイルと小さなフロントエンドアップデータスクリプトを使用します。ロックファイルは基本的に、特定のファイル(/var/run/yourscript.lck)が存在するかどうかをチェックすることで実装され、存在する場合はファイルがしばらく消えるのを待ち、存在しない場合は失敗します。また、ファイルの更新が完了したら、ロックファイルを削除する必要があります。

ファイルがビジーであるためにスクリプトがファイルを更新できない状況に対処する準備をします。


8
トリック:mkdirアトミックテストアンドクリエイトとして機能するため、ロックにファイルの代わりにディレクトリを使用します。
mattdm

1
あなたたちは、ロックについて話をしたい場合は、同様に使用している場合がありますflock(2)
Ehteshチョードリー

@mattdm ln -s dummy lockfileシンボリックリンクが既に存在する場合は失敗するため、シンボリックリンク(破損している場合でも)も機能することがわかった。それが本当に100%安全かどうかをテストする方法はあるのだろうか。
アクエリアスパワー

1

この質問をグーグルで検索したところ、サブシェルから状態(シェル変数)を更新する問題を解決しようとしていました。そのため、たとえばパイプラインの内部で変数を割り当てることができ、その割り当ては親に透過的に表示されます。

もちろん、パイプラインの個々の部分はサブシェルで実行されるため、これは単純な方法では不可能です。サブシェルforkは親シェルから取得され、親のメモリにコピーオンライトビューのメモリがあります。ただし、IPCの共有メモリ」に基づいて、スリムで透過的なソリューションが可能になると考えました。

そして、私はまさにこの設計の実装さえ見つけました...しかし、それはPerlにあります。

とにかくこの答えを可能な解決策として追加します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.