ログインシェルとインタラクティブシェルと~/.bashrc達の関係


## Update &amp; 注意 (2017.5.9)
+ 最初の投稿からかなりの時間が経過しましたが、いくつか修正点が見つかりましたので、それぞれ訂正の注記を入れておきました。また、ポイントのまとめを表に改めました。
+ 以下の記述は次の環境で動作確認しています。
  - OS X 10.11.6, Homebrew よりインストールされた Bash 4.4.12
  - Ubuntu 14.04.5 LTS, Bash 4.3.11(1)-RELEASE
  - macOS 10.12.4, OSデフォルトの GNU bash, version 3.2.57(1)-release
+ 
ログインシェルとして Bash が使用されていることを確認するには、```echo $SHELL``` として環境変数 ```$SHELL```に bash の実行ファイルが指定されていることを確認します。
(__2018.5.16追記:__ Ubuntu等、左記の方法では確かめられないOSもあります。)
   - Bash が起動されているかどうかの確認方法の一つとしては、```ls -l /proc/$$/exe``` があります。このシンボリックリンクの参照先が```/bin/bash```等であるかを見ます。
      - RedHat 系ではBash, shいずれの時も ```/usr/bin/bash``` を表示してしまうので、ディストリビューション非依存なやり方については調査中です。

## 何のこっちゃ
発端は

``` bash:bash
 [hogeuser@fugahost ~]$ echo $PS1
 [\\u@\h \\W]\\$
```

というアレ(```PS1```という、bashのプロンプト設定のための変数)が「うまく設定されない？？なんで？？？」、と困ったことでした。

どうして？？そもそも、```~/.bashrc```と```~/.bash_profile``` の究極の違いって何でしょう。いろいろ検索した結果、[ログインシェルとインタラクティブシェルの違いを説明しているページ](http://hacktux.com/bash/bashrc/bash_profile)に行き着きました。

## ポイント

__[修正 2018.5.16]__

|シェルの種類|起動方法|起動時実行スクリプト|
|:-------------|:------|:------------------|
|ログインシェル|```ssh user@host``` <br> ```su - [user]```<br> ```bash --login``` <br> macOS Terminal.app 新規ウインドウ/タブ <br> ```tmux``` 新規ウインドウ|```~/.bash_profile``` <br> ※1|
|インタラクティブシェル|```su [user]``` <br> ```bash```|```~/.bashrc```|
|非インタラクティブシェル|```su user -c /path/to/command``` <br> ```bash -c /path/to/command``` <br> 
```ssh user@host /path/to/command```
 ※2|なし|

※1 以下でも述べていますが、ほとんどの場合```~/.bash_profile```内に、```~/.bashrc```を実行する記述があります。なお、**ログインシェルでは ```.bashrc``` は自動実行されません。**
※2 このコマンドでは、非インタラクティブシェルすら起動しないとの指摘を頂きました。訂正が遅れに遅れていたこと、お詫びします。

以下は、[上記のページ](http://hacktux.com/bash/bashrc/bash_profile)の受け売りです。

## ログインシェル
bash をプログラムとして起動するとき、オプション ``` - ``` または ``` --login ``` が付加された際にスタートするシェル。

次のようなコマンドで起動する：

``` bash:sh
sudo su -
bash --login
ssh user@host
```
- ログインシェルの場合、次のようなファイルが列挙した順に実行される：
	1. ```/etc/profile```
	1. ```~/.bash_profile```
	1. ```~/.bash_login```
	1. ```~/.profile```
- ```~/.bashrc``` はこのリストの中にないが、ほとんどの ```~/.bash_profile``` では ```~/.bashrc``` を呼び出して実行している。

## (純粋な)インタラクティブシェル

インタラクティブシェルとは、オプション -c を付加されずに起動されるシェルで、標準入出力が(仮想)端末に接続されているもの。インタラクティブシェルの全てがログインシェルであるとは限らない。

次のようなコマンドを打つとログインシェルではなく、純粋なインタラクティブシェルが起動される：

``` bash:sh
sudo su
bash
```

このインタラクティブではあるがログインシェルではないシェルでは、 ```~/.bashrc``` のみが実行される。ただし、デフォルトでは多くの場合、 ```~/.bashrc``` にシステム標準の```bashrc```ファイル (例: ```/etc/bashrc```。ディストリビューションにより異なる) をも実行するように記述されている。

- ```~/.bashrc``` ファイル中で ```echo``` で画面出力させないように注意。さもないと、```ssh user@host /path/to/command``` などを実行した際にコマンドに関係のない文字列が出力されてしまう。
   - __[追記 2015.12.1]__ ```~/.bashrc``` で、ログインシェルの時だけにコマンドを実行するには次のように。
 
``` bash:~/.bashrc
case $- in                                                                        
*i*)                                                                              
    /path/to/command                                                                
    ;;                                                                            
esac 
```

__[修正 2017.11.4]__ ```ssh user@host /path/to/command ``` はシェルを起動しないとの指摘をいただきましたので、下記非インタラクティブシェルに入れる形で修正しました。
__[2018.6.25 削除]__
## 非インタラクティブシェル
もある**[2017.5.4 名称変更]**。このたぐいのシェルは ```~/.bashrc``` や ```~/.bash_profile``` のようなスクリプトは、何も自動的に実行しない。

非インタラクティブシェルの起動例：

``` bash:sh
su user -c /path/to/command
bash -c /path/to/command
```

## 結局、```PS1=```はどこに書けばよいのか
```bash:sh
PS1=[\u@\h \W]$
```
は、インタラクティブであるシェルにおいて起動時に実行されればよいわけです。ので、```~/.bashrc``` に記述すればよいでしょう。

そして、```~/.bash_profile```に、```~/.bashrc```を起動する次のような記述があるのを確認しておくことになります。

``` bash:sh
# .bashrc
if [ -f ~/.bashrc ]; then
        . ~/.bashrc
fi
```

## 参考 URL
### inside Qiita
- [本当に正しい .bashrc と .bash_profile の使ひ分け](http://qiita.com/magicant/items/d3bb7ea1192e63fba850)
- [.bash_profile ? .bashrc ? いろいろあるけどこいつらなにもの？](http://qiita.com/hirokishirai/items/5a529c8395c4b336bf31)


### outside
- [An Explanation of .bashrc and .bash_profile | HACKTUX](http://hacktux.com/bash/bashrc/bash_profile)
- [How to: Change / Setup bash custom prompt (PS1) - nixCraft](http://www.cyberciti.biz/tips/howto-linux-unix-bash-shell-setup-prompt.html)
- [Bash Reference Manual: Invoking Bash](https://www.gnu.org/software/bash/manual/html_node/Invoking-Bash.html)