60 シェルの設定ファイルのお勉強

自分一人ならばどうとでもなるのだけど。少し今の相場を勉強しておこう。


詳しいのを見つけた。


設定ファイルについての考え方は、前者でよく分かる (知っている・どこかで読んだ覚えのあることがあったけれど、 知らないこともあった)。具体的な設定は後者が参考になった。

bash でログインシェルの場合に読まれる設定ファイル     次の順で検索され、最初に見つかったものだけを読む。

  1. .bash_profile
  2. .bash_login
  3. .profile

(この場合、特に .bashrc を読もうとはしないことに注意する。 ログインシェルでなくて、 対話型シェルとして起動された場合に .bashrc を読もうとする、 ということだ。)


.profile だけを作る、というのは危ないな。 後から .bash_profile.bash_login を作られると、 読まれなくなってしまう。

.bash_profile を作ってしまえば自分でコントロールできる。 最近、 色々なソフトウェアのインストーラーが勝手に設定ファイルをいじることを考えると、 そうするのが安全であろう。

.bash_profile にほとんどのことを書いてしまうというのも考えられるが、 書き分けておいて、.bash_profile からそれらを読む、 という方針が勧められている。そうしてみようかな。

.bash_login は使わないことにしようという意見がある。なるほど (必要ないし、あると混乱の元になるかも、一切使わないことにしよう。 思考の経済。…csh の使い手用に用意されたものなのかな。 つまり .cshrc.login を利用するのが習慣だった人向けとか。 うがちすぎかしら。)。

bash の管理 考えられる管理方針      3つあげている。

(1) .bashrc ですべてやる (.bash_profile.bashrcのみ使う)     
bash_profile
# .bash_profile
if [ -f ~/.bashrc ]; then
    . ~/.bashrc
fi
.bashrc
# .bashrc
[ -z "$PS1" ] && return    # 非インタラクティブの場合は return

# ここにお好きな設定を記載
# エイリアス・環境変数・シェルオプション・プロンプト設定

ログイン・シェルの場合は、 .bash_profile があれば、とにかくそれが (ユーザー作成の設定ファイルの内で) 最初に読まれるので、 そこから .bashrc に制御を渡してしまう。

プロンプトを表す文字列 (環境変数 PS1 の値) の長さが0ならば、 という条件で非インタラクティブと判定している。

あれ?非インタラクティブのときは、環境変数まで設定しないの? という疑問はある (実は真面目に考えていないのだな)。 まあ、とにかく全て .bashrc でやるのだ、ということか。

(2) 環境変数は .bash_profile で設定し、その他は .bashrc でやる (.bash_profile.bashrcのみ使う)     

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

# ここに環境変数を定義
export PATH="$HOME/hoge:$PATH"
# .bashrc
[ -z "$PS1" ] && return    # 非インタラクティブの場合は return

# ここにお好きな設定を記載
# エイリアス・シェルオプション・プロンプト設定

これは一応スッキリしていて、ずっと以前はこれで良かったのかも。

(3) 環境変数は .profile で、その他は .bashrc でやる (.bash_profile, .profile, .bashrc のみ使う)     
.bash_profile
# .bash_profile
if [ -f ~/.profile ]; then
    . ~/.profile
fi

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

# これ以降に環境変数を定義
export PATH="$HOME/hoge:$PATH"
.bashrc
# .bashrc
[ -z "$PS1" ] && return    # 非インタラクティブの場合は return

# これ以降お好きな設定を記載
# エイリアス, シェルオプション, プロンプト設定など

.bash_profile では、 .profile.bashrc の読み込みだけを行う。

環境変数は .profile だけで設定する。 シェルの種類に依存しないもの(zshでも使える)を記述することにすれば、 複数のシェルで環境変数が統一できる。

対話操作で必要なこと(エイリアス、プロンプト、シェルのオプション)は、 .bashrc だけで行う。 ここで標準出力、標準エラー出力への出力をしてはいけない (ssh のパイプ処理などでトラぶる)。

「厳格管理」と言っていいるけれど、複雑ではないし、 確かにトラブルを起こしにくいように感じる。

