Submit Hint Search The Forums LinksStatsPollsHeadlinesRSS
14,000 hints and counting!

Create on-the-fly hostname lists for ssh tab completion UNIX
If you don't want to manage server lists for tab completion with ssh, put the following line in your .bash_profile file in your home directory: This will allow you to tab complete any hostname you've previously ssh'd to.

[robg adds: This worked as described for me. The complete command is a built-in bash function that lets you specify lists of options to be used with tab completion on a given command. The version above parses your known_hosts to create the list of options. You can read more about the complete built-in function in the bash man pages -- man bash, then search for the section titled Programmable Completion.]
    •    
  • Currently 2.27 / 5
  You rated: 3 / 5 (11 votes cast)
 
[21,673 views]  

Create on-the-fly hostname lists for ssh tab completion | 20 comments | Create New Account
Click here to return to the 'Create on-the-fly hostname lists for ssh tab completion' hint
The following comments are owned by whoever posted them. This site is not responsible for what they say.
Implications For sudo Command
Authored by: bfad on Mar 24, '08 08:15:51AM

One of the most frustrating things for me is that commands don't tab-complete when prefixed by sudo, but now I can modify this for the sudo command. Does anyone with better Unix knowledge then me know how I could use this to read in my $PATH variable to get the list of directories for sudo to look under for tab completion? Otherwise I'll just have to add all the paths individually, including the one's I've specified.



