envとprintenvは、どの環境/シェル変数を示しています。

envとprintenvは、どの環境/シェル変数を示しています。

私は以下の関連質問を見ました。これしかし、彼らは私の質問に対する正確な答えを提供していません

私の実験でもこの回答printenvほぼenv同じシステム変数のセットを表示します。

変数を次に設定すると

  1. /etc/bash.bashrc (システム全体のシステム変数でなければなりません)

    SYSTEM_ENVI=1000
    
  2. ~/.bashrc(ユーザー固有のシステム変数に使用する必要があります)

    USER_ENVI=10
    

/etc/environment が適用されるようにログアウトしてログインすることもありました。次のシナリオが発生します。

$echo $SYSTEM_ENVI
//outputs 1000
$echo $USER_ENVI
//outputs 10
$CURR_ENVI=1
$env | grep USER_ENVI
//nothing shows up, the same if I grepped SYSTEM_ENVI or CURR_ENVI
$set | grep USER_ENVI
//shows up USER_ENVI assignment, the same if I grepped SYSTEM_ENVI or CURR_ENVI

私の質問は次のとおりです

  1. printenvどのシステム変数が実行/印刷されますかenv
  2. 代わりに、setアクセス可能なすべての変数(システム変数とローカル変数)を使用する必要がありますか?printenvenv

繰り返さない理由

私の場合、この質問と示された答えは次の事実を理解するのに役立ちました。

  1. シェル変数は環境変数ではありません
  2. 仕事/etc/bash.bashrcまたは~/.bashrc環境変数を作成するのではなく、対話型の非ログインシェルプロセスにこれらの変数を作成して初期化するように指示します。シェル変数スタートアップについて。

私の質問は必ずしも以下に関連しているとは思わない。これしかし、この質問に示されている回答を読むことは、この記事に記載されている回答ほど満足できませんでした。

答え1

envそして、printenvそれを実行するコマンドによって提供される環境文字列のリスト(環境変数定義を含むことを意図しています)を印刷します。呼び出し側は最終的に次のことを行います。

execve("/usr/bin/env", argv, envp);

argvここで、envpとは2つの文字列のリストであるシステムコールです。

env/printenvの文字列のリストだけを1行envpに1つずつ印刷します。

慣例により、 の文字列はenvp形式になっていますが、var=value必ずしもそうする必要はなく(execve()これを強制する実装についてはわかりません)、ほとんどのenv実装ではprintenv文字列をいつ表示するか気にしません。

呼び出し元がPOSIXシェルの場合は、表示されたシェルenvpに渡された変数のリストに含まれます。env出口(ユーザーがexport/を呼び出しtypeset -xたとき、または変数がシェルの起動時に受信した環境にすでに存在するため)。

起動時にシェルが受信した一部の環境変数をシェル変数にマップできない場合envp、または受信した文字列に=文字が含まれていない場合、シェルの実装によっては、これらの文字列は影響を受けずに渡されます。それ以外の場合、シェルはその文字列をGoから削除します。またはそれらのいくつか。

たとえばbash、GNUを使用すると、任意envの変数名のリストを渡すことができます(envただし、任意のenvp文字列は許可されず、aを含める必要があり、=使用された文字列は1で始まる変数をsetenv()渡すことはできません=)。

$ env -i '=foo' '1=x' '+=y' bash -c printenv
+=y
1=x
[...]

(名前が空の変数は削除されますが、他の変数は削除されません。)

また、シェルがenvp同じ変数名に対して複数の文字列を受け取ると、シェルに応じてすべてが渡されます。最初の文字列のみが渡され、最後の文字列のみが渡されます。

setエクスポートを表示するかどうかに関係なく、配列/ハッシュ型をサポートするシェルのビスカラー変数を含む、POSIXシェルのシェル変数のリストを印刷します。

POSIXシェルでは、それを使用してエクスポート用にマークされたexport -p変数を一覧表示することもできます。env/とは異なり、エクスポートされたとしてマークさprintenvれているがまだ値が割り当てられていない変数も一覧表示されます。

あるいはksh、などのKorn様シェルでを使用して、変数属性を含む追加情報を取得し、型別に変数を一覧表示することもできます(配列変数のリストなど)。zshbashtypesettypeset -a

ここでは、USER_ENVI=10次を追加して、~/.bashrcシェルの対話型非ログイン呼び出しをbash構成できます。USER_ENVI シェル起動時の変数。使用していないため、export変数はまだシェル変数であるため(起動時に環境にない限りbash)、次のように使用されません。環境このシェルで実行されるコマンドの変数です。

/etc/environmentUbuntu 16.04のプラグイン認証モジュールからデフォルトで読み取られますpam_env.so。ログインアプリケーション(たとえばlogin、、、、、sshd)はlightdmこれらのファイルを読み込みます(そのファイルを使用しpam_env.soて転送するように設定されている場合)。/etc/pam.d環境変数(ここではシェル変数とは関係ありません)は、認証後にユーザー名で実行されるコマンド(たとえば、login/のログインシェルsshdまたは...のグラフィカルセッションマネージャlightdm)です。

環境はデフォルトで継承されるため、セッションマネージャがターミナルエミュレータを実行すると(ログインシェルが実行される)、これらの環境変数は各ステップで渡され、シェルは拡張可能なシェル変数にマップされます。のようなコマンドと一致しますecho "$VAR"

pam_envenvファイルは/etc/environmentシェルスクリプトのように見えますが、pam_envそれを解析するためにシェルは呼び出されず、シェル構文のサブセットだけが理解され、名前が1つ以上のASCII英数字または下線で構成される変数の定義のみを受け入れます。123有効なPOSIXシェル変数名でなくても、変数を定義できます。


1. 任意の環境文字列のリストを渡すには、execve()次のように直接呼び出すこともできます。

perl -e 'require "syscall.ph";
         $cmd = "/bin/zsh";
         $args = pack("p*x[p]", "sh", "-c", "printenv");
         $env = pack("p*x[p]", "a=b", "a=c", "", "+=+", "=foo", "bar");
         syscall(SYS_execve(), $cmd, $args, $env)'

zsh代わりにここでテストしてください。bash

答え2

以下を実行してください。

USER_ENVI=10

変数を設定していますが、環境変数は設定しません。これを行うには、次のものが必要です。

export USER_ENVI=10

または

USER_ENVI=10; export USER_ENVI

それは合理的です。これはあなたには効果がありません:

$ env | grep SYSTEM_ENVI

setという環境変数はありませんSYSTEM_ENVI/etc/environmentあなたはコンテンツを公開しておらず、使用しないように見えるので、これについては申し上げません。

env印刷する内容を正確に印刷しますprintenv(オプションなし)。

答え:

  1. envとprintenvはどちらも、実際に設定されたものとまったく同じ変数のリストを報告します。投資ファンドコマンドの後にオプションや変数のリストはありません。

  2. set(オプションなし)を使用すると、すべての変数セットを表示できます。これはあなたを意味しません〜しなければならないそれを書いてください。それはあなたがリストしたいものに依存します。環境変数のリストを作成するだけで完全に有効で正確です。

関連情報