(疑問: エイリアスってインタラクティブな場合だけに使うのかな?? もしそうならば .bash_profile でやればいいような気もする。 .bashrc の中でインタラクティブな場合、 そうでない場合と分けるのが本当のように思える。)

.bash_profile は定型でいじらない。 環境変数はとにかく .profile, その他 (エイリアス・プロンプト等) は .bashrc というのは分かりやすい。

bash と zsh を混用する場合も分かりやすい。 特に私が Mac を使う場合は該当しそうだ。

.zprofile 要するに .bash_profile 相当
# .zprofile
if [ -f ~/.profile ]; then
    emulate sh -c 'source ~/.profile'
fi

# ,zshrc は自動的に読まれる?
#if [ -f ~/.zshrc ]; then
#    . ~/.zshrc
#fi
.profile -- bash, zsh で共用
# .profile

# ここに環境変数を定義
export PATH="$HOME/hoge:$PATH"
# .zshrc
[ -z "$PS1" ] && return    # 非インタラクティブの場合は return

# ここにお好きな設定を記載
# エイリアス・シェルオプション・プロンプト設定
# 補完など
# autoload -U compinit
# compinit

これを真似してしばらく走ってみよう。

個人的に使っているエイリアス (設定の書き換えに vic, 設定の読み直しに rerun) を修正する。

設定を変える時に編集するのは .zshrc (.bashrc) だけれど、 読み直しは .zprofile (.bash_profile) だ。
.zshrc
alias rerun='source ~/.zprofile'
alias vic='vi ~/.zshrc'
.bashrc
alias rerun='source ~/.bash_profile'
alias vic='vi ~/.bashrc'

ログイン・シェルとは    
A login shell is one whose first character of argument zero is a -, or one started with the -login option.
具体的には

ログイン・シェルは /etc/profile を実行する。 そこから .bash_profile, .bash_login, .profile の順に検索し、最初に見つかったものを実行する。

ログイン・シェルではないが、インタラクティブ・シェルであれば、 .bashrc を読んで実行しようとする。


(少し時間が経って思うには) PATH の順番とか考えないと。/etc/paths.d/ とかあるし。 ディレクトリィがPATHに重複して登録されるのを防ぐには、 やはりチェックするのが安全だろう。設定ファイルの読み直ししたいし。 一方で、そういうチェックを入れるのならば、 単一のファイルで全てやる、という方針も可能かもしれない、と思う。

とはいえ、設定ファイルを自分以外の何者 (気の利かないインストーラーとか) かがいじるという時代なので、それを考慮した方針が大事だ。

初めて UNIX に触れた頃は、telnet はあったけれど、 ssh どころか rsh も使えなかったし、 X Window System も使えなかった。 bash がなくて、csh を使っていた。 設定ファイルとして、.login.cshrc を書いていた。 sh (Bourne shell) には .profile しかないんだっけ? bash が .bash_profile, .bash_login, .profile, .bashrc を用意した気持ちが想像できなくもない。 C shell 使いには .bash_login.bashrc という感じなのかな (ちょっと節操がない感じがする)。


(2023/2/14追記) anaconda がやってくれることと、なかなか整合しないな…頭痛い。 anaconda 使いたい時だけ、一時的に設定を変えられないだろうか… 試行錯誤は続く… とりあえず Anaconda をインストールするときに、 .zshrc に(勝手に)書き込んでくれること(PATHの設定をしている)を .profile の上の方に移してみているけれど、 それで問題がないか、良く分からない。しばらくは様子見。

(2023/7/23追記) zsh について、設定ファイルの名前がよく似ているので、 動作も bash と同じようなものだと思っていたら、 どうも違うみたいだ。ややこしいね。 ログイン・シェルであっても、.zshrc を読むみたいだ。 だとすると、.zprofile の中で .zshrc を読む必要はないのか。

(2023/7/29追記) 今の macOS では、bash を使うと警告が出る。黙らせるために
export BASH_SILENCE_DEPRECATION_WARNING=1
とする。私は .bash_profile に入れてある。

桂田 祐史