【Shell】シェルの種類と設定ファイルの読み込み順（ざっくりまとめ）

## 概要
以下の人向けに、ざっくりまとめた備忘録です。

- あの〜、そもそもシェルって何でしたっけ？
- 「sh」「bash」「zsh」とかあるけど、何がどれでしたっけ？
- `.bash_profile` とか `.zshrc` とか `.zprofile` って何？
- シェルの確認方法と設定方法を知りたい（思い出したい）

## そもそも「シェル」とは
シェル（Shell）とは、ユーザがコンピュータを操作するために、コンピュータのOS（オペレーティングシステム）に命令を橋渡しをするプログラムです。より具体的には、コンピュータのOSの核である「カーネル」とやりとりをする部分です。
カーネルを覆う「殻」（＝ 英語で、Shell）ようなイメージから、この言葉がきています。

ユーザはシェルを通じて、コンピュータに様々な命令を入力し、その結果を画面で受け取っています。

シェルの中には、デスクトップ画面やそこからマウスなどを使って操作する「グラフィカルシェル」と、CLIツールの中でコマンドを使って操作する「コマンドラインシェル」があります。

Windows や Mac を例にすると、以下の通り。

|OS|グラフィカルシェル|標準コマンドラインシェル|標準 CLI ツール|
|---|---|---|---|
|Windows|Windows shell（デスクトップ画面・スタートメニュー・タスクバーなど含む）|PowerShell|PowerShell（旧：コマンドプロンプト）|
|macOS|Finder|Z Shell|ターミナル|

※ Mac の場合、デスクトップ上に常に"終了できないアプリ"として Finder が常時起動・表示されているので見たことあるかもしれませんが、Windows の画面には Windows shell という文字を見ることはないため、普段は認識できないと思います。

![シェルとは_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/f1861284-e845-ba77-38f7-a4fe6c9f9788.png)

（おまけ）
尚、シェルスクリプトのファイルを作る際には、一行目にシバン（shebang）という `#!` から始まる「おまじない」を記載するルールがある。今回はこれについては説明しません。

## シェルの種類
さて、上記の概要は一旦横に置いておいて、コマンドラインで主に利用される代表的なシェルは以下の３種類です。

|シェル|概要|
|---|---|
|Bourne Shell（sh）|Unix 系の OS で最も古くから存在するシェル。AT&T ベル研究所のスティーブン・ボーン氏が開発。<br>bash や zsh が主流となり、最近はメインで使われてはいない。<br>`.sh` は、sh のシェルコマンドを１つのファイルにまとめたシェルスクリプトの拡張子。|
|Bash（bash）|「Bourne-again shell」の略。sh を基に開発された Linux の標準シェル。以前は macOS でも標準がこれだった|
|Z Shell（zsh）|「sh と bash の良いとこ取り ＋ 独自機能」の高機能シェル。bash で出来ることは zsh にも出来る。<br>現在の macOS の標準はこれになっているが、以前の標準が bash だったため、長く同じ PC を使ってるユーザによっては `.bash_profile` と `.zshrc` 等が混在する場合がある。|

「この処理をする時は bash、この処理をする時は zsh」の様に混在して使うのはオススメしません。
出来るだけ自分が使う OS に合わせて、どれを利用するのか絞りましょう。

## シェルの設定ファイルの種類
シェルには１つの種類をとっても、その中にさらに利用シーンによって複数の設定ファイルがあり、特定のタイミングで読み込まれて自動実行されます。

- **ログインシェル**：ログインの時に読み込まれるシェル
- **対話シェル（インタラクティブシェル）**：ターミナルとか起動した時に読み込まれるシェル

例えば、bash の場合なら「ログイン時に自動実行される `.bash_profile`（または `.bash_login`）」や「ターミナルなどの対話シェルの起動時に自動実行される `~/.bashrc`」などがあります。

各設定ファイルは以下の通りで、上から順に実行されます。
尚、基本的にそのタイミングで該当するファイルが無ければ、無視されて次の処理に移ります。
（主流の bash と zsh のみ記載）

