Linuxでは、私の知る限りでは、すべてのUnixシステムで、ターミナルエミュレータは対話型の非ログインシェルをデフォルトで実行します。つまり、bashの場合、起動したシェルは次のようになります。
ログインシェルではないインタラクティブシェルが起動すると、b [は、これらのファイルが存在する場合、
/etc/bash.bashrc
および~/.bashrc
からコマンドを読み取り、実行します。これは、--norc
オプションを使用することで禁止できます。
--rcfile
ファイルオプションは、/etc/bash.bashrc
および~/.bashrc
の代わりに、bashにファイルからのコマンドの読み取りと実行を強制します。
そしてログインシェルのために:
Bashが対話型ログインシェルとして、または
--login
オプションを使用した非対話型シェルとして呼び出されると、ファイル/etc/profile
が存在する場合、そのファイルからコマンドを読み取り、実行します。そのファイルを読み取った後、~/.bash_profile
、~/.bash_login
、および~/.profile
をこの順序で検索し、存在し、読み取り可能な最初のコマンドからコマンドを読み取って実行します。シェルの起動時に
--noprofile
オプションを使用して、この動作を禁止できます。
ただし、OSXでは、デフォルトのターミナル(Terminal.app)で起動されたデフォルトのシェル(bash)は、実際には~/.bash_profile
または~.profile
などをソースします。つまり、ログインシェルのように機能します。
主な質問:デフォルトのインタラクティブシェルがOSXのログインシェルである理由なぜOSXはこれを選択したのですか?つまり、~/.bashrc
での変更に関するシェルベースの説明やチュートリアルは、OSXでは失敗し、~/.profile
ではその逆になります。それでも、多くの非難はAppleで平準化できるが、無能なまたはばかげた開発者を雇うことはそれらの1つではない。おそらく、これには十分な理由があったので、なぜですか?
サブ質問:Terminal.appは実際にインタラクティブログインシェルを実行しますか、それともbashの動作を変更しましたか?これはTerminal.appに固有ですか、それともターミナルエミュレータから独立していますか?
想定の動作は、シェルプロンプトが表示された時点で、.profile
と.bashrc
の両方が実行されているということです。その時点までの具体的な詳細は二次的な関連性がありますが、いずれかのファイルがまったく実行されなかった場合は、設定が不完全なシェルができます。
Linux(および他のXベースのシステム)のターミナルエミュレータが.profile
自体を実行しないneedしない理由は、通常Xにログインしたときにすでに実行されているためです。.profile
の設定はログイン時に(たとえば、.Xsession
を介して)1回実行される限り、サブプロセスが継承できる種類のものであることが想定されているため、それ以降のサブシェルで再実行する必要はありません。
Debian wiki page Alan Shutkoによってリンクされた説明:
「それでは、なぜ
.bashrc
は.bash_profile
とは別のファイルなのですか?これは、今日のワークステーションと比較してマシンが極端に遅い場合に、歴史的な理由で行われます。特に.profile
または.bash_profile
でコマンドを処理すると、特に多くの作業は外部コマンド(プリバッシュ)で行う必要がありました。そのため、子プロセスに渡すことができる環境変数を作成する難しい初期設定コマンドを.bash_profile
に入れます。一時的な設定とエイリアス継承されないものは.bashrc
に入れられるため、すべてのサブシェルで再読み取りできます。」
OSXにも同じ規則がすべて適用されますが、OSX GUIは、グローバル設定をロードする独自の方法があるため、ログイン時に.profile
を実行しません。しかし、それはOSXのターミナルエミュレーターdoesが.profile
を実行する必要があることを意味します(シェルに起動シェルであることをシェルに通知することにより)。そうしないと、シェルが機能しなくなる可能性があります。
現在、他のほとんどのシェルでは共有されていない、bashのばかげた特徴の1つは、ログインシェルとして起動した場合、.bashrc
が自動的に実行されないことです。そのための標準的な回避策は、次のようなコマンドを.bash_profile
に含めることです。
[[ -e ~/.profile ]] && source ~/.profile # load generic profile settings
[[ -e ~/.bashrc ]] && source ~/.bashrc # load aliases etc.
あるいは、.bash_profile
をまったく使用せず、bash固有のコードをジェネリック.profile
ファイルに含めて、必要に応じて.bashrc
を実行することもできます。
OSXのデフォルトの.bash_profile
または.profile
しないの場合、これは間違いなくバグです。いずれの場合も、適切な回避策は、これらの行を単に.bash_profile
に追加することです。
Edit:Strugee notes 、OSXのデフォルトのシェルは、以前はtcshでしたが、この点で動作は非常に健全です:対話型ログインシェルとして実行すると、tcshは自動的に.profile
and.tcshrc
/.cshrc
の両方を読み取るため、上記の.bash_profile
トリックのような回避策は必要ありません。
これに基づいて、OSXが適切なデフォルト.bash_profile
を提供できないことが99%確信しているのは、tcshからbashに切り替えたときにAppleの人々が単に気づかなかったためですtcshを使用すると、そのようなトリックは必要ありません。OSX端末エミュレーターJust Just Worksからログインシェルとしてtcshを起動し、そのようなクルージなしで正しいことを行います。
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した場合のみ?多くのボックスがsshのターゲットになることは決してないので、それは一種の意味がないように見えます。端末がデフォルトでログインシェルを実行するようにして、.profileがいつか実行されるようにすることもできます。
では、.bashrcはどうでしょうか?役に立たないの?いいえ。VT100の時代の目的がまだ残っています。これは、ターミナルウィンドウを開く以外のときにシェルを開くときに使用されます。つまり、Emacsやviからシェル化した場合、またはsuユーザーを実行した場合です。
彼らがなぜそうしたのか、私にはわかりません。しかし、これは私の推測です。
まず第一に、GNU/Linuxシステムでは、もちろんvt1、vt2などに切り替えることができます。そこにログインシェルが表示されます。 OS Xシステムでは、これに相当するものはありません。 UNIXの基盤にアクセスする唯一の方法は、ターミナルエミュレーターまたはシングルユーザーモードを使用することです(免責事項:実際にシングルユーザーモードを使用したことはありません。コマンドライン方式のIIRCですが、間違っている可能性があります)。したがって、OS Xでは、エミュレータのデフォルトはすべてシステム全体のデフォルトです。
では、なぜデフォルトをログインシェルにするのでしょうか?これを行うために私が考えることができるいくつかの(読んだ:多くはない)理由があります。
tcsh
でした。これは、あなたが得ることができるのと同じくらいワイルドな推測ですが、tcsh
は通常、ログインシェルとして実行したときに何かを行い、履歴パターンがスタックしている可能性があります。 (私はそれを疑います-多分古い常連の1人が私たちに言うことができました。)正直なところ、私はダーウィンを6年ほど使用しており、この質問に正しく答えることができません。それも私にはあまり意味がありません。
あなたのサブ質問に答えるために、bash
にはパッチが適用されていません(少なくともこれについては)。デフォルトのターミナルエミュレータはデフォルトでログインシェルを実行し、おそらくiTermがそれをコピーします。
これは現在のステータスの更新です。新しい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)が設定されず、〜/ .bashrcおよび.bash_profile(または.profile)の$ PATH設定に他のカスタマイズ(実際の$ 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を設定していません)。ログインする必要があるという点で、XTermセッションよりもSSHログインのように動作します。/etc/profileおよび〜/ .bash_profileまたは〜/ .profileから値を設定するためのセッション
上記の回答は、対話型シェルがデフォルトでmacOSのログインシェルである理由を説明しています:/etc/profile
、~/.profile
の設定は、Xベースのシステムの非ログインシェルによって継承されますが、 macOSの場合。ここでは、path_helper
が存在するため、macOSでは常にログインシェルを使用するが必要であることを思い出させたいと思います。
❯ 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行に1つの値を入力します。
❯ cat /etc/paths.d/Wireshark
/Applications/Wireshark.app/Contents/MacOS
参照:
man path_helper