回答:
これは、シェルがインタラクティブかどうかをチェックしています。この場合、~/.bash_profile
シェルが対話型の場合にのみファイルを調達します。
「このシェルはインタラクティブですか?」を参照してください。その特定のイディオムを引用しているbashマニュアル。(また、$-
特殊変数にi
文字が含まれているかどうかをテストして、シェルがインタラクティブかどうかを確認することをお勧めします。これは、この問題へのより良いアプローチです。)
bash
設定解除非対話(あなたの以前のコメントにタイプミス)がIMOバグですPS1は、PS1はbashの固有の変数ではありません、それはそれを設定解除一切ビジネスを持っていません。それを行う唯一のシェルです(ただし、非対話型の場合でもデフォルト値にyash
設定さPS1
れます)。
[[ $- = *i* ]] && source ~/.bash_profile
)。
[ -n "${PS1}" ]
、にそれほど問題はないと思いますが、bashのマニュアルでも$-
シェルが対話型かどうかを判断するための検査を提案/推奨していることを強調するために、回答を更新しました。回答が改善されると思います。乾杯!
これは、シェルがインタラクティブであるかどうかをテストするための広範な方法です。これはbashでのみ機能し、他のシェルでは機能しないことに注意してください。したがって、(ばかげている場合は)okですが.bashrc
、動作しません.profile
(これはshによって読み取られ、bashはshの可能な実装の1つにすぎず、最も一般的な実装ではありません)。
対話型シェルは、シェル変数PS1
をデフォルトのプロンプト文字列に設定します。したがって、シェルがインタラクティブである場合は、PS1
が設定されます(ユーザーのシェルがシェル.bashrc
を削除した場合を除きます。これは、の上部でまだ発生しておらず、.bashrc
とにかく愚かなことだと考えることができます)。
逆はbashにも当てはまります。bashの非インタラクティブなインスタンスはPS1
開始時に設定解除されます。この動作は、(なぜでしょうbashのに固有のものであり、間違いなくバグであることを注意bash -c '… do stuff with $var…'
するときに動作しない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
ために役立ちます。.profile
つまり、コードが行うことの逆です!読む.profile
bashの場合は、(非対話型)ログインシェルである、そしてそれは、対話型シェルの場合は、それを読んでいません。
if [[ $- != *i* && -r ~/.profile ]]; then . ~/.profile; fi
[[ -o interactive ]]
(kshのは、bash、zshの)またはcase $- in (*i*) ...; esac
(POSIX)
PS1
インタラクティブに実行しないと実際には設定が解除されているようです。テストは簡単です。PS1=cuckoo bash -c '[ -n "${PS1}" ] && echo "PS1=[${PS1}]"'
何もPS1=cuckoo bash -i -c '[ -n "${PS1}" ] && echo "PS1=[${PS1}]"'
出力しません$PS1
が、bashスタートアップファイルのset の値を出力します(文字列 "cuckoo"は出力しません)。
$-
含むことは必要ありませんi
。
[ -n "${PS1}" ]
間違った呼び出しは少し行き過ぎです(あなたの答えでは、それは悪い考えだと言い、理由にさえ行きます)、それは影響しませんとにかくbashします(シェルが非対話型の場合はPS1とPS2の設定が解除されるためです)。「非推奨」などの単語を使用するか、アプローチの「制限」について話すのがよいでしょう。私はそれが完全に「間違っている」とは思わない。PS1のエクスポートに問題がある場合、それは間違いありません。とにかく、これについて詳しく説明してくれてありがとう。
この奇妙な概念はbash
、POSIXシェルクローンとしてではなく、Bourne Shell
クローンとして始まったという事実の結果であると思われます。
その結果、POSIXインタラクティブ動作($ENV
インタラクティブシェルで呼び出される)が後で追加されbash
、広く知られていません。
同様の動作を許可するシェルが1つあります。これはcsh
、$prompt
特定の値を持つcsh許可です。
$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
のPS1
いずれかの非対話型シェルでは、標準で許可されていないと、他のシェルで行われていません。
したがって、クリーンなプログラミング(を使用してもbash
)は、対話型シェルのコマンドをに配置すること$HOME/.bashrc
です。
まずDebianについて話をしますが、ほとんどの場合、Ubuntuもbashに設定しています。そして、後者は他のシステムに触れます。
シェル起動ファイルの設定には多くの意見があります。
私も私の意見はありますが、正しい設定の既存の例を示すようにします。
ファイルの例を見つけるのは非常に簡単なので、debuanを使用します。
そして、debianは頻繁に使用されるため、設定は十分にテストされています。
シェルがインタラクティブかどうかを確認するためだけです。
debianおよびubuntu のデフォルト/etc/profile
(/ usr / share / base-files / profileから):
if [ "${PS1-}" ]; then
if [ "${BASH-}" ] && [ "$BASH" != "/bin/sh" ]; then
ifの読み取り:ifインタラクティブ(PS1のデフォルトセット)で、bashシェルの場合(ただし、デフォルトとして機能しないsh
)、PS1を特定の新しいもの(デフォルトではない)に変更します。
debianのデフォルトに/etc/bash.bashrc
は以下も含まれます:
# 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
、ほとんどのシェル用であり、~/.bashrc
(ほぼと同等~/.bash_profile
)、bash専用です。
したがって、ソース~/.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
は、特定のユースケースにすでにロードされているはずの一般的なルールを再適用するだけなので、「それほど悪くない」(私は「良い」とは言っていません)。そして、ファイルのソースがループする可能性があるので、私は良いと言っていません。サブディレクトリが親をロードするときのように、それはディレクトリループです。~/.bash_profile
~/.bashrc
そして、この相互調達において、対話型シェルのチェックが意味をなしています。シェルがインタラクティブである場合にのみ~/.bashrc
読み込まれますが、今度はそれが読み込まれる~/.profile
(またはその逆)可能性があり、この場合はインタラクティブシェルのチェックを使用できます。
( export PS1='abc$ '; bash -c 'echo "[$PS1]"' )
だけで印刷され、[]
。zshのは、少なくとも実験から、同じことをしていないようだ...いずれにせよ、意思のは、[ -n "$PS1" ]
シェルが対話であるかどうかをチェックすることです。