Zdalne polecenia SSH - ostrzeżenie bash bind: edycja linii nie jest włączona

17

Korzystam z wersji bash 4.3.11 (1) i mam zainstalowaną następującą wtyczkę historii (przez .bash_it ):

# enter a few characters and press UpArrow/DownArrow
# to search backwards/forwards through the history
bind '"^[[A":history-search-backward'
bind '"^[[B":history-search-forward'

Kiedy loguję się do sesji interaktywnej, wszystko jest w porządku, ale kiedy uruchamiam ssh host 'ls -als'na przykład polecenia zdalne , widzę następujące dane wyjściowe:

: ssh host 'ls -als'
/home/ubuntu/.bash_it/plugins/enabled/history.plugin.bash: line 3: bind: warning: line editing not enabled
/home/ubuntu/.bash_it/plugins/enabled/history.plugin.bash: line 4: bind: warning: line editing not enabled

Kiedy modyfikuję wtyczkę historii przy echo -e '\0033\0143'każdym wywołaniu powiązania, nie otrzymuję już ostrzeżeń, ale moja konsola jest czyszczona. Nie jest to duża wada, ale byłoby miło poznać bardziej przejrzysty sposób na stłumienie tego dla zdalnych poleceń.

# Works, but annoyingly clears console
# enter a few characters and press UpArrow/DownArrow
# to search backwards/forwards through the history
bind '"^[[A":history-search-backward'
echo -e '\0033\0143'
bind '"^[[B":history-search-forward'
echo -e '\0033\0143'
Brian
źródło

Odpowiedzi:

28
ssh host 'ls -als'

Gdy poprosisz ssh o uruchomienie polecenia w systemie zdalnym, ssh zwykle nie przydziela PTY (pseudo-TTY) dla sesji zdalnej. Możesz uruchomić ssh, -taby zmusić go do przydzielenia tty:

ssh -t host 'ls -als'

Jeśli nie chcesz tego pisać cały czas, możesz dodać ten wiersz do pliku „.ssh / config” na lokalnym hoście:

RequestTTY yes

Alternatywnie można naprawić plik „.bashrc” w systemie zdalnym, aby uniknąć uruchamiania poleceń, które zakładają, że sesja jest interaktywna, gdy nie jest. Jednym ze sposobów jest zawarcie poleceń w teście, że sesja ma TTY:

if [ -t 1 ]
then
    # standard output is a tty
    # do interactive initialization
fi
Kenster
źródło
1
W rzeczywistości ta odpowiedź jest niepoprawna, patrz odpowiedź @ Alexander-vorobiev poniżej.
Ahmed Masud
2

Sesja interaktywna nie wystarczy binddo pracy. Na przykład powłoka emacs zapewnia interaktywną sesję, która pozytywnie przechodzi if [ -t 1 ]test, ale nie ma edycji linii, więc jakiekolwiek binds ~/.bashrcwygenerują ostrzeżenia. Zamiast tego możesz sprawdzić, czy edycja linii jest włączona, wykonując coś takiego (czy istnieje prostszy / lepszy sposób?):

if [[ "$(set -o | grep 'emacs\|\bvi\b' | cut -f2 | tr '\n' ':')" != 'off:off:' ]]; then
  echo "line editing is on"
fi
Alexander Vorobiev
źródło
To powinna być poprawna odpowiedź
Ahmed Masud
1
Łatwiejszym sposobem byłoby użycie[[ ${SHELLOPTS} =~ (vi|emacs) ]] && echo 'line-editing on' || echo 'line-editing off'
Ahmed Masud
1

Umieść polecenia bind w instrukcji „if”, która sprawdza, czy sesja bash pozwala na edycję linii:

if [[ ${SHELLOPTS} =~ (vi|emacs) ]]; then
    bind '"^[[A":history-search-backward'
    bind '"^[[B":history-search-forward'
fi
Jonathan Hartley
źródło
1

Jeśli nie ma edycji linii, bindsame te polecenia są nieszkodliwe. Pomiń ostrzeżenia:

bind '"^[[A":history-search-backward' 2>/dev/null
bind '"^[[B":history-search-forward'  2>/dev/null

To jest trochę nieeleganckie, ale powinno działać. Inne odpowiedzi nie zgadzają się co do najlepszego / wystarczającego testu. Moje podejście to obchodzi. Jednak nie skaluje się dobrze. Same dwa polecenia nie powinny mieć wielkiego znaczenia; ale gdybyś miał więcej, jak dziesiątki, wówczas poprawne warunki byłyby prawdopodobnie lepsze.

Kamil Maciorowski
źródło
Słuszna uwaga. Zyskaj głos. :-)
Jonathan Hartley,