ssh backspace не работает, пока я вручную не запущу TERM=xterm

ssh backspace не работает, пока я вручную не запущу TERM=xterm

Я понимаю, что backspace теперь может работать в sshсеансе, если TERMустановлен неправильно. Но странно, у меня есть сервер, где TERMустановлен правильно, но backspace не работает, пока я не установлю его вручную 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% случаев backspace не работает, пока я не запущу TERM=xterm, а в 10% случаев мне не нужно запускать команду, TERM=потому что backspace уже работает. Я сравнил вывод envдля каждого случая, и они идентичны (за исключением того SSH_CLIENT, SSH_CONNECTIONчто изменился только порт на стороне клиента)

Есть ли у вас идеи, что может быть причиной такого поведения или как можно это обойти?


Ответ на комментарии

Я использую OpenSSH_6.8p1, BoringSSLиз https://android.googlesource.com/platform/external/openssh, и я бегу GNU 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)

Интересно, если я sourceмой bashrc, мой backspace снова начинает работать. Я знаю, что bashrcэто исходный код при входе в систему, хотя это единственное место, где я устанавливаю свое Ps1значение

решение1

Похоже на взаимодействие readline/терминала, начните с проверки переменных среды .inputrc, /etc/inputrc, /etc/default/login, INPUTRCво время процесса входа в систему, а затем привязок readline (через bind -q backward-delete-char).

Не повредит дважды проверить, что находится в директивах клиента (ssh_config) SendEnvи сервера (sshd_config ), если что-то есть (хотя это не передается от клиента к серверу таким образом в OpenSSH, клиент всегда включает значение в настройку сеанса, а сервер устанавливает его из этого). Единственное, что я могу придумать, чтобы объяснить непостоянный характер этого, — это случайное присутствие или в среде.AcceptEnvTERMTERMTERMTERMINFOTERMCAP

Readline применяет «rubout» к тому, что терминал объявляет своим «стиранием», а rubout — это то, что readline вызывает через backward-delete-char.

TERMявляется одной из специальных переменных, которые отслеживает bash, когда она установлена ​​(независимо от того, установлена ​​ли онаизменения)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» означает TERM, TERMCAPи TERMINFO) поэтому это объясняет, почему простая установка TERMтекущего значения на самом деле выполняет действие.

Если вы не можете его отследить, добавление « TERM=${TERM}» в конце вашего .profile/ .bashrcможет стать обходным решением.

В крайнем случае вы также можете попробовать некоторые судебно-медицинские меры, как подробно описано в моем ответе здесь:Контролировать и оповещать пользователя об изменении настроек stty?

Связанный контент