環境変数とは正確には何ですか?


42

これVARIABLE=valueにより環境変数がexport VARIABLE=value作成され、現在のシェルで作成されたプロセスで使用できるようになります。envは現在の環境変数を示していますが、どこにありますか?環境変数(またはそのことについては環境)を構成するものは何ですか?

回答:


29

環境は、見た目ほど魔法ではありません。シェルはそれをメモリに保存し、execve()システムコールに渡します。子プロセスは、それをという配列ポインタとして継承しますenvironexecveマンページから:

あらすじ

   #include <unistd.h>

   int execve(const char *filename, char *const argv[],
              char *const envp[]);

argv新しいプログラムに渡される引数文字列の配列です。
慣例により、これらの文字列の最初には、実行中のファイルに関連付けられたファイル名が含まれている必要があります。envp環境として新しいプログラムに渡される、通常はkey = valueの形式の文字列の配列です。

environ(7)マニュアルページにも、いくつかの洞察力を提供しています:

あらすじ

   extern char **environ;

説明

変数 environは、「環境」と呼ばれる文字列へのポインタの配列を指します。この配列の最後のポインターには値がありますNULL。(この変数はユーザープログラムで宣言する必要があり<unistd.h>ますが、ヘッダーファイルがlibc4またはlibc5から来た場合、およびそれらがglibcから来て_GNU_SOURCEが定義されている場合、ヘッダーファイルで宣言されます。)プロセスを開始したexec(3)呼び出しによるプロセス。

これらのGNUマンページは両方ともPOSIX仕様に一致します


4
+1 exec(3)ファミリーの一部のメンバー(つまり、exec * vに一致しないメンバー)が** environを隠れて通過することは、おそらく注目に値します。
msw

5
子プロセス(子プロセスは親のすべてのメモリを継承する)ではなく、実行されたプログラム(同じプロセス内)であるため、execve()システムコールでデータを渡す別の方法であることに注意してください(そうでなければメモリを消去します)プロセスの)。
ステファンシャゼル

@msw:exec*e暗黙的にenvironグローバル変数を使用する代わりに、envを明示的に渡すバリアントです。v手段「ベクター」、およびアレイ(よりむしろ「リスト」(可変長関数))として渡されたコマンドライン引数を指す execveシステムコールであり、そして他のすべてのexec*機能は、それのためのlibcラッパーです。
ピーター・コーデス

19

少し間違っています:SOME_NAME=valueシェル変数を作成します(ほとんどのシェルで)。export SOME_NAME=value環境変数を作成します。良くも悪くも、ほとんどのUnix / Linux / * BSDシェルは、環境変数とシェル変数にアクセスする際に同一の構文を使用します。

もっと大きな意味では、「環境」はプログラムの実行に伴う情報にすぎません。Cプログラムでは、getpid()呼び出しでプロセスIDを見つけることができます。シェルプログラムでは、変数アクセスを使用します$$。プロセスIDは、プログラムの環境の一部にすぎません。「環境」という用語は、プログラム実行のモデリングなど、より理論的なコンピューターサイエンスのトピックに由来すると考えています。プログラム実行のモデルには、「変数とその値の間の関連を含む」環境があります

そして後者のより強力な定義は、Unix / Linux / * BSDシェルの「環境」とは何か:名前(「変数」)とその値との関連付けです。ほとんどのUnixスタイルのシェルでは、値はすべて文字列ですが、以前ほど厳密ではありません。最近では、Ksh、Zsh、およびBashにはすべて型変数があります。シェル関数定義もエクスポートできます。

プレーンシェル変数とは別の環境を使用するには、fork/execすべてのUnixが使用する新しいプロセスを開始する方法が必要です。いつexport名前/値のペア、その名前/値のペアを持つシェルによって開始された新しい実行ファイルの環境中に存在するであろうexecve(2)(通常は、以下のシステムコールfork(2)場合を除いて、execシェルコマンドを使用しました)。

