Friday, August 15, 2008

Book Review: The Bash Cookbook

The Elevator Pitch

The Bash Cookbook is a must own book for anyone that uses Unix and Linux for fun or profit. Bash is a powerful shell environment available in everything from Mac OS X to commercial Unix offerings like Solaris. Being comfortable and productive with this shell is going to make your life a helluva lot easier. The Bash Cookbook serves as a digestible tutor to this powerful shell while maintaining a depth that makes it a valuable reference for solutions to many of the common problems that command line power users face.

The Full Review

I've been a Unix user since my first days studying Computer Science at college in the early nineties. While coming from using MS-DOS in high school and being plunked in front of a terminal with a dollar ($) prompt probably wasn't as disorienting as a move from Windows might have been, it was still pretty confusing. I struggled through the first few years until I took a systems programming class and finally started to understand the big picture of Unix. Still, it wasn't until almost a decade later that I decided to really try to wrap my mind around the Unix command line, and more specifically the bash shell.

As a Unix administrator, I have now been using the shell environment professionally for over five years. Bash is my shell of choice and I use it to do everything from processing various system logs, to running assorted backups, to creating system monitors, to wrapping more complex commands into usable interfaces, to transforming data into more usable formats. To get to that point, I spent a lot of time reading books like Learning the Bash Shell, hanging out on the shell scripting forums at Unix.com and reading various sysadmin blogs. All that is to say that I think I have a good grasp of the Unix/Linux command line in general and the bash shell in particular.

Recently, I had the opportunity to read the Bash Cookbook. Of all the technical books that I read for personal and professional gain, I prefer the formats of both O'Reilly's Hacks series and its Cookbooks for how they cover common problems and solutions in various technical subjects. I find them easy to digest, as both formats generally break large technical topics into bite sized chunks that present problems and solutions in very thorough, but approachable, ways. I find myself flying though these books. After reading a couple of pages that cover a single hack or recipe, I generally feel like I have learned something versus having to slog through twenty or so chapter pages in a typical tech book.

Thankfully, The Bash Cookbook stands up with its predecessors. The authors, Carl Albing, JP Vossen and Cameron Newham (also an author of the aforementioned Learning the Bash Shell) have backgrounds ranging from general technologists and authors to software developers for the Cray supercomputer company. This multifaceted experience set serves them well as they tackle various bash scripting topics from the mundane to the puzzling to the downright arcane. All of this is done with an approachable style and format that first identifies a problem, then offers a generalized solution, and finally follows up with a detailed discussion of the problem and solutions. This approach helps identify both the reasoning behind their solutions and the corner cases that will either further inform your own implementations or warn you that here be dragons.

The Bash Cookbook is divided into nineteen chapters and five appendixes, a few of which (most notably "Appendix D: Revision Control") could have served as full-on chapters by themselves. Topics include getting started with bash on various platforms (chapter 1); dealing with the intricacies of standard input and output redirection (chapters 2 and 3); job control (chapter 4); shell variables and arithmetic (chapters 5 and 6); finding and manipulating data (chapters 7, 8, and 9); working with functions and trapping conditions (chapter 10); manipulating dates and time (chapter 11); wrapping complex tasks (chapter 12); parsing files (chapter 13); writing scripts securely (chapter 14) ; bash corner cashes (chapter 15); customizing the bash environment (chapter 16); common system administration tasks (chapter 17); bash tips to be more productive (chapter 18); and, finally, common traps and workarounds for novice bash scripters (chapter 19). As you can see, there is a wealth of information to be had between the covers of this book.

