What is blib, you say?
Blib is a library of scripts that I developed to make my life as a sysadmin a little more pleasant. It is an collection of functions that have evolved of time into a set of libraries that I use as the basis of my server management scripts. It is my intention of sharing this work that other may find it inspirational and hopefully useful in their scripting endeavors. After years of script writing and not just in bash; in fact I’ve even dabbled with php cli scripts which to be truthful would be my first choice were it more prevalent in the command line environment. That however is a subject for yet another article.
Currently bash has enjoyed a resurgence of sorts after spending what seemed like a decade at version 2 we are up to version 4. This library has only been tested against version 3 but I assume it will work relatively well with 4 but not likely with the 2.x strain. Let me state however that not all is all right and rosy within the bash scripting world, for as soon as you need to do something sophisticated with your script you realize that bash is likely not the best language for the task.
Whether you use blib or not It is worth investigating as the library demonstrates some of the lesser leveraged capabilities of bash. Over the years I have examined numerous scripts and what always struck me as odd is that most scripters avoid defining functions. Instead I see a lot of code block duplication without much thought given to it’s longterm reusability. It almost seems that there is an unwritten rule among scripters that reads something like, “The moment you decide to define functions in bash is the same instant that you need to abandon it for another language.” I find this axiom a bit unsettling because for me the function is the basic block of advanced structured scripting.
So without further ado let’s take a look at blib to get and idea of what bash really can do. In this article we will examine one function from blib that I use in every script I write. In fact this function formed the based of my desire to create blib in the first place. Refer to the code segment below for the function throw.
# This encapsulates the exception handling into a fairly simple # and concise package. # It makes use of basic parameter passing and executes exception # processing based on predetermined action levels. # @method throw # @param string $1 # @global $EXCEPTION function throw(){ if [[ ${1+isset} = isset ]]; then EXCEPTION=${1} fi case ${EXCEPTION} in # Normal level [0]*) ;; # Critical error level exception [1]*) outputMsg exit ${EXCEPTION} ;; # Warning level exception [2]*) outputMsg ;; # Missing file specification [3]*) ouputMsg "Missing filename specification. " exit ${EXCEPTION} ;; # Required parameter is missing [4]*) outputMsg exit ${EXCEPTION} ;; # [5]*) ;; # [6]*) ;; # [7]*) ;; # [8]*) ;; # Oops level exception *) MSG="You know I've looked every where and what you have done has left me completely flummoxed. I honestly do not know what it is that you've done to receive this message, thus you win a prize. You can pick up your prize behind the Port Authority bus terminal at 0200 on the second Tuesday in January. In all likelyhood you have called throw without a parameter or neglected to properly set your EXCEPTION level." outputMsg exit ${EXCEPTION} ;; esac }
function pseudo() { if [[ ! ${1+isset} = isset ]]; then Course=${1} change ${Course} else MSG="${FUNCNAME}: Unable to change course at this time, I hope we don't run aground!" throw 4 fi echo ${Course} }
Thus in the example above we have a critical piece of information that must be passed when the pseudo function is called. Failing to present this information must cause cause the program to do something drastic. Consider that I could write an if then type clause that handles this case and another the next time I need to handle a lesser error, but why should I? I mean isn’t the concept of programming supposed to make out lives easier? So as a programmer why not make my life easier and reduce multiple lines fo code down to a statement or two?
Therefore what I have done is simply wrap my error handling conditional algorithm into a function that I can pass the error level to. By setting the variable MSG immediately prior to calling throw allows me to set the error message on the fly as related to the function calling throw. If however I only needed a predefined message I could call throw with one of the other exception levels. Which you probably have already noticed I have not defined. It’s one of those things that haven’t gotten around to doing yet but it is still on my to do list.
So rather than detailing what outputMsg does let’s just discuss it for a second. When you look through the base.blib that contains the core functionality of blib you will note there are some other functions that set values for things like silent and quiet operation. Using these options to adjust what outputMsg actually displays and where. As I said earlier it is simply a wrapper for echo, but with some logic that determines when it is allowed to print.
The last thing I would like to discuss about blib today is the std.blib which is the root of the blib system. By simply sourcing in this library prior to any other you open up some of the power of blib. To do this you simply add something similar to the following near the top of your bash script depending upon where you installed blib. I am assuming that you installed it in the default location and if you did not then that may cause some unusual developments. Likely nothing will work as I have not evolved it to that point yet.
. /usr/local/lib/blib/std.blib
My goal for blib moving forward is to heavily rely on the two core functions include and require. Of course you are probably wondering why would I have gone to the trouble of writing wrapper functions for a built-in method. Why not just source in other code as we did with the std.blib example above? The reason is advanced logic necessary to check for the existence of the file to be sourced. I modeled the include and require method very loosely after the functions of the same name found in PHP.
The difference is that I use include for things that are nice to have but that will not break program execution. Namely I use this for config file sourcing where I have default values already set within the application I am writing and the config file would just override these values. That is why it only throws an exception level of 2 which would echo a warning of some sort but continue normal execution.
On the other hand I use require for things that must be present of the execution will stop. I built into the function logic to determine if the item being required is present before sourcing it in and if not then it throws an exception level 3 halting program execution.
I realize that this article has become rather lengthy but I believe that I have covered the important notes on working blib into your bash scripting repertoire. In the next article I plan on covering the basics of building an application on top of this for lack of a better term framework. Until then I hope that you consider downloading and experimenting with blib.
As with just about everything in programming there really is not right or wrong way to do something. Some may be more efficient than others but only you the developer can decide what works best for your purpose. My goal for blib is to create a set of libraries focused for certain tasks that make scripting easier for all. You will see that there are many tangent in the library some are dead ends others are new beginnings like the string.blib, therefore; if you develop a function and wish to include it please feel free to ping me. Hopefully with some community involvement this can grow this into something interesting.
This version of blib has been release under the New/Simplified BSD License (http://opensource.org/licenses/bsd-license.php) with the additional requirement that you notify the originator of your usage. The latter is just so I can track how it’s being used. Good luck and happy scripting.
Download a copy of blib from: https://www.jafdip.net/downloads/blib-1_0.tbz
Related articles
- Advanced Mac OS X Shell Scripting (jafdip.com)
- Name Based Vhosting in Mac OS X Snow Leopard Server (jafdip.com)
- Performing MacPorts Magick (jafdip.com)
- Trolling For A Quality Operating System (jafdip.com)