SSH エスケープ キー ("~") は、接続がスタックしている場合にのみ機能しますか?

SSH エスケープ キー ("~") は、接続がスタックしている場合にのみ機能しますか?

SSH 接続が応答しない場合は、 で接続を終了できます<enter>~.。ただし、接続が応答している場合は、~エスケープは機能しません。コンソールにチルダが出力されるだけです。

したがって、SSH ポート転送を変更して を押すと、<enter>~C<enter>次のメッセージが表示されます。

~C: command not found

( からであってbash、 からではありませんssh。)

SSH エスケープ キーが正しく機能するには、何をする必要がありますか?

編集:大きな手がかりが見つかりました。リモート シェルは実際には でありash、 ではありませんでしたbash。リモート マシンで を実行するとbash、SSH エスケープ キーが機能します。内部ashで を実行しても、やはり機能しません。bashash

しかし、これは非常に奇妙です。エスケープ キーは SSH クライアントによってキャッチされ、リモート シェルに転送されることはありません。では、どのリモート シェルが SSH から入力を受け取っているかがなぜ重要なのでしょうか。

答え1

簡単な回避策:catコマンドを実行してから、エスケープ シーケンスを入力します。

このcatコマンドは、デフォルトで渡されたものを印刷しますstdin。そのため、実行中はエスケープ文字は送信されず、通常どおり ssh エスケープ キーを使用できます。完了したら、シェルに戻りますctrl-ccat

必要に応じて、プロンプトを開き、cat入力してcatEnter キーを押して実行します。

$ 
$ 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-2338BusyBox ソースのから:

/* 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 エスケープ コードを返すように指示し、シェルに端末ウィンドウ内のカーソル (テキスト挿入ポイント) の位置を伝えます。

したがって、 を押すとすぐにEnterashが を出力し<ESC>[6n、それをそこからターミナル エミュレーターにsshd渡します。 を押す直前に、ターミナル エミュレーターは のようなものを標準入力に送信し、それを接続を介してそこから に渡して、カーソルの位置を伝えます。ssh~<ESC>[47;13Rsshsshdashash

さて、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 回入力して送信します
(エスケープは改行の直後のみ認識されることに注意してください)

関連情報