[ Reply to This | # ]
Implications For sudo Command
Authored by: ccase on Mar 24, '08 12:04:00PM
Try: complete -c -f command sudo

[ Reply to This | # ]
Implications For sudo Command
Authored by: bfad on Mar 25, '08 10:40:00AM

Thank you ccase! That works perfectly.



[ Reply to This | # ]
Any way to use the with ssh/config aliases.
Authored by: drudus on Mar 24, '08 08:37:04AM

It would be great to use this with the aliases in the ssh config, any suggestions?

D



[ Reply to This | # ]
Create on-the-fly hostname lists for ssh tab completion
Authored by: deviantintegral on Mar 24, '08 09:04:37AM

Or better yet, install the bash-completion package from macports and then add the following to your .bashrc:

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

This gives a variety of neat additions, including ssh, ping, ftp, tar, etc.



[ Reply to This | # ]
Create on-the-fly hostname lists for ssh tab completion
Authored by: thegooch49 on Mar 24, '08 09:24:27AM

Any way to make this work with tcsh? I tried this in my .tcshrc, and I got an error of an 'illeagal variable'.



[ Reply to This | # ]
Create on-the-fly hostname lists for ssh tab completion (TCSH)
Authored by: joab on Mar 24, '08 03:45:22PM

Enter this into your .tcshrc:

set hosts = `sed -e 's/^ *//' -e '/^#/d' -e 's/[, ].*//' -e '/\[/d' ~/.ssh/known_hosts | sort -u`
complete ssh 'p/1/$hosts/' 'p/2/c'

It completes first hosts and then commands.



[ Reply to This | # ]
Create on-the-fly hostname lists for ssh tab completion
Authored by: pauldy on Mar 24, '08 09:33:33AM

Worked great for me but only for servers already in the list, is there a way to make this evaluate everytime you press tab?



[ Reply to This | # ]
Create on-the-fly hostname lists for ssh tab completion
Authored by: BobHarris on Mar 24, '08 09:05:54PM
I do not know how to directly make completion re-evaluate known_hosts for every TAB, but maybe this is the next best thing.

If you put the following code in your .bashrc (or .bash_profile; where ever you setup your PS1 prompt variable), then after each command when the prompt is output, the known_hosts file will be checked to see if has been modified, and if so, it will be re-evaluated:

update_hosts_complete()
{
    typeset ref=/tmp/hosts_complete.$$
    typeset khosts=$HOME/.ssh/known_hosts

    if [[ $khosts -nt $ref ]]; then
        touch $ref
        complete -W "$(awk -F'[, ]' '
            $1 !~ /[/ {hosts[$1]=1}
            END{
                for(host in hosts)
                    printf(" %s", host)
            }' $khosts)" ssh
    fi
}
PS1="$(update_hosts_complete) your prompt goes here> "

Bob Harris

[ Reply to This | # ]

Create on-the-fly hostname lists for ssh tab completion
Authored by: Nem on Mar 24, '08 09:34:23AM
The macports suggestion is a good one, but IMO, includes too much. If you don't have macports installed, you can add the following to your .bash_profile (I wouldn't add it to my .bashrc, since that gets read in by cron jobs and remote commands).

There are a couple improvements here. First, this will also read in aliases in your ~/.ssh/config file. Secondly, it will ignore commented out entries in your ~/.ssh/known_hosts file. Finally, this is a function and not a static list. Thus, it is immediately aware of any new additions to either file (although on really slow machines it will be slower than a static list).


_complete_ssh_hosts ()
{
        COMPREPLY=()
        cur="${COMP_WORDS[COMP_CWORD]}"
        comp_ssh_hosts=`cat ~/.ssh/known_hosts | \
                        cut -f 1 -d ' ' | \
                        sed -e s/,.*//g | \
                        grep -v ^# | \
                        uniq | \
                        grep -v "\[" ;
                cat ~/.ssh/config | \
                        grep "^Host " | \
                        awk '{print $2}'
                `
        COMPREPLY=( $(compgen -W "${comp_ssh_hosts}" -- $cur))
        return 0
}
complete -F _complete_ssh_hosts ssh


---
Nem W. Schlecht
http://geekmuse.net/

[ Reply to This | # ]

Create on-the-fly hostname lists for ssh tab completion
Authored by: leono on Mar 24, '08 11:05:40AM
Nice job, Nem! I don't actually have a ~/.ssh/config file, so here's a modification to deal with that situation:

_complete_ssh_hosts ()
{
        COMPREPLY=()
        cur="${COMP_WORDS[COMP_CWORD]}"
        comp_ssh_hosts=`cat ~/.ssh/known_hosts | \
                        cut -f 1 -d ' ' | \
                        sed -e s/,.*//g | \
                        grep -v ^# | \
                        uniq | \
                        grep -v "\[" ;
                if [ -f ~/.ssh/config ]; then
                        cat ~/.ssh/config | \
                                grep "^Host " | \
                                awk '{print $2}'
                fi
                `
        COMPREPLY=( $(compgen -W "${comp_ssh_hosts}" -- $cur))
        return 0
}
complete -F _complete_ssh_hosts ssh


[ Reply to This | # ]
Create on-the-fly hostname lists for ssh tab completion
Authored by: slswift on Mar 24, '08 07:34:52PM

Thanks for the slick inclusion of .ssh/config. However, I had to make a quick tweak to 'awk' out the 3rd entry rather than the 2nd.

awk '{print $3}'

My .ssh/config uses this syntax, which may or may not be 'standard', but definitely works. My config syntax comes from ssh v. 1, so the current accepted syntax could be VASTLY different.

Host = solutions



[ Reply to This | # ]
Create on-the-fly hostname lists for ssh tab completion
Authored by: ssevenup on Mar 24, '08 06:37:29PM

tcsh and/or zsh versions? I actually would find the aliases in config more useful than known_hosts I think? My user name is rarely the same on the box I'm logging into.

---
Mark Moorcroft
ELORET Corp. - NASA/Ames RC
Sys. Admin.



[ Reply to This | # ]
Create on-the-fly hostname lists for ssh tab completion
Authored by: edaominoratto on Mar 24, '08 10:49:55AM
Does anyone know how to get complete to work case insensitive?

I have set completion-ignore-case On (in .inputrc), but what I define to get completed remains case sensitive.

Example: When I use complete -W "Foo" ls, then ls f[TAB] doesn't return a result (while ls F[TAB] does).

[ Reply to This | # ]
Create on-the-fly hostname lists for ssh tab completion
Authored by: CarlRJ on Mar 24, '08 01:53:09PM
For what it's worth, the core bit of the process:
cat ~/.ssh/known_hosts | cut -f 1 -d ' ' | sed -e s/,.*//g | uniq | grep -v "\["
can be reduced from five commands and four pipe to two commands and one pipe:
sed -e 's/^  *//' -e '/^#/d' -e 's/[, ].*//' -e '/\[/d' ~/.ssh/known_hosts | sort -u
This also handles comment lines in known_hosts (starting with "#") and duplicates which do not follow each other (by using "sort -u" in place of "uniq").

[ Reply to This | # ]
Create on-the-fly hostname lists for ssh tab completion
Authored by: corienti on Mar 24, '08 04:00:44PM

VERY nice, CarlRJ! I am impressed - and you got rid of a classical "useless use of cat" as well! Sed is a beautiful thing...



[ Reply to This | # ]
zsh
Authored by: adrianm on Mar 24, '08 11:28:27PM

If you use zsh (IMO, the best interactive shell), you not only get completion on hosts, but also on known usernames (and it adds the @ after them).

Just put:

autoload -U compinit
compinit

in your .zshrc

---
~/.sig: not found



[ Reply to This | # ]
zsh
Authored by: ssevenup on Mar 25, '08 06:55:56PM

Thanks oodles man :-)

---
Mark Moorcroft
ELORET Corp. - NASA/Ames RC
Sys. Admin.



[ Reply to This | # ]
Create on-the-fly hostname lists for ssh tab completion
Authored by: nevstokes on Mar 25, '08 02:26:27AM

Or you could just use reverse-i-search for autocompletion of anything in your bash history.

Hit control+r and start typing



[ Reply to This | # ]
Create on-the-fly hostname lists for ssh tab completion
Authored by: russkey on Dec 06, '10 07:47:55AM
Is there a way to add a list of custom words that the read built-in can then read? For example, i would like to say something like complete -W "alice bob" read; and then when i call up read to get user input, they can type a[TAB] and have it completed to alice. The code above works with read a[TAB] completing but not with the input to the read command itself.

[ Reply to This | # ]