8

I have big list of servers which I normally ssh to all the time. Is there any way using bash or zsh so that I can keep the list of hostname and bash auto-completion goes through the file and gives me suggestion for the boxes starting with those letters whenever I type the first few letters of the hostname.

4 Answers4

9

The bash completion package includes completions for ssh commands, including:

  • ssh
  • ssh-add
  • ssh-copy-id
  • sshfs

You can browse the source here: https://alioth.debian.org/scm/browser.php?group_id=100114

jasonwryan
  • 73,126
8

Zsh completion works with so called ssh bookmarks. These are per host configurations in ~/.ssh/config.

For example,

  host baz
    hostname 192.168.1.2
    port 22
    user warrick

  host bar
    hostname example.com
    port 2200
    user kevin
    identityfile /home/warrick/.ssh/ec2.pem

man ssh_config to see a full list of options.

EDIT

I am using the completion script from ohmyzsh:

https://raw.github.com/robbyrussell/oh-my-zsh/master/lib/completion.zsh

In similiar style to ohmyzsh, I placed the above script into ~/.zsh/libs/completion.zsh and added this to ~/.zshrc.

# ~/.zshrc
for f in ~/.zsh/libs/*; do
  source $f
done
kwarrick
  • 3,128
  • 1
  • 16
  • 10
6

Copied from my own answer on unix.SE:

If you are on an Ubuntu host, then you should know 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, you can read the configured entries from ~/.ssh/config, which are not hashed. 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

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!

dotancohen
  • 15,864
  • 2
    +1 but I would replace the awk line with opts=$(grep '^Host' ~/.ssh/config | sed 's@^Host @@') because the ~/.ssh/config syntax allows for multiple names on a single line – nhed May 22 '15 at 01:36
  • @nhed: Thank you! I did not know that was allowed. – dotancohen May 22 '15 at 07:31
0

For this to work, put any hosts you want to complete in your /etc/hosts file.

You need also bash-completion package (containing file /etc/bash_completion and directory /etc/bash_completion.d)

and source it in ~/.bashrc (. /etc/bash_completion - sometimes it's commented out in /etc/bash.bashrc or in ~/.bashrc).

pevik
  • 1,463
  • 17
  • 28
  • 4
    I'd recommend against using /etc/hosts. Instead add so called ssh bookmarks in ~/.ssh/config. man ssh_config for more details, but it is far more versatile allowing you to specify multiple aliases, username, port, and much much more. – kwarrick Oct 05 '12 at 20:52
  • With archlinux, when I put something in /etc/ssh/ssh_config, I have no completion working for the configured hosts. – Gilles Quénot Oct 05 '12 at 20:56
  • See my extended answer, I am using completion from ohmyzsh. – kwarrick Oct 05 '12 at 21:05
  • 1
    If you look at the source, you will see that the script checks known_hosts as well as the other config files, eg., ~/.ssh/config – jasonwryan Oct 05 '12 at 21:21