unix – .bashrc, .profile, .bash_profile などを選択する

environment-variables unix

これは恥ずかしいことなのですが、長年 POSIX システムをフルに使ってきた私は、シェルのカスタマイズが .bashrc.profile か、それともどこか他の場所にあるべきなのか、いまだに理解するのに苦労しています。.pam_environment のような OS 固有の設定ファイルのいくつかは言うまでもありません

はい、私はドキュメントをパズルのように解く方法を知っていますし、各ファイルがいつロードされているか、されていないかを知る方法を知っています。私が疑問に思っているのは、誰かが特定のタイプのカスタマイズをどのファイルに入れるかを決めるための包括的なガイドラインをまとめたことがあるかどうかということです

  225  Avdi  2014-07-29


ベストアンサー

TL;DR:

  • ~/.bash_profileは超シンプルにして、.profile.bashrcを(順番に)ロードすればいいだけ

  • ~/.profileには、環境変数(PATHや友人など)のような、特にbashに関係のないものがあります

  • ~/.bashrc には、対話的なコマンドラインで欲しいものが何でも入っています。コマンドプロンプト、EDITOR 変数、私が使用するための bash エイリアス

他にもいくつか注意点があります

  • グラフィカルアプリケーションや sh (または sh として起動された bash) で利用できるものはすべて ~/.profile に入れなければなりません (MUST)

  • ~/.bashrcは何も出力してはいけません

  • ログインシェルでしか使えないはずのものは、~/.profileに入るべきです

  • ~/.bash_loginが存在しないことを確認する

250  Dan Rabinowitz  2014-07-29


ここ数年、私は多くの時間を無駄にしていたので、私は10分だけではなく、少しのためにこれを研究しました。これがベストなレイアウトなのかどうかは全くわからないのですが、たまたまほとんどのケースで正しく動作するようになっただけなのです

The requirements:

  • ~/.profile は /bin/sh と互換性がなければなりません – これには bash, dash, ksh, その他ディストロが使用することを選択したものも含まれます

  • 環境変数は、コンソールログイン(すなわち’ログイン’シェル)とグラフィカルログイン(すなわちGDM、LightDM、LXDMのようなディスプレイマネージャ)の両方で読めるファイルに入れなければなりません

  • ~/.profile~/.bash_profile の両方を持つことにはほとんど意味がありません。後者が欠けている場合、bash は喜んで前者を使用しますし、bash 固有の行は $BASH$BASH_VERSION のチェックでガードできます

  • *profile*rcの分離は、前者は’login’シェルに、後者はターミナルウィンドウを開くたびに使うということです。しかし、’login’モードのbashは~/.bashrcをソースにしないので、~/.profileは手動で行う必要があります

一番シンプルな構成になります

  • (bash 固有のものを除いて) すべての環境変数を設定する ~/.profile を持ち、おそらく一行か二行を表示し、bash で実行されている場合は ~/.bashrc をソースとし、それ以外の場合は sh 互換の構文に固執します

    export TZ="Europe/Paris"
    export EDITOR="vim"
    if [ "$BASH" ]; then
    . ~/.bashrc
    fi
    uptime
    
  • シェル固有の設定を実行する ~/.bashrc を持ち、Debian の sftp のようなものを壊さないように、対話モードのチェックで保護しています (bash は対話的でないシェルでも ~/.bashrc をロードするオプションでコンパイルされています)

    [[ $- == *i* ]] || return 0
    
    PS1='\h \w \$ '
    
    start() { sudo service "$1" start; }
    

しかし、ある種の非インタラクティブなコマンド(例えば ssh <host> ls)は ~/.profile をスキップしてしまうという問題もありますが、環境変数はそれらのコマンドにとっては非常に便利でしょう

  • 特定のディストリビューション (例: Debian) は、このような非対話型ログイン用に ~/.bashrc をソースにするオプションを付けて bash をコンパイルしています。この場合、すべての環境変数 (export ... 行) を別のファイル ~/.environ に移動し、.profile.bashrc の両方からソースを作成し、二度手間にならないようにガードを付けておくと便利です

    if ! [ "$PREFIX" ]; then   # or $EDITOR, or $TZ, or ...
    . ~/.environ           # generally any variable that .environ itself would set
    fi
    
  • 残念ながら、他のディストリビューション (例えば Arch) では、あまり良い解決策を見つけられませんでした。一つの可能性としては、(デフォルトで有効になっている) pam_env PAM モジュールを使用して、~/.pam_environment に以下のように記述することです

    BASH_ENV=./.environ        # not a typo; it needs to be a path, but ~ won't work
    

    そして、もちろん~/.environunset BASH_ENVに更新する


