Linux Bash and Variable Variables (aka Indirect References)
My latest Bash adventure was to create an operational set of Bash scripts to help mange my growing QEMU-KVM virtual machine inventory. But why is this so special?
BACKGROUND: My virtualization journey started with VMWare Server 1.0x running on Slackware. When it came time to migrate to VMWare 2.x I chose to switch to a completely different virtualiztion solution, QEMU-KVM. Since QEMU-KVM was based on using Linux itself as the hypervisor I chose to learn QEMU-KVM from the command line and not use a virt-manager style application. As my library of commands grew I saved them to a text file so I could cut and paste to the CLI to manage my virtual environment. Once my commands became standardized it was time for me to revisit using a virt-manager application or develop my own control scripts. I'm on the control script path which is how my latest Bash adventure started.
DISCLAIMER: I'm a not an expert Bash programmer but given enough time, motivation and access to good documentation I can create some pretty decent scripts.
As the development of the scripts progressed I ran into new learning opportunities. I wanted to create generic scripts and manage variables from a config file. Initially I used the source command to include a Bash script of variable assignments. What I really wanted was script to read a config file that was just text and not a Bash script. A challenge showed up early that I needed to have both variable values and names. Variable variables made reading a text config file easy.
Bash defines a variable assignment as lvalue=rvalue which means the "left value" is the name and the "right value" is the value. Using variable variables on the "rvalue" or right side is well documented using a 2-step technique.
TEMP=NAME${VARIABLE}
TARGET=${!TEMP}
echo TARGET:$TARGET
This enables the value contained in NAME${VARIABLE} to be referenced or assigned to the variable TARGET.
Working with variable variables on the "lvalue" or left side is not as well documented or at least not as easy to find. That's because the feature is buried in the description of Chapter 28. Indirect References. As you can see it's also a 2-step process and uses the Bash built-in commands eval and echo.
TEMP=NAME${VARIABLE}
eval $(echo TEMP=$VALUE)
echo $TEMP:${!TEMP}
This makes the name a variable variable! Thanks to this technique I was able to read my config file and set the variables for the control scripts to use. My "A Ha!" moment!
Finally, here's a screen shot of the top level menu script that relies heavily on the Dialog utility which is included with Slackware. My script system uses a multi-level menu, multiple control scripts and a config file. As the system is refined over time I'll write about it in more detail.
Thanks to the Advanced Bash-Scripting Guide for documenting this and other useful Bash scripting techniques and information.