Configuration Files - a pattern for windows batch scripts
It's a very common practice in perl and linux/unix shell scripting to use an external configuration file (.conf or .properties), keeping all the script's necessary settings organised tidily in one place. This makes it easier to configure in the first place (because you don't have to hunt through the whole script to find what needs tweaking, or which environment variables need to be set), and also makes maintenance of the script so much easier (because you don't need to reconfigure after installing an updated script).
For some reason though, this practice never seemed to get widely adopted in the Windows batch file world. Either Windows script-kiddies just never learned to think like a sysadmin, or we never expected the DOS shell to be capable enough! Or maybe we never bothered, because surely windows batch files should be extinct by now?
I guess the dominant approaches to configuring batch files on Windows are:
- Command line arguments [painful if you have too many, annoying if they are invariant for your setup, and may entice you to write a wrapper script just to save all the typing]
- Environment variables [can lead to pollution of your environment, but also not usually backed up along with your scripts]
- Good ol' "just edit the batch file and fill in the settings" approach
Well, it is possible to take advantage of the elegance of external configuration files. For some time I've been using a technique that I adapted from what I'd normally do with perl and bash scripts. I'm sure this was invented decades ago, but it surprises me that I haven't yet found a good example or tutorial on the net.
So I thought maybe time to polish up the "pattern" and share it here.
The Pattern
It's pretty simple! The flowchart on the right provides an overview.To make this work with simple windows batch files, we use a configuration file that it itself a batch file (.bat or .cmd) and it is called from the main script. The configuration file would usually set a range of environment variables
A nice usability touch is that when the script is first executed (i.e. no configuration file present), it will generate a default configuration file, give the user some helpful instructions on how to edit the configuration file, and exit.
This makes your script "safe" for users who are liable to run it just to find out what it does(!).
But it also means that you can maintain the default configuration file structure - with as much built-in documentation as you like - inside the script itself (therefore only one file to maintain).
The Script Template
Here's a script template that includes the configuration file handling (also available for download here). As you can see, not rocket science!If you have multiple scripts that all need to share a common configuration, you can extract the config file handling as a separate script and include (call) that from all the others. See the scriptTemplate.cmd and config.cmd in this kit of examples.
@echo off
REM $Id$
setlocal
echo Welcome to %0
REM Initialise the config flag [CONFIGSET] and config file [LOCALCONF]
REM You must name the config file .bat or .cmd to ensure Windows can execute it cleanly
set CONFIGSET=NO
set LOCALCONF=%~dp0conf\%~n0-%COMPUTERNAME%.cmd
REM ===============================================================
REM Configuration section
REM ---------------------------------------------------------------
if "%LOCALCONF%"=="" goto config_help
goto config_do
:config_help
echo This is a configuration help script
echo Call from another script with first parameter being the config file name
echo This script will set the variable CONFIGSET
echo CONFIGSET=NO in the case of error or undefined configuration
echo CONFIGSET=YES in the case where configuration has been successfully read
goto config_exit
:config_do
REM handle configuration file
IF EXIST %LOCALCONF% goto config_cont
REM generate default setting file
REM adapt this to you needs. Here are some samples
echo REM configuration file> %LOCALCONF%
echo set JAVA_HOME=C:\bin\jdk1.6.0_03>> %LOCALCONF%
echo set TMPFILE=c:\temp\mytemp.txt>> %LOCALCONF%
echo set SUBJECT=A subject line>> %LOCALCONF%
echo set DBUID=dbusername>> %LOCALCONF%
echo set DBPWD=dbpassword>> %LOCALCONF%
echo #
echo # Local configuration not yet set.
echo # A default configuration file (%LOCALCONF%) has been created.
echo # Review and edit this file, then run this process again.
echo #
goto config_exit
:config_cont
call %LOCALCONF%
set CONFIGSET=YES
:config_exit
if "%CONFIGSET%"=="YES" goto config_ok
echo Configuration is not set
goto exit
:config_ok
REM ---------------------------------------------------------------
REM Configuration section ends
REM ===============================================================
echo The main script starts from here.
echo The following configuration is set:
echo JAVA_HOME=%JAVA_HOME%
echo TMPFILE=%TMPFILE%
echo SUBJECT=%SUBJECT%
echo DBUID=%DBUID%
echo DBPWD=%DBPWD%
:exit
endlocal
Sample Output
Here's an example of running the script above. The first time through, no configuration file is detected, so it creates one and exits.At that point, the user could edit the configuration file if necessary.
Subsequent runs pick up the settings in the configuration file.
D:\MyDocs>scriptWithConfigTemplate.cmd
#
# Local configuration not yet set.
# A default configuration file (scriptWithConfigTemplate-conf.bat) has been created.
# Review and edit this file, then run this process again.
#
Configuration is not set
D:\MyDocs>scriptWithConfigTemplate.cmd
The main script starts from here.
The following configuration is set:
JAVA_HOME=C:\bin\jdk1.6.0_03
TMPFILE=c:\temp\mytemp.txt
SUBJECT=A subject line
DBUID=dbusername
DBPWD=dbpassword
D:\MyDocs>
read more and comment..
Complex ACL filters with OVD
Access Control Rules are a very important aspect to get right when setting up Oracle Virtual Directory. But at the same time, I guess they are probably the most complex configuration option, especially if you haven't had some hard core LDAP experience before.
In Using OVD Filtered Directories for LDAP Authentication, I talked about using ACLs to restrict access to certain parts of a directory: each Access Control Rule has a filter setting, which is an LDAP filter that specifies which directory entries the rule applies to.
However I also discovered that using complex (multiple term) Access Control Rule filters is a great way to kill the OVD server process.
NB:it bombs with a java.lang.NullPointerException, and it is necessary to go and manually remove the offending filter from the $OVD_HOME/conf/acls.os_xml file on the server before it will startup again.
Say, for example, you wanted to grant access to entries for the ITGroup and HR departments. In RFC 4515 LDAP search filter terms, we can write this simply as:
(|(departmentNumber=ITGroup)(departmentNumber=HR))
But as mentioned, this will kill your OVD server (OVD 10.1.4.0.1 build 06.07.19).
There is a simple work-around though, by reverting to simple set theory and write multiple rules. In other words, granting (|(departmentNumber=ITGroup)(departmentNumber=HR)) is equivalent to two rules applied in sequence:
- Grant: (departmentNumber=ITGroup)
- Grant: (departmentNumber=HR)
read more and comment..
Freakonomics
Long on my "must read" list, I finally picked up Freakonomics (by Steven D. Levitt and Stephen J. Dubner) this weekend, and discovered a fascinating book about interesting questions.
Questions that are not often asked, but once posed are seen at once to cut to the fundamentals of our society, but also usually discarded as unanswerable. That seems to be the trick that Steven Levitt has perfected (the economist in the writing team): fixing on an "imponderable" question, and then ingeniously hunting down the situations and data that let him lock an answer within his sights. What seems to set him apart from other economists is his willingness and ability to collaborate across disciplinary lines when it is the best way to an answer. What the authors talk about as an a-disciplinary approach. Levitt apparently has more in common with Sherlock Holmes that Milton Friedman. There is an interesting congruence with Malcolm Gladwell's The Tipping Point (which I've also recommended before). While they intersect on some common examples (such as the broken windows theory), each book takes away something different. Gladwell is of course intrigued by the inflexion - how closely can you isolate and identify the point at which things tip? What is the mechanism that causes the worm to turn? Freakonomics on the other hand is seeking to explain why things are the way the are (whether steady-state, trend or tipping point). The search for causality not just correlation. No less than the search for truth! Of course the more interesting investigations are the ones that show truth to be at odds with conventional wisdom! NB: if you like this kind of questioning, checkout PsyBlog. I came across this recently and it has some great articles. The authors are strident in professing that there is no central theme to this book, but I think that is disingenuous. I'd suggest that the book as a whole is an object lesson in the dangers of being lead by theories based on observation, which can lead to very different conclusions than those based on careful data analysis. It is a convincing polemic warning us against naive acceptance of conventional wisdom, theorists and experts of all kinds. An expert must be bold if he hopes to alchemize his homespun theory into conventional wisdom. As Gil Grissom would say: Let the evidence speak for itself.. |
read more and comment..