I found useful information from the beginning chapters (which are often throw away generalized instructions for getting up to speed in most tech books) all the way to the appendices themselves. Some standout recipes from the book include:
  • 3.7 Selecting from a List of Options
  • 5.2 Embedding Documentation in Shell Scripts
  • 5.17 Giving an Error Message for Unset Parameters
  • 5.19 Using Array Variables
  • 7.15 Showing Data As a Quick and Easy Histogram
  • 8.3 Sorting IP Addresses
  • 9.9 Finding Files by Content
  • 10.6 Trapping Interrupts
  • 13.4 Parsing Output into an Array
  • 13.12 Isolating Specific Fields in Data
  • 15.10 Finding My IP Address
  • 15.13 Working Around "argument list too long" Errors
  • 15.15 Sending Email from Your Script
  • 16.4 Change your $PATH Temporarily
  • 17.1 Renaming Many Files
  • 17.8 Capturing File Metadata for Recovery
  • 17.13 Prepending Data to a File
  • 17.16 Finding Lines in One File But Not in the Other
  • 17.17 Keeping the Most Recent N Objects
  • 19.11 Seeing Odd Behavior from printf
Chapter 14 of The Bash Cookbook demands special mention in this review. Titled "Writing Secure Shell Scripts", it opens with a general discussion of the need for writing secure shell scripts and gives a basic template utilizing many of the features that can make the average shell script more secure. The subsequent twenty three recipes flesh out this template with surprising, but approachable, detail. Of all the subjects in this book, this chapter's topic makes it worth buying and retaining as a goto reference. After skimming the recipes of chapter fourteen, I found a number of ways to make my scripts better. For instance, much of the "common wisdom" for creating temporary files that I have found around the Internet and in various books is simply wrong and, as chapter fourteen lays out, highly susceptible to race conditions. Some day, out of curiosity, I'd like to survey some open source projects that make use of shell scripts for installation, configuration, and maintenance and see how their handling of temporary files matches up. From the cursory searches that I have made, I am afraid what the results might show.

The writing in the Cookbook is clear and to the point and incredibly consistent given that it was written by three writers. This is either a testament to the writing team and their ability to assimilate each other's styles or to O'Reilly's editorial staff's ability to tie the whole thing together (or, I assume, both). I particularly enjoyed the in depth discussion that many recipes received. It had the feel of looking over the shoulder of a veteran Unix admin and having the chance to pick his brain about why he was making the choices he was and why he was going about his business in a particular way. That is the book's greatest strength. As someone who has had to pick up Unix and Linux skills largely on his own, I found this approach invaluable. If you aren't surrounded by a Unix culture, it can be hard to pick up some of the more useful, but more complex, tricks of the trade. Think of The Bash Cookbook as your grey beard Unix hacker mentor on a shelf.

The book and its Table of Contents and Index are so comprehensive with regards to the common types of tasks that one generally performs while writing shell scripts, that it has become, in the short time that I have had it, my first (and usually last) goto reference. If I forget how to search for keywords in files across directories for instance, it just took a quick scan of the Index to find a very good and working answer. I use this book so much, that I am considering buying a second copy to keep at home so I don't have to haul my dog-eared version back and forth to and from work. It is that useful.

Really.

Some Nits to Pick

As with any large project such as a book, there are bound to be a few things that slip through the cracks. The Bash Cookbook is no different. For instance, recipe 6.6 talks about the different ways to check for equality in bash including the use of the single equals (=) or double equals (==) signs. Functionally these two constructs are exactly the same, but using the single equals is more portable as it follows the POSIX standard. That's fine, and very good to know. However, the use of these constructs isn't consistent in the book, which could lead to confusion as the explanation that it really doesn't matter doesn't happen until page sixty four. Even worse, much earlier in the book recipe 3.7 is an example of the use of these two constructs not even being consistent in a single script where the variable $directory is checked for equality with the string "Finished" on one line with the double equals construct (==) and another with the single equals construct (=). From a script maintainability respect, being this inconsistency is a bad idea.

