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

  • 48
    いいね
  • 0
    コメント

Update & 注意 (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 の実行ファイルが指定されていることを確認します。

何のこっちゃ

発端は

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

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

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

ポイント

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

※ 以下でも述べていますが、ほとんどの場合~/.bash_profile内に、~/.bashrcを実行する記述があります。なお、ログインシェルでは .bashrc は自動実行されません。

以下は、上記のページの受け売りです。

ログインシェル

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

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

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

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

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

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

sh
sudo su
bash
ssh user@host /path/to/command

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

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

非インタラクティブシェル

もある[2017.5.4 名称変更]。このたぐいのシェルは ~/.bashrc~/.bash_profile のようなスクリプトは、何も自動的に実行しない。

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

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

結局、PS1=はどこに書けばよいのか

sh
PS1=[\u@\h \W]$

は、インタラクティブであるシェルにおいて起動時に実行されればよいわけです。ので、~/.bashrc に記述すればよいでしょう。

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

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

参考 URL

inside Qiita

outside