OSXログインシェルでデフォルトでインタラクティブシェルが使用されるのはなぜですか?


43

Linuxおよび私の知る限り、すべてのUnixシステムでは、ターミナルエミュレータはデフォルトで対話型の非ログインシェルを実行します。これは、bashの場合、開始されたシェルが次のことを行うことを意味します。

ログインシェルではないインタラクティブシェルが開始されると、bashはこれらのファイルが存在する場合、/etc/bash.bashrcおよびからコマンドを読み取り、実行します~/.bashrc--norc オプションを使用すると、これを禁止 できます。

--rcfile ファイルのオプションは、ファイルからコマンドを読み込み、実行するためにはbashを強制代わりのだろう/etc/bash.bashrc~/.bashrc

ログインシェルの場合:

bashが対話型ログインシェルとして、または--loginオプション付きの非対話型シェルとして呼び出されると、bashは/etc/profile、ファイルが存在する場合、まずfileからコマンドを読み取って実行します。そのファイルを読んだ後、それは探し~/.bash_profile~/.bash_login、および~/.profile、そのためには、および読み込み、存在し、読み取り可能である最初のものから実行するコマンドを。

--noprofileシェルは、この動作を抑制するために開始されたときにオプションを使用することができます。

OSX上で、しかし、デフォルトのターミナル(Terminal.app)で起動(bashの場合)デフォルトのシェル実際にソース~/.bash_profile~.profileなどは言い換えれば、それは、ログインシェルのような役割を果たします。

主な質問:なぜデフォルトのインタラクティブシェルがOSXのログインシェルなのですか?OSXがこれを行うことにしたのはなぜですか?これは、~/.bashrcOSX で変更を記述するシェルベースのものに関するすべての指示/チュートリアルがOSXで失敗することを意味します~/.profile。それでも、多くの告発はAppleで平準化できるが、無能な開発者やばかげた開発者を雇うことはそれらの1つではない。おそらく、彼らにはこれには十分な理由があったのに、なぜですか?

サブ質問:Terminal.appは実際にインタラクティブなログインシェルを実行しますか、それともbashの動作を変更しましたか?これはTerminal.app固有のものですか、それとも端末エミュレーターから独立していますか?


2
Terminal.appはログインシェルを実行します。Appleがなぜそうすることを選んだのかはわかりません。
ジル 'SO-悪であるのをやめる'

回答:


33

それはの道はずの仕事は、あなたがプロンプトシェルを取得するときに両方の点で、それである.profile.bashrc実行されています。そのポイントに到達する方法の具体的な詳細は二次的な関連性がありますが、いずれかのファイルがまったく実行されなかった場合は、設定が不完全なシェルになります。

Linux(および他のXベースのシステム)のターミナルエミュレーターを実行する必要がないの.profileは、通常、Xにログインしたときに既に実行されているためです。設定.profileは、サブプロセスに継承されるため、(たとえば経由で.Xsession)ログイン時に1回実行される限り、それ以降のサブシェルで再実行する必要はありません。

Alan ShutkoによってリンクされたDebian wikiページが説明しているように:

「なぜある.bashrcとは別のファイルには.bash_profile、その後、?これは、マシンが非常に遅く、今日のワークステーションと比較したとき、ほとんど歴史的な理由のために行われている。内のコマンドを処理する.profileか、.bash_profile非常に長い時間がかかることがあり、特に多くの作業機械に外部コマンド(プレバッシュ)で実行する必要があったため、子プロセスに渡すことができる環境変数を作成する困難な初期設定コマンドが入れられ.bash_profileます。継承されない一時的な設定とエイリアスは入れられますで.bashrc、彼らはすべてのサブシェルで再読み取ることができるように。」

OSXにも同じルールが適用されますが、1つだけ例外があり.profileます。OSXGUIは、グローバル設定を読み込む独自の方法があるため、ログインしても実行されません。しかし、手段OSX上の端末エミュレータがあることことを実行する必要.profileそうでない場合、あなたが潜在的に不自由シェルで終わるだろう、(それがログインシェルだとシェルそれ上市を伝えることを)。


現在、他のほとんどのシェルでは共有されていないバッシュの一種の愚かな特性は.bashrc、ログインシェルとして起動された場合、自動的に実行されないことです。そのための標準的な回避策は、次のコマンドのようなものを含めることです.bash_profile

[[ -e ~/.profile ]] && source ~/.profile    # load generic profile settings
[[ -e ~/.bashrc  ]] && source ~/.bashrc     # load aliases etc.

または、まったく持たず.bash_profile、必要に応じ.profileて実行するbash固有のコードを汎用ファイルに含めることも.bashrcできます。

