[ -n "$PS1" ]
の[ -n "$PS1" ] && source ~/.bash_profile;
の目的は何ですか?この行は、ドットファイルの.bashrc
repo に含まれています。
これは、シェルがインタラクティブかどうかを確認しています。この場合、~/.bash_profile
シェルがインタラクティブな場合はファイル。
特定のイディオムを引用しているbashマニュアルの "Is this Shell Interactive?" を参照してください。 (また、$-
特殊変数にはi
文字が含まれています。これは、この問題へのより良いアプローチです。)
これは、シェルがインタラクティブであるかどうかをテストするための広範な方法です。これはbashでのみ機能し、他のシェルでは機能しないことに注意してください。したがって、.bashrc
の場合は(ばかげている場合は)問題ありませんが、.profile
では機能しません(これはshによって読み取られ、bashはshの可能な実装の1つにすぎず、最も一般的ではありません1)。
対話型シェルは Shell変数PS1
をデフォルトのプロンプト文字列に設定します。したがって、シェルがインタラクティブである場合、PS1
が設定されます(ユーザーの.bashrc
がそれを削除した場合を除き、これは.bashrc
の上部でまだ発生していない可能性があります。とにかく愚かなこと)。
逆はbashに当てはまります。bashの非対話型インスタンスは、開始時にPS1
を設定解除します。この動作はbashに固有のものであり、間違いなくバグであることに注意してください(var
がbash -c '… do stuff with $var…'
?であるときにPS1
が機能しないのはなぜですか)。しかし、4.4(私が書いている最新バージョン)までのすべてのバージョンのbashがこれを行います。
多くのシステムはPS1
を環境にエクスポートします。多くの異なるシェルがPS1
を使用するが、構文が異なるため、これは悪い考えです(たとえば、 bashのプロンプトエスケープ は zshのプロンプトエスケープ )とは完全に異なります。しかし、実際にはPS1
が設定されていることを確認しても、シェルがインタラクティブであることを示す信頼できる指標ではありません。シェルは環境からPS1
を継承した可能性があります。
.bashrc
は、対話型の起動時にbashが読み取るファイルです。あまり知られていない事実ですが、bashは.bashrc
も読み取りシェルであり、bashのヒューリスティックはこれがリモートセッションであると結論します(bashはその親がrshd
またはsshd
かどうかをチェックします) )。この2番目のケースでは、ドットファイルがまだ実行されていないため、環境でPS1
が設定されることはほとんどありません。
ただし、コードがこの情報を使用する方法は逆効果です。
.bash_profile
を実行します。ただし、.bash_profile
はログイン時のスクリプトです。セッションごとに1回だけ実行することを目的とした一部のプログラムを実行する場合があります。シェルを実行する前に、ユーザーが意図的に別の値に設定したいくつかの環境変数を上書きする可能性があります。ログインしていないシェルで.bash_profile
を実行すると中断が発生します。.bash_profile
は読み込まれません。しかし、これは.bash_profile
のロードが役立つ場合です。非インタラクティブログインシェルは/etc/profile
と~/.profile
を自動的にロードしないためです。これを行う理由は、GUIを介してログインするユーザー(非常に一般的なケース)であり、環境変数の設定を.bash_profile
ではなく.profile
に置くユーザーのためだと思います。ほとんどのGUIログインメカニズムは.profile
を呼び出しますが、.bash_profile
は呼び出しません(.bash_profile
を読み取るには、セッションの起動の一部として、shではなくbashを実行する必要があります)。この構成では、ユーザーがターミナルを開くと、環境変数が取得されます。ただし、ユーザーは、非常に一般的な混乱の原因であるGUIアプリケーションで環境変数を取得しません。ここでの解決策は、.profile
ではなく.bash_profile
を使用して環境変数を設定することです。 .bashrc
と.bash_profile
の間にブリッジを追加すると、解決する以上の問題が発生します。
現在のシェルがインタラクティブかどうかをテストする簡単で移植可能な方法があります。オプション-i
が有効かどうかをテストします。
case $- in
*i*) echo "This Shell is interactive";;
*) echo "This Shell is not interactive";;
esac
これは.bashrc
からread .profile
で、シェルが非インタラクティブの場合にのみ役立ちます。つまり、コードの動作が逆になります。 bashが(非対話型)ログインシェルの場合は.profile
を読み取り、対話型シェルの場合は読み取らないでください。
if [[ $- != *i* && -r ~/.profile ]]; then . ~/.profile; fi
この奇妙な概念は、bash
がPOSIXシェルクローンではなくBourne Shell
クローンとして始まったという事実の結果であると思われます。
その結果、POSIXインタラクティブ動作($ENV
はインタラクティブシェルに対して呼び出されます)がbash
に後で追加され、広く知られていません。
同様の動作を許可するシェルが1つあります。これはcsh
であり、c [は$Prompt
に特定の値があることを許可します。
$Prompt not set non-interactive Shell, test $?prompt.
$Prompt set but == "" .cshrc called by the which(1) command.
$Prompt set and != "" normal interactive Shell.
しかし、これはボーンシェルにもPOSIXシェルにも当てはまりません。
POSIXシェルの場合、許可される唯一の方法は、対話型シェルのコードをファイルに入れることです。
$ENV
シェル固有の名前があります。それは例えば.
$HOME/.kshrc for the korn Shell
$HOME/.bashrc for bash
$HOME/.mkshrc for mksh
$HOME/.shrc for the POSIX Bourne Shell
他の人々はシェルフラグ-i
に言及しましたが、これは信頼できるプログラミングには使用できません。 POSIXは、set -i
が機能することも、$-
がインタラクティブシェルのi
を含むことも必要としません。 POSIXは、sh -i
がシェルをインタラクティブモードに強制することを要求するだけです。
変数$PS1
は環境からインポートできるため、非インタラクティブモードでも値が含まれる場合があります。非対話型シェルのbash
unset
s PS1
は、標準では許可されておらず、他のシェルでは実行されません。
したがって、クリーンなプログラミング(bash
を使用しても)は、対話型シェルのコマンドを$HOME/.bashrc
に配置することです。
まずDebianについて話をしますが、ほとんどの場合、Ubuntuもbashに設定しています。そして、後者は他のシステムに触れます。
シェル起動ファイルの設定には多くの意見があります。
私も私の意見はありますが、正しい設定の既存の例を示すようにします。
ファイルの例を見つけるのは非常に簡単なので、debuanを使用します。
そして、debianは頻繁に使用されているため、設定は十分にテストされています。
シェルがインタラクティブであるかどうかを確認するだけです。
debian とubuntu(/ usr/share/base-files/profileから)のデフォルト_/etc/profile
_:
_if [ "${PS1-}" ]; then
if [ "${BASH-}" ] && [ "$BASH" != "/bin/sh" ]; then
_
Ifの読み取り:ifインタラクティブ(PS1のデフォルトセット)でbashシェルの場合(ただし、デフォルトとして機能しないsh
)、PS1を特定の新しいもの(デフォルトではない)に変更します。
default _/etc/bash.bashrc
_ in debian には以下も含まれます:
_# If not running interactively, don't do anything
[ -z "$PS1" ] && return
_
それはそれが何をするかでかなり明確です:対話型の場合、ソースしないでください(残り)。
ただし、_/etc/skel/.bashrc
_の は、インタラクティブシェルをテストする正しい方法の例 です(_$-
_を使用):
_# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
_
PS1の理由と代替案が明確に示されているはずです。
レポートしている設定は避けてください。
順序(システム設定から(bashの場合)より具体的なユーザー設定)は、_/etc/profile
_、_/etc/bash.bashrc
_、_~/.profile
_、最後に_~/.bashrc
_です。これにより、最も広範な効果(およびより多くのシェル)が_/etc/profile
_(ルートが所有)に続き、_/etc/bash.bashrc
_(ルートも所有)が続きますが、bashにのみ影響します。次に、_$HOME
_の個人設定を使用します。最初の設定は、ほとんどのシェルでは_~/.profile
_であり、bashのみに固有の_~/.bashrc
_(_~/.bash_profile
_とほぼ同等)です。
したがって、_~/.bashrc
_で_~/.profile
_をソース化することは間違っています。これは、bashの特定のユーザー設定をより一般的な シェルに影響する に変換しています。 がこのように行われた場合を除いて :
_# ~/.profile: executed by the command interpreter for login shells
# if running bash
if [ -n "$BASH_VERSION" ]; then
# include .bashrc if it exists
if [ -f "$HOME/.bashrc" ]; then
. "$HOME/.bashrc"
fi
fi
_
Bashが実行されていることを確認し、その場合は_.bashrc
_のみをロードします。
これはDebianからの上流の決定です。 根拠はここで説明されています 。
実際、逆のソーシング_~/.profile
_ in _~/.bash_profile
_(または_~/.bashrc
_)は、特定のユースケースに既にロードされているはずの一般的なルールを再適用するだけなので、「悪い」(「良い」とは言っていません)。そして、ファイルのソースがループする可能性があるので、私は良いと言っていません。サブディレクトリが親をロードするときのように、それはディレクトリループです。
そして、インタラクティブシェルのチェックが意味をなすのは、このクロスソースです。シェルがインタラクティブな場合にのみ_~/.bashrc
_が読み込まれますが、次に_~/.profile
_(またはその逆)が読み込まれる可能性があり、この場合はインタラクティブシェルのチェックを使用できます。