SSH tab completion
This is awesome. Put the following into your ~/.bash_profile file:
complete -W "$(echo `cat ~/.ssh/known_hosts | cut -f 1 -d ' ' \ | sed -e s/,.*//g | uniq | grep -v "\["`;)" ssh
Open a new shell and type ssh tab tab. I love tab completion, don’t you?
From Ubuntu 7.04+’s /etc/bash_completion:
_known_hosts()
{
local cur curd ocur user suffix aliases global_kh user_kh hosts i host
local -a kh khd config
COMPREPLY=()
cur=`_get_cword`
ocur=$cur
[ "$1" = -a ] || [ "$2" = -a ] && aliases=’yes’
[ "$1" = -c ] || [ "$2" = -c ] && suffix=’:’
[[ $cur == *@* ]] && user=${cur%@*}@ && cur=${cur#*@}
kh=()
# ssh config files
[ -r /etc/ssh/ssh_config ] &&
config=( “${config[@]}” “/etc/ssh/ssh_config” )
[ -r "${HOME}/.ssh/config" ] &&
config=( “${config[@]}” “${HOME}/.ssh/config” )
[ -r "${HOME}/.ssh2/config" ] &&
config=( “${config[@]}” “${HOME}/.ssh2/config” )
if [ ${#config[@]} -gt 0 ]; then
# expand path (if present) to global known hosts file
global_kh=$( eval echo $( sed -ne ’s/^[ \t]*[Gg][Ll][Oo][Bb][Aa][Ll][Kk][Nn][Oo][Ww][Nn][Hh][Oo][Ss][Tt][Ss][Ff][Ii][Ll][Ee]['"$'\t '"']*\(.*\)$/\1/p’ “${config[@]}” ) )
# expand path (if present) to user known hosts file
user_kh=$( eval echo $( sed -ne ’s/^[ \t]*[Uu][Ss][Ee][Rr][Kk][Nn][Oo][Ww][Nn][Hh][Oo][Ss][Tt][Ss][Ff][Ii][Ll][Ee]['"$'\t '"']*\(.*\)$/\1/p’ “${config[@]}” ) )
fi
# Global known_hosts files
[ -r "$global_kh" ] &&
kh=( “${kh[@]}” “$global_kh” )
[ -r /etc/ssh/ssh_known_hosts ] &&
kh=( “${kh[@]}” /etc/ssh/ssh_known_hosts )
[ -r /etc/ssh/ssh_known_hosts2 ] &&
kh=( “${kh[@]}” /etc/ssh/ssh_known_hosts2 )
[ -r /etc/known_hosts ] &&
kh=( “${kh[@]}” /etc/known_hosts )
[ -r /etc/known_hosts2 ] &&
kh=( “${kh[@]}” /etc/known_hosts2 )
[ -d /etc/ssh2/knownhosts ] &&
khd=( “${khd[@]}” /etc/ssh2/knownhosts/*pub )
# User known_hosts files
[ -r "$user_kh" ] &&
kh=( “${kh[@]}” “$user_kh” )
[ -r ~/.ssh/known_hosts ] &&
kh=( “${kh[@]}” ~/.ssh/known_hosts )
[ -r ~/.ssh/known_hosts2 ] &&
kh=( “${kh[@]}” ~/.ssh/known_hosts2 )
[ -d ~/.ssh2/hostkeys ] &&
khd=( “${khd[@]}” ~/.ssh2/hostkeys/*pub )
# If we have known_hosts files to use
if [ ${#kh[@]} -gt 0 -o ${#khd[@]} -gt 0 ]; then
# Escape slashes and dots in paths for awk
cur=${cur//\//\\\/}
cur=${cur//\./\\\.}
curd=$cur
if [[ "$cur" == [0-9]*.* ]]; then
# Digits followed by a dot - just search for that
cur=”^$cur.*”
elif [[ "$cur" == [0-9]* ]]; then
# Digits followed by no dot - search for digits followed
# by a dot
cur=”^$cur.*\.”
elif [ -z "$cur" ]; then
# A blank - search for a dot or an alpha character
cur=”[a-z.]”
else
cur=”^$cur”
fi
if [ ${#kh[@]} -gt 0 ]; then
# FS needs to look for a comma separated list
COMPREPLY=( $( awk ‘BEGIN {FS=”,”}
/^[^|]/ {for (i=1; i/dev/null ) )
fi
if [ ${#khd[@]} -gt 0 ]; then
# Needs to look for files called
# …/.ssh2/key_22_.pub
# dont fork any processes, because in a cluster environment,
# there can be hundreds of hostkeys
for i in “${khd[@]}” ; do
if [[ "$i" == *key_22_$curd*.pub ]] && [ -r "$i" ] ; then
host=${i/#*key_22_/}
host=${host/%.pub/}
COMPREPLY=( “${COMPREPLY[@]}” $host )
fi
done
fi
# append any available aliases from config files
if [ ${#config[@]} -gt 0 ] && [ -n "$aliases" ]; then
local host_aliases=$( sed -ne ’s/^[Hh][Oo][Ss][Tt]\([Nn][Aa][Mm][Ee]\)\?['"$'\t '"']\+\([^*?]*\)$/\2/p’ “${config[@]}” )
hosts=$( compgen -W “$host_aliases” — $ocur )
COMPREPLY=( “${COMPREPLY[@]}” $hosts )
fi
# Now add results of normal hostname completion
COMPREPLY=( “${COMPREPLY[@]}” $( compgen -A hostname — $ocur ) )
# apply suffix
for (( i=0; i < ${#COMPREPLY[@]}; i++ )); do
COMPREPLY[i]=$user${COMPREPLY[i]}$suffix
done
else
# Just do normal hostname completion
COMPREPLY=( $( compgen -A hostname -S “$suffix” — $cur ) )
fi
return 0
}
Although, simply enough, with recent versions of bash most will just need (bashrc):
# enable bash completion in interactive shells
if [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
Comment by AJ — 16 November, 2008 @ 8:46 pm