How to edit command completion for ssh on bash?

6,871

Solution 1

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.

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

Solution 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

Solution 4

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

Solution 5

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.

Share:
6,871

Related videos on Youtube

iconoclast
Author by

iconoclast

Contractor at Infinite Red, a mobile app &amp; web site design &amp; development company with employees worldwide, experts in React Native, Rails, Phoenix, and all things JavaScript!

Updated on September 17, 2022

Comments

  • iconoclast
    iconoclast almost 2 years

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

    • Sean the Bean
      Sean the Bean about 8 years
      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.
  • Powerlord
    Powerlord almost 14 years
    "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.
  • Richard Holloway
    Richard Holloway almost 14 years
    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.
  • BiAiB
    BiAiB over 12 years
    thanks for this answer. but how can I add a server to the ~/.ssh/config file, I can't find the correct syntax ?
  • Richard Holloway
    Richard Holloway over 12 years
    @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.
  • dotancohen
    dotancohen over 9 years
    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.