PS1が設定されていることを確認する目的は何ですか?

PS1が設定されていることを確認する目的は何ですか?

[ -n "$PS1" ]の目的は何ですか[ -n "$PS1" ] && source ~/.bash_profile;?この行は.bashrcドットファイルに含まれています。買戻契約

答え1

これはシェルが対話型であることを確認します。この場合、~/.bash_profileシェルが対話型の場合にのみファイルをインポートします。

バラより「これはシェルインタラクティブですか?」Bashのマニュアルには特定のイディオムが引用されています。 ($-特殊変数にこの文字が含まれているかどうかをテストしてシェルが対話型であることを確認することは、iこの問題を解決するためのより良い方法でもあります。)

答え2

これは何のためであるか。

これは、シェルが対話型であるかどうかをテストするために広く使用されています。他のシェルでは動作せず、bashでのみ動作します。したがって、については問題ありませんが(愚かな場合).bashrcは機能しません.profile(shで読むと、bashはshの可能な実装の1つにすぎず、最も一般的な実装ではありません)。

働く理由(bashでのみ!)

対話型シェルの設定シェル変数PS1デフォルトのプロンプト文字列として。したがって、シェルがインタラクティブである場合PS1(ユーザーが.bashrcそれを削除しない限り、これはまだ最上位で起こる可能性がなく、愚かなことと考える.bashrcことができます)。

Bashでは、その逆は本当です。 Bashの非対話型インスタンスはPS1起動時に設定を解除します。この動作はbashに固有のものであり、間違いなくバグです(bash -c '… do stuff with $var…'isの場合、なぜ動作しないのですか?)。しかし、bashのすべてのバージョン(4.4を含む)(私が書いた最新バージョン)はこれを行います。varPS1

多くのシステムがPS1環境にエクスポートされます。多くの異なるシェルがPS1異なる構文を使用しているため、これは悪い考えです(例:bashプロンプトエスケープとは全く違うzshプロンプトエスケープ)。ただし、これはあまりにも一般的であり、実際に設定PS1を表示することは、シェルが対話型であるという信頼できる表示ではありません。シェルはPS1環境から継承できます。

ここではなぜ(間違って)使用されたのですか?

.bashrc対話式で起動したときに bash が読み取るファイルです。よく知られていないという事実は、bashが.bashrcisもログインシェルであるということであり、bashの経験的な結論はこれがリモートセッションであるということです(bashは親セッションがあるかどうかをrshd確認しますsshd)。 2番目のケースでは、PS1ドットファイルがまだ実行されていないため、環境に設定される可能性はありません。

ただし、コードがこの情報を使用する方法は逆効果を生む可能性があります。

  • シェルが対話型シェルの場合、.bash_profileそのシェルで実行されます。しかし、.bash_profileそれはログイン時間スクリプトです。セッションごとに一度だけ実行されるようになっているいくつかのプログラムを実行することもできます。シェルを実行する前に、ユーザーが意図的に異なる値に設定した特定の環境変数をオーバーライドできます。.bash_profile非ログインシェルで実行すると混乱が発生する可能性があります。
  • シェルが非対話型リモートログインシェルの場合、ロードされません.bash_profile。ただし、この場合、.bash_profile非対話型ログインシェルは自動的に/etc/profileロードされないため、ロードすると便利です~/.profile

人々がこれを行う理由は、ユーザーがGUI(非常に一般的な場合)を介してログインし、.bash_profile代わりに環境変数設定を置くためだと思います.profile。ほとんどのGUIログインメカニズムは呼び出されます.profileが、呼び出されません.bash_profile.bash_profileセッションの一部として読み取るときにbashを実行する必要があります)。 shではなく開始)。この構成では、ユーザーが端末を開くと環境変数が取得されます。ただし、ユーザーは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シェルが非対話型の場合にのみ読む——つまり、コードがすることと正反対です!.profilebashが(非対話型)ログインシェルの場合はお読みください。対話型シェルの場合は読まないでください。

if [[ $- != *i* && -r ~/.profile ]]; then . ~/.profile; fi

答え3

bashこの奇妙な概念は、POSIXシェルクローンで始まらず、クローンでBourne Shell始まるという事実によるものです。

したがって、POSIX対話型の動作($ENV対話型シェルが呼び出されます)が後で追加されましたが、bashよく知られていません。

同様の動作を達成するシェルがあります。これはcshcshによって与えられた特定の値です$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.

ただし、これはBourneシェルや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有効である必要はなく、インタラクティブシェルも$-含めません。 POSIXでは、シェルをインタラクティブモードに強制するだけiです。sh -i

変数は$PS1環境から取得できるため、非対話型モードでも値を持つことができます。実際、非対話型シェルのbash unsetsはPS1標準によって付与されず、他のシェルでも施行されません。

したがって、きちんとしたプログラミング(を使用している場合でもbash)は、インタラクティブシェルのコマンドをに入れることです$HOME/.bashrc

答え4

まず、DebianとUbuntuがbashのために設定したことについて話しましょう。後者は他のシステムに関連しています。

シェル起動ファイルの設定については多くのコメントがあります。
私も私の意見がありますが、正しい設定の既存の例を見せようとしています。
私はドキュメントの例を見つけるのが簡単なのでdebuanを使用します。
そしてDebianをたくさん使うので設定テストもうまくいき、

PS1が設定されていることを確認する目的は何ですか?

シェルが対話型かどうかを確認するためです。

これ/etc/profileDebian のデフォルト値とUbuntu(/usr/share/base-files/profileから):

if [ "${PS1-}" ]; then
    if [ "${BASH-}" ] && [ "$BASH" != "/bin/sh" ]; then

読み取る場合:対話型(PS1デフォルト)でbashシェル(ただしデフォルトシェルとして機能しないsh)の場合は、PS1を特定の新しいシェル(デフォルトシェルではない)に変更します。

これ/etc/bash.bashrcDebian のデフォルト値以下も含まれます:

# 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(root所有)に最も広範な影響(およびより多くのシェル)を置き/etc/bash.bashrc(またroot所有)に影響しますが、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(またはその逆)にロードすることができます。この場合は、対話型シェル検証を使用できます。

関連情報