に続いてexecve()main()新しいバイナリの関数には、コマンドライン引数、環境(var=value文字列へのポインターのNULL終了配列として格納されます。man environ(7)ページを参照)があります。継承されるその他の状態には、ulimit設定、現在の作業ディレクトリ、およびexecve()呼び出し側がFD_CLOEXECを設定していないオープンファイル記述子が含まれます。ttyの現在の状態(エコー有効、rawモードなど)は、新しく作成されたexecプロセスに継承された実行状態の一部と見なすこともできます。

簡単なコマンド(組み込み関数またはシェル関数以外)bashについては、実行環境に関するマニュアルの説明を参照してください。

Unix環境は、少なくとも他のいくつかのオペレーティングシステムとは異なります。VMSの「字句」は、子プロセスによって変更でき、その変更は親で確認できます。cd子プロセスのVMS は、親の作業ディレクトリに影響します。少なくともいくつかの状況では、私の記憶は私を失敗させているかもしれません。

いくつかの環境変数は、よく知られており$HOME$PATH$LD_LIBRARY_PATHなど。一部は特定のプログラミングシステムに慣習的であるため、親シェルは、特定の一時ディレクトリ、またはに表示されないユーザーIDとパスワードなど、多くの特別な目的の情報をプログラムに渡すことができますps -ef。単純なCGIプログラムは、たとえば環境変数を介してWebサーバーから多くの情報を継承します。


1
まだ少し複雑に思えます。bashでは、少なくともSOME_NAME=value commandそのコマンド呼び出しのSOME_NAME環境変数を設定します。紛らわしいことに、同じ名前のシェル変数を設定していないようです。
サミュエルエドウィン区

2
より正確には、環境変数は継承されず、シェルから生成されたプログラムに明示的に渡されます。
msw

2
@SamuelEdwinWardがSOME_NAME=value command期待に反して振る舞う理由は、「コマンドに渡される環境にSOME_NAMEを追加するが、このシェルの変数を変更しない」ことを意味する特別な構文であるためです。
msw

1
魅力的な、ラムダ計算/関数型プログラミングへのリンク。それは非常に理にかなっている興味深いつながりです。
マット

1
これのいくつかはまったく正しくありません。例えば、サブシェルは、サブプロセスであり、でなければならないfork()編が、彼らはやるシェル変数(のコピー)を受け取ります。
ruakh

7

最も生の形式の環境変数は、名前/値のペアのセットです。man 1 bash環境セクションのbashのマニュアルページ()で説明されているように:

   When  a  program  is invoked it is given an array of strings called the
   environment.   This  is  a  list  of  name-value  pairs,  of  the  form
   name=value.

   The  shell  provides  several  ways  to manipulate the environment.  On
   invocation, the shell scans its own environment and creates a parameter
   for  each name found, automatically marking it for export to child pro-
   cesses.  Executed commands inherit the  environment.

実際的には、現在のシェルから呼び出されたプログラムに共有または固有の動作を定義できます。たとえば、使用する場合、crontabまたは環境変数を定義して、システムがデフォルトで使用するエディター以外の別のエディターを定義するvisudoことができEDITORます。同じことがmanPAGER環境を調べてマニュアルページの出力を表示するために使用するページャープログラムを決定するコマンドなどの場合にも当てはまります。

多くのUNIXコマンドが環境を読み取り、そこに設定されている内容に応じて、これらに応じて出力/処理/アクションを変更します。一部は共有され、一部はプログラムに固有です。ほとんどのマニュアルページには、環境変数が説明されているプログラムにどのように影響するかに関する情報が含まれています。

他の実用的な図は、同じプラットフォーム上に複数のOracleがインストールされているシステムなどのものです。を設定することによりORACLE_HOME、(PATH環境変数からロードされた)oracleコマンドのスイート全体が、その最上位ディレクトリの下から設定、定義、マッピング、およびライブラリを取得します。JAVA_HOME環境変数を使用したjavaなどの他のプログラムにも同じことが当てはまります。

bashの自体は、多くの歴史から物事の範囲の動作を変更することができ、環境変数(持っているHISTSIZEHISTFILEなど)、画面サイズ(COLUMNS)、タブ補完(FIGNOREGLOBIGNORE)ロケールと文字エンコーディング/デコーディングを(LANGLC_*)(、プロンプトPS1... PS4)、およびなど(再度bashのマニュアルページから知識を求めます)。

