%20%E3%81%AF%E3%80%81%E6%8E%A5%E7%B6%9A%E3%81%8C%E3%82%B9%E3%82%BF%E3%83%83%E3%82%AF%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B%E5%A0%B4%E5%90%88%E3%81%AB%E3%81%AE%E3%81%BF%E6%A9%9F%E8%83%BD%E3%81%97%E3%81%BE%E3%81%99%E3%81%8B%3F.png)
SSH 接続が応答しない場合は、 で接続を終了できます<enter>~.
。ただし、接続が応答している場合は、~
エスケープは機能しません。コンソールにチルダが出力されるだけです。
したがって、SSH ポート転送を変更して を押すと、<enter>~C<enter>
次のメッセージが表示されます。
~C: command not found
( からであってbash
、 からではありませんssh
。)
SSH エスケープ キーが正しく機能するには、何をする必要がありますか?
編集:大きな手がかりが見つかりました。リモート シェルは実際には でありash
、 ではありませんでしたbash
。リモート マシンで を実行するとbash
、SSH エスケープ キーが機能します。内部ash
で を実行しても、やはり機能しません。bash
ash
しかし、これは非常に奇妙です。エスケープ キーは SSH クライアントによってキャッチされ、リモート シェルに転送されることはありません。では、どのリモート シェルが SSH から入力を受け取っているかがなぜ重要なのでしょうか。
答え1
簡単な回避策:cat
コマンドを実行してから、エスケープ シーケンスを入力します。
このcat
コマンドは、デフォルトで渡されたものを印刷しますstdin
。そのため、実行中はエスケープ文字は送信されず、通常どおり ssh エスケープ キーを使用できます。完了したら、シェルに戻りますctrl-c
。cat
例
必要に応じて、プロンプトを開き、cat
入力してcat
Enter キーを押して実行します。
$
$ cat
では、~と入力してください。
~?
Supported escape sequences:
~. - terminate connection (and any multiplexed sessions)
~B - send a BREAK to the remote system
~C - open a command line
~R - request rekey
~V/v - decrease/increase verbosity (LogLevel)
~^Z - suspend ssh
~# - list forwarded connections
~& - background ssh (when waiting for connections to terminate)
~? - this message
~~ - send the escape character by typing it twice
うまくいきました! 今度は任意のコマンドを入力します。プロンプトに戻るには、Ctrl + C を押します。
^C
$
答え2
秘密が分かりました!
上記の「編集」で投稿したように、リモート シェルはash
ではなくBusyBox でしたbash
。
libbb/lineedit.c:2336-2338
BusyBox ソースのから:
/* Print out the command prompt, optionally ask where cursor is */
parse_and_put_prompt(prompt);
ask_terminal();
これは、 のコマンド プロンプトを出力するために使用されますash
。ただし、プロンプトを出力するとすぐに、 という別の関数がask_terminal
呼び出されることに注意してください。 は何をask_terminal
するのでしょうか。次の文字を出力します<ESCAPE>[6n
。
これらの文字は端末では表示されません。実際、これらは ANSI 端末制御エスケープ コードです。<ESC>[6n
は「カーソル位置の照会」コマンドです。端末エミュレータに別の ANSI エスケープ コードを返すように指示し、シェルに端末ウィンドウ内のカーソル (テキスト挿入ポイント) の位置を伝えます。
したがって、 を押すとすぐにEnter
、ash
が を出力し<ESC>[6n
、それをそこからターミナル エミュレーターにsshd
渡します。 を押す直前に、ターミナル エミュレーターは のようなものを標準入力に送信し、それを接続を介してそこから に渡して、カーソルの位置を伝えます。ssh
~
<ESC>[47;13R
ssh
sshd
ash
ash
さて、SSH クライアントは、これらの ANSI エスケープ コードが何を意味するのか実際には知りません。SSH にとって、これらはすべて標準入力から読み取られた単なる文字です。SSH<ENTER>~C
クライアントは、 ではなく を認識し、の直後を<ENTER><ESC>[47;13R~C
認識しないため、それがエスケープ コードであるとは認識しません。~
Enter
問題は、これをどうするかです。OpenSSH が端末から送信された ANSI エスケープを理解し、~
ANSI 端末制御コマンドの後のエスケープ文字も受け入れてくれると良いのですが。OpenSSH の担当者にパッチを送って、この問題を修正する意思があるかどうか確認するかもしれません...
答え3
あなたは尋ねた確かに、SSH クライアントのエスケープ キーはこのように動作するはずではありませんか?
はい、動作するはずです:
を押すとEnter、プロンプトにエスケープ~文字が表示されなくなり、が機能します。~
ssh
もう一度押すと~プロンプトに表示され、作業シェル(例ではbash)に作用して、拡大する知っている通りに使用します。
作業するには、~
最初にする必要があります。ラインバッファなので、文字を入力して全て消すと、その行はもう新しいもう一度押す必要がありますEnter。
押すと~?
取得します
サポートされているエスケープ シーケンス:
~. - 接続 (および多重化されたセッション) を終了します
~B - リモート システムに BREAK を送信します
~C - コマンド ラインを開きます
~R - キーの再生成を要求します (SSH プロトコル 2 のみ)
~^Z - ssh を一時停止します
~# - 転送された接続を一覧表示します
~& - バックグラウンド ssh (接続の終了を待機している場合)
~? - このメッセージ
~~ - エスケープ文字を 2 回入力して送信します
(エスケープは改行の直後のみ認識されることに注意してください)