ssh <Host> <command>
構文を使用してSSHホストで直接コマンドを実行すると、.bashrc
(または.bash_profile
)の出力ではなく、.profile
の出力が表示されることに気づきました。
たとえば、次のコマンドを両方のファイルの先頭に配置すると、
echo ${BASH_SOURCE[0]}
手動で.bash_profile
をソースします(これは.bashrc
を順にソースします)。
$ . .bash_profile
.bash_profile
.bashrc
これは、コマンドのssh <Host>
形式を使用して、SSH経由でこのコンピューターにリモートでログインした場合に表示される出力と同じです。 (そして、.bash_profile
を一時的にどこかに格納した場合、これらの行はどちらもエコーされません。)
ただし、ssh
のssh <Host> <command>
形式を使用してリモートマシンで直接コマンドを実行すると、出力は次のようになります。
$ ssh <Host> echo foo
/home/rlue/.bashrc
foo
.bash_profile
と.bashrc
の違いは、前者はログインシェル用であり、後者はインタラクティブな非ログインシェル用であることを理解しています。
私は次のように結論しました:
ssh <Host>
は.bash_profile
のみをソースしますが、ssh <Host> <command>
は.bashrc
のみをソースします。つまり、これらの結論は正しいですか? ssh <Host> <command>
が対話型の非ログインシェルとして扱われるのはなぜですか? SSHはまだコマンドを実行するためにリモートマシンにログインしていませんか?
OpenSSH(おそらくあなたが実行しているもの)は、ログインシェルを作成するかどうかを決定し、特定のコマンドを実行していない場合にのみ作成します。 man ssh
から:
If command is specified, it is executed on the remote Host instead of a login Shell.
そのため、ログインシェルを作成するかどうかに関係なく、sshサーバーの実装の選択であり、実行するコマンドを指定した場合は実行されません。
ssh
はログインを実行しますが、コマンドを実行して終了する場合は、ログイン環境を取得するよりも、そのコマンドを実行するためにシェルを作成することに非常によく似ています。それを考えると、OpenSSHを書いている人々はそれをそのような仕事のように扱うことに決めたようです。
コマンドを実行するための非インタラクティブ、非ログインシェルを作成します。これは、別のコンテキスト/シェルでコマンドを実行する精神だからです。ただし、通常、非インタラクティブシェルは~/.bashrc
を自動的にソースしません。これは明らかにここで発生しています。 bash
は実際にここで私たちを助けようとしています。から ドキュメント
リモートシェルデーモンによって呼び出されます
Bashは、標準の入力がネットワーク接続に接続された状態で実行されているとき、リモートシェルデーモン(通常はrshd)またはセキュアシェルデーモンsshdによって実行されている場合を判断します。この方法で実行されているとBashが判断した場合、そのファイルが存在して読み取り可能であれば、〜/ .bashrcからコマンドを読み取って実行します。 shとして呼び出された場合、これは行われません。 --norcオプションを使用してこの動作を禁止し、-rcfileオプションを使用して別のファイルを強制的に読み取ることができますが、rshdもsshdも通常、これらのオプションを使用してシェルを呼び出したり、それらを指定したりできません。
この動作のwhyはシェルよりも低いレベルにあります:ssh Host
(「ログインシェル」の場合)は pseudoterminal リモートホスト上で、sshd
サーバープロセスとシェルの間で通信します。 ssh Host command
は、代わりにsshd
とcommand
の間のパイプを使用します。シェルなどのコマンドインタープリターやスクリプト言語の " read-eval-print "モードを対話的に使用するには、疑似ターミナルが必要です。それらは、タイプミスを介してバックスペースすることができるように人間に優しい機能の束を実装します。ただし、オーバーヘッドが大きくなり、(構成によっては)任意のデータを変更せずに通過させることができないため、SSHは相互作用が発生しない場合にそれらの使用を回避します。
SSHのコマンド/コマンドなしのヒューリスティックがこれを誤ることがあります。 -t
および-T
スイッチでオーバーライドできます。たとえば、リモートマシンにログインし、中断されたscreen
セッションをすぐに再接続するには、ssh -t Host screen -R
を実行する必要があります。 ssh Host screen -R
は、screen
が端末に接続されていないことを報告します。実際にwantを使用して-T
を使用するような状況は考えられませんが、見つけた場合はあります。
まず、さまざまなタイプを確認する必要があります。これを読むことができます。
これでbashrcを開くと、最初にこれが表示されます。
# If not running interactively, don't do anything
[ -z "$PS1" ] && return
つまり、システムへのアクセス方法に応じて、このファイルはコードを内部にロードするかどうかを決定します。