また、独自のカスタム環境変数を使用するスクリプト/プログラムを作成することもできます(設定を渡す、または機能を変更するため)。


0

「環境変数」は、実行中のプロセスがコンピューター上で動作する方法に影響を与える可能性がある動的な名前付きの値のセットです。

これらは、プロセスが実行されるオペレーティング環境の一部です。たとえば、実行中のプロセスは、TEMP環境変数の値を照会して一時ファイルを保存する適切な場所を見つけたり、HOMEまたはUSERPROFILE変数を呼び出してプロセスを実行しているユーザーが所有するディレクトリ構造を見つけたりできます。

詳細はこちら→ http://en.wikipedia.org/wiki/Environment_variable

環境変数について知りたいことすべて...↑


1
このリンクがなくなることはまずありませんが、ここで質問に関連するテキストで回答し、バックアップ情報の追加としてリンクを提供することをお勧めします。
アントン

@Anthon私はあなたが正しいと信じています。できるだけ早く変更を行います...アドバイスをありがとう
...-SoCalDiegoRob

-1

この回答には、変数、値、変数置換、プロンプト、エコー、カーネル、シェル、ユーティリティ、セッション、プロセスという用語に関するシェルスクリプトの経験と知識が必要です。

環境変数(ENVAR)指定されたプロセスは、コンピュータのオペレーティングシステム上で動作します方法を行うことができるグローバル定義された変数の集合です。

1.模範的な紹介:

envarsをa $および大文字で置き換えます。例:$PS1

この方法でenvarを印刷できます。

echo $PS1

$PS1Unixプロンプトの値を保持します。そのネイティブの値はであるとし\u \w $ます。

  • \u (現在の)ユーザーを表し、
  • \w 作業ディレクトリを表し、
  • $ プロンプトの境界を定めることです。

だから、私たちがしなければ:echo $PS1、我々はの値を参照してください\u\wプラス最後にドル記号。

そのenvarの値を変更すると、そのコンテキストでUnixの動作を変更できます。例えば:

PS1="\w >"

プロンプトは次のようになります(作業ディレクトリの名前が「John」であると仮定):

John >

できることと同じ方法PS1="Hello, I'm your prompt >"で、以下echo $PS1をもたらします。

Hello, I'm your prompt >

Bash 4.xxでは、envコマンドを使用してシステム内のすべてのenvarを出力できます。envターミナルで実行することをお勧めし、出力を確認します。

2.これらのデータはどのように表示および操作されますか。

セッションのターミナルでは、Bashに付属するenvarをカスタマイズできます。

前述の変更は通常一時的なものであり、その理由は次のとおりです。

各セッション(サブセッションではない)は一意であり、複数のプロセスを同時に一意に実行できます(それぞれ独自の一連のenvarsを使用)が、通常はセッション0からセッション1以上に継承があります。

1つのプロセスに加えた変更はそのプロセスに固有のものであり、何らかの方法で保存せずに閉じた場合に停止します。

それでは、これらの変更をどのように保存できますか:

選択したスコープに応じて、envarの変更を保存する方法はいくつかあります。このような変更のさまざまなスコープ(レベル)は次のとおりです。

  • プロセスレベル:envarは、現在のセッションのプログラムでのみ使用できます。
  • エクスポートレベル:envarは、現在のセッションまたはそのすべてのサブセッションのプログラムで使用できます。
  • グローバルレベル:変更はすべてのセッション(プライマリおよびすべてのサブ)で保存されます。

envarデータの保存場所:

Unixは、カーネル、シェル、ユーティリティの3つの主要な層で構成されています。私の知る限り、各シェルには独自のエンバーがあり、これらは主にまたは排他的にシェル内に構築されます。

これらをグローバルに変更する特定の場所は通常/etc/profileですが.bashrc、もちろんそれもできます。

3.新しいenvarの作成:

新しいenvarを作成できます。ここに方法があります。Bash 4.xxの時点では、ネイティブenavarという名前はありませんMESSAGE(前述のとおり、envarは通常大文字です)。

