Comandos SSH remotos - aviso de ligação do bash: edição de linha não ativada

17

Estou usando o bash 4.3.11 (1) e tenho o seguinte plugin de histórico instalado (via .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'

Quando entro em uma sessão interativa, tudo está bem, mas quando executo comandos remotos ssh host 'ls -als'por exemplo, vejo a seguinte saída:

: 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

Quando modifico o plug-in de histórico echo -e '\0033\0143'após cada chamada de ligação, não recebo mais os avisos, mas meu console está limpo. Não é uma grande desvantagem, mas seria bom conhecer uma maneira mais limpa de suprimir isso para comandos remotos.

# 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
fonte

Respostas:

28
ssh host 'ls -als'

Quando você pede ao ssh para executar um comando no sistema remoto, o ssh normalmente não aloca um PTY (pseudo-TTY) para a sessão remota. Você pode executar o ssh com -tpara forçá-lo a alocar um tty:

ssh -t host 'ls -als'

Se você não quiser digitar isso o tempo todo, poderá adicionar esta linha ao arquivo ".ssh / config" no host local:

RequestTTY yes

Como alternativa, você pode corrigir o arquivo ".bashrc" no sistema remoto para evitar a execução de comandos que presumem que a sessão é interativa quando não é. Uma maneira é colocar os comandos em um teste de que a sessão possui um TTY:

if [ -t 1 ]
then
    # standard output is a tty
    # do interactive initialization
fi
Kenster
fonte
1
Na verdade, esta resposta está incorreta, veja a resposta de @ alexander-vorobiev abaixo.
Ahmed Masud
2

Ter uma sessão interativa não é suficiente para bindfuncionar. Por exemplo, o emacs shell fornece uma sessão interativa que passa no if [ -t 1 ]teste, mas não possui a edição de linha, portanto qualquer binds no seu ~/.bashrcgera os avisos. Em vez disso, você pode verificar se a edição de linha está ativada fazendo algo assim (existe uma maneira mais simples / melhor?):

if [[ "$(set -o | grep 'emacs\|\bvi\b' | cut -f2 | tr '\n' ':')" != 'off:off:' ]]; then
  echo "line editing is on"
fi
Alexander Vorobiev
fonte
Esta deve ser a resposta correta
Ahmed Masud
1
A maneira mais fácil seria usar[[ ${SHELLOPTS} =~ (vi|emacs) ]] && echo 'line-editing on' || echo 'line-editing off'
Ahmed Masud
1

Coloque os comandos bind em uma instrução 'if' que verifique se a sessão bash permite a edição de linha:

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

Se não houver edição de linha, esses bindcomandos serão inofensivos. Suprima os avisos:

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

Isso é um tanto deselegante, mas deve funcionar. Outras respostas não concordam sobre o melhor / suficiente teste. Minha abordagem contorna isso. Mas não escala bem. Os dois comandos por si só não devem fazer uma grande diferença; mas se você tivesse mais, como dezenas, uma condicional adequada provavelmente seria melhor.

Kamil Maciorowski
fonte
Bom ponto. Tenha um voto positivo. :-)
Jonathan Hartley