はじめに
シェルセッションを介してサーバーとやり取りする場合、シェルがその動作とリソースへのアクセスを決定するためにコンパイルする多くの情報があります。これらの設定の一部は構成設定に含まれ、その他はユーザーの入力によって決定されます。
シェルがこれらすべての設定と詳細を追跡する方法の一つは、シェルが保持する環境と呼ばれる領域を使用することです。環境は、システムプロパティを定義する変数を含むセッションを開始するたびにシェルが構築する領域です。
このガイドでは、環境の扱い方、さらに環境変数、シェル変数をインタラクティブに、または設定ファイルを使用して、読み込みまたは設定する方法について説明します。
環境および環境変数の仕組み
シェルセッションが作成されるたびに、シェルプロセスとその子プロセスで使用可能な情報を収集してコンパイルするプロセスが実行されます。これらの設定データは、システム上のさまざまなファイルや設定から取得されます。
環境は、シェルプロセスが設定を取得または設定し、それらを子プロセスに渡すための媒体を提供します。
環境は、キーと値のペアを表す文字列として実装されます。複数の値が渡される場合、通常はコロン (:
) 文字で区切られます。それぞれのペアは通常、次のようになります。
KEY=value1:value2:...
値に有効なスペース(空白)が含まれている場合は、引用符が使用されます。
KEY="value with spaces"
これらの状況のキーは変数です。これらは、環境変数またはシェル変数の2つのタイプのいずれかになります。
環境変数は、現在のシェルに対して定義され、子シェルまたはプロセスによって引き継がれる変数です。環境変数は、シェルから作成されたプロセスに情報を渡すために使用されます。
シェル変数は、設定または定義されたシェル内にのみ含まれている変数です。これらは現在の作業ディレクトリなど、一時的なデータを追跡するためによく使用されます。
慣例では、これらのタイプの変数は通常、すべて大文字を使用して定義されます。これにより、ユーザーは他のコンテキスト内で環境変数を区別することができます。
シェル変数および環境変数の出力
それぞれのシェルセッションは、独自のシェル変数と環境変数を追跡します。これらにはいくつかの方法でアクセスできます。
環境変数のリストを表示するには、env
またはprintenv
コマンドを使用します。デフォルトの状態では、この2つのコマンドは全く同じように機能するはずです。
- printenv
OutputSHELL=/bin/bash
TERM=xterm
USER=demouser
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca:...
MAIL=/var/mail/demouser
PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
PWD=/home/demouser
LANG=en_US.UTF-8
SHLVL=1
HOME=/home/demouser
LOGNAME=demouser
LESSOPEN=| /usr/bin/lesspipe %s
LESSCLOSE=/usr/bin/lesspipe %s %s
_=/usr/bin/printenv
これは、printenv
とenv
の両方の出力の、ごく一般的な例です。2つのコマンドの違いは、より具体的な機能でのみ明らかです。たとえば、printenv
を使用すると、個々の変数の値を要求できます。
- printenv SHELL
Output/bin/bash
一方、env
を使用すると、一連の変数定義を次のようなコマンドに渡すことによって、プログラムが実行する環境を変更できます。
- env VAR1="value" command_to_run command_options
上記で学習したように、子プロセスは通常、親プロセスの環境変数を引き継ぐため、子プロセスの値を上書きしたり、変数を追加したりすることができます。
printenv
コマンドの出力からわかるように、ユーザーの入力なしで、システムファイルとプロセスを介して設定される環境変数がかなり多くあります。
これらは環境変数を示していますが、シェル変数はどのように表示されるのでしょうか?
これには、set
コマンドが使用されます。追加のパラメーターを指定せずにset
を入力すると、すべてのシェル変数、環境変数、ローカル変数、およびシェル関数のリストが表示されます。
- set
OutputBASH=/bin/bash
BASHOPTS=checkwinsize:cmdhist:expand_aliases:extglob:extquote:force_fignore:histappend:interactive_comments:login_shell:progcomp:promptvars:sourcepath
BASH_ALIASES=()
BASH_ARGC=()
BASH_ARGV=()
BASH_CMDS=()
. . .
これは通常、膨大なリストです。より簡単に処理できる出力量にするために、ページャープログラムにパイプすると良いでしょう。
- set | less
受け取る追加情報の量には、少し圧倒されるでしょう。例えば、定義されているすべてのbash関数を知る必要はおそらくないでしょう。
シェル関数を出力しないPOSIXモードで動作するようにset
を指定することで、出力をクリーンアップすることができます。これをサブシェルで実行すると、現在の環境を変更せずにできます。
- (set -o posix; set)
これにより、定義されている環境変数とシェル変数のすべてがリスト表示されます。
この出力をenv
またはprintenv
コマンドの出力と比較して、シェル変数のみのリストを取得しようとすることはできますが、これらのコマンドが情報を出力する方法が異なるため、完全に比較することはできません。
- comm -23 <(set -o posix; set | sort) <(env | sort)
set
コマンドは引用符で囲まれた値を出力するのに対して、printenv
とenv
コマンドは文字列の値を引用符で囲まないため、これにはまだいくつかの環境変数が含まれている可能性があります。
これで、セッションで設定されている環境変数とシェル変数をさらによく理解することができるでしょう。
これらの変数は、あらゆる種類のものに使用されます。これらは、ファイルに変更を書き込むことなく、プロセス間のセッションに永続的な値を設定する別の方法を提供します。
一般的な環境変数およびシェル変数
環境変数とシェル変数の中には非常に有用で、かなり頻繁に参照されるものがあります。よく利用される一般的な環境変数を次に紹介します。
SHELL
: 入力したコマンドを解釈するシェルを表します。ほとんどの場合、デフォルトではbashですが、他のオプションが必要な場合は他の値を設定できます。TERM
: シェルの実行時にエミュレートする端末の種類を指定します。さまざまな動作要件に応じて、さまざまなハードウェア端末をエミュレートできます。ただし、通常はこれを気にかける必要はありません。USER
:現在ログインしているユーザー。PWD
:現在の作業ディレクトリ。OLDPWD
:直前の作業ディレクトリ。これは、cd -
を実行して直前のディレクトリに切り替えるためにシェルによって保持されます。LS_COLORS
:ls
コマンドにオプションでカラー出力を追加するために使用されるカラーコードを定義します。これは、さまざまなファイルタイプを区別し、ユーザーに一目でより多くの情報を提供するために使用されます。MAIL
:現在のユーザーのメールボックスへのパス。PATH
:システムがコマンドを検索するときにチェックするディレクトリのリスト。ユーザーがコマンドを入力すると、システムはこの順序で実行可能ファイルのディレクトリをチェックします。LANG
:文字エンコードを含む、現在の言語とローカリゼーションの設定。HOME
:現在のユーザーのホームディレクトリ。_
: 直前に実行されたコマンド。
これらの環境変数に加えて、よく見られるシェル変数には次のようなものがあります。
BASHOPTS
: bashの実行時に使用されたオプションのリスト。これは、シェル環境が希望通りに動作するかどうかを確認するのに役立ちます。BASH_VERSION
: 実行中のbashのバージョン(人間が読める形式)。BASH_VERSINFO
:bashのバージョン(機械判読可能な出力形式)。COLUMNS
:画面出力の作成に使用されている出力幅(桁数)。DIRSTACK
:pushd
とpopd
コマンドで使用できるディレクトリのスタック。HISTFILEZE
: ファイルに保存されるコマンド履歴の件数。HISTSIZE
:メモリに保存されるコマンド履歴の件数。HOSTNAME
:現在のコンピュータのホスト名。IFS
:コマンドラインの入力を区切る内部フィールドセパレーター。デフォルトでは、これはスペースです。PS1
:プライマリコマンドプロンプトの定義。これは、シェルセッションを開始するときにプロンプトがどのように表示されるかを定義するために使用されます。PS2
は、コマンドが複数行にわたる場合のセカンダリプロンプトを宣言するために使用されます。SHELLOPTS
:set
オプションで設定できるシェルオプション。UID
:現在のユーザーのUID。
シェル変数および環境変数の設定
シェル変数と環境変数の違いをよりよく理解し、これらの変数を設定する構文を紹介するために、簡単なデモンストレーションを行います。
シェル変数の作成
まず、現在のセッションでシェル変数を定義することから始めます。これは簡単に実行できます。名前と値を指定するだけです。変数名をすべて大文字にするという規則に従い、簡単な文字列に設定します。
- TEST_VAR='Hello World!'
ここでは、変数の値にスペースが含まれているため、引用符を使用しました。さらに、感嘆符はbashシェルの特殊文字であり、エスケープされていない場合やシングルクォートで囲まれていない場合は、通常bashの履歴展開が行われるため、シングルクォートを使用しました。
これでシェル変数が作成されました。この変数は現在のセッションで利用できますが、子プロセスには渡されません。
set
出力で新しい変数にgrepを使用してこれを確認できます。
- set | grep TEST_VAR
OutputTEST_VAR='Hello World!'
printenv
を使用して同じことを試してみると、これが環境変数ではないことを確認できます。
- printenv | grep TEST_VAR
出力は返されません。
これを機会として、シェル変数または環境変数の値にアクセスする方法を示しましょう。
- echo $TEST_VAR
OutputHello World!
ご覧のとおり、変数の前に$
記号を付けて、変数の値を参照します。シェルは、この記号を見つけた場合、変数の値を置き換える必要があると解釈します。
これでシェル変数が作成されました。これは子プロセスに渡されるものではありません。現在のシェル内から新しいbashシェルを作成して、このことを実証できます。
- bash
- echo $TEST_VAR
bash
と入力して子シェルを作成し、変数の内容にアクセスしても、何も返されません。これは予想していたことです。
exit
と入力して元のシェルに戻ります。
- exit
環境変数の作成
それでは、シェル変数を環境変数に変換しましょう。これは、変数をエクスポートすることで実行できます。これを行うコマンドには、適切な名前が付けられています。
- export TEST_VAR
これにより、シェル変数が環境変数に変換されます。環境変数のリストを再び出力することで、これを確認できます。
- printenv | grep TEST_VAR
OutputTEST_VAR=Hello World!
今回は、変数が表示されます。子シェルを使用して、もう一度試してみましょう。
- bash
- echo $TEST_VAR
OutputHello World!
いいですね!子シェルは、親シェルが設定した変数を受け取りました。この子シェルを終了する前に、別の変数をエクスポートしてみましょう。次のような1つのステップで環境変数を設定できます。
- export NEW_VAR="Testing export"
環境変数としてエクスポートされることをテストします。
- printenv | grep NEW_VAR
OutputNEW_VAR=Testing export
それでは、元のシェルに戻りましょう。
- exit
新しい変数が使用可能かどうかを確認しましょう。
- echo $NEW_VAR
何も返されません。
環境変数は子プロセスにのみ渡されるためです。親シェルの環境変数を設定する組み込み方法はありません。これはほとんどの場合に有効であり、プログラムが呼び出された動作環境に影響を与えるのを防ぐことができます。
NEW_VAR
変数は、子シェルの環境変数として設定されました。この変数は、そのシェル自体とその子シェルおよびプロセスのいずれにおいても使用できます。メインシェルに戻ると、その環境は破棄されました。
変数の格下げと設定解除
TEST_VAR
変数はまだ環境変数として定義されています。次のように入力して、シェル変数に戻すことができます。
- export -n TEST_VAR
これでもう環境変数ではありません。
- printenv | grep TEST_VAR
ただし、まだシェル変数です。
- set | grep TEST_VAR
OutputTEST_VAR='Hello World!'
シェルまたは環境変数の設定を完全に解除したい場合は、unset
コマンドを使用します。
- unset TEST_VAR
設定されていないことを確認できます。
- echo $TEST_VAR
変数の設定が解除されたため、何も返されません。
ログイン時の環境変数の設定
多くのプログラムが環境変数を使用して操作方法の詳細を決定することは、既に説明しました。新しいシェルセッションを開始するたびに重要な変数を設定する必要はなく、ログイン時に既にいくつかの変数が設定されていることも確認しました。それでは、変数を自動的に作成および定義するにはどうすればよいでしょうか?
bashシェルは開始方法に応じて読み込む多数の設定ファイルがあるため、最初に考えていたよりも実際は複雑な問題です。
ログイン、非ログイン、インタラクティブ、および非インタラクティブシェルセッションの違い
bashシェルは、セッションの開始方法に応じてさまざまな設定ファイルを読み込みます。
それぞれのセッション間の違いの1つは、シェルがログインセッションまたは非ログインセッションのどちらで作成されているかということです。
ログインシェルは、ユーザーの認証から始まるシェルセッションです。端末セッションまたはSSHを通じて、サインインして認証を行う場合、シェルセッションはログインシェルとして設定されます。
端末からbash
コマンドを呼び出す場合のように、認証されたセッション内で新しいシェルセッションを開始した場合は、非ログインシェルセッションが開始されます。子シェルを開始したときに、認証の詳細を要求されませんでした。
もう一つの違いとして、シェルセッションがインタラクティブか、非インタラクティブか、という区別があります。
インタラクティブなシェルセッションは、端末に接続されているシェルセッションです。非インタラクティブなシェルセッションは、 端末に接続されていないシェルセッションです。
したがって、各シェルセッションは、ログインまたは非ログイン、インタラクティブまたは非インタラクティブのいずれかに分類されます。
SSHを使用して開始する通常のセッションは、一般に、インタラクティブなログインシェルです。コマンドラインから実行されるスクリプトは、通常、非インタラクティブの非ログインシェルで実行されます。端末セッションは、これらの2つのプロパティの任意の組み合わせになります。
シェルセッションがログインシェルまたは非ログインシェルのどちらに分類されるかは、シェルセッションを初期化するためにどのファイルが読み込まれるかに影響します。
ログインセッションとして開始されたセッションは、最初に/etc/profile
ファイルから設定の詳細を読み込みます。次に、ユーザーのホームディレクトリで最初のログインシェル設定ファイルを検索して、ユーザー固有の設定詳細を取得します。
~/.bash_profile
、~/.bash_login
、~/.profile
の順番で最初に見つけることができたファイルだけを読み込み、それ以上のファイルは読み込みません。
一方、非ログインシェルとして定義されたセッションは、/etc/bash.bashrc
を読み込み、ユーザー固有の~/.bashrc
ファイルを読み込んで環境を構築します。
非インタラクティブシェルは BASH_ENV
という環境変数を読み込み、指定されたファイルを読み込んで新しい環境を定義します。
環境変数の実装
ご覧のとおり、設定を行うためには、通常さまざまなファイルを確認する必要があります。
これにより、ログインシェルでの特定の設定や、非ログインシェルでその他の設定が必要な特定の状況で役立つ多くの柔軟性が得られます。ただし、ほとんどの場合、どちらの状況でも同じ設定が必要になります。
幸いにも、ほとんどのLinuxディストリビューションでは、非ログインの設定ファイルをもとにしてログイン設定ファイルを設定しています。つまり、非ログイン設定ファイル内の両方に必要な環境変数を定義できます。その後、両方の状況で読み込まれます。
通常、ユーザー固有の環境変数を設定し、ログインシェルと非ログインシェルの両方で設定を使用できるようにします。つまり、これらの変数を定義する場所は ~/.bashrc
ファイルにあります。
このファイルをこれから開きます。
- nano ~/.bashrc
ファイルに既にかなりのデータが含まれている可能性があります。ここでの定義のほとんどは、環境変数と関連のないbashオプションを設定するためのものです。コマンドラインから行うのと同様に、環境変数を設定できます。
- export VARNAME=value
新しい環境変数は、他のコマンドまたはforループの途中に配置されない限り、~/.bashrc
ファイルの任意の場所に追加できます。その後、ファイルを保存して閉じることができます。次にシェルセッションを開始すると、環境変数の宣言が読み込まれ、シェル環境に渡されます。次のように入力すると、現在のセッションでファイルの読み込みを要求することができます。
- source ~/.bashrc
システム全体の変数を設定する必要がある場合は、/etc/profile
、/etc/bash.bashrc
、または/etc/environment
に変数を追加することを検討するのがよいでしょう。
まとめ
環境変数およびシェル変数は常にシェルセッションに存在し、非常に有用です。これは親プロセスが子プロセスの設定の詳細を設定するための興味深い方法であり、ファイルの外部でオプションを設定する方法です。
これは、特定の状況で多くの利点があります。たとえば、環境変数に基づいて認証情報を設定するデプロイ方法があります。これは、外部の第三者に見られる可能性のあるファイルに保管する必要がないため実用的です。
システムの環境を読み込み、変更する必要がある、よりありふれた、しかしながらより一般的な状況は他にもたくさんあります。これらのツールと手法があれば、システム環境の変更を行い、正しく使用するための優れた基盤を築くことができます。