TERM=xterm を手動で実行するまで、ssh のバックスペースは機能しません

TERM=xterm を手動で実行するまで、ssh のバックスペースは機能しません

sshが誤って設定されている場合、セッションでバックスペースが機能する可能性があることは理解していますTERM。しかし奇妙なことに、 が正しく設定されているサーバーがありますTERMが、シェルで手動で設定するまでバックスペースは機能しませんTERM=xterm(これは冗長であるはずです)。こちらを参照してください。

~ ] ssh [email protected]
root 192.168.10.40 / # echo $0
-bash
root 192.168.10.40 / # echo $TERM
xterm-256color
root 192.168.10.40 / #     # backspace does not work :(
root 192.168.10.40 / # 
root 192.168.10.40 / # TERM=xterm-256color
root 192.168.10.40 / # # now backspace works!!
root 192.168.10.40 / # logout

約 90% のケースでは、 を実行するまでバックスペースは機能しませんTERM=xterm。また、10% のケースでは、バックスペースがすでに機能しているため、 コマンドを実行する必要はありません。各ケースの のTERM=出力を比較しましたが、それらは同一です (クライアント側のポートのみが変更された と を除く) 。envSSH_CLIENTSSH_CONNECTION

この動作の原因は何なのか、または回避策は何なのか、何かご存知ですか?


コメントへの返信

OpenSSH_6.8p1, BoringSSL私はから使用しておりhttps://android.googlesource.com/platform/external/opensshGNU bash, version 4.3.42(1)-release (arm-android-eabi)から実行していますhttps://github.com/CyanogenMod/android_external_bash.git

stty -a設定前と設定後では違いは見られませんXTERM。出力は次のようになります。

speed 38400 baud; rows 102; columns 319; line = 2;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0;
-parenb -parodd cs8 -hupcl -cstopb cread -clocal -crtscts
-ignbrk -brkint ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc -ixany imaxbel -iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke

bind -p|egrep 'delete|rubout|kill'設定前と設定後の違いも表示されませんXTERM。出力は次のようになります。

"\C-h": backward-delete-char
"\C-?": backward-delete-char
"\C-x\C-?": backward-kill-line
"\e\C-h": backward-kill-word
"\e\C-?": backward-kill-word
# copy-region-as-kill (not bound)
"\C-d": delete-char
"\e[3~": delete-char
# delete-char-or-list (not bound)
"\e\\": delete-horizontal-space
# forward-backward-delete-char (not bound)
"\C-k": kill-line
# kill-region (not bound)
# kill-whole-line (not bound)
"\ed": kill-word
# shell-backward-kill-word (not bound)
# shell-kill-word (not bound)
# unix-filename-rubout (not bound)
"\C-w": unix-word-rubout
# vi-delete (not bound)
# vi-delete-to (not bound)
# vi-overstrike-delete (not bound)
# vi-rubout (not bound)

興味深いことに、 を押すとsourcebashrcバックスペースが再び機能し始めます。 はbashrcログイン時に取得されますが、これは私がPs1値を設定している唯一の場所であるためです。

答え1

readline/terminal の相互作用のようです。まずログイン プロセス中に.inputrc、、、環境変数をチェックし、次に readline バインディング ( 経由) をチェック/etc/inputrcします。/etc/default/loginINPUTRCbind -q backward-delete-char

SendEnvクライアント (ssh_config)およびサーバー (sshd_config AcceptEnv) ディレクティブの内容も二重チェックしても問題ありません( TERMOpenSSH ではこの方法でクライアントからサーバーに送信されませんが、クライアントは常にTERMセッション設定に値を含め、サーバーはそこから設定します)。環境内にまたは がTERM時々存在するということだけが、この断続的な性質を説明するために考えられる唯一のことです。TERMINFOTERMCAP

Readline は、端末が「消去」と宣言したものに「rubout」を適用します。rubout は、readline が を介して呼び出すものですbackward-delete-char

TERMbashが監視する特別な変数の1つで、設定されているかどうかに関係なく変更bashはターミナルをリセットします:

/* What to do just after one of the TERMxxx variables has changed.
   If we are an interactive shell, then try to reset the terminal
   information in readline. */
void
sv_terminal (name)
     char *name;
{
  if (interactive_shell && no_line_editing == 0)
    rl_reset_terminal (get_string_value ("TERM"));
}

(ここで、「 」は、、TERMxxxを意味します)。したがって、現在の値に設定するだけで実際にアクションが実行される理由が説明されます。TERMTERMCAPTERMINFOTERM

追跡できない場合は、/TERM=${TERM}の末尾に「 」を追加すると回避策になる可能性があります。.profile.bashrc

最後の手段として、私の回答に詳述されているように、いくつかの法医学的手段を試すこともできます。stty 設定が変更されたときに監視してユーザーに警告しますか?

関連情報