Solve your command parsing problems by using scripts

February 9, 2013

Every so often sysadmins have a common form of problem: they need to configure program A to run program B with various arguments but program A's configuration system has some sort of baroque system for specifying commands and evaluating their arguments. What gets quoted or unquoted when, how things are handed to what, and so on are often unclear, unhelpful, or both. Everything works fine in simple cases but if you need to specify arguments for program B that have troublesome elements (like spaces) or do things like pipelines or redirections, well, you have a headache. Maybe several.

In this situation my standard advice is this: the easy way to solve all of these issues is to do all the work with a script. Instead of trying to configure program A to run a complex or troublesome command line, put the complex command line into a script and have program A run the script. Give the script whatever dynamic arguments it needs to have, but do so in a simple form; the script can glue arguments back together again or manipulate them as it needs to.

(The script should itself contain any and all constant arguments; there's no need to pass them from program A to the script. Configuration settings can go either way; it may be better to put them in program A's configuration file and pass them to the script than to embed them into the script.)

This has several benefits. First off, you are no longer wrestling with program A about how it handles command lines. Almost any program that supports running outside programs at all has solid support for simple forms such as '${run /some/script $arg1 $arg2}', and that's all you need. Any complex things you need you can do in the shell, which is probably both more powerful and more predictable than program A's configuration language (and if you run into problems, there are lots of resources for shell quoting issues).

Second, you are probably better off from a security perspective. Securely running programs in the face of potentially malicious input is somewhat of a minefield, but the simplest form of it is the easiest for programs to get correct and thus where they're most likely to have done so. Every bit of complexity you add to program A's handling of command parsing is another potential problem.

(If you care about this (and you probably should), you should test how program A behaves.)

(This is the flipside of the advice to program implementers that I put in my entry on securely running programs.)

By the way (and I am going to write more about this later), if you are ever tempted to solve your command parsing problems by doing something that looks like '${run /bin/sh -c ....}', STOP. Do not do that. Deliberately running the shell directly by hand straight from program A's configuration file makes your problems much, much worse. This is not a pattern or a solution, this is an anti-pattern. Use a script.

Written on 09 February 2013.
« Linux's great advantage as a Unix is its willingness to make wrenching changes
A little irritating (but understandable) limitation on Go interfaces »

Page tools: View Source, Add Comment.
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Sat Feb 9 01:08:39 2013
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.