#はじめに
こんにちは、いっきゅうです。
twitter:@ikk_hck
たまには人の役に立ちそうな記事をかいてみようということで、すでに擦られた内容ではありますが、できるだけわかりやすくまとめてみようと思います。
先に答えだけ知りたい方は下の方の本題から読んでください。
#前提
そもそもシェルとひとくちにいっても色いろなタイプがあります。
ここでいうタイプとはbashやzshなどではなく”モード”のことです。
インタラクティブかどうか、またログインシェルかどうかの組み合わせの2x2で、4つのタイプがあります。
- インタラクティブなログインシェル
- インタラクティブなノンログインシェル
- ノンインタラクティブなノンログインシェル
- ノンインタラクティブなログインシェル
これらを理解するためにはさらにログインシェルとインタラクティブシェルを理解する必要があります。
###ログインシェル
sshでマシンにログインしたときなどに起動されるシェルです。後に触れますが、GUIでログインしてターミナルを立ち上げた場合もログインシェルが起動します。
一方、ログインシェルからさらに新しくbashを起動すると、それはノンログインシェルとして起動されます。bashを起動する際に
$ bash --login
のように--loginをつけると新しく起動する場合でもログインシェルになります。
####ログインシェルとノンログインシェルの見分け方
- ログインシェルの場合
$ echo $0
-bash
ログインシェルの場合bashという文字列にハイフンがつきます。
もしくは
$ shopt login_shell
login_shell on
login_shellがonになっています。
- ノンログインシェルの場合
$ echo $0
bash
bashという文字列の前にハイフンがつきません。
もしくは
$ shopt login_shell
login_shell off
login_shellがoffになっています。
###インタラクティブシェル
インタラクティブなシェルはttyのユーザ入力からコマンドを受け取り実行します。つまりユーザの入力に対して出力をします。
一方ノンインタラクティブなシェルとは、たとえばシェルスクリプトを実行する際に使用されるシェルのことです。このシェルはユーザ入力を受け取りません。
####インタラクティブシェルかどうかの見分け方
- インタラクティブシェルの場合
$ echo $-
himBH
出力は"himBH"となります。
- ノンインタラクティブシェルの場合
$ bash -c 'echo $-'
hBc
ノンインタラクティブシェルで'echo $-'実行するコマンドです。
-cは、渡される文字列をコマンドとして認識して実行するというオプションです。
上記のコマンドで起動されるシェルは、渡されたコマンドを実行するためだけに起動されるのでノンインタラクティブです。また出力は"hBc"となります。
###4つのタイプ
以下具体例をあげてそれぞれのタイプに触れていきます。
- インタラクティブなログインシェル たとえばGUIでログインし、アプリケーションなどからterminalを開いたりしますが、あれです。あるいはsshでログインした場合などは自動的にインタラクティブなログインシェルが起動されます。
- インタラクティブなノンログインシェル ノンログインシェルとは、ログインシェルから"$bash"などと入力して起動したシェルのことです。
- ノンインタラクティブなノンログインシェル シェルスクリプトを実行する際に起動される。シェルスクリプトは独自のサブシェルで実行され、このシェルは対話型ではありません。スクリプトを実行するためだけに開かれ、スクリプトが終了するとすぐに閉じます。
- ノンインタラクティブなログインシェル このシェルの説明をあえて最後に持ってきたのは使う機会が稀だからです。たとえば以下のようにsshで自身に接続し(ログインシェルが起動)、実行したいコマンドを流し込めば(非対話型)非対話的なログインシェルの挙動が確認できます。 shoptコマンドについては後に触れます。
$ echo 'echo $-; shopt login_shell' | ssh localhost
Pseudo-terminal will not be allocated because stdin is not a terminal.
Password:
hB
login_shell on
以上の4つのタイプのシェルそれぞれでインタラクティブかどうか、またログインシェルかどうかをためしてみると、たしかにそうなっていることがわかると思います。
#本題
いよいよ本題のbash_profileとbashrcの違いについて触れていきたいと思います。
下の図を見てください。今までの内容がわかれば下のフローチャートも理解できると思います。めんどくさいのですごくわかりやすい図なので他のサイトの図を引用させていただきました。
(図の引用元:https://blog1.mammb.com/entry/2019/12/01/090000 )
基本的にはターミナルを操作するときはログインシェルをインタラクティブに利用することが多いかと思います。したがってよく耳にする「まずbash_profileが読み込まれてbashrcがよみこまれる」ということになるわけですね。
また、ノンログインシェルをインタラクティブに使用する際はbash_profileは読み込まれずbashrcが読み込まれます。したがってスクリプトを実行するときに反映させたいシェルの設定をbash_profileに書いていても反映されないわけです。
##bash_profile
端的に言えば、bash_profileの特徴をいくつかあげると
- ログイン時にのみ1回実行される
- 環境変数はプロセス間で引き継がれるのでbash_profileに記述する
- bash_profile内にbashrcを読み込むための記述を書き込むことが多い
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
のような記述でbashrcを読み込む記述がされています。
##bashrc
bashrcの特徴をいくつがあげると
- bashが起動されるたびによみこまれる
- エイリアスやshell変数を記述
では。