Migraine-inducing bash one-liner
Background: lab machines are DHCP, therefore the IP address cannot be counted on, nor can the canonical name be set in DNS (apparently). rSnapshot requires a canonical something (obviously) so it know where to go to grab the snapshot.
Solution: put each client machine in the hosts file so rSnapshot knows where each machine is. This of creates a
Problem: if the client machine's IP address changes, the hosts file on the rSnapshot server needs to be adjusted.
I looked at using nmap/arp to do this job, but came to the conclusion that the results were unreliable. Occasionally, a machine would not report back to the request, making hte script unreliable. For posterity, this is how the script worked:
1) set var="MAC address" for each machine (e.g. machineName="00:DE:6F:34:34:00")
2) set ipArr=( $(nmap -sP 192.168.16.192/26|grep -oh '[0-9]\{3\}\.[0-9]\{3\}\.[0-9]\{3\}\.[0-9]\{3\}'| tr '\n' ' ') ) - which will output an array that looks something like this:
(192.168.16.197 192.168.16.198 192.168.16.203 192.168.16.204 192.168.16.206 192.168.16.214 192.168.16.217 192.168.16.220 192.168.16.223 192.168.16.228 192.168.16.230 192.168.16.237 192.168.16.241 192.168.16.242 192.168.16.250 192.168.16.254)
3) iterate through the array and run arp on each IP:
for (( i = 0 ; i < ${#active_IP_addresses[@]} ; i++ ))
do
echo `arp -a ${active_IP_addresses[$i]}`
done
~~~~
which will produce output that looks like this:
machine.name.as.found.in.remote.hosts.file (192.168.16.X) at XX:XX:XX:XX:XX:XX [ether] on eth0
ad nauseum
Once you get all that you can wrangle it in to a hosts file for the rSnapshot machine. As I said, though, sometimes it won't be complete - and I have no idea why; it remains a more elegant solution if it can be made more reliable. I say this because it would all run from the server. The solution I'm currently working on is a local/remote combo that I just don't like.
So the solution I have right now is to enter each machine in to the rSnapshot config file and set a cron job to grab a snapshot (for this example let's say that the daily snapshot will happen at 4pm).
On each client machine, set a cron job that sets the hostname and current IP address and sends it to the rSnapshot server. Here's how I'm doing this:
1) Set up SSH-keys on the client so it can send stuff to the server on its own.
2) Run this doozy on the client end to add *this* client's info to the rSnapshot server's /etc/hosts file, removing old entries for *this* machine along the way:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rhost=$(h=$(echo -e $HOSTNAME);echo $h `ifconfig eth0|grep 'inet addr:'|cut -d ":" -f2|sed 's/ Bcast//gI'`) ; ssh rsnapshot.server.name "sed -i /\"$h\"/d /etc/hosts;echo $rhost >> /etc/hosts"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Right now I'm working on getting it running from cron but I'm having some trouble with it. When I just dump the above in to a bash script and run it from the command line (or from cron)
I get an error: "sed: -e expression #1, char 2: unterminated address regex" which I do not currently understand.
However, here's how it works:
1) echo -e $HOSTNAME returns the name you gave the machine
2) `ifconfig eth0|grep 'inet addr:'|cut -d ":" -f2|sed 's/ Bcast//gI'` gets you the IP address for the machine by asking ifconfig for all the info it has on eth0 (the NIC), chopping it up and discarding extraneous stuff (the *cut* bit returns the second field after the colon, while the *sed* bit deletes the stuff after the IP address - in this case that's " Bcast").
3) wrap this up in a pair of variables (h being the hostname and rhost being the hostname IP address combination). This is the first part of the oneliner: rhost=$(h=$()).
4) once we have values for host name and IP address (h and rhost) we head over to the remote machine via ssh and send the remote machine (our rSnapshot server) a couple of commands. We do this by adding a quoted command to the end of the ssh invocation. We do this with double quotes; double-quotes will expand variables, single-quotes won't and we have variables.
5) the commands on the rSnapshot side go like this:
sed -i /\"$h\"/d /etc/hosts (which removes any lines, using the d command, which include our host name - this gets rid of old entries)
echo $rhost >> /etc/hosts (which adds an entry for the client to the hosts file)
Things I need to do to make this really useable:
1) make it work from inside a script that cron can successfully run (see above for the problem)
2) adjust the remote sed command to only remove lines that begin with hostname. Right now, this will remove *any* line that includes the hostname at all. For example, consider a file like this:
tron 192.168.1.1
megatron 192.168.1.2
neutron 192.168.1.3
If I want to edit the line for the machine called tron and I use my sed command up above I'll end up with an empty file because each machine includes the string "tron". I don't name machines in a way that this would be a problem, but it's a pretty big problem if I inadvertently do something stupid when naming a new machine.