30 シェルについての勉強 -- ログイン・シェルとインタラクティブ・シェル

「シェルの設定ファイルのお勉強」 というのを書いたことがあり、その続きのようなもの。

ログイン・シェル、インタラクティブ・シェルの定義?

ログイン・シェル、インタラクティブ・シェルという言葉がある。 UNIX を使い始めたのは割と早く (まだ学部生だったかな?)、 漠然と意味は分かっていたつもり???

以前の私が何となく理解(誤解含む)していたこと
シェルは、ターミナル等から呼び出されて、 ユーザーの相手をする(対話する)場合と、 スクリプトの面倒をみる場合があって、 前者の場合はインタラクティブ・シェルと呼ばれる。

ログイン・シェルというのは、 システムに “ログイン” したユーザーの相手をするためのシェル。 (ログインって何だろう?とは当時の私は考えなかった。 わかっているつもりだった。 今改めて定義は何かと言われると意外と難しい。)

これによると、 ログイン・シェルというのはインタラクティブ・シェルである、 ということになるが、実はこれは間違いで、 インタラクティブ・シェルでなくても --login をつけて起動されれば、 ログイン・シェルとなる。

結局、必要条件でも十分条件でもない。ログイン・シェルであるかどうか、 インタラクティブ・シェルであるかどうか、 $ 2\times 2=4$ 通りの場合がある。

ネットで、 「ログインシェルとインタラクティブシェルの違い」 というのを見つけたのだけど、多分この人は誤解していて、 ここに書いてあるのは正しくは「ログインシェルとそうでないシェル (インタラクティブ・シェルではある)の違い」 ということなのだろう。

「ログインシェル、インタラクティブシェルの見分け方(bash)」 は正しそうだ。落ち着いて見ると、タイトルだけ見て分かるのかも (「AとBの違い」, 「A, Bの見分け方」)。

ログイン・シェルか、そうでないかの見分け方

shopt login_shell というコマンドを使え、ということをいう人もいる。
bash を使っているとき
% shopt login_shell
login_shell    	on
%
あるいは
% shopt login_shell
login_shell     off
%
この shopt は bash の内部コマンドらしい。 bash の場合はこれで解決 (終了)。

zsh には shopt はなくて、代わりに setopt がある。
zsh を使っているとき
% setopt
combiningchars
interactive
login
monitor
shinstdin
zle
%


それから、完全に判定できる訳ではないが、 echo $0 として、 - がついていればログイン・シェルである、という判定法もある。

注意: ログイン・シェルでも、- がついていないことがある。

以上が本当かどうかは、簡単に試せる。

普段 (zsh で) 作業しているターミナルで
% echo $0
-zsh
% zsh
% echo $0
zsh
% setopt
combiningchars
interactive
monitor
shinstdin
zle
% exit
% su 誰か
Password: むにゃむにゃ
% echo $0
zsh
% setopt
combiningchars
interactive
monitor
shinstdin
zle
% exit
% su - 誰か
Password: むにゃむにゃ
% echo $0
-zsh
% exit
% zsh --login
% echo $0
zsh
% setopt
combiningchars
interactive
login
monitor
shinstdin
zle
% exit
%

以上から分かることは

bash をログイン・シェルに登録して同様のことを
% echo $0
-bash
% bash
% echo $0
bash
% shopt login_shell
login_shell    	off
% exit
% su 誰か
% echo $0
bash
% shopt login_shell
login_shell     off
% exit
% su - 誰か
% echo $0
-bash
% exit
% bash --login
% echo $0
bash
% shopt login_shell
login_shell    	on
% exit

こういう仕掛けが何の役に立つかについて、少し考えてみる。

インタラクティブ・シェルか、そうでないかの見分け方

もちろん setoptを使う、という手がある (zshの場合に限定 … 具体的には setopt | grep interactive かなあ?)。

echo $- として、 i が含まれていればインタラクティブ・シェル、という判定法もあるとか。

% echo $-
569XZilms
% zsh
% echo $-
569XZims
% exit
% su toor
Password:
% echo $-
569XZims
% exit
% su - toor
Password:
% echo $-
569XZilms
% cat my.sh
#!/bin/sh
echo $-
% ./my.sh
hB
確かに、 一番最後のシェル・スクリプトの中で echo $- をした場合を除き、 すべての場合に i がついている。

(ところで、L の小文字 l ってログイン・シェルを意味しているのでは?? でもたとえそうだとしても、$0 のときと同じで、 ログイン・シェルでも l がない場合があるようだ。)

もう一つ、echo $PS1 として環境変数 PS1 をチェックする、 という方法を紹介する人もいるが (bash スクリプトで良く見かけるね)、 これは bash 限定みたいで、 zsh では “PS1: Undefined variable.” と叱られる。

参考: PS1が定義されていなければ($PS1の文字列長が0ならば)
if [ -z "$PS1" ]; then
   return
fi

ログイン・シェルとそうでないインタラクティブ・シェルの違い

環境変数以外に、読む設定ファイルが異なる、というのが大きいかな。

bash がログイン・シェルとして起動されると、 /etc/profile が存在するならば読む。 続いて、~/.bash_profile, ~/.bash_login, ~/.profile の順に検索して、 最初に見つかる存在してかつ読めるもの(だけ)を読む。

bash がログイン・シェルとしてではなく、 ただのインタラクティブ・シェルとして起動されると、 ~/.bashrc を読もうとする。

~/.bash_profile の中で、 ~/.bashrc を読むように設定してあることが多い。 (そうしないと、読まれない、ということだ。)

ちなみに、インタラクティブでないシェルは、 これらの設定ファイルを読まないらしい。



桂田 祐史