Tuesday, November 2, 2010

Exit vs Exit /B

Geek moment: This seems like an extremely trivial issue, or decision, or difference, but it has a real impact.  I’m talking about BAT / CMD script coding here.  The “EXIT” statement terminates a script.  But the /B argument (or “parameter”) has a minor, yet noticable different impact:

Using /B instructs the shell processor to terminate the script, but not the shell process in which it runs.  When you launch a BAT or CMD script file, it launches an instance of CMD.exe in which to run.  CMD.exe is the shell processor for those kinds of scripts.  If you have BAT file “A” execute a CALL to run BAT file “B”, and within “B” you use EXIT %errorlevel%, it not only terminates “B” but “A” and the CMD shell instance.  If you use EXIT /B %errorlevel%, only “B” terminates and hands focus back to “A” to continue on.

Let’s test, shall we?

A.BAT
@echo off
echo this is script A.bat running...
CALL B.bat
echo after B.bat errorlevel is %errorlevel%
pause
  
B.BAT
@echo off
echo this is script B.bat running...
EXIT /B %errorlevel%

Copy each chunk of code into their respective files and save them with the appropriate names.  Then open a command console (cmd.exe) and run A.BAT and watch the output and the behavior.  (do NOT simply double-click on “A.BAT” to test this!  It is important you open CMD first and then run the script)

Now, modify the last line in B.BAT so it is EXIT %errorlevel% (remove /B from the line).  Then save the file and run A.BAT again.  See the difference?

But wait, that’s not all.

Let’s say you need to build a script to be packaged and advertised through something like Altiris (or whatever Symantec decides to name it today), or Microsoft System Center Configuration Manager 2007 (say that ten times in a single breath!  go ahead… I dare you!), what impact might this small “feature” have?

I’m glad you asked.  Because it’s not always possible (or desirable) to have one script “do everything” in the course of getting from A to Z (sorry to confuse the letters on you).  Maybe you have scripts that do very well-defined jobs and you simply want to “string” them together to accomplish a group of tasks without actually merging the script code.  This is not uncommon, so stop shaking your head, I’m watching you.  Maybe you have script InstallApp.bat followed by ConfigureOps.bat and RunInventory.bat.  I’m just picking names, indulge me for a minute…

If InstallApp.bat calls upon ConfigureOps.bat, which calls upon RunInventory.bat, and somewhere in RunInventory.bat or even ConfigureOps.bat there is a(n) EXIT statement without a /B parameter, then guess what happens to that entire house of cards running in memory?  That’s right, it implodes and the “parent” script in the process chain (in this case: InstallApp.bat) never finishes.  That is dangerous!

This hasn’t happened to me in production, but I did trip over it during testing, which is another reason why I can’t say it enough: test test test!

These are the O-rings in the Morton-Thiokol solid rocket boosters.  The low-grade concrete Halliburton purchased for the Deepwater Horizon project.  The tree limbs that knocked out a major Northeast power grid.  The little things that get overlooked but which can cause enormous problems later on.  Do you think these people were thinking about o-rings when this picture was taken?

No comments: