4

(I've asked this question regarding zsh, but I also use bash and would find it useful there too--as I'm guessing many others would too since bash has many more users than zsh.)

I'd like to set up command completion on bash to display host names after I type

ssh [TAB]

taking the names out of my .ssh/config file (and preferably from known_hosts and /etc/hosts and anywhere else that makes sense) and presenting one single list.

It does some of this currently, but

  1. it doesn't use .ssh/config at all
  2. it requires a username first, even though using .ssh/config makes typing usernames unnecessary
  3. it presents multiple lists (probably one from known_hosts and another from /etc/hosts, but I haven't verified that)

So I want to be include known usernames as well as known hostnames in the (preferably single) list after typing ssh [TAB]

(I'm coming here before Google because 1) it'll result in the answer getting stored here, and 2) it's probably more efficient. If no one else answers, I'll hunt down the answer.)

1
  • 1
    If you ended up here looking for a way to exclude hostnames defined in /etc/hosts from ssh completion, you can simply add export COMP_KNOWN_HOSTS_WITH_HOSTFILE="" to your .bashrc. Jun 20, 2016 at 19:56

5 Answers 5

3

I wrote this two part guide a while ago:

http://www.debian-administration.org/article/316/An_introduction_to_bash_completion_part_1

http://www.debian-administration.org/article/317/An_introduction_to_bash_completion_part_2

It explains how you can write completion scripts - though as the previous answer indicates what you want should be already available to you.

1
  • Thank you Steve! I was able to use your guide to enable SSH autocompletion in Ubuntu which is an especially problematic system due to known_hosts hashing.
    – dotancohen
    Jan 28, 2015 at 16:56
3

This is what I have in my .bashrc for ssh hostname completion :

SSH_COMPLETE=( $(cut -f1 -d' ' ~/.ssh/known_hosts |\
                 tr ',' '\n' |\
                 sort -u |\
                 grep -e '[:alpha:]') )
complete -o default -W "${SSH_COMPLETE[*]}" ssh
2

This functionality is already provided by bash completion. The actual file if you want to edit its functionality is /etc/bash_completion.d/ssh.

This is provided by the package bash-completion.

On typing ssh < TAB > it will list all hosts in /etc/hosts and ~/.ssh/config in one list.

If you have the User specified for a given host you don't need to specify this when using ssh.

So if you want to ssh to server brandon

Type ssh br< TAB > and it should autocomplete the word brandon as long as that host is in either /etc/hosts or ~/.ssh/config.

4
  • "This is provided by the package bash-completion." Isn't this making an assumption about OS/distribution is being used? I would think FreeBSD would use a different package than Ubuntu Linux, for example.
    – Powerlord
    Aug 16, 2010 at 20:35
  • Apologies R. Bemrose you are right. I have been jumping between Ubuntu Stack Exchange and Server Fault and you are correct that I assumed the OS is Linux. Aug 16, 2010 at 20:46
  • thanks for this answer. but how can I add a server to the ~/.ssh/config file, I can't find the correct syntax ?
    – BiAiB
    Nov 23, 2011 at 11:16
  • 1
    @BiAiB: An example from my .ssh/config file is .... : Host nemesis {newline} User richard {newline} Hostname 192.168.1.34 {newline} IdentityFile ~/.ssh/id_rsa. That sort of entry will work. FOr more info check out man ssh_config. Nov 25, 2011 at 22:36
2

If you are on an Ubuntu Server machine, then you should know that in Ubuntu the entries in ~/.ssh/known_hosts are hashed, so SSH completion cannot read them. The Canonical devs consider this 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, you can read the configured entries from ~/.ssh/config, which are not hashed. Based on the links from Steve Kemp's answer, 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 | awk '{print $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
1

If you're on a mac you can use Homebrew to install bash-completion:

brew install bash-completion

Add the following to ~/.bash_profile

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

If you've installed bash-completion with MacPorts, add this to the bash_profile

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

Now you have the package / functionality that Richard Holloway was talking about.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .