Remote SSH Commands - bash bind warning: line editing not enabled

7,252

Solution 1

Having an interactive session is not enough for bind to work. For instance emacs shell provides an interactive session which passes the if [ -t 1 ] test but it does not have the line editing so any binds in your ~/.bashrc will generate the warnings. Instead, you can check if the line editing is enabled by doing something like this (is there a simpler/better way?):

if [[ "$(set -o | grep 'emacs\|\bvi\b' | cut -f2 | tr '\n' ':')" != 'off:off:' ]]; then
  echo "line editing is on"
fi

Solution 2

ssh host 'ls -als'

When you ask ssh to run a command on the remote system, ssh doesn't normally allocate a PTY (pseudo-TTY) for the remote session. You can run ssh with -t to force it to allocate a tty:

ssh -t host 'ls -als'

If you don't want to type that all the time, you could add this line to the ".ssh/config" file on your local host:

RequestTTY yes

Alternately, you could fix the ".bashrc" file on your remote system to avoid running commands that presume the session is interactive when it isn't. One way is to enclose the commands in a test that the session has a TTY:

if [ -t 1 ]
then
    # standard output is a tty
    # do interactive initialization
fi

Solution 3

If there is no line editing, these bind commands themselves are harmless. Suppress the warnings:

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

This is somewhat inelegant, still it should work. Other answers don't agree about the best/sufficient test. My approach circumvents this. It doesn't scale well though. The two commands alone should not make a big difference; but if you had more, like dozens, then a proper conditional would probably be better.

Solution 4

Put the bind commands into an 'if' statement that checks whether the bash session allows line editing:

if [[ ${SHELLOPTS} =~ (vi|emacs) ]]; then
    bind '"^[[A":history-search-backward'
    bind '"^[[B":history-search-forward'
fi
Share:
7,252

Related videos on Youtube

Lin Forrest Yang
Author by

Lin Forrest Yang

Software architect, maker of things. FPV multirotor aerial video enthusiast. All of my code and snippets in questions/answers are WTFPL unless otherwise noted. "No plan survives first contact with implementation."

Updated on September 18, 2022

Comments

  • Lin Forrest Yang
    Lin Forrest Yang almost 2 years

    I am using bash 4.3.11(1) and have the following history plugin installed (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'
    

    When I log in to an interactive session all is well but when I run remote commands via ssh host 'ls -als' for example, I see the following output:

    : 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
    

    When I modify the history plugin with echo -e '\0033\0143' after each bind call I no longer get the warnings but my console is cleared. Not a huge drawback but it would be nice to know a cleaner way to suppress this for remote commands.

    # 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'
    
  • Ahmed Masud
    Ahmed Masud almost 5 years
    Actually this answer is incorrect, see @alexander-vorobiev's answer below.
  • Ahmed Masud
    Ahmed Masud almost 5 years
    This should be the correct answer
  • Ahmed Masud
    Ahmed Masud almost 5 years
    The easier way would be to use [[ ${SHELLOPTS} =~ (vi|emacs) ]] && echo 'line-editing on' || echo 'line-editing off'
  • Jonathan Hartley
    Jonathan Hartley over 4 years
    Good point. Have an upvote. :-)
  • hraban
    hraban over 4 years
    less faff regex and more robust: if set -o | grep 'on$' | grep -q '^\(vi\|emacs\)\b'; then ....
  • Yongwei Wu
    Yongwei Wu about 4 years
    Whether it is strictly correct or not, -t 1 does solve the problem for me. It does not affect the vim terminal session or external command, either.
  • Yongwei Wu
    Yongwei Wu about 4 years
    FYI: Vim's terminal session works with bind, and its SHELLOPTS contains the string "emacs" (though I am not sure of the reason).
  • IpsRich
    IpsRich about 3 years
    Looks like this is the "proper" way of detecting whether a shell is interactive.