OSXがデフォルト.bash_profileまたはこれを行わ.profile ない場合、それは間違いなくバグです。いずれにせよ、適切な回避策は、単にこれらの行をに追加すること.bash_profileです。


編集: strugee notesのように、OSXのデフォルトシェルは以前はtcshでしたが、その動作はこの点で非常に賢明です:対話型ログインシェルとして実行すると、tcshは自動的に両方.profile .tcshrc /を読み取る.cshrcため、.bash_profileトリックのような回避策は不要です上に示しました。

これに基づいて、OSXが適切なデフォルトを提供できなかったことは99%確信しています。.bash_profileなぜなら、彼らがtcshからbashに切り替えたとき、Appleの人々は単にbashの起動動作のこの小さないぼに気付かなかったからです。tcshでは、このようなトリックは必要ありませんでした。OSX端末エミュレーターJust Plain Worksからログインシェルとしてtcshを起動し、そのようなklugesなしで正しいことを行います。


1
おかげで、私はそのすべてを知っていた。私の質問は、なぜ OSXが.bashrc無関係になるようにセットアップすることを選んだのですか?なぜ彼らはすべてのシェルにログインシェルを作ることにしたのですか?私が知る限り、あなたの最後の文だけがそれに対処し、それがバグだと言うだけです。
テルドン

1
いいえ、問題は、ターミナルエミュレータでログインシェルを起動することです。ドットファイルはデフォルトのbashの動作です。ログインシェルを起動すると、bashrcなどではなくプロファイルなどが読み込まれます。問題は、ログインシェルが非ログインシェルではなく実行される理由です。
テルドン

2
はい、私とアランは、Linuxとは異なり.profile、ユーザーがGUIにログインしたときにOSXが実行されないため、後で実行する必要$PATH.profileあります。 。副作用として、これが原因で.bashrcはないという事実はバグです。それがbashまたはOSXのバグであるかどうかについて議論することができますが、正しい動作が環境変数from .profileとbash config設定の両方.bashrcがロードされることを保証することであるという事実は変わりません。
イルマリカロネン

1
すべてのサブシェルが再実行されるため、.bashrcソースを持つ.profileことは悪い考え.profileです。他に何もなければ、これは冗長なエントリをに追加し続ける.profileような一般的なイディオムを引き起こしexport PATH = "$HOME/bin:$PATH"ます$PATH.profileソース.bashrcを持つことの方がはるかに理にかなっていますが、実際に実行しているシェルが実際にはbashであることを確認してからです。持つ.bash_profileソースの両方を.profile して .bashrc、私は上記の提案として、、IMO、最も賢明なオプションです。
イルマリカロネン

2
そして、私は「なぜ彼らはログインシェルを使用するのか?」に対する答えを言っています。「ロードする必要があるため.profile」である一方、「なぜ、彼らはソース.bashrcから.profileではないのですか?」である「それはバグだから!」真剣に、それはおそらく意図的な決定ではありえません。おそらく、Macエコシステムでは、シェルはほとんどのユーザーが対処するべきではない二流市民であるため、見落とされているだけです。(追伸:歴史的説明についてはstrugeeの回答も参照してください。これは、ほぼ確実にtcshからbashへの切り替えからの回帰です。)
イルマリカロネン

14

Xターミナルアプリケーションがデフォルトで非ログインシェルを実行する主な理由は、時間の初めに、.Xsessionが.profileを実行して初期ログインアイテムを設定することです。次に、それはすべて既にセットアップされているため、ターミナルアプリで実行する必要はなく、.bashrcを実行できます。これが重要な理由の議論はhttps://wiki.debian.org/DotFilesにあります

例としてxdmを取り上げましょう。pierreはある日休暇から戻ってきて、システム管理者がDebianシステムにxdmをインストールしたことを発見します。彼は正常にログインし、xdmは彼の.xsessionファイルを読み取り、fluxboxを実行します。間違ったロケールでエラーメッセージが表示されるまで、すべては問題ないようです。彼は.bash_profileのLANG変数をオーバーライドし、xdmは.bash_profileを読み取らないため、彼のLANG変数はfr_CAではなくen_USに設定されます。

現在、この問題の単純な解決策は、「xterm」を起動する代わりに、「xterm -ls」を起動するようにウィンドウマネージャーを構成できることです。このフラグは、通常のシェルを起動する代わりに、ログインシェルを起動する必要があることをxtermに伝えます。この設定では、xtermは/ bin / bashを生成しますが、引数ベクトルに「-/ bin / bash」(または「-bash」)を挿入するため、bashはログインシェルのように機能します。これは、彼が新しいxtermを開くたびに、/ etc / profileと.bash_profile(組み込みのbash動作)を読み取り、次に.bashrc(.bash_profileがそうするように指示するため)を読み取ることを意味します。これは最初はうまくいくように見えるかもしれません-彼のドットファイルは重くないので、彼は遅延に気づきさえしません-しかし、より微妙な問題があります。彼はまた、fluxboxメニューから直接Webブラウザーを起動し、また、WebブラウザーはfluxboxからLANG変数を継承しますが、これは現在、間違ったロケールに設定されています。したがって、彼のxtermは問題なく、彼のxtermから起動されたものは問題ないかもしれませんが、彼のWebブラウザーは依然として間違ったロケールのページを提供しています。

