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.)

iconoclast
  • 1,688
  • 2
  • 18
  • 30
  • 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. – Sean the Bean Jun 20 '16 at 19:56

5 Answers5

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.

  • Thank you Steve! I was able to use your guide to enable [SSH autocompletion in Ubuntu](http://unix.stackexchange.com/questions/136351/autocomplete-server-names-for-ssh-and-scp) which is an especially problematic system due to known_hosts hashing. – dotancohen Jan 28 '15 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.

Richard Holloway
  • 7,256
  • 2
  • 24
  • 30
  • "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 '10 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. – Richard Holloway Aug 16 '10 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 '11 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`. – Richard Holloway Nov 25 '11 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
dotancohen
  • 2,410
  • 2
  • 24
  • 38
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.

Kirk
  • 113
  • 5