はじめに
プログラムでは、ホームディレクトリ、言語、検索パス、アプリケーション設定など、小さな設定値が必要になることがあります。Linux のプロセスは、これらの値の多くを、名前付き文字列の集合である 環境 から受け取ります。
この実験では、環境変数の仕組みを段階的に学びます。まず、現在のシェルだけに属する変数を作成します。次に、変数を子プロセスへエクスポートし、標準変数を確認し、PATH を拡張して、今後の Zsh セッションにも設定が反映されるようにします。各ステップでは、シェルが実際に行った処理を確認できるファイルやコマンド結果を残します。
シェル変数を作成して展開する
このステップでは、シェル変数を作成し、引用符が展開に与える影響を確認します。
シェル変数は、現在のシェル内で名前と値を組み合わせたものです。代入時、= の前後にスペースは入れません。値を引用符で囲むと、値に含まれるスペースを保持できます。
cd /home/labex/project/environment-lab
course_name="Linux for Noobs"
名前の先頭に $ を付けると、シェルはその名前を値に 展開 します。
echo "$course_name"
ダブルクォートでは変数が展開され、展開結果全体が 1 つの引数として扱われます。シングルクォートではドル記号がそのまま文字として扱われます。次のコマンドで違いを比較してください。
printf 'double: %s\n' "$course_name"
printf 'single: %s\n' '$course_name'
展開された値をファイルに保存し、結果を確認します。
printf 'course=%s\n' "$course_name" > shell-variable.txt
cat shell-variable.txt
この変数は、エクスポートしない限り現在のシェルにだけ存在します。
子プロセスへの継承を確認する
このステップでは、通常のシェル変数とエクスポートされた変数を、子プロセス内で比較します。
すべてのコマンドはプロセス内で実行されます。子プロセスは親プロセスからエクスポートされた環境変数を受け取りますが、通常のシェル変数は受け取りません。
ワークスペースに戻り、それぞれの種類の変数を 1 つずつ作成します。
cd /home/labex/project/environment-lab
local_message="visible only in this shell"
export SHARED_MESSAGE="visible in child processes"
2 つの変数名を表示する小さな Bash の子プロセスを作成します。引用符付きの heredoc マーカーにより、スクリプトを書き込むときに現在のシェルが変数を展開しないようにします。
cat > inspect-child.sh <<'EOF'
#!/bin/bash
printf 'local=%s\n' "${local_message:-<missing>}"
printf 'shared=%s\n' "${SHARED_MESSAGE:-<missing>}"
EOF
chmod +x inspect-child.sh
スクリプトを実行して出力をファイルにリダイレクトし、その後ファイルを表示します。コマンドを分けることで、どの操作が子プロセスを実行し、どの操作が保存した結果を確認しているのかが明確になります。
./inspect-child.sh > child-environment.txt
cat child-environment.txt
通常の変数は <missing> と表示され、SHARED_MESSAGE は継承されます。エクスポートした名前が環境に存在することも確認してください。
env | grep '^SHARED_MESSAGE='
標準環境変数を確認する
このステップでは、アカウント、作業ディレクトリ、ターミナル、コマンド検索パスを示す標準変数を確認します。
Linux のシェルには、通常、次のような便利な標準変数が用意されています。
HOMEはホームディレクトリです。USERはアカウント名です。SHELLは設定されているログインシェルです。PWDは現在の作業ディレクトリを示します。PATHは、コロンで区切られたコマンド検索用ディレクトリの一覧です。TERMは、対話型プログラムに対してターミナルの機能を示します。
エクスポートされた変数を名前で読み取る printenv を使って、指定した値を表示します。
printenv HOME USER SHELL PWD TERM
PATH は、1 行に 1 つのエントリとして表示すると読みやすくなります。値を tr に渡し、すべてのコロンを改行に置き換えます。
printf '%s\n' "$PATH" | tr ':' '\n'
この実験で値が決まっている変数から、確認しやすいレポートを作成します。
cd /home/labex/project/environment-lab
printf 'HOME=%s\nUSER=%s\n' "$HOME" "$USER" > standard-environment.txt
cat standard-environment.txt
個人用コマンドを PATH に追加する
このステップでは、個人用の実行ファイルディレクトリを PATH に追加し、別のディレクトリから名前だけでコマンドを実行します。
スラッシュを含まないコマンドを入力すると、シェルは PATH に記載されたディレクトリを左から右へ検索します。既存の検索パスを置き換えずに、個人用の実行ファイルディレクトリを追加できます。
course-status という名前のコマンドを作成します。
mkdir -p "$HOME/bin"
cat > "$HOME/bin/course-status" <<'EOF'
#!/bin/bash
echo "Linux learning environment is ready"
EOF
chmod +x "$HOME/bin/course-status"
ディレクトリを現在の PATH に追加します。$PATH を残すことで、標準コマンドへのアクセスを維持できます。
export PATH="$PATH:$HOME/bin"
シェルが実行するファイルを確認してから、別のディレクトリへ移動してコマンドを実行します。
command -v course-status
cd /tmp
course-status
実行結果を実験のワークスペースに保存します。
course-status > /home/labex/project/environment-lab/path-command.txt
今後の Zsh セッション用に設定を永続化する
このステップでは、今後の Zsh セッションを設定し、永続的な設定と現在のシェルの状態の違いを確認します。
export は現在のプロセスと、そのプロセスから起動する今後の子プロセスを変更しますが、設定ファイルは編集しません。後から開いたターミナルにも設定を反映するには、スタートアップファイルで設定を再作成する必要があります。LabEx Terminal は Zsh を使用しており、対話型のスタートアップファイルは ~/.zshrc です。
目印を付けたブロックを追加します。新しい対話型 Zsh が起動するたびに、各 export 行が環境設定を 1 つずつ再作成します。この初心者向けの例では、スタートアップファイルを意図的に単純にしています。既存の PATH を維持し、その末尾に個人用ディレクトリを追加します。
cat >> "$HOME/.zshrc" <<'EOF'
## LABEX_ENV_LAB_START
export PROJECT_DIR="$HOME/project"
export PATH="$PATH:$HOME/bin"
## LABEX_ENV_LAB_END
EOF
source コマンドは、指定したファイルを現在のシェルで読み込みます。Terminal を閉じずに設定を使えるよう、今すぐ .zshrc を再読み込みします。
source "$HOME/.zshrc"
再読み込みした変数が利用できることを確認します。
printf 'PROJECT_DIR=%s\n' "$PROJECT_DIR"
PROJECT_DIR=/home/labex/project と表示されるはずです。新しい Zsh プロセスを起動して、今後のセッションでも同じ設定が読み込まれることを確認することもできます。zsh -ic では、-i が .zshrc を読み込む対話型シェルを要求し、-c がそのシェルで実行するコマンドを指定します。2 行の出力を future-shell.txt にリダイレクトしてから、ファイルを確認します。
zsh -ic 'printf "PROJECT_DIR=%s\n" "$PROJECT_DIR"; command -v course-status' > /home/labex/project/environment-lab/future-shell.txt
cat /home/labex/project/environment-lab/future-shell.txt
1 行目には /home/labex/project、2 行目には /home/labex/bin/course-status と表示されるはずです。
最後に、現在の状態と永続的な設定の違いを確認します。一時的な環境変数を作成して削除してください。
export TEMP_NOTE="remove me"
printenv TEMP_NOTE
unset TEMP_NOTE
printenv TEMP_NOTE
最後の printenv は、名前が存在しなくなったため何も出力せず、ゼロ以外のステータスを返します。unset は、現在のシェルからその名前を削除します。スタートアップファイルにその名前の定義が残っている場合は、設定行を削除するまで、今後のシェルでその変数が再作成されます。
まとめ
混同されやすい 3 つの仕組みを確認しました。シェル変数は 1 つのシェルに属し、export は値を子プロセスへ渡し、スタートアップファイルは今後のシェルで設定を再作成します。また、標準環境変数を確認し、既存のエントリを失わずに PATH を拡張し、コマンド検索を検証し、unset で一時的な状態を削除しました。



