リモート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
があります その場合、コマンドライン解析を実行するシェルがあります。しかし、リモートコマンドを直接使用する場合、シェルがないように見えるのに、なぜ二重引用符が必要なのですか?
承認された回答:
常にリモートシェルがあります。 SSHプロトコルでは、クライアントはサーバーに実行する文字列を送信します。 SSHコマンドラインクライアントは、コマンドライン引数を受け取り、引数の間にスペースを入れてそれらを連結します。サーバーはその文字列を受け取り、ユーザーのログインシェルを実行して、その文字列を渡します。 (より正確には、サーバーはユーザーデータベースにユーザーのシェルとして登録されているプログラムを実行し、2つのコマンドライン引数を渡します:-c
クライアントから送信された文字列。シェルはログインシェルとして呼び出されません。サーバーは、0番目の引数を-
で始まる文字列に設定しません。 。)
リモートシェルをバイパスすることはできません。このプロトコルには、サーバー上でargv配列として解析できる文字列の配列を送信するようなものはありません。また、SSHサーバーは、セキュリティ上の制限となる可能性があるため、リモートシェルをバイパスしません。ユーザーのシェルとして制限付きプログラムを使用することは、特定のコマンドの実行のみが許可される制限付きアカウントを提供する方法です(たとえば、rsyncのみのアカウントまたはgitのみのアカウント)。
pstree
にシェルが表示されない場合があります すでになくなっているかもしれないからです。多くのシェルには最適化があり、「この外部コマンドを実行し、完了するのを待って、コマンドのステータスで終了する」ことを検出すると、シェルは「execve
」を実行します。 代わりに、この外部コマンドの」。これが最初の例で起こっていることです。次の3つのコマンドを比較してください。
ssh otherhost pstree -a -p
ssh otherhost 'pstree -a -p'
ssh otherhost 'pstree -a -p; true'
最初の2つは同じです。クライアントは、まったく同じデータをサーバーに送信します。 3つ目は、シェルのexec最適化を無効にするシェルコマンドを送信します。
関連:スピンロックとセマフォの違いは何ですか?