OS Xでは、ユーザー環境は多数のシェルスクリプトによって起動されることはなく、launchdはいつでも.profileをソースしません。(これは、環境変数を設定するのがはるかに面倒だということを意味するので、一種の恥ずべきことですが、それは人生です。)そうではないので、いつ.profileを実行しますか? ssh'dでのみ?多くのボックスがsshのターゲットになることは決してないので、それは無意味に思えます。同様に、デフォルトで端末がログインシェルを実行するようにして、.profileがいつか実行されるようにします。

では、.bashrcはどうですか?役に立たない?いいえ。VT100の時代に持っていた目的がまだあります。これは、ターミナルウィンドウを開く以外のシェルを開くときに使用されます。したがって、Emacsまたはviをシェルアウトする場合、またはsuユーザーを実行する場合。


1
引用しているDebianページは、OSXがデフォルトですべてのシェルをログインシェルにすることを決定した理由ではなく、Debianの.profileソースを説明.bashrcしています。実際、あなたは私の別の質問に答えています、ありがとう!ただし、あなたの答えはOSXの選択を説明するものではなく、Debianの引用は、私が知る限りここでは完全に無関係です(要点を逃している場合はお知らせください)。OSXの方法は、.bashrcetcなどを役に立たなくし、.profileそれ以上の有用性をもたらしません。
テルドン

4

なぜ彼らがそうしたのか分かりません。しかし、これは私の推測です。

まず、GNU / Linuxシステムでは、当然vt1、vt2などに切り替えることができます。ログインシェルが表示されることに注意してください。OS Xシステムには、同等のものはありません。UNIXの基盤にアクセスする唯一の方法は、ターミナルエミュレーターまたはシングルユーザーモードを使用することです(免責事項:私は実際にシングルユーザーモードを使用したことがありません。コマンドライン駆動型IIRCですが、間違っている可能性があります)。したがって、OS Xでは、エミュレータのデフォルトがシステム全体のデフォルトになります。

では、なぜデフォルトをログインシェルにするのでしょうか?これを行うために考えられるいくつかの理由があります(多くはありません)。

  • ボックスにSSHで接続すると、一貫したユーザーエクスペリエンスが提供されます。(OS Xのサーバーエディションでは特に重要です。おそらく、OS Xサーバーを実行している場合、あなたは初心者です。)
  • OS Xのデフォルトのシェルはでしたtcsh。これはあなたが得ることのできる推測とほぼ同じですが、tcsh通常はログインシェルとして実行すると何かが行われ、履歴パターンがスタックする可能性があります。(しかし、私はそれを疑います-多分、古い常連の誰かが私たちに話すことができました。)
  • 「私たちはアップルです。私たちは地球上で最大のUNIXディストリビューションのベンダーです。私たちの理由がいかに些細なことでもかまいません。決定を下す場合、あなたのツールはそれに対処しなければなりません。」

正直なところ、私はダーウィンを約6年間使用しており、この質問に適切に答えることができません。私にとっても意味がありません。

あなたのサブ質問に答えるために、bashパッチを適用したり、何もしません(少なくともこのため)。デフォルトのターミナルエミュレータはデフォルトでログインシェルを実行し、おそらくiTermはそれをコピーします。


1
tcshに言及するための+1は、この点でbashの動作よりもはるかに安全であるためです。対話型ログインシェルとして起動した場合、tcshは両方 .profile、および.tcshrc/で.cshrc答えたようなKlugを必要としません。それを考えると、この動作はtcshからbashへの切り替えによって引き起こされる未解決の回帰であると思われます。
イルマリカロネン

@IlmariKaronen tcshのソースおよび/ は(ここ)意味しますか?tcshがソースを取得しても意味がありません。通常、受け入れられない構文のコマンドが含まれています。macOSはありませんが、Ubuntu 16.04でログインシェルを作成しました。調達されていません。tcsh(1)はそのファイルについて言及しておらず、このtcsh(1)も言及していません。.login.tcshrc.cshrc.profileshtcsh/bin/tcsh.profile
エリアケイガン

3

これは現在のステータスの更新です。新しいMacOSXバージョンがリリースされ、ログイン動作が変更されたため、回答は古くなっています。