MESSAGE="Hello world!"

これを作成して、echo $MESSAGEと入力するとが得られhello world!ます。

bash現在の作業セッション(ウィンドウ)で実行する場合、新しいbashサブセッションを開始し、実行しない限り、元のプロセスでは動作しなくなりexitます。

注:ターミナルエミュレーターを備えたオペレーティングシステム(Ubuntuデスクトップなど)では、サブセッションは通常同じウィンドウで実行されますが、別のウィンドウの新しいセッションは既存のサブセッションではありません(隣接するプロセスです) 。

注:envar値に!などの特別な記号を使用しないでください。または保存されません。

元のセッションからすべてのサブセッションに環境変数をエクスポートします。

最初のセッションで作成されたenvarは、ユーザーレベルまたはグローバルレベルのconfファイルに登録せずに、2番目のセッションでも使用できます(次のデータを参照)。その方法は次のとおりです。

元のセッション(現在のウィンドウまたは別のウィンドウ)に移動して、次を実行します。

export MESSAGE

エクスポートするときは、$記号を使用しないでください。

現在、すべてのサブセッションにエクスポートされています。echo $MESSAGEサブセッションで行う場合は、ユーザーからでも別からでも、印刷されます。

などのシェル内部変数PS1はエクスポートしないでくださいが、何らかの理由でそれらをエクスポートしたいが表示されない場合は、bashexportに実行せず、むしろを実行してくださいbash –norc

4. $ PATH環境変数:

$PATH ユーザーが通常最も変更する環境変数です。

の場合echo $PATH、このストリームが表示されます。

/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games

このenvarの出力値はコロン(:)で区切られていますが、より快適な方法があります(これらは同じ値です)。

/usr/local/bin
/usr/bin
/bin
/usr/local/games
/usr/games

これらは、ユーティリティを実行するときに検索するディレクトリです。

実行which echoすることで、ファイルの場所を取得します/bin/echo。たとえば、に存在することがわかります。

それに基づいて、echo envarと入力してevnarの値を表示する必要はありません。次のこともできます。

/bin/echo $ENVAR

envarは引き続き実行されます。例:

/bin/echo $HOME

私たちに与えます

/home/User || /root

同じように:

echo $HOME

私たちに与えます

/home/User || /root

注:$HOMEはと略され~ます。

system- $ PATH関係、および可能なユーザーインタラクション:

Bash 4.xxでは、フルパスなしでユーティリティを使用すると、システムは上記の6つの値すべてを使用します$PATH。したがって、それはから始まり、/user/local/binすべてのコンテンツに従ってecho実行可能ファイルを探します。

この場合、で停止し/bin/echoます。この場合、実行可能ファイルが存在します。

したがって、$PATHenvarをカスタマイズする主な理由は、ネイティブ値のいずれにも属さない実行可能ファイルをインストールすることです。

そのような実行可能ファイルをインストールした後$PATH、それに応じて値を設定する必要があります。そうすれば、それらのファイルを操作できるようになります。

5.付録-展開$PATH

次の方法でexport $PATH、サブセッション(WordPressのWP-CLIやDrupalのDrushなどのbash拡張機能を含む)をbash できます。

export PATH="/home/John:$PATH"

これにより、に新しい値が追加さ/home/John$PATH、その後すぐに、ネイティブ値(コロンの直後)が付加されます$PATH。これらは構文の下に格納されます。

このような永続的な変更は、関連するスクリプトで、通常/etc/profile、名前の下に名前で行うことができます.bashrc


3
この回答に!は非常に多くの間違いがあります:セッションとプロセスの融合、動作を示す例のすぐ下にある環境変数値の動作に関する警告、サブセッションの誤った概念、何をすべきかについての非常に奇妙なアドバイスシェル変数とグローバル環境変数の誤った概念をエクスポートした後。
JdeBP

warning about ! in an environment variable value not working that is right below an example showing it working?例としてください。
-JohnDoea

quite bizarre advice about what to do after exporting a shell variable、正確にはどういう意味ですか?
-JohnDoea

false notion of global environment variables、正確にはどういう意味ですか?
ジョンドエア
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.