The other day I was faced with continuing to work on an extraordinarily repetitive task which has bored me to tears on several occasions, resulting in its not having been done yet (despite my manager’s patient status requests every week): installing a standardized snmpd.conf file for all of our snmp-monitored clients on the network. Friends, the snmpd.conf file is very, very boring. And yet, with the extent of our configuration, also very error-prone, especially when you’re staring glassy-eyed at line after line that differs from its predecessor by, say, one byte. Even if you’re copying and pasting, or reading in source files, or what have you, it’s easy to make a mistake and then wind up having to spork your eyes out because your monitoring system explodes in your face with alarms of things being down and you cannot figure out why because it is right there why aren’t you working you stupid piece of junk!
Not that this has ever happened to me, of course. This is purely hypothetical.
As alluded to previously, in order to solve the snmpd.conf problem (and also to make it far less sucky in the future), I began to convert the snmpd.conf into GNU m4. m4 is an easy to use macro language. (Quit laughing.) Basically, the idea is that you can take some string and turn it into an abbreviation for another string. Glue enough of these together and you have yourself a compact little config file generation system.
m4 is very clever — it’s incredibly simple to look at, but (as with so many other things in life), you can build things just as complex as you like. One nice thing about it is that it is iterative and will recurse over a string until there is nothing else to expand. So, if you have something like, say:
NAME=”Marshall Field & Company”
You could later write define STREET_ADDRESS to be, say, “STREETNO STREETDIR STREET STREETTYPE,” and then just call STREET_ADDRESS, which m4 will expand into STREETNO, STREETDIR, STREET, and STREETTYPE, which it then further expands into “111,” “North,” “State,” and “Street.” You can build these towers of recursive macros as tall as you like, if you want to maximize your chances of having your coworkers beat you up with Nerf guns.
In order to make your config m4-ized, the application here is to figure out how to:
- store portions of the config in small chunks;
- tokenize the snmpd variables so they can be modified on the fly based on user-specified m4 variables;
- store the local expansions of static snmpd variables — for example, the things we might choose to put in the “syslocation” field — in library files; and
- turn what we end-users will edit as the “snmp config file” into a compact and yet clear macro (.mc) file.
The most obvious example of using m4 to make a complex configuration easily user-modified without worrying about the guts of it is, naturally, Sendmail. The sendmail.cf is an extremely complicated (and kind of ugly) configuration file, and, in fact, some of the best advice I ever got was from Eric Allman, who advised that users should consider the sendmail.cf to be an application, and never ever touch it; we should only ever edit the cf macros. Seriously, if you can just forget about the sendmail.cf file, it really makes things a lot more clear. (And this is coming from someone who has written her own complex rulesets (and then as a direct consequence wanted to blow up her bat book with M80s, but that’s another story).) And the way that sticking to the Sendmail cf macros makes the process of configuring sendmail clear and simple is by throwing all of the ugly, messy $+ . $@ . $-
Continued in Part II.