<table>
<tr>
<th>タイミング</th>
<th>bash</th>
<th>zsh</th>
</tr>
<tr>
<td rowspan="5">ログイン</td>
<td>/etc/profile</td>
<td>/etc/zshenv<br>~/.zshenv</td>
</tr>
<tr>
<td>/etc/bash.bashrc</td>
<td>/etc/zrofile<br>~/.zprofile</td>
</tr>
<tr>
<td>~/.bash_profile</td>
<td>/etc/zshrc<br>~/.zshrc</td>
</tr>
<tr>
<td>~/.bash_login<br>（上記が無い場合のみ実行）</td>
<td>/etc/zlogin<br>~/.zlogin</td>
</tr>
<tr>
<td>~/.profile<br>（上記が無い場合のみ実行）</td>
<td></td>
</tr>
<tr>
<td rowspan="2">対話シェル起動</td>
<td>/etc/bash.bashrc</td>
<td>/etc/zshenv<br>~/.zshenv</td>
</tr>
<tr>
<td>~/.bashrc</td>
<td>/etc/zshrc<br>~/.zshrc</td>
</tr>
<tr>
<td>非対話シェル起動<br>（ログインシェル/対話シェル<br>以外のシェル起動時）</td>
<td>$BASH_ENV</td>
<td>/etc/zshenv<br>~/.zshenv</td>
</tr>
<tr>
<td>ログアウト</td>
<td>~/.bash_logout</td>
<td>~/.zlogout<br>/etc/zlogout</td>
</tr>
</table>

※ OS によって、実行順序やファイル名が異なる可能性があります
※ 記事によっては、「対話シェル」を「インタラクティブシェル」、「非対話シェル」を「ノンインタラクティブシェル」と、英語で表現している場合もあります
※ `.zsh_history`, `.zsh_sessions` などの設定ファイルではない保存ファイル等の説明は割愛します

### 設定ファイルを強制実行する
上記以外のタイミング以外で設定ファイルを強制的に反映させたい場合は、`source` コマンドを使って、その後に対象ファイルを指定すると実行できます。

```bash
# 例：bash のプロファイルを反映させる
source ~/.bash_profile
```
※ ただし、sh では使えない

## 注意点
### 「ログインシェル」は、特定のシェルを指す言葉ではない
上記の表の補足になりますが、よくネット記事で **「ログインシェル」** という単語が出ますが、これは **「ログイン専用の特定のシェル」を** 指しているのではなく、**「ログインのタイミングに実行されるシェル群」** を指します。

なので、デフォルト設定はマシンや OS で変わりますし、自分でも変更可能なので、**ログインシェル** が具体的に何なのかは、マシン毎に変わります。

### ログインシェルかどうかの見分け方

#### デフォルトシェルを確認する
普通にマシンでターミナルを起動した場合にデフォルトで選択されるシェルはログインシェルが使用されます。**これは、現在のシェルを確認するコマンドではありませんので注意が必要です**。

```bash
# 確認コマンド
echo $SHELL

# 出力例（Zsh になっている場合）
/bin/zsh
```

#### `$0` を確認する
**非推奨** ですが、他にも Special Parameters `$0` という変数の中身を確認する方法もあります。
実行結果の前に `-` が表示されていれば、そのシェルはログインシェルとして使用されています。

```bash
# 変数 $0 を確認する
$ echo $0

# 実行結果: "-" があるのでログインシェルである
-zsh
```

ただし、このコマンドは、シェル名の前に `-` が無くても、ログインシェルである場合があるため注意が必要です。
例えば、`bash --login`、`bash -l` でログインシェルとして起動された場合は、`$0` のシェル名の前に `-` が表示されないことがあります（だから非推奨）。

### 対話シェル（インタラクティブシェル）かどうかの見分け方
一方、ログインシェルではなく、対話シェル（インタラクティブシェル）かどうかを確認する方法についてです。

#### 対話シェルは何か？ の確認方法
対話シェル（インタラクティブシェル）は何なのか？…を確認する方法は、`ps -o comm= -p $$` がベターだと思います。

```bash
# 確認コマンド
% ps -o comm= -p $$

# 出力例（Zsh になっている場合）
-zsh
```

### GUI の設定も確認すべし
macOS の「ターミナル」の設定例

コマンド上の設定も確認は必要ですが、そもそも GUI 上でデフォルト設定がどうなっているのかも確認してください。

ターミナルを開き、「設定」👉「一般」👉「開くシェル」がどうなっているかで挙動が変わります。

![シェルのデフォルト確認.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/c593e471-a068-1706-cd3b-24de36ce516b.png)

基本的には「デフォルトのログインシェル」であれば良いと思います。
何かの事情があって、デフォルトシェル（ログインシェル）と同じでない場合、指定したシェルが起動してしまうので、状況に合わせて対応する必要があります。

## まとめ

- シェルは、OS のカーネルに対して処理命令を仲介してくれるもの
- シェルには種類があり、OS に合わせて利用する
  - sh
  - bash
  - zsh
- シェルの設定ファイルには実行タイミングがあり、各タイミングで該当のファイルが存在すると自動で読み込まれる
  - ログイン時
  - 対話シェル起動時
  - 独自のシェルファイル実行時
  - ログアウト時
- 規定のタイミング外の場合でも、シェルによっては `source` コマンドで実行できる