Setting a Dynamic Hostname by DNS
From Debian Clusters
Often, rather than having to set /etc/hostname for each worker node, it's more helpful to have it assign the hostname to itself automatically at boot based on the information handed to it by DNS (see Name Service: DNS and BIND). This is particularly true since it's most expedient to create one worker node image and then broadcast that image onto the other nodes, and it's pain to go through and change each one's hostname. Further, since all the information for which machine is which is located in DNS, why make it necessary to change that in two places?
Dotquad.c
There's a small script that set this for you, if DNS has been set up. It requires the binary from dotquad.c. First, save the following, dotquad.c, on the machine.
/* This file is in the public domain. */
#include <stdlib.h>
#include <stdio.h>
void range(int a){
/* die if not valid octet */
if (a<0) exit(1); if (a>255) exit(1);
}
int main(int argc, char* argv[]){
int a, b, c, d;
unsigned int ip = 0;
if (argc != 2) exit(1);
if (sscanf(argv[1], "%i.%i.%i.%i", &a, &b, &c, &d)<4) exit(1);
range(a); range(b); range(c); range(d);
ip = ip * 256 + a;
ip = ip * 256 + b;
ip = ip * 256 + c;
ip = ip * 256 + d;
printf("%u\n", ip);
exit(0);
}
The binary of this file needs to be compiled and placed at /bin/dotquad, because the custom hostnames script will reference it there. If you haven't installed g++ yet, do that now (apt-get install g++). Then,
g++ dotquad.c -o /bin/dotquad
Custom Hostname Script
Below is the script that will automatically set the hostname based on DNS for the machine. I recommend setting /etc/hostname to some default value common to all of the machines, like amnesia. Then you can tell at a glance if DNS is working. Before this script will work, host must be installed on the machine. Do this with
apt-get install host
Then save the file below in /etc/init.d/, make it executable (chmod +x <filename>), and then symlink it into /etc/rc2.d, something like this:
ln -s /etc/init.d/hostnamecustom /etc/rc2.d/S21hostnamecustom
You can also start or stop it at the command line, after it's moved to /etc/init.d/. This won't take affect for any existing bash sessions; you'll have to log out and log back in to see the change.
/etc/init.d/hostnamecustom start
Hostnamecustom
#!/bin/sh
DOTQUAD=/bin/dotquad
case "$1" in
start)
echo -n 'Setting system hostname: '
sleep 2
for x in `ls /proc/sys/net/ipv4/conf/ | grep -v lo | grep -v all | grep -v default` ; do
interface=$x
echo Trying interface $x
ip=`ifconfig $interface | grep "inet addr" | cut -d":" -f 2 | awk '{print $1}'`
echo "IP resolved to $ip"
if $DOTQUAD "$ip" >/dev/null ;
then
host=`host $ip 2>/dev/null | head -n 1 | awk '{print $2}' 2>/dev/null`
echo "$host"
if [ "x$host" != "x" ] ; then
hname=`echo $host | cut -d"." -f1`
echo "Host name is $hname"
sysctl -w kernel.hostname=$hname
dname=`echo $host | cut -d"." -f2-`
echo "Domain name is $dname"
sysctl -w kernel.domainname=$dname || true
# save the current /etc/hosts file
cp /etc/hosts /etc/hosts.orig || true
# strip out any existing entry for this host
cat /etc/hosts | grep -v $hname | cat > /etc/hosts.new
# add the new IP fqdn hname to the /etc/hosts.new file
echo $ip $hname $host >> /etc/hosts.new
# mv the new file into place
mv /etc/hosts.new /etc/hosts
# save the current /etc/hostname file
cp /etc/hostname /etc/hostname.orig || true
# add the new hostname to /etc/hostname.new
echo $hname >> /etc/hostname.new
# move hostname.new into place
mv /etc/hostname.new /etc/hostname
exit 0
fi
fi
done
if [ "x$interface" = "x" ] ; then
echo "Assigning hostname failed."
else
echo `ifconfig eth0`
echo done.
fi
;;
stop)
echo -n 'Restoring original hostname '
if [ -f /etc/hostname ] ; then
hostname --file /etc/hostname
fi
if [ -f /etc/hosts.orig ] ; then
mv /etc/hosts.orig /etc/hosts || true
fi
;;
restart|reload|force-reload)
$0 stop
sleep 2
$0 start
;;
esac

