シェル環境変数 - export・env・.bashrc・.bash_profile
この記事で達成できること
- シェル変数と環境変数の違いを子プロセス継承の観点で説明できる
exportがなぜ必要かを正確に理解できる- ログインシェルと非ログインシェルの起動ファイル読み込み順序を説明できる
.bashrcと.bash_profileを用途に応じて正しく使い分けられる- 設定変更が反映されない原因を特定できる
LPIC-1 主題 105.1「シェル環境のカスタマイズと使用」の中核。環境変数の継承モデルと起動ファイルの読み込み順序が要点。
シェル変数と環境変数の判断
| 観点 | シェル変数 | 環境変数 |
|---|---|---|
| 設定方法 | VAR=value |
export VAR=value |
| 子プロセスへの継承 | されない | される |
| 一覧表示 | set |
env / printenv |
| 用途 | 現在のシェル内の一時値 | 子プロセスに渡す設定(PATH 等) |
子プロセス(実行したコマンド・スクリプト)に値を渡す必要があるなら export で環境変数にする。シェル内だけの一時計算ならシェル変数で十分。
起動ファイルの読み込み順序
| シェル種別 | 読み込まれるファイル |
|---|---|
| ログインシェル | /etc/profile → ~/.bash_profile(なければ ~/.bash_login → ~/.profile) |
| 非ログイン対話シェル | /etc/bash.bashrc → ~/.bashrc |
| 非対話シェル(スクリプト) | $BASH_ENV が指すファイル(通常なし) |
慣例として ~/.bash_profile 内で ~/.bashrc を source し、設定を ~/.bashrc に集約するのが定石。これを知らないと「SSH ログインでは反映されるが端末を開くと反映されない(またはその逆)」を説明できない。
手順
Step 1: シェル変数を設定し継承を確認する
MYVAR=hello echo $MYVAR bash -c 'echo "child sees: $MYVAR"'
hello child sees:
MYVAR はシェル変数なので子プロセス(bash -c)には継承されず空になる。これが環境変数との決定的な違い。
Step 2: export で環境変数に昇格する
export MYVAR bash -c 'echo "child sees: $MYVAR"' export GREETING=hi env | grep GREETING
child sees: hello GREETING=hi
export でシェル変数を環境変数に昇格すると子プロセスに継承される。export VAR=value で設定と昇格を同時に行える。
Step 3: 変数一覧を確認する
set | grep MYVAR env | grep MYVAR printenv PATH
MYVAR=hello MYVAR=hello /usr/local/bin:/usr/bin:/bin
set はシェル変数を含む全変数、env(printenv)は環境変数のみを表示する。両方に出るなら export 済み、set にだけ出るならシェル変数のまま。
Step 4: 起動ファイルを編集して反映する
echo 'export EDITOR=vim' >> ~/.bashrc echo "alias ll='ls -alF'" >> ~/.bashrc source ~/.bashrc echo $EDITOR
vim
.bashrc への追記は新規シェルから有効になる。現在のシェルに即座に反映するには source ~/.bashrc(. ~/.bashrc と等価)を実行する。
Step 5: 変数を削除する
unset MYVAR echo "[$MYVAR]" unalias ll
[]
unset は変数を削除する。エイリアスは unalias で解除する。一時的に環境変数なしでコマンドを実行するには env -u VAR command も使える。
なぜ export が必要なのか
Linux のプロセスは fork + exec で子プロセスを生成する。このとき親プロセスの「環境(environment)」だけが子にコピーされ、シェル変数は子のメモリ空間に渡されない。export は変数に「環境としてエクスポートする」属性を付与する操作であり、これにより exec 時に子プロセスの環境に含まれるようになる。
PATH や LANG が子プロセスでも有効なのは、それらがログイン時に export 済みの環境変数だから。逆に export していないシェル変数をスクリプトから参照できないのは、スクリプトが子プロセスとして起動され環境を継承するこのモデルが原因。継承は親→子の一方向で、子で変更した環境変数が親に戻ることはない。
トラブルシューティング
症状: .bashrc の変更が SSH ログインで反映されない
原因: SSH ログインはログインシェルで、~/.bashrc ではなく ~/.bash_profile が読まれる
確認:
grep bashrc ~/.bash_profile
対処: ~/.bash_profile に [ -f ~/.bashrc ] && . ~/.bashrc を追加し、設定を ~/.bashrc に集約する。
症状: スクリプトから変数が見えない
原因: シェル変数のまま export していない
確認:
export -p | grep VAR
対処: 子プロセス(スクリプト)に渡す変数は export VAR で環境変数に昇格する。
症状: source せず変数が反映されない
原因: 起動ファイルへの追記は新規シェルからしか有効にならない
確認:
echo $EDITOR
対処: 現在のシェルに即時反映するには source ~/.bashrc を実行する。新しい端末を開いても反映される。
作業完了チェックリスト
- [ ] シェル変数が子プロセスに継承されないことを確認した
- [ ]
export後に子プロセスへ継承されることを確認した - [ ]
setとenvの表示差を確認した - [ ]
.bashrcを編集しsourceで即時反映した - [ ]
unsetで変数を削除した
まとめ
| 場面 | コマンド | 目的 |
|---|---|---|
| シェル変数 | VAR=value |
現在のシェル内の一時値 |
| 環境変数昇格 | export VAR |
子プロセスへ継承 |
| 一覧(環境) | env / printenv |
環境変数の確認 |
| 一覧(全体) | set |
シェル変数も含む |
| 即時反映 | source ~/.bashrc |
起動ファイル再読込 |
環境変数モデルはプロセス継承の理解に直結する。次はプロセス優先度の制御に進むと運用知識が連結する。