Edited at

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

More than 1 year has passed since last update.


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 の実行ファイルが指定されていることを確認します。(2018.5.16追記: Ubuntu等、左記の方法では確かめられないOSもあります。)


    • Bash が起動されているかどうかの確認方法の一つとしては、ls -l /proc/$$/exe があります。このシンボリックリンクの参照先が/bin/bash等であるかを見ます。


      • RedHat 系ではBash, shいずれの時も /usr/bin/bash を表示してしまうので、ディストリビューション非依存なやり方については調査中です。






何のこっちゃ

発端は


bash

 [hogeuser@fugahost ~]$ echo $PS1

[\\u@\h \\W]\\$

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

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


ポイント

[修正 2018.5.16]

シェルの種類
起動方法
起動時実行スクリプト

ログインシェル

ssh user@host
su - [user]
bash --login
macOS Terminal.app 新規ウインドウ/タブ
tmux 新規ウインドウ

~/.bash_profile
※1

インタラクティブシェル

su [user]
bash

~/.bashrc

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

su user -c /path/to/command
bash -c /path/to/command
ssh user@host /path/to/command ※2
なし

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

※2 このコマンドでは、非インタラクティブシェルすら起動しないとの指摘を頂きました。訂正が遅れに遅れていたこと、お詫びします。

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


ログインシェル

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

このインタラクティブではあるがログインシェルではないシェルでは、 ~/.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.11.4] ssh user@host /path/to/command はシェルを起動しないとの指摘をいただきましたので、下記非インタラクティブシェルに入れる形で修正しました。[2018.6.25 削除]


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

もある[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