mirror of
Fork 0

Add more options for shell commands

This commit introduces an extended configuration syntax for shell
commands. This syntax allows for specifying whether the stdin, stdout,
and stderr streams are enabled.
This commit is contained in:
Anish Athalye 2015-02-03 11:53:05 -05:00
parent 0b4b79e422
commit 38c0f65801
2 changed files with 50 additions and 8 deletions

View File

@ -159,15 +159,28 @@ base directory (that is specified when running the installer).
#### Format
Shell commands are specified as an array of commands, where each command is a
two element array containing the actual shell command as the first element and
a human-readable description as the second element.
Shell commands can be specified in several different ways. The simplest way is
just to specify a command as a string containing the command to be run. Another
way is to specify a two element array where the first element is the shell
command and the second is an optional human-readable description. Shell
commands support an extended syntax as well, which provides more fine-grained
control. A command can be specified as a dictionary that contains the command
to be run, a description, and whether stdin, stdout, and stderr are enabled. In
this syntax, all keys are optional except for the command itself.
##### Example (YAML)
- shell:
- mkdir -p ~/src
- [mkdir -p ~/downloads, Creating downloads directory]
command: read var && echo Your variable is $var
stdin: true
stdout: true
command: read fail
stderr: true
##### Example (JSON)
@ -175,7 +188,17 @@ a human-readable description as the second element.
"shell": [
["mkdir -p ~/downloads", "Creating downloads directory"]
"mkdir -p ~/src",
["mkdir -p ~/downloads", "Creating downloads directory"],
"command": "read var && echo Your variable is $var",
"stdin": true,
"stdout": true
"command": "read fail",
"stderr": true

View File

@ -20,10 +20,29 @@ class CommandRunner(Executor):
def _process_commands(self, data):
success = True
with open(os.devnull, 'w') as devnull:
for cmd, msg in data:
self._log.lowinfo('%s [%s]' % (msg, cmd))
ret = subprocess.call(cmd, shell = True, stdout = devnull,
stderr = devnull, cwd = self._base_directory)
for item in data:
stdin = stdout = stderr = devnull
if isinstance(item, dict):
cmd = item['command']
msg = item.get('description', None)
if item.get('stdin', False) is True:
stdin = None
if item.get('stdout', False) is True:
stdout = None
if item.get('stderr', False) is True:
stderr = None
elif isinstance(item, list):
cmd = item[0]
msg = item[1] if len(item) > 1 else None
cmd = item
msg = None
if msg is None:
self._log.lowinfo('%s [%s]' % (msg, cmd))
ret = subprocess.call(cmd, shell = True, stdin = stdin, stdout = stdout,
stderr = stderr, cwd = self._base_directory)
if ret != 0:
success = False
self._log.warning('Command [%s] failed' % cmd)