Source Guru

SSH Host Completion – zsh Stylee

by on Dec.06, 2009, under Personal

Ok, so recently, Richard Johnson and Michael Lustfield blogged about tab completion for SSH hosts.

I’m an avid user of zsh, and have my own way of doing this (liberally stolen from Daniel Silverstone).

Now, this requires a little setup to start with, as some Linux Distributions have a habit of creating “hashed” known_hosts files.  So, what I’ve done, is before I ever SSH into a host, I add the following line to my ~/.ssh/config

HashKnownHosts no

From here, I can then add the following line to my ~/.zshrc

zstyle -e ':completion::*:*:*:hosts' hosts 'reply=(${=${${(f)"$(cat {/etc/ssh_,~/.ssh/known_}hosts(|2)(N) /dev/null)"}%%[# ]*}//,/ })'

Now, when I try and ssh into a host, I can use tab completion to complete any host I’ve previously ssh’d into and any new hosts I ssh into get automatically added to the list

:, ,

7 Comments for this entry

  • tomás zerolo

    Cute.

    To be fair, you should note why “hashed” known_hosts files are a good idea: an attacker getting hold of your account (at the moment your secret key is “unlocked”) will have a nice directory of hosts to try next.

    That’s why it was introduced in the first place.

    So whoever follows your advice should take this into consideration to strike the correct tradeoff.

    Regards
    – tomás

  • Ingmar Vanhassel

    As far as I can see zsh does this by default?
    I don’t see why you need that zstyle call in zshrc.

  • cstamas

    I do not know if you are familiar with grml.org/zsh If not you should give a try.

    regards,
    cstamas

  • Josip Rodin

    Why so ugly, and inflexible?

    if [ -f ~/.ssh/known_hosts ]; then
    hosts=(`awk ‘{print $1}’ ~/.ssh/known_hosts | tr ‘,’ ‘\n’ `)
    fi
    if [ -f ~/.ssh/config ]; then
    hosts=($hosts `grep ^Host ~/.ssh/config | sed s/Host\ // | egrep -v ‘^\*$’`)
    fi
    if [ -f /var/lib/misc/ssh_known_hosts ]; then
    hosts=($hosts `awk -F “[, ]” ‘{print $1}’ /var/lib/misc/ssh_known_hosts | sort -u`)
    fi
    if [ "$hosts" ]; then
    zstyle ‘:completion:*:hosts’ hosts $hosts
    fi

  • Jason 'vanRijn' Kasper

    Really nice, Martin! =:) I can’t do without zsh and the stupid hashed known_hosts file has been irking me for quite a while. Thanks for sharing!! =:)

  • MTecknology

    BTW- The correct link for my blog:
    http://profarius.com/content/ssh-tab-complete

    Josip: That is.. Ugly..
    [[ -f ~/.ssh/known_hosts ]] && hosts=(`awk ‘{print $1}’ ~/.ssh/known_hosts | tr ‘,’ ‘\n’ `)
    [[ -f ~/.ssh/config ]] && hosts=($hosts `grep ^Host ~/.ssh/config | sed s/Host\ // | egrep -v ‘^\*$’`)
    [[ -f /var/lib/misc/ssh_known_hosts ]] && hosts=($hosts `awk -F “[, ]” ‘{print $1}’ /var/lib/misc/ssh_known_hosts | sort -u`)
    [[ "$hosts" ]] && zstyle ‘:completion:*:hosts’ hosts $hosts

    Upi could also make each line into a single sed statement rather than all the pipes.

  • crs

    Way cleaner way to do it I believe is:

    hosts=$(awk ‘/^Host / {printf(“%s “,$2)}’ ~/.ssh/config 2>/dev/null)
    zstyle ‘:completion:*:hosts’ hosts $hosts

Leave a Reply

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!