この質問は2014年に質問され、回答されました。さまざまなLinuxディストリビューションとBSD(ディストリビューションではない場合はそれらを呼んでも)で使用する共通の.bashrcおよび.bash_profileセットを作成しようとして、このテーマを調査しました。

Sierraがインストールされた中古のMac Miniを最近購入したので、現在10.6、10.10、10.11、および10.12のシステムがあります。古いものを変更しましたが(手がかりを以前の状態に残しています)、10.12 Sierraのインストールは変更されていません。

結果:10.12 Sierraでは、デフォルトの.bashrc、.bash_profile、または.profileは作成されません。/ etcには、bashrc、bashrc_Apple_Terminal、およびプロファイルがあります。/ etc / profileの内容:

# System-wide .profile for sh(1)

if [ -x /usr/libexec/path_helper ]; then
    eval `/usr/libexec/path_helper -s`
fi

if [ "${BASH-no}" != "no" ]; then
    [ -r /etc/bashrc ] && . /etc/bashrc
fi

/ etc / bashrcの内容:

# System-wide .bashrc file for interactive bash(1) shells.
if [ -z "$PS1" ]; then
   return
fi

PS1='\h:\W \u\$ '
# Make bash check its window size after a process completes
shopt -s checkwinsize

[ -r "/etc/bashrc_$TERM_PROGRAM" ] && . "/etc/bashrc_$TERM_PROGRAM"

/ etc / bashrc_Apple_Terminalスクリプトは、PROMPT_COMMAND変数を設定し、各端末のセッション状態を保持するメカニズムを設定します。ターミナルアプリを終了すると、アプリを再度起動したときに前のセッションの状態が復元されます。それ以外の場合、/ etc / bashrcにはほとんど何も設定されず(最小$ PS1)、他のカスタマイズ(実際の$ PS1、エイリアス、関数)は〜。 、.bash_profileがソース)。

ログインセッションを開始するデフォルトの動作が表示され、編集できることを除いて、iTerm2はターミナルアプリと同じように動作することを確認しました。

X11(現在はXQuartz)XTermターミナルセッションを実行すると、Linuxシステムの場合と同じ非ログインセッションが表示されます。.bash_profile(または.profile)はスキップされ、.bashrcが取得されます。

そして、ここに私の答えがあります:

ターミナルアプリはxterm(TERM = xterm-256color)であると主張していますが、X11がインストールされていない限り、$ DISPLAY変数を設定しません。X環境のシミュレーションを見ていますが、完全に実際の環境ではありません。-Xスイッチ(X11転送を有効にする)を使用して別のシステムにSSHで接続すると、$ DISPLAY変数がないため失敗します。X11をインストールしてから、別のシステムにSSH接続した場合、X11の転送は成功します。

結論(および短い答え):ターミナルアプリは真のX11ターミナルではありません($ DISPLAYを設定しません)。/ etc / profileおよび〜/ .bash_profileまたは〜/ .profileから値を設定するためにログインセッションである必要があるという点で、XTermセッションよりもSSHログインのように動作します。


0

上記の回答は、対話型シェルがデフォルトでmacOS上のログインシェルである理由を説明しました:の設定は/etc/profile~/.profileXベースシステム上の非ログインシェルによって継承されますが、 macOSでは継承されません。ここでは、macOSでログインシェルを常に使用する必要があることを思い出してくださいpath_helper

 cat /etc/profile # or cat /etc/zprofile
# System-wide .profile for sh(1)

if [ -x /usr/libexec/path_helper ]; then
    eval `/usr/libexec/path_helper -s`
fi

if [ "${BASH-no}" != "no" ]; then
    [ -r /etc/bashrc ] && . /etc/bashrc
fi

path_helperユーティリティは、ディレクトリ内のファイルの内容を読み取り/etc/paths.d/etc/manpaths.d し、にその内容を追加PATHし、MANPATHそれぞれの環境変数。(MANPATH環境変数は、環境で既に設定されていない限り変更されません。)

非ログインシェルを使用している場合、一部のパスはインポートされません。

私はそれは常ににファイルを配置する開発者のための良いアイデアだと思う/etc/paths.d彼らのパスの値をインポートすることではなく、のような場所に呼び出し可能なバイナリをシンボリックリンクしません/usr/bin/bin。(デフォルトPATHは、/usr/bin:/bin:/usr/sbin:/sbin誰もがHomebrewまたはMacPortsを使用してカスタム値を追加するPATHわけではありません。そのため、呼び出し可能なコマンドのシンボリックリンクを置く安全な場所が常にあるとは限りません。)

のファイルの例を次に示します/etc/paths.d。基本的に、各行に1つの値を入れています。

 cat /etc/paths.d/Wireshark
/Applications/Wireshark.app/Contents/MacOS

参照:

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.