To those trained and experienced in .NET, Visual Basic, C libraries and other non-shell interfaces, the command-line may seem like an old-school way to get things done. (If you’re already lost, here’s a good introduction to the basic concepts).
If your focus is on ease-of-development and server uptime, however, command-line applications are often a smarter and more cost-effective choice.
I can hear the disbelief already: “Huh? Are you saying that there’s been no real progress since the command-line interface was invented?!? Visual Studio is at version 9, what else do you want!”
Granted, in computer terms, the command-line has been around almost since man came down from the trees. Who wants to remember all those option switches? Even so, take a moment to understand why the command-line interface still makes sense – often a lot of sense – for many high-level processes in today’s mission-critical server implementations.
Processes vs. Threads
Command line tools generally operate in independent instances, each an individual process which in turn may initiate other, also distinct (and internally independent) subprocesses. Each process does one thing at a time, in isolation. Each process may be administratively killed if it runs amok.
Threading, as implemented in most DLL-based Windows server applications, was originally designed to get multiple things happening in the same application. Memory was very expensive, and threads seemed easier than launching a separate process. The downside was (and remains) that if anything goes wrong, it goes wrong for the whole application, not simply for the specific instance that encounters the problem input.
Today, it’s possible to exchange the (very) modest overhead associated with launching fresh processes for the reliability and ease of development that comes from leveraging the functional isolation of tasks into individual command-line processes.
Look deep into the Chrome
One way to understand the advantage that processes enjoy over threads for mission-critical server applications is to look at Google’s Chrome browser.
In designing what they regard as the perfect browser architecture, Google eschewed threading. Why? Read it for yourself; it’s a comic, you don’t have to be a developer to get it.
The short version is this: Google decided that reliability was key. Users with 20 tabs open cannot afford to have the browser go down because one tab locks up due to a freaked-out server or some runaway client-side JavaScript.
Chrome’s designers therefore specified that each browser tab should run as a completely independent process. In a threaded browser (like the one you are using now, if you aren’t using Chrome), there’s no way to isolate a problem tab from the rest of the application. Runaway tabs can cause a loss of data in other tabs, or require a complete restart of the application, and sometimes, the whole machine. That can’t happen in Chrome.
Meanwhile, back on the command-line
Servers should be at LEAST as stable as web-browsers, don’t you think?
If reliability is your watchword, then like Google’s Chrome, command-line server software delivers a key advantage: process isolation. If one instance of an application hangs due to a particular document, 10 other instances of the application can just keep on rollin’ while an administrator takes a look at the stuck instance. There’s no reason for any application, larger process, or machine, for that matter, to go down.
Ease of Administration
We’ve already noted that in threaded applications, a thread that starts eating memory or processor time almost always means that the application must be terminated. Entire server clusters are conceived, installed and maintained precisely to hedge against these all-too-common events where whole application instances or machines need their power cycled (to chose the kindest of available euphemisms).
Administrative control of each process fosters reliability and resiliency in the system; that’s what “easy administration” should be all about.
While the answer to reliability concerns is usually “get more machines”, with command-line software it doesn’t have to be. Simply terminate the offending process. Calmly examine and rectify the problem file or record while business as usual takes place all around you. You can get by with far fewer servers if you don’t have to constantly restart them!
The administrators have their reasons, but process isolation is actually a boon for developers as well, because isolated processes can be used to test changes in one’s own code. Independent of your own code, a command-line tool can be proven to work or not work, right there at the command-line. Support and problem-resolution is greatly simplified when there’s no fuzziness about which code is at fault.
Three Reasons why Command-Line Software Makes Sense for Servers
1. Functional isolation makes for easier administration and maximizes server uptime
Since command-line application instances are completely independent entities with clear functional definitions of input and expected output, they differ from typical Windows applications which need regular restarts (Windows servers also need regular restarts, minimally, after each “update Tuesday”). When launching processes from the command-line, you don’t need to stop the server to maintain or update the application. You don’t even need to stop the application!
2. Shorter development cycles, easier to code and debug
Since command-line applications provide a very specific set of operations; failures to execute are readily identified. Threading, shared DLLs, shared code and other houses-of-cards defy bright lines delineating functional or performance responsibilities. It’s harder to debug a function that requires dozens or hundreds of library calls as compared to one call, and that’s true even if you’re running “pure .NET, dude”. An example:
A developer is tasked with producing a server procedure to fill a PDF form.
Using a typical Windows library, the developer has to understand, contextualize and write dozens or hundreds of library calls to open the PDF, look for fields, choose a field, modify the field, find the next field, and so on. When something goes wrong, tracking down the problem can mean a lot of work. Is the problem in the library itself? In the developers code? It’s hard to tell.
With a command-line application, one call identifies the form and the data to be loaded and any options. It’s just that simple, so you get to focus on what the overall application is supposed to be accomplishing rather than learning all about how to (for example) populate fields.
Yes, if you’re not a UNIX, Linux or PHP developer, you’ll need to package up a string, shell to the command-line then handle the response. That’s a good thing. Command-line software allows you to focus on business logic, and leave the grunt work in the care of testable, predictable, reliable, stand-alone software that can fit neatly into any implementation – so long as you’re willing to shell.
3. Any development environment, more operating systems
To operate command-line applications, simply pass plain text, producible by any programming or scripting language. A command-line app doesn’t care if you’re generating your commands with PHP, C, Java, VB or .NET. Or, for that matter, Fortran, Pascal or even COBOL! Command line applications are entirely agnostic with respect to the overall development environment. Try that with Visual Studio!
As for the operating system, you generally have more choices than with any other option. Command-line software is frequently available not just for Windows but for Linux, Solaris, AIX and more. Do you want to bet that you’ll never want to deploy your implementation on a different set of hardware, or that the next guy who runs it won’t?
Conclusion
Command-line software is cost-effective because it’s easier to set up, easier to debug, more reliable to run and simpler to maintain and administer. The command-line just works, and lets you spend more time thinking about business objectives instead of debugging micro-level library calls.
Which one do you think your boss wants you to be doing?
By Duff Johnson