Variable Variables: Double Interpolation in Bash
by someguy on Sep.12, 2006, under Uncategorized
Ok, so most of you are wondering why I’d be even bothering to do double interpolation in Bash rather than a real language. Well, I already had some scripts in progress and I didn’t want to start from scratch. What is double interpolation and why would I bother?
In my case, I knew that I was going to have a dynamic list (an array), and that for every array member, there would be a number of other things I would need to know about it (yes, like a multi-dimensional array).
Perhaps we want to do some simple monitoring of an unknown amount of servers in each data center and for each server we need to know how to reach it -- the IP address, and the way we want to reach it to test (i.e.http/ping/etc.). So ideally, we need to be able to keep a separate config file which just holds X number of shell variables with server configurations in it -- but that the contents of that config file might be wildly different (number of servers, server specs, etc.) between environments and keep the script simple.
So, in one environment we want to monitor the servers, moe, larry, and curly (woop, woop, woop) :
We write a config file that has one array for the server names, then for each of those we define variables to hold the IP and check-type.
The config file, servers.cfg, looks like:
SERVERS="moe larry curly"
moe_IP=10.10.10.10
moe_CHECKTYPE=http
larry_IP=10.10.10.11
larry_CHECKTYPE=ping
curly_IP=10.10.10.12
curly_CHECKTYPE=ping
Then we write a script which just loops through the given servers and does the check based on whatever check-type and IP we’ve configured.
#!/bin/bash
# Source our config file
. servers.cfg
# Loop through the servers and test them!
for server in $SERVERS;
do
IP=$(eval echo $`echo ${server}`_IP);
CHECKTYPE=$(eval echo $`echo ${server}`_CHECKTYPE);
if [ "$CHECKTYPE" = "http" ];
then
# Do dome kind of http check - this is oversimplified for this example
wget $IP
elseif [ "$CHECKTYPE" = "http" ]
then
# Ping it! Normally we would test the success/failure of the ping here
ping $IP
fi
done
The beauty of what we have here is that we don’t need to reconfigure the script to add or remove servers, just maintain a simple config file.