リモートSSHコマンドパラメータを二重エスケープする必要性に関する質問と回答を見ました。私の質問は:2番目の解析が正確にいつどこで完了するのですか?
次のコマンドを実行すると:
$ ssh otherhost pstree -a -p
出力に以下が表示されます。
|-sshd,3736
| `-sshd,1102
| `-sshd,1109
| `-pstree,1112 -a -p
リモートコマンド()pstree
の親プロセスには、リモートコマンドのsshd
コマンドライン引数を解析するシェルがないように見えるので、二重引用符やエスケープは必要ありません(実際にはそうです)。代わりに、最初にsshを介してログインシェルを取得してから実行すると、pstree -a -p
出力に次のものが表示されます。
├─sshd,3736
│ └─sshd,3733
│ └─sshd,3735
│ └─bash,3737
│ └─pstree,4130 -a -p
bash
明らかに、このような状況でコマンドライン解析を実行できるシェルがあります。しかし、リモートコマンドを直接使用するとシェルがないようですが、なぜ二重引用符が必要なのでしょうか?
ベストアンサー1
常にリモートシェルがあります。 SSH プロトコルでは、クライアントは実行する文字列をサーバーに送信します。 SSHコマンドラインクライアントはコマンドライン引数を取得し、引数の間にスペースを使用して連結します。サーバーは文字列を取得し、ユーザーのログインシェルを実行し、ここに文字列を渡します。 (より正確に言えば、サーバーはユーザーデータベースにユーザーシェルとして登録されたプログラムを実行し、2つのコマンドライン引数-c
とクライアントから送信された文字列を渡します。このシェルはログインシェルとして呼び出されません。サーバーはこれを行いません。番目のパラメータは)で始まる文字列に設定されます-
。
リモートシェルをバイパスすることは不可能です。プロトコルは、サーバーからargv配列に解析できる文字列配列などを送信しません。そして、SSHサーバーはリモートシェルをバイパスしません。これはセキュリティ制限である可能性があるためです。制限されたプログラムをユーザーのシェルとして使用することは、特定のコマンド(rsync専用アカウントまたはGit専用アカウントアカウントなど)です。
pstree
ケースが消えて見えないことがあります。多くのシェルには、「この外部コマンドを実行して完了するのを待ってからコマンド状態で終了」がすぐに実行されることを検出すると、シェルが実行される最適化機能があります。execve
external command"の代わりに。これは最初の例で起こります。次の3つのコマンドを比較してください。
ssh otherhost pstree -a -p
ssh otherhost 'pstree -a -p'
ssh otherhost 'pstree -a -p; true'
最初の2つは同じです。クライアントはまったく同じデータをサーバーに送信します。 3番目は、シェルのexec最適化を中断するシェルコマンドを送信します。