Archのインストールでは、/etc/bash.bashrc
および/etc/skel/.bashrc
次の行が含まれています:
# If not running interactively, don't do anything
[[ $- != *i* ]] && return
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
man bash
によると ただし、非対話型シェルはこれらのファイルを読み取ることさえしません:
When bash is started non-interactively, to run a shell script, for
example, it looks for the variable BASH_ENV in the environment, expands
its value if it appears there, and uses the expanded value as the name
of a file to read and execute. Bash behaves as if the following com‐
mand were executed:
if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi
but the value of the PATH variable is not used to search for the file‐
name.
私が正しく理解していれば、*.bashrc
BASH_ENV
の場合にのみファイルが読み取られます それらを指すように設定されています。これは偶然には起こり得ないことであり、誰かがそれに応じて変数を明示的に設定した場合にのみ発生します。
これにより、スクリプトがユーザーの.bashrc
をソースする可能性が失われるようです。 BASH_ENV
を設定することで自動的に 、便利なもの。明示的に指示されない限り、bashが非対話的に実行されたときにこれらのファイルを読み取ることは決してないので、デフォルトの*bashrc
を実行するのはなぜですか。 ファイルはそれを許可しませんか?
承認された回答:
これは私が数週間前にここに投稿しようとしていた質問です。 terdonのように 、.bashrc
インタラクティブなBashシェルのみをソースとしているため、.bashrc
は必要ありません。 インタラクティブシェルで実行されているかどうかを確認します。紛らわしいことに、すべて 私が使用しているディストリビューション(Ubuntu、RHEL、Cygwin)には、ある種のチェック($-
のテスト)がありました。 または$PS1
)現在のシェルがインタラクティブであることを確認します。カーゴカルトプログラミングが好きではないので、.bashrc
でこのコードの目的を理解することにしました。 。
Bashにはリモートシェル用の特別なケースがあります
この問題を調査したところ、リモートシェルであることがわかりました。 扱いが異なります。非対話型のBashシェルは通常、~/.bashrc
を実行しませんが 起動時のコマンドでは、シェルがリモートシェルデーモンによって呼び出されたときに特別なケースが作成されます:
Bashは、リモートシェル
デーモン(通常はrshd
)によって実行される場合のように、ネットワーク接続に接続された標準入力
で実行されているかどうかを判断しようとします。 、またはセキュアシェルデーモンsshd
。 Bashが
この方法で実行されていると判断した場合、そのファイルが存在し、読み取り可能であれば、〜/.bashrcから
コマンドを読み取って実行します。
がsh
として呼び出された場合、これは行われません。 。--norc
オプションを使用して、この動作を禁止できます。
および--rcfile
オプションを使用して別のファイルを強制的に読み取ることができますが、
どちらもrshd
また、sshd
通常、これらのオプションを使用してシェルを呼び出すか、
それらを指定できるようにします。
例
リモートの.bashrc
の先頭に以下を挿入します 。 (.bashrc
の場合 .profile
によって供給されます または.bash_profile
、テスト中にこれを一時的に無効にします):
echo bashrc
fun()
{
echo functions work
}
次のコマンドをローカルで実行します。
$ ssh remote_host 'echo $- $0'
bashrc
hBc bash
- いいえ
i
$-
で シェルが非対話型であることを示します 。 - 先頭の
-
はありません$0
で シェルがログインシェルではないことを示します 。
リモートの.bashrc
で定義されたシェル関数 実行することもできます:
$ ssh remote_host fun
bashrc
functions work
~/.bashrc
に気づきました のみ ssh
の引数としてコマンドが指定されている場合に供給されます 。これは理にかなっています:ssh
の場合 通常のログインシェル.profile
を開始するために使用されます または.bash_profile
実行されます(および.bashrc
これらのファイルのいずれかによって明示的に行われた場合にのみソースされます。
.bashrc
を使用することで得られる主なメリット (非対話型の)リモートコマンドを実行するときに得られるのは、シェル関数を実行できるということです。ただし、一般的な.bashrc
のほとんどのコマンド インタラクティブシェルにのみ関連します。たとえば、シェルがインタラクティブでない限り、エイリアスは展開されません。
リモートファイル転送が失敗する可能性があります
rsh
の場合、これは通常問題にはなりません。 またはssh
対話型ログインシェルを開始するため、または非対話型シェルを使用してコマンドを実行する場合に使用されます。ただし、問題になる可能性があります rcp
などのプログラムの場合 、scp
およびsftp
リモートシェルを使用する データ転送用。
scp
を使用すると、リモートユーザーのデフォルトシェル(Bashなど)が暗黙的に開始されることがわかりました。 指図。マニュアルページにはこれについての言及はありません。scp
についての言及だけです。 ssh
を使用します そのデータ転送のため。これは、 .bashrc
の場合にという結果になります 標準出力に出力するコマンドが含まれている場合、ファイル転送は失敗します たとえば、scpはエラーなしで失敗します。
なぜscp
およびsftp
失敗
SCP(セキュアコピー)とSFTP(セキュアファイル転送プロトコル)には、転送されるファイルに関する情報を交換するためのローカルエンドとリモートエンド用の独自のプロトコルがあります。リモートエンドからの予期しないテキストは(誤って)プロトコルの一部として解釈され、転送は失敗します。カタツムリの本からのFAQによると
ただし、よくあることは、サーバー上の
システムまたはユーザーごとのシェル起動ファイル(.bashrc
)のいずれかにステートメントがあることです。 、.profile
、/etc/csh.cshrc
、.login
、など)ログイン時にテキストメッセージを出力します。
人間が読むことを目的としています(fortune
など)。 、echo "Hi there!"
など)。このようなコードは、
tty
がある場合にのみ、インタラクティブログインで出力を生成する必要があります。 標準入力に接続されています。このテストを行わない場合は、
これらのテキストメッセージが属していない場所に挿入されます。この場合、
scp2
間のプロトコルストリームを汚染します。 /sftp
およびsftp-server
。シェルの起動ファイルがまったく関連している理由は、
sshd
であるためです。 ユーザーに代わってプログラムを起動するときに、ユーザーのシェルを使用します (例:/ bin / sh -c「コマンド」を使用)。これはUnixの伝統であり、
利点があります:
- リモートコマンドを実行すると、ユーザーの通常の設定(コマンドエイリアス、環境変数、umask、
など)が有効になります。- アカウントのシェルを/bin/ falseに設定して無効にする一般的な方法は、
何らかの理由で認証が誤って成功した場合でも、所有者がコマンドを実行できないようにします。
SCPプロトコルの詳細
SCPの動作の詳細に興味がある人のために、リモート側でおしゃべりなシェルプロファイルを使用してscpを実行する方法の詳細を含むSCPプロトコルの動作方法に興味深い情報を見つけました。 :
たとえば、これを
リモートシステムのシェルプロファイルに追加すると発生する可能性があります:エコー「」
なぜそれがハングするのですか?これは、
scp
ソース mode
は、最初のプロトコルメッセージの確認を待ちます。バイナリ
0でない場合は、リモートの問題の通知であると想定し、新しい行が到着するまで
さらに多くの文字がエラーメッセージを形成するのを待ちます。
最初の行の後に別の新しい行を印刷しなかったため、ローカルのscp
ちょうど
ループにとどまり、read(2)
でブロックされます 。その間、シェルの
プロファイルがリモート側で処理された後、scp
シンクモードで開始されました。
これもread(2)
でブロックされます 、データ転送の開始を示すバイナリゼロを待機しています
。
結論/TLDR
典型的な.bashrc
のほとんどのステートメント rsh
を使用してリモートコマンドを実行する場合ではなく、インタラクティブシェルでのみ役立ちます。 またはssh
。このようなほとんどの状況では、シェル変数、エイリアスの設定、関数の定義は望ましくありません。任意のテキストを出力します。 scp
などのプログラムを使用してファイルを転送する場合、標準化することは積極的に有害です。 またはsftp
。現在のシェルが非対話型であることを確認した後に終了するのが、.bashrc
の最も安全な動作です。 。