A while ago I wrote up a method for switching between /etc/hosts files
. That post is pretty popular and clearly been useful to a few people.
Since then I’ve actually extended this method into a tool that can manage multiple /etc/hosts
files. Using this new method you can have a folder that you can add hosts configurations to, and those files become available for switching into /etc/hosts
straight away.
There’s no reason why an adaptation of this method wouldn’t work in Linux as well.
Here’s how you do it:
1. Create the host configuration directory
We’ll store all the /etc/hosts
type files in /usr/local/share/hs
.
You’ll need to do all of this as a root user. So switch to root using sudo -s
first (you’ll need to be an administrator to do this).
$ mkdir -p /usr/local/share/hs
$ chmod 755 /usr/local/share/hs
Now to start with, let’s make a copy of the existing /etc/hosts
file in this directory.
$ cp /etc/hosts /usr/local/share/hs/hosts.normal
$ chmod 744 /usr/local/share/hs/hosts.normal
Then make the real /etc/hosts
a symbolic link to that new file.
$ ln -sf /usr/local/share/hs/hosts.normal /etc/hosts
Any additional host configurations in this folder need to be named using a similar hosts.*
pattern.
2. Create the host switching script
Take the following bash script and save it to a file located at /usr/local/bin/hs
#!/bin/bash
if [ $1 ]; then
HFILE=hosts.$1
else
HFILE=hosts.normal
fi
# Change this if you put your host files elsewhere
HPATH="/usr/local/share/hs/"
echo "Attempting to switch host file to $HPATH$HFILE"
if [ ! -e $HPATH$HFILE ]; then
echo "--> File does not exist!"
echo "--> Exiting with status 1"
exit 1
fi
if [ -d $HPATH$HFILE ]; then
echo "--> File is a directory!"
echo "--> Exiting with status 2"
exit 2
fi
if [ -h $HPATH$HFILE ]; then
echo "--> File is a symbolic link!"
echo "--> Exiting with status 3"
exit 3
fi
if [ ! -h /etc/hosts ]; then
echo "--> Current hosts file is a real file!"
echo "--> Exiting with status 4"
exit 4
fi
# Link it up
sudo ln -sf $HPATH$HFILE /etc/hosts
# Flush the system-wide DNS cache
if [ -x /usr/bin/dscacheutil ]; then
# Mac OS X 10.5
/usr/bin/dscacheutil -flushcache
elif [ -x /usr/bin/lookupd ]; then
# Mac OS X Less than 10.5
/usr/bin/lookupd -flushcache
elif [ -x /usr/sbin/lookupd ]; then
# Mac OS X Less than 10.5 (alternative)
/usr/sbin/lookupd -flushcache
fi
echo "--> Done"
The script does some basic validity checking on the file and also makes sure that /etc/hosts
is just a symbolic link and not a real file.
You will need to adjust the permissions on this script so that only admins can run it.
$ chmod 750 /usr/local/bin/hs
You also need to make sure that /usr/local/bin
is in your PATH so that the hs
command can be found. We can test that.
$ echo $PATH
… will output something like …
/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/X11/bin
If it’s not there then you need to add it in your users ~/.profile
file. Add the following line to that file, you can create the file if it isn’t there.
export PATH=/usr/local/bin:$PATH
Now reload your profile and the hs
command should be available.
$ . ~/.profile
You could also just close and open your terminal window to reload your profile.
3. Trying it out
The hs
command takes one argument. The argument is used to specify the hosts configuration file to be loaded from /usr/local/share/hs
. If no argument is given, then the assumed file is hosts.normal
.
So for our first test we should add another hosts configuration.
$ cp /usr/local/share/hs/hosts.normal /usr/local/share/hs/hosts.test
Edit the new hosts configuration file to your liking.
Now we can try the switching command to switch to that configuration. You will need to supply your password if you are not already running as root.
$ hs test
Attempting to switch host file to /usr/local/share/hs/hosts.test
Password:
--> Done
The symbolic link at /etc/hosts
should now be pointing to /usr/local/share/hs/hosts.test
.
$ ls -l /etc/hosts
/etc/hosts -> /usr/local/share/hs/hosts.test
Now try switching back to your normal configuration.
$ hs
Attempting to switch host file to /usr/local/share/hs/hosts.normal
Password:
--> Done
Any more configurations that you add to /usr/local/share/hs
are available this way.
Neat, huh?
4. Fancy schmancy tab completion
So that’s all great until you have 10 different hosts config files and you can’t remember their names.
The simple solution is to register additional commands so that command line tab completion can be used. The following additional script registers all the available hosts configs as separate commands. So instead of typing hs test
we can type hstest
. More importantly we can type hs
then hit the “tab” key twice and get a full list of all available commands (one per configuration file).
Hard to explain, easier to just do. Add the following lines of code to the end of your ~/.profile
file.
# Setup hs* commands
HSPATH=/usr/local/share/hs
if [ -d $HSPATH ]; then
HSFILES=(`ls $HSPATH`)
HSCOUNT=${#HSFILES[*]}
for (( HSI=0 ; $HSI < $HSCOUNT ; HSI=$HSI+1 )); do
HSFILE=${HSFILES[HSI]}
HSFILE=${HSFILE:6}
alias hs$HSFILE='hs '$HSFILE
done
fi
unset HSPATH HSFILES HSCOUNT HSI HSFILE
This script loops through all the files in /usr/local/share/hs
and adds a command for each. Once that is added, reload your profile to make the script work.
$ . ~/.profile
Now you should be able to type hs
then hit the “tab” key twice and get a list of the available commands.
$ hs TAB TAB
hs hsnormal hstest
If you add any new configuration files to /usr/local/share/hs
you need to reload your profile for it to turn up as a new command (or just relaunch your terminal window).
Enjoy!