Autocomplete server names for SSH and SCP
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!
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.
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.