Autocomplete server names for SSH and SCP

I have a few servers configured in ~/.ssh/config, such as alpha and beta. How might I configure Bash such that the commands $ ssh alTab and $ scp file.tgz alTab autocomplete the names of the configured servers?

I don’t want to add the servers to another file (i.e. a Bash array) each time one is added, as we add and remove servers regularly and the list is quite large.

This is on Kubuntu 12.10, and I do have bash-completion installed.

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

Found it!!

It seems that in Ubuntu the entries in ~/.ssh/known_hosts are hashed, so SSH completion cannot read them. This is a feature, not a bug. Even by adding HashKnownHosts no to ~/.ssh/config and /etc/ssh/ssh_config I was unable to prevent the host hashing.

However, the hosts that I am interested in are also found in ~/.ssh/config. Here is a script for Bash Completion that reads the entries from that file:

_ssh() 
{
    local cur prev opts
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"
    opts=$(grep '^Host' ~/.ssh/config ~/.ssh/config.d/* 2>/dev/null | grep -v '[?*]' | cut -d ' ' -f 2-)

    COMPREPLY=( $(compgen -W "$opts" -- ${cur}) )
    return 0
}
complete -F _ssh ssh

Put that script in /etc/bash_completion.d/ssh and then source it with the following command:

$ . /etc/bash_completion.d/ssh

I found this guide invaluable and I would not have been able to script this without it. Thank you Steve Kemp for writing that terrific guide!

Method 2

Pre-packaged

You don’t say what distro you’re using but on my Fedora 19 system I have the following package installed, bash-completion which provides this feature through this completion rule file:

/usr/share/bash-completion/completions/ssh

Here’s the package I have installed:

$ rpm -aq |grep completion
bash-completion-2.1-2.fc19.noarch

If you look through that rule file you’ll see stanzas that are interrogating the $HOME/.ssh/config file:

$ grep config /usr/share/bash-completion/completions/ssh
    local configfile
    local -a config
        # Search COMP_WORDS for '-F configfile' or '-Fconfigfile' argument
                    configfile="$(dequote "${1:2}")"
                    [[ $1 ]] && configfile="$(dequote "$1")"
        _known_hosts_real -a -F "$configfile" "$cur"
    local configfile
        # Search COMP_WORDS for '-F configfile' argument
                    configfile="$(dequote "${1:2}")"
                    [[ $1 ]] && configfile="$(dequote "$1")"
        _known_hosts_real -a -F "$configfile" "$cur"
    local configfile prefix
        # Search COMP_WORDS for '-F configfile' or '-Fconfigfile' argument
                    configfile="$(dequote "${1:2}")"
                    [[ $1 ]] && configfile="$(dequote "$1")"
                _known_hosts_real -c -a -F "$configfile" "$cur"

Rolling your own

I also found this Gist, known_hosts_autocomplete.sh, that does something similar except with the $HOME/.ssh/known_hosts file.

# add to ~/.bash_profile, and close/reopen a shell.  Will autocomplete any
# hosts found in known_hosts.

complete -W "$(echo `cat ~/.ssh/known_hosts | cut -f 1 -d ' ' | 
    sed -e s/,.*//g | uniq | grep -v "["`;)" ssh

You could do something similar using your $HOME/.ssh/config file if for some reason you’re unable to find the completion rule file for ssh already pre-packaged.

Method 3

I found that the autocomplete was not working because Ubuntu hashes known hosts. You can add

Host *
    HashKnownHosts no

To your .ssh/config file but existing hosts won’t be un-hashed.

Method 4

To enable ssh autocompletion in Debian and Ubuntu:

sudo apt-get install bash-completion

Note that this has nothing at all to do with known_hosts hashing, contrary to what was stated above and the original question. If you wanted to autocomplete from known_hosts, then of course you would have to disable hashing, but that is strongly recommended against.

For example, I have:

Host *
    HashKnownHosts yes

in my .ssh/config, and I still have ssh auto-completion working just fine against hosts listed in .ssh/config and /etc/hosts. You do need to add the host to .ssh/config as the OP stated:

Host my-awesome-host
Hostname the.real.host.name

(Or, you can add a host entry to /etc/hosts, which is another source for the Debian/Ubuntu scripts.)

Then, you can just type ssh my-awe<tab> and it will be automagically completed. Again, this is even if you HashKnownHosts, which is highly recommended. (Note that bash completion needs to be enabled in your bash shell, and you need to specifically have those scripts installed as above for your distribution.)

Then, add these lines to your .bashrc to enable it (requires a logout and log back in, or just a new bash typed in to launch a new shell. (You don’t need to enable if it’s already enabled in /etc/bash.bashrc and /etc/profile sources /etc/bash.bashrc).

if [ -f /etc/bash_completion ]; then
    . /etc/bash_completion
fi

This will enable ssh autocompletion (among other things!) from ~/.ssh/config, /etc/hosts, etc.

Note that Debian defaults to ash instead of bash. You can switch to bash easily:

sudo usermod -s /bin/bash "$USER"

(You’ll need to log out and log back in for this to take effect.)

Method 5

On Ubuntu 14.04, ssh auto-completes servers mentioned in your ~/.ssh/config

I noticed it when I realized that only one of the servers I commonly access auto-completed. The only difference between the two was an entry in the ssh config file that was related to authentication. When I added a new entry to the config file for the other server, it started auto-completing too.

Here’s the entry for those who were asking:

HOST server-name 
    GSSAPIAuthentication=no

I would be very surprised if it mattered what you were specifying in the config (as long as it is still valid, of course).

Method 6

On CentOS 7 all it took was
yum install bash-completion
to auto complete hosts from .ssh/config when typing ssh and hitting Tab.

Method 7

On macosx brew install bash-completion then add the following to ~/.profile

if [ -f $(brew --prefix)/etc/bash_completion ]; then
  . $(brew --prefix)/etc/bash_completion
fi

Method 8

Add the following into ~/.bashrc or ~/.bash_profile

# Autocomplete ssh commands
WL="$(perl -ne 'print "$1n" if /^Host (.+)$/' ~/.ssh/config | grep -v "*" | tr "n" " ")"
complete -o plusdirs -f -W "$WL" ssh scp

Then run source ~/.bashrc or source ~/.bash_profile to pick up the configuration

Credit > https://blog.tinned-software.net/use-ssh-comfortably-with-command-history-and-auto-complete/


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x