シェル変数と環境変数の違いとは
この記事では、シェル変数と環境変数の違いと、そもそもシェルとは何なのかについて
調べたことをまとめてみたいと思います。
シェルとは
コンピュータにはシステム全体を管理するソフトウェアであるOSがあり、そのOSの
中核にはOSの基本機能を担うソフトウェアであるカーネルがあります。しかし人間が
コンピュータを操作するときはカーネル等に直接指示を出すのではなく「シェル」と
呼ばれるソフトウェアを介してカーネル等に指示を出したり出力を受け取ったりします。
シェルはユーザにインターフェースを提供するプログラムであり、カーネルの周りを
まるで卵の殻のように包み込んでるイメージであることからshell(殻)と呼ばれています。
殊Linuxの場合、具体的にはコマンドラインインターフェースがシェルに該当します。
また、シェルにはいくつもの種類が存在しており、それぞれ様々な特性があります。
サーバにログインし、現在使用しているシェルを確認したい場合は
下記のようにコマンドを実行することで確認することができます。
現在、私はbashシェルを使用しているようです。
bashシェルを介してカーネルに指示を出したり出力を受けとったりしているんですね。他に使用可能なシェルを確認したい場合は下記のようにコマンドを実行することで確認することができます。
シェル変数とは
変数は文字列や数値を代入することができるものであり、よく箱などの入れ物に例え
られます。その中でもシェル変数とは「現在実行しているシェルでのみ有効な変数」
のことを指します。
現在、私の使用しているbashシェルのシェル変数の値は新しいbashを起動した際や
その他のrbashシェルなどを使用する際には引き継がれないということになります。
実際に検証してみます。
- まず初めに現在実行しているbashシェルのプロセスIDを確認してみます。
現在のシェルのプロセスIDは22421のようです。
- 続いてここでシェル変数を設定します。「シェル変数=値」で設定できます。
- 続いてbashコマンドで新しいbashを起動してみます。
- 何も変化がなく不安になりますが、再度bashシェルのプロセスIDを確認してみると現在のシェルのプロセスIDは22431となっており、先程とは別のbashシェルにいることが分かります。
- この新しいbashシェルで前のbashシェルで設定したシェル変数を確認すると、何も表示されないことが確認できます。
- では新しいbashシェルから抜けてみます。
- このままではどこにexitしたか分からないので、再度bashシェルのプロセスIDを確認してみると、プロセスIDは22421となっており最初のbashシェルに戻ってきたことが確認できます。
- ここで再度シェル変数を確認してみると問題なく表示されることが確認できます。
たしかにシェル変数は「現在実行しているシェルでのみ有効な変数」であることが確認できました。
ここで、シェルを移動しても同じ変数を使用したいケースが出てくるかと思いますが、
そのようなときに使用するのが「環境変数」です。
環境変数とは
環境変数は設定が削除されるまで「どのシェルでも利用できる変数」です。
シェル変数を export することで環境変数を設定することができます。
こちらも実際に検証してみます。
- まず初めに現在実行しているbashシェルのプロセスIDを確認してみます。
現在のシェルのプロセスIDは22444のようです。
- 次に現在設定されている環境変数を確認してみます。exportコマンドで確認
することが可能です。(環境変数が大量に表示されたためgrepで絞っています)
- 続いて環境変数を設定していきます。まずシェル変数を設定してからexportコマンドでシェル変数を指定してもよいのですが、シェル変数の設定をexportコマンドで指定することでシェル変数と環境変数を同時に一行で設定することができます。
- 再度exportコマンドを実行してみると、環境変数が正常に設定されていることが確認できます。
- ではbashコマンドで新しいbashを起動してみます。現在のシェルのプロセスIDは22460となっており、先程とは別のbashシェルにいることが分かります。
- ここで先程のシェルで設定した環境変数を確認してみると、新しいbashシェルでも変数を参照できていることが確認できます。
たしかに環境変数は「どのシェルでも利用できる変数」であることが確認できました。
今回はシェルがbashであったため、Bシェル系と呼ばれるシェルの変数の設定方法を
確認してきましたがcshやtcshなどのCシェル系のシェルは設定コマンドが異なります。
※しかしながらどちらの系統のシェルであってもシェル変数と環境変数の
参照は「set」コマンドを使用し、削除は「unset」コマンドを使用します。
変数の削除
先程設定した環境変数を削除してみます。
- unsetコマンドで$を付けずに変数を指定します。
- 変数が削除されたことを確認できました。
なお、ログアウトした場合はシェル変数・環境変数ともに上記のように明示的に削除
せずとも変数は消えます。ログアウトしても変数を維持したい場合は、ログイン時に
読み込まれる設定ファイルに設定を記述する必要があります。
環境変数の永続化
正確には永続化の設定ではなくログイン時に読み込まれるファイルにて都度
設定しているため永続化しているように見える設定といったものになります。
ログイン時に読み込まれるファイルにはいくつか種類があります。
読み込まれる順番 | ファイル | 説明 |
1 | /etc/profile | 全ユーザに適用される |
2 | ~/.bash_profile | ログイン時に一度だけ読み込まれる |
3 | ~/.bash_login | 2のファイルがない場合に読み込まれる |
4 | ~/.profile | 3のファイルがない場合に読み込まれる |
そして関連するファイルは他にも様々あります。
ファイル | 説明 |
~/.bashrc | bashを起動する都度読み込まれる |
~/.bash_logout | ログアウト時に読み込まれる |
/etc/bashrc | /etc/bashrc エイリアスの設定などが記載されている |
ここでは1番目に読み込まれる全ユーザに適用される設定ファイルではなく
ユーザのホームディレクトリ配下にあり、2番目に読み込まれる設定である
「~/.bash_profile」に環境変数を記述して事実上の永続化を試みてみます。
- ホームディレクトリを確認したところ当該ファイルが存在していませんでした。
(この場合、上記の表の4番目にある .profile が読み込まれることになります)
- 「~/.bash_profile」ファイルが無かったので作ってしまいます。
- ファイルに環境変数を記述します。
- 一度ログアウトして再度ログインします。
- 環境変数を確認してみると想定通り設定されていることが確認できました。
ログインする度に環境変数が設定されるようになり、これで環境変数の事実上の永続化
を実現することができました。
「su -」のハイフンの意味
Linuxサーバにて他のユーザにスイッチする場合は、「su - (他のユーザ名)」のコマンド
を実行することで他のユーザにスイッチすることができます。実はこの「- (ハイフン)」
はsuコマンドのオプションになっており、「シェルをログインシェルにする」といった
意味を持ちます。つまりスイッチした他のユーザのログインシェルでログインするため
他のユーザの環境変数を使用するといった意味になります。
この「- (ハイフン)」はオプションのため、「su (他のユーザ名)」でもスイッチは
可能ですがスイッチ前の現在のユーザの環境変数がスイッチ後も引き継がれます。
では実際に確認してみます。先程上記で設定した testuser の環境変数を引き継がない
ように「su - testuser」ではなく「su testuser」でログインしてみたいと思います。
- 現在の testuser で先程設定した環境変数を参照できることを確認します。
- 次にログアウトして「su testuser」でログインします。
- 再度 testuser で先程設定した環境変数を参照するも、testuserのログイン時に
読み込むファイルを読み込んでいないため、環境変数は表示されませんでした。
(プロンプトの表示もハイフンオプションを付けたときとは異なっていますね)
このsuコマンドはサーバで設定変更などの重要な作業する際や、障害調査でログを確認
する際などにルートの権限が必要になることで、実行することが多いコマンドかと思い
ますが、この際にルートの環境変数を使用しないと、せっかくルートにスイッチしても
実行できないコマンドが出てくるなどの弊害があるため、suコマンドを実行する際には
ハイフンオプションを付けて実行することがほとんどです。
ユーザ変数とシステム変数
ユーザが自身で設定した変数はユーザ変数と呼ばれています。先程から私が設定している
SV=ShellVariable もユーザ変数ということになります。これに対して、システム側で予め
用意されている変数が存在しており、これをシステム変数と呼びます。実は普段何気なく
実行しているコマンドもシステム変数のおかげで何気なく実行することができています。
先程より何度も実行しているechoコマンドを例に確認していきます。echoは「反響」の意
でありechoコマンドは文字列をやまびこのように反響して画面に表示するコマンドです。
echoコマンドを実行するということは、文字列を画面に表示するプログラムを実行する事
を意味しています。
プログラムファイル(コマンドの実体)の在り処はwhichコマンドで調べることができます。
私の環境の場合、echoコマンドの実体はどうやら /bin/echo にあるようです。この
フルパスを指定してechoコマンドを実行しても同じ出力結果を得ることができます。
コマンドを実行する際に実体のプログラムファイルを指定しなくても実行できるのは、
PATHという環境変数が設定されているためです。これはシステム変数の一つであり、
ユーザが作業しやすいようにシステム側であらかじめ設定されているものになります。
それではPATHを確認してみます。
出力結果から分かる通り、echoの実体が置かれている「/bin」だけでなく「/usr/bin」や
「/usr/local/bin」などの複数のディレクトリがコロンで区切られて羅列されています。
Linuxのコマンドは用途に応じて複数の格納場所があり、実行したいコマンドがあるとき、
ユーザがこれらのディレクトリの中から実体を探しだして実行するのはとても大変です。
PATHに格納場所が記述されている場合、コマンドを実行するとコマンドの文字列をPATHに記載されたディレクトリの中から順番に検索して実行するため、ユーザはコマンドの実体の在り処を把握せずともコマンドを実行することができます。
そのためこのパスは「コマンドサーチパス」と呼ばれています。
このPATHにコマンドの格納場所を記述して、コマンドを実行できるようにすることを
「パスを通す」と言ったりします。パスが通るとプログラムはシステム側にコマンド
と認識されることになります。逆に格納場所が記述されていないとコマンドの実体を
検索することができないため、コマンドを実行することができません。その場合は
パスを通すか、フルパスでプログラムファイルを指定して実行する必要があります。
先程のsuコマンドでハイフンオプションを付けてルートにスイッチしないと実行できないコマンドが出てくるといった話はここに繋がります。システム変数であるコマンドサーチパスに記載されているディレクトリが、ユーザ毎に異なっている可能性があるからです。
これも実際に確認してみます。
まずはルートのコマンドサーチパスを確認してみます。
続いてtestuserのコマンドサーチパスを確認してみます。
重要な違いとしては、rootには「/sbin」があり testuser にはない点です。「/sbin」は
システム管理用のコマンドやプログラムを置くディレクトリのため、testuserからroot
にsuコマンドでハイフンを付けずに(環境変数を引き継いで)スイッチした場合、rootに
スイッチした意味がなくなってしまいます。
システム変数は PATH(コマンドサーチパス) 以外にもたくさんあります。
▼ ホスト名
▼ ログインユーザ名
▼ カレントディレクトリパス
, etc.
この記事の冒頭で「現在使用しているシェルを確認するコマンド」を実行しましたが、
SHELLもシステムがあらかじめ用意してくれていたシステム変数の1つだったんですね。
以上、シェル変数と環境変数についてのまとめでした。
最後までご覧いただきありがとうございました。