export
の目的をここで読みました シェルでは、シェルから開始されたサブプロセスで変数を使用できるようにします。
ただし、こことここで、「プロセスは親(プロセスを開始したプロセス)から環境を継承する」ことも読みました。
この場合、なぜexport
が必要なのですか。 ?何が足りないのですか?
デフォルトでは、シェル変数は環境の一部ではありませんか?違いは何ですか?
承認された回答:
あなたの仮定は、シェル変数が環境内にあるということです。 。これは正しくありません。 export
コマンドは、環境内に存在する名前を定義するものです。したがって:
a=1 b=2
export b
結果は現在のシェルになります その$a
を知っている 1に展開され、$b
2になりますが、サブプロセスはa
について何も知りません。 これは環境の一部ではないためです(現在のシェルでも)。
いくつかの便利なツール:
set
:現在のシェルのパラメータを表示するのに便利です。エクスポートされているかどうか-
set -k
:割り当てられた引数を設定します 環境で。f() { set -k; env; }; f a=1
-
set -a
:環境に設定される名前を付けるようにシェルに指示します。export
を置くような すべての割り当ての前に。.env
に便利ですset -a; . .env; set +a
を設定します 。 export
:環境に名前を付けるようにシェルに指示します。エクスポートと割り当ては、まったく異なる2つの操作です。-
env
:外部コマンドとして、env
継承についてのみ伝えることができます したがって、環境は健全性チェックに役立ちます。 -
env -i
:サブプロセスを開始する前に環境をクリアするのに便利です。
export
の代替手段 :
-
name=val command
#コマンドの前に割り当てると、その名前がコマンドにエクスポートされます。 declare/local -x name
#名前をエクスポートします。名前をスコープ外に公開したくない場合にシェル関数で特に役立ちます。-
set -a
#次のすべての割り当てをエクスポートします。
モチベーション
では、なぜシェルは独自の変数と異なる環境を持つ必要があるのでしょうか。歴史的な理由はいくつかあると思いますが、主な理由はスコーピングだと思います。環境はサブプロセス用ですが、サブプロセスをフォークせずにシェルで実行できる操作はたくさんあります。ループするとします:
for i in {0..50}; do
somecommand
done
somecommand
のためにメモリを浪費する理由 i
を含める 、その環境を必要以上に大きくしますか?シェルで選択した変数名が、プログラムに意図されていない何かを意味している場合はどうなりますか? (私の個人的なお気に入りには、DEBUG
が含まれます およびVERBOSE
。これらの名前はどこでも使用されており、名前付けが適切に行われることはめったにありません。)
シェルでない場合の環境は何ですか?
Unixの動作を理解するには、カーネルやOSと対話するための基本的なAPIであるsyscallsを調べる必要がある場合があります。ここでは、exec
を見ています。 呼び出しのファミリー。これは、シェルがサブプロセスを作成するときに使用するものです。 exec(3)
のマンページからの引用です。 (私の強調):
execle()
およびexecvpe()
関数を使用すると、呼び出し元は引数envpを介して実行されたプログラムの環境を指定できます。 envp引数は、nullで終了する文字列へのポインタの配列であり、NULLポインタで終了する必要があります。 他の関数は、呼び出しプロセスの外部変数environから新しいプロセスイメージの環境を取得します。
したがって、export somename
と書く シェル内では、名前をグローバルディクショナリenviron
にコピーするのと同じです。 Cで。ただし、somename
を割り当てる エクスポートせずに、environ
にコピーせずに、Cで割り当てるのと同じようになります。 変数。