結論は?貝殻は苦痛だ環境変数は苦痛です。ディストリビューション固有のコンパイル時オプションは非常に厄介です

58  community wiki  2014-07-29


このShreevatsaRによる優れたブログ記事を見てみてください。ここでは抜粋していますが、ブログ記事に行くと、”ログインシェル “のような用語の説明、フローチャート、Zshの同様のテーブルが含まれています

Bashの場合、以下のように動作します。適当なカラムを読み下す。Aを実行し、次にBを実行し、次にCを実行する。B1,B2,B3は、見つかったファイルの最初のものだけを実行することを意味します

+----------------+-----------+-----------+------+
|                |Interactive|Interactive|Script|
|                |login      |non-login  |      |
+----------------+-----------+-----------+------+
|/etc/profile    |   A       |           |      |
+----------------+-----------+-----------+------+
|/etc/bash.bashrc|           |    A      |      |
+----------------+-----------+-----------+------+
|~/.bashrc       |           |    B      |      |
+----------------+-----------+-----------+------+
|~/.bash_profile |   B1      |           |      |
+----------------+-----------+-----------+------+
|~/.bash_login   |   B2      |           |      |
+----------------+-----------+-----------+------+
|~/.profile      |   B3      |           |      |
+----------------+-----------+-----------+------+
|BASH_ENV        |           |           |  A   |
+----------------+-----------+-----------+------+
|                |           |           |      |
+----------------+-----------+-----------+------+
|                |           |           |      |
+----------------+-----------+-----------+------+
|~/.bash_logout  |    C      |           |      |
+----------------+-----------+-----------+------+

38  Flimm  2014-07-29


私の「総合的な」ガイドラインを提供します

  • .bash_profile.profileは、.bashrcが存在する場合には、 [ -r $HOME/.bashrc ] && source $HOME/.bashrcなどを使って.bashrcをロードするようにします
  • 他のものは全て.bashrcに入れてください
  • Stop worrying.
  • 4年に1度かそこらで 10分かけてこの質問を調べて 諦める前に “心配しない “に戻るんだ

EDIT: 誰もがそれを信じたいと思っている場合に備えて、”包括的な “に恐怖の引用符を追加しました。)

23  Mechanical Fish  2014-07-29


私はこれを解明しようとすることを諦めて、一つのスクリプト(~/.shell-setup)を作り、他のすべてのスクリプトをソースにしました

このアプローチでは、~/.shell-setupが2つの特徴を持つことが必要です

  1. 繰り返しソースされても一度だけ実行する(インクルードガードを使用する)
  2. 不要な出力を発生させない(出力がOKの場合は検出)

#1 はかなり標準的なものですが、シェルスクリプトではあまり使われていないかもしれません

#2はもっと厄介です。私がbashで使っているのはこんな感じです

if [ "" == "$BASH_EXECUTION_STRING" -a "" == "$DESKTOP_SESSION" ]; then
echo "Hello user!" # ... etc
fi

残念ながら、どのようにしてそれを思いついたのか、対話型シェルの検出が不十分だった理由は覚えていません

1  ShadSterling  2014-07-31


すべてを.bashrcに入れて、.bashrc.profileからソースにする

bash の man ページから (OS X 10.9 の場合)

ログインシェルではない対話型シェルが起動されると、bash は ~/.bashrc ファイルが存在する場合には ~/.bashrc からコマンドを読み込んで実行します。これは –norc オプションを使用することで禁止されます。 rcfile file オプションは、~/.bashrc の代わりにファイルからコマンドを読み込んで実行するように bash を強制します

上の文章のように、すべてを.bashrcに入れているのはそのためです。しかし、ログインシェルを扱っている場合は少し挙動が異なります。もう一度、マンページから引用します

対話的なログインシェルとして、あるいは –login オプションを指定して非対話的なシェルとして bash が起動されると、まず /etc/profile ファイルが存在する場合には、/etc/profile からコマンドを読み込んで実行します。そのファイルを読んだ後、~/.bash_profile、~/.bash_login、~/.profile の順に探し、最初に存在して読めるものからコマンドを読み込んで実行します。シェルの起動時に –noprofile オプションを使用すると、この動作を抑制することができます

.profile はログインシェル用に読み込まれますが、.bashrc は読み込まれません。.bashrc にあるものをすべて複製するのは良くないので、動作が一貫しているようにするためには .profile でソースを作成する必要があります

ただし、.bashrc.profileから無条件にソースにするのはやめましょう。詳細はコメントや他の回答をご覧ください

-2  mattr-  2014-07-29


タイトルとURLをコピーしました