Linuxにおける環境変数のエクスポート方法と応用

Bashではexport NAME=valueで現在のシェル変数を「これから起動する子プロセスへ渡す」対象にします。親プロセス、すでに動いているプロセス、別端末へ逆向きには伝わりません。一コマンドだけならNAME=value commandとし、シェル全体を汚しません。値は引用し、printenv NAMEと子シェルで確認します。永続化は起動形態に合う設定ファイル/サービス定義で行い、PATHの空要素や書込可能ディレクトリ、LD_PRELOAD等の危険値、プロキシ資格情報、APIトークンを安易にexportしません。

目次

シェル変数と環境変数を区別する

NAME=valueは現在のBashにシェル変数を作ります。export NAMEまたはexport NAME=valueで、その後Bashが起動する外部コマンドの環境へ含めます。環境はname=value文字列の配列で、子は親のコピーを受け取ります。

子が値を変更しても親へ戻らず、既存子プロセスも更新されません。「exportしたのにGUIアプリが変わらない」場合、そのアプリがexport前から動いているか、別のセッションマネージャーから起動された可能性を確認します。

値を引用して一行で設定する

空白を含む値はexport APP_MODE="staging blue"、既存変数参照はexport LOG_DIR="$HOME/app logs"のように引用します。等号の前後へ空白を入れると代入ではなくコマンドとして解釈されます。変数名は一般に英字/アンダースコアで始め、大小を区別します。

値に改行を含めることは可能でも、ログ、設定ファイル、ツール間受渡しで壊れやすく、NULは環境文字列に含められません。複雑な構造はJSONファイル等の形式と権限を決め、環境変数に詰め込みません。

一コマンドだけの環境を優先する

APP_ENV=development ./run-testsはそのコマンドの環境だけへ値を渡します。複数ならLANG=C TZ=UTC commandのように前置きします。テストや一時オプションに適し、後続コマンドへ残しません。実行後に現在シェルの値が変わっていないことを確認します。

関数呼出し前の代入はBashで関数内とその子へ見えるなど外部コマンドと細部が違います。再現可能な運用スクリプトでは環境を明示的に構築し、暗黙の対話設定へ依存しません。

表示は対象名だけに限定する

現在の値はprintf '%s\n' "$APP_ENV"、export済みかはexport -pやprintenv APP_ENVで確認します。子プロセス確認はbash -c 'printenv APP_ENV'です。未設定と空文字は異なる場合があるため[[ -v APP_ENV ]]等で区別します。

envやexport -p全量をCIログ/チケットへ貼ると、トークン、Cookie、内部パスが漏れます。必要な名前だけを出し、値を共有する必要がなければ設定有無や長さだけを記録します。

export解除と変数削除を区別する

export -n NAMEはexport属性を外し、Bash内の値は残します。unset NAMEは変数を削除します。NAME=は空文字として設定された状態で、未設定とは違います。アプリの仕様が未設定/空をどう扱うか確認して使い分けます。

readonly変数や特殊変数は解除できない/影響が大きい場合があります。環境クリーンアップを目的に名前パターンで大量unsetせず、変更した正確な名前だけを戻します。

PATHは空要素と優先順位を防ぐ

PATHはコロン区切りで先頭から検索します。空要素(先頭/末尾コロンや::)は現在ディレクトリを意味する旧動作があり危険です。追加先を確認し、例はnew=/opt/myapp/bin; export PATH="$new${PATH:+:$PATH}"です。既存PATHが空でも末尾コロンを作りません。

同じディレクトリを重複追加せず、rootやサービスのPATH先頭へ一般ユーザー書込可能場所を置きません。type -a commandで解決先を確認し、設定前後を記録します。相対パスや.をPATHへ入れません。

ロケールは存在確認して段階設定する

利用可能ロケールをlocale -aで確認してからexport LANG=ja_JP.UTF-8等を設定します。LANGは既定、各LC_*がカテゴリ別に上書きし、LC_ALLは全カテゴリを強制的に上書きします。通常運用でLC_ALLを永続化すると個別設定を無効にするため慎重にします。

ロケールはsort順、grepの文字分類、数値/日時表示、エラーメッセージへ影響します。自動処理でC/UTCが必要なら一コマンドだけへ指定し、ユーザー全体の言語を変えません。

プロキシ変数はアプリ仕様を確認する

http_proxy、https_proxy、no_proxyや大文字版の対応はアプリごとに異なります。URL、スキーム、ポート、除外書式を公式資料で確認し、シェル全体へ広げる前に一コマンドで試します。

http://user:password@proxyのような資格情報入り値をexportすると、子、診断、履歴、クラッシュ情報へ広がります。認証は資格情報ストア、エージェント、保護ファイル等の対応方式を使います。

秘密を環境へ常駐させない

環境変数は子プロセスへ複製され、同一ユーザーや管理者の診断、/proc、コアダンプ、ログに現れ得ます。APIトークンや秘密鍵を対話シェルで長時間exportせず、秘密管理サービス、権限制御されたファイル、標準入力/ファイル記述子などアプリ対応方式を優先します。

やむを得ない場合も一コマンドだけ、最小権限/短寿命の秘密、ログ抑止、終了後unset、失効手順を用意します。値をコマンドライン引数やコメントへ移しても安全にはなりません。

永続化先を起動主体に合わせる

対話非ログインBashなら~/.bashrc、ログインBashならprofile系ですが、通常は役割を分けます。systemdサービス、cron、コンテナ、GUIはこれらを読まない/異なる場合があり、ユニットのEnvironment/EnvironmentFile、ジョブ定義、コンテナ設定など管理主体の仕組みを使います。

/etc/environmentは多くの環境でPAMが処理するname=valueファイルで、Bashスクリプトとは限りません。exportや$PATH展開を当然視せず、OSのPAM/セッション仕様を確認します。全ユーザー変更は管理者レビューと段階展開を行います。

BASH_ENVとローダー変数を信頼境界として扱う

非対話BashはBASH_ENVが指すファイルを読みます。攻撃者が値やファイルを変更できる環境で設定すると、スクリプト起動時にコードが実行されます。LD_PRELOAD、LD_LIBRARY_PATH、IFSなどもプログラム解決/解析を変え、man-pagesは異常値によるセキュリティリスクを警告しています。

特権処理は信頼済みの最小環境を構築し、不要変数を継承しません。ただしenv -iで全削除するとHOME、PATH、ロケール、証明書パス等も消えるため、必要値を明示したテストから始めます。

現在・子・新規セッションで検証して戻す

設定直後に現在シェル、bash -cの子、対象アプリで値を確認します。永続化した場合はbash -n後に新しい端末/ログインで確認し、既存セッションと差を記録します。設定ファイルをsourceして途中失敗すると一部だけ残るため、最初は新規シェルで試します。

ロールバックは追加した行とexport属性/値を変更前へ戻し、新規セッションと対象アプリを再起動して確認します。PATH全体、環境全体を空にせず、変更した変数だけを戻します。

確認チェックリスト

  • exportが将来の子へ渡り親/既存プロセスへ戻らないと理解した
  • 値と変数展開を引用した
  • 一時値はNAME=value commandへ限定した
  • 未設定・空・export -n・unsetを区別した
  • PATHの空要素/相対/書込可能場所/重複を除いた
  • ロケールとプロキシはアプリ/環境仕様を確認した
  • 秘密とBASH_ENV/LD_*を信頼境界として扱った
  • 適切な永続化先と現在/子/新規セッションを検証した

公式情報・参考資料

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次