Traincoding: SSH aliases
It’s been a while since I published a traincoding snippet. Here’s a small one for your .bashrc that creates ‘alias host=ssh host’ for all hosts you know. It helps if you disable HashKnownHosts in your ~/.ssh/config.
if [ -d ~/.ssh ]; then
# Touch files we expect to exist
if [ ! -e ~/.ssh/config ]; then touch ~/.ssh/config; fi
if [ ! -e ~/.ssh/known_hosts ]; then touch ~/.ssh/known_hosts; fi
# Parse ~/.ssh/known_hosts and ~/.ssh/config to find hosts
for x in `sed -e ’s/[, ].*//’ ~/.ssh/known_hosts; awk ‘/^Host [^*?]+$/{print $2}’ ~/.ssh/config`; do
# Don’t override commands
type $x > /dev/null 2>&1 && continue
alias $x=”ssh $x”
# Remove the domainname
y=${x/.*/}
if [ "$y" != "$x" ]; then
if ! type $y > /dev/null 2>&1; then
alias $y=”ssh $x”
fi
fi
# Remove prefix. Add prefixes you want removed here
y=${y/pf1-/}
y=${y/pf2-/}
if [ "$y" != "$x" ]; then
if ! type $y > /dev/null 2>&1; then
alias $y=”ssh $x”
fi
fi
done
fi
If you add this to your ~/.bashrc, the following will be done when you start a shell:
alias pf1-foo.bar.com=”ssh pf1-foo.bar.com”
alias pf1-foo=”ssh pf1-foo.bar.com”
alias foo=”ssh pf1-foo.bar.com”
This helps a lot if you connect to a lot of machines with names like annoyingprefix-machine1.annoyingly.long.domain.name (Guess what I need to connect to often :))
It checks whether a command with a certain name exists already, so it won’t do things like alias svn=”ssh svn.gnome.org” which would be annoying.
See man 5 ssh_config for a nicer solution:
$ cat ~/.ssh/config
Host shortname
HostName some.really.long.hostname
User username_that_i_never_remember
$ ssh shortname # == ssh username_that_i_never_remember@some.really.long.hostname
Works regardless of your shell, and scp/sftp recognize the shortnames as well.
Great script! I made some mods that you might like (and I hope pre works!):
#!/bin/bash
shopt -s extglob
isint(){
case $1 in
?([-+])+([0-9]) )
return 0;;
*) return 1;;
esac
}
if [[ -d ~/.ssh ]]; then
# Touch files we expect to exist
if [[ ! -e ~/.ssh/config ]]; then touch ~/.ssh/config; fi
if [[ ! -e ~/.ssh/known_hosts ]]; then touch ~/.ssh/known_hosts; fi
# Parse ~/.ssh/known_hosts and ~/.ssh/config to find hosts
for x in `sed -e ’s/[, ].*//’ ~/.ssh/known_hosts; awk ‘/^Host [^*?]+$/{print $2}’ ~/.ssh/config`; do
# Don’t override commands
type “${x}” > /dev/null 2>&1 && continue
# Remove the domainname
y=${x%%.*}
# you don’t want IP addresses for aliases, trust me.
isint $y && continue
# If it’s a short-name, move on
#z=${x##*.}
#[[ "${z}" == 'edu' || "${z}" == 'com' || "${z}" == 'net' ]] || continue
# So the above is commented out because you’d be surprised at how much you rely on your search path
# You should pipe the output of this script to sort and your fqdn’s will override your shorts.
echo alias “${x}”=”ssh $x”
if [[ "$y" != "$x" ]]; then
if ! type $y > /dev/null 2>&1; then
echo alias $y=”ssh $x”
fi
fi
done
fi
ephemient: That’s unmaintainable for hundreds of hosts :) My .ssh/config is fairly short, uses lots of wildcards and ProxyCommands.
Hmm, my .ssh/config has a stanza for every host I’ve ever accessed more than once, I don’t see why it’s unmaintainable.
But the lack of the ability to do something like
Host foo-%1
HostName foo-%1.bar.baz.bam
does make me sad.
bash can do hostname completion.
$ export HOSTFILE=~/hostnames
$ cat $HOSTFILE
example.com
me.homelinux.org
http://ftp.isp.com
$ ssh
example.com http://ftp.isp.com me.homelinux.org
$ ssh e
$ ssh example.com
The bash-completion package has much better completion for ssh/scp etc, including remote filename completion for scp and rsync :)