One problem is the seeming omission of the treatment of arrays in bash. Most people unfamiliar with bash don't even realize that there are simple single dimensional arrays available in the environment, so I was happy to see some recipes that covered this topic. However, some of the more powerful array manipulations techniques, such as the ability to find the number of elements in an array with the simple ${array_name[@]} construct or the length of an individual array item with the ${#array_name[index number]} construct which is covered in the discussion of recipe 13.4, "Parsing Output into an Array", are buried in other recipes and hard to find even with the index. This misunderstanding could probably be helped if the See Also sections of each recipe pointed to other recipes in the book that dealt with similar subjects. Recipe 5.19, "Using Array Variables," only points to a section the the O'Reilly book Learning the Bash Shell. Other recipes in the book do a fine job of pointing out external sources of information as well as other recipes, so I think this is just a matter of some editorial consistency that would need to be beefed up for the next edition.

The authors make a conscious effort to stick with core bash tools throughout the text. As the note in the "Preface" of the book, Perl is covered elsewhere. Though they do say they are okay using the right tool for the job and sometimes they tell you when it is best to use something else... much better than having the reader beat their heads against a wall in my opinion. This is a book about bash after all and it would be maddening if many solutions switched to other non-bash solutions whenever something wasn't readily able to be solved with the bash tool set. Unfortunately there are times when they overlook common bash tools in favor of other scripting languages like sed and awk. The prime example of recipe 7.10, "Keeping Some Output, Discarding the Rest" where they use awk to solve the problem. Sure, awk works, but I would have preferred if they would have at least mentioned the cut utility in this context if only for comparison sake. They should have at least linked to recipe 8.4, "Cutting Out Parts of Your Output", and recipe 13.12, "Isolating Specific Fields in Data." Again, I this is just a matter of editorial consistency and just one of only a few examples where the fact that the book was written by multiple authors becomes mildly apparent.

Some other minor editorial issues revolve around typos and other minor errata. On page 84, "Thought" in the third Discussion paragraph should be "Though." On page 64, the comment (after the #) at the end of the script states "end of while not finished" which can be confusing as the loop construct is actually an until statement. Page 207 should be "what" instead of "hat" in the first full sentence of the page and similarly "fpllowing" on page 233 should be "following." For a book this long (622 pages), that's not bad at all. There may be others, but they weren't obvious during my reading. For a technical book, in its first edition, I was happy with the overall quality of the material.

My final suggestion is for the inclusion of sample input and outputs for the scripts. Many scripts give these types of examples, which makes it endlessly easier to understand exactly what the scripts are doing, but this isn't consistent throughout the book and I am not sure what the editorial decision was in not including these types of examples for those scripts that don't have them. My personal opinion is that there should be input and output examples for every recipe in the Bash Cookbook. I liken it to one of my favorite cooking guides, Cooks Illustrated, whose pictures often clear any confusion about preparations for recipes that the text of the recipe may have missed. I think the same holds for sample input and outputs for the tech recipes of the Bash Cookbook. Every recipe, in my opinion should have these examples even if they are only available from O'Reilly's website.

Conclusion

Nitpicks and suggestions aside, this is a great bash scripting resource and should find a good home on any scripter's bookshelf. It provides enough instruction to help a new-ish user understand the deeper power of bash scripting while having enough breadth and depth to serve as an invaluable resource for the experienced scripting guru.

Book Information


Title:
Bash Cookbook
Authors: Carl Albing, JP Vossen & Cameron Newham
Paperback: 622 pages
Publisher: O'Reilly Media, Inc., 1 edition (May 24, 2007)
ISBN: 0596526784

2 comments:

JP said...

Wow, thanks for the great review and feedback. I will enter your errata into the O'Reilly errata page (http://oreilly.com/catalog/9780596526788/errata/) for the book (real soon now :) and take notes on your other suggestions for the second edition, if/when.

As far as examples go, I know this isn't quite what you were talking about, but all the bigger examples are available for free download from the O'Reilly site, whether you bought the book or not (http://examples.oreilly.com/bashckbk/).

We're very happy that you found the book so useful.

-- JP Vossen (co-author)

Jim said...

Thanks for the great book, JP.

I forgot to mention the examples were available at http://examples.oreilly.com/bashckbk/. So, thanks for the reminder.