The cmd state module manages the enforcement of executed commands, this state can tell a command to run under certain circumstances.
A simple example to execute a command:
# Store the current date in a file 'date > /tmp/salt-run': cmd.run
Only run if another execution failed, in this case truncate syslog if there is no disk space:
'> /var/log/messages/: cmd.run: - unless: echo 'foo' > /tmp/.test && rm -f /tmp/.test
Only run if the file specified by creates
does not exist, in this case touch /tmp/foo if it does not exist:
touch /tmp/foo: cmd.run: - creates: /tmp/foo
creates
also accepts a list of files:
"echo 'foo' | tee /tmp/bar > /tmp/baz": cmd.run: - creates: - /tmp/bar - /tmp/baz
Note
The creates
option was added to version 2014.7.0
Sometimes when running a command that starts up a daemon, the init script doesn't return properly which causes Salt to wait indefinitely for a response. In situations like this try the following:
run_installer: cmd.run: - name: /tmp/installer.bin > /dev/null 2>&1
Salt determines whether the cmd
state is successfully enforced based on the exit code returned by the command. If the command returns a zero exit code, then salt determines that the state was successfully enforced. If the script returns a non-zero exit code, then salt determines that it failed to successfully enforce the state. If a command returns a non-zero exit code but you wish to treat this as a success, then you must place the command in a script and explicitly set the exit code of the script to zero.
Please note that the success or failure of the state is not affected by whether a state change occurred nor the stateful argument.
When executing a command or script, the state (i.e., changed or not) of the command is unknown to Salt's state system. Therefore, by default, the cmd
state assumes that any command execution results in a changed state.
This means that if a cmd
state is watched by another state then the state that's watching will always be executed due to the changed state in the cmd
state.
Many state functions in this module now also accept a stateful
argument. If stateful
is specified to be true then it is assumed that the command or script will determine its own state and communicate it back by following a simple protocol described below:
If there's nothing in the stdout of the command, then assume no changes. Otherwise, the stdout must be either in JSON or its last non-empty line must be a string of key=value pairs delimited by spaces (no spaces on either side of =
).
If it's JSON then it must be a JSON object (e.g., {}). If it's key=value pairs then quoting may be used to include spaces. (Python's shlex module is used to parse the key=value string)
Two special keys or attributes are recognized in the output:
changed: bool (i.e., 'yes', 'no', 'true', 'false', case-insensitive) comment: str (i.e., any string)
So, only if changed
is True
then assume the command execution has changed the state, and any other key values or attributes in the output will be set as part of the changes.
If there's a comment then it will be used as the comment of the state.
Here's an example of how one might write a shell script for use with a stateful command:
#!/bin/bash # echo "Working hard..." # writing the state line echo # an empty line here so the next line will be the last. echo "changed=yes comment='something has changed' whatever=123"
And an example SLS file using this module:
Run myscript: cmd.run: - name: /path/to/myscript - cwd: / - stateful: True Run only if myscript changed something: cmd.run: - name: echo hello - cwd: / - onchanges: - cmd: Run myscript
Note that if the second cmd.run
state also specifies stateful: True
it can then be watched by some other states as well.
The stateful argument can optionally include a test_name parameter.
This is used to specify a command to run in test mode. This command should return stateful data for changes that would be made by the command in the name parameter.
New in version 2015.2.0.
Run myscript: cmd.run: - name: /path/to/myscript - cwd: / - stateful: - test_name: /path/to/myscript test Run masterscript: cmd.script: - name: masterscript - source: salt://path/to/masterscript - cwd: / - stateful: - test_name: masterscript test
cmd.run
or cmd.wait
?These two states are often confused. The important thing to remember about them is that cmd.run
states are run each time the SLS file that contains them is applied. If it is more desirable to have a command that only runs after some other state changes, then cmd.wait
does just that. cmd.wait
is designed to watch other states, and is executed when the state it is watching changes. Example:
/usr/local/bin/postinstall.sh: cmd.wait: - watch: - pkg: mycustompkg file.managed: - source: salt://utils/scripts/postinstall.sh mycustompkg: pkg.installed: - require: - file: /usr/local/bin/postinstall.sh
cmd.wait
itself does not do anything; all functionality is inside its mod_watch
function, which is called by watch
on changes.
The preferred format is using the onchanges Requisite, which works on cmd.run
as well as on any other state. The example would then look as follows:
/usr/local/bin/postinstall.sh: cmd.run: - onchanges: - pkg: mycustompkg file.managed: - source: salt://utils/scripts/postinstall.sh mycustompkg: pkg.installed: - require: - file: /usr/local/bin/postinstall.sh
The map that comes from a pillar can be directly consumed by the env option! To use it, one may pass it like this. Example:
printenv: cmd.run: - env: {{ salt['pillar.get']('example:key', {}) }}
Invoke a pre-defined Python function with arguments specified in the state declaration. This function is mainly used by the salt.renderers.pydsl
renderer.
The interpretation of onlyif
and unless
arguments are identical to those of cmd.run
, and all other arguments(cwd
, runas
, ...) allowed by cmd.run
are allowed here, except that their effects apply only to the commands specified in onlyif and unless rather than to the function to be invoked.
In addition, the stateful
argument has no effects here.
The return value of the invoked function will be interpreted as follows.
If it's a dictionary then it will be passed through to the state system, which expects it to have the usual structure returned by any salt state function.
Otherwise, the return value (denoted as result
in the code below) is expected to be a JSON serializable object, and this dictionary is returned:
{ 'name': name 'changes': {'retval': result}, 'result': True if result is None else bool(result), 'comment': result if isinstance(result, six.string_types) else '' }
Execute the onlyif and unless logic. Return a result dict if: * onlyif failed (onlyif != 0) * unless succeeded (unless == 0) else return True
Execute a cmd function based on a watch call
Note
This state exists to support special handling of the watch
requisite. It should not be called directly.
Parameters for this function should be set by the state being triggered.
Run a command if certain circumstances are met. Use cmd.wait
if you want to use the watch
requisite.
onlyif
option returns a zero exit statusunless
option returns a non-zero exit statusA list of environment variables to be set prior to execution. Example:
script-foo: cmd.run: - env: - BATCH: 'yes'
Warning
The above illustrates a common PyYAML pitfall, that yes, no, on, off, true, and false are all loaded as boolean True
and False
values, and must be enclosed in quotes to be used as strings. More info on this (and other) PyYAML idiosyncrasies can be found here.
Variables as values are not evaluated. So $PATH in the following example is a literal '$PATH':
script-bar: cmd.run: - env: "PATH=/some/path:$PATH"
One can still use the existing $PATH by using a bit of Jinja:
{% set current_path = salt['environ.get']('PATH', '/bin:/usr/bin') %}
mycommand:
cmd.run:
- name: ls -l /
- env:
- PATH: {{ [current_path, '/my/special/bin']|join(':') }}
$PATH segment to prepend (trailing ':' not necessary) to $PATH. This is an easier alternative to the Jinja workaround.
New in version 2018.3.0.
Control the loglevel at which the output from the command is logged to the minion log.
Note
The command being run will still be logged at the debug
loglevel regardless, unless quiet
is used for this value.
Suppress stdout and stderr in the state's results.
Note
This is separate from output_loglevel
, which only handles how Salt logs to the minion log.
New in version 2018.3.0.
This option no longer has any functionality and will be removed, please set output_loglevel
to quiet
to suppress logging of the command.
Deprecated since version 2014.1.0.
Ignore the timeout of commands, which is useful for running nohup processes.
New in version 2015.8.0.
Only run if the file or files specified by creates
do not exist.
New in version 2014.7.0.
If True
, run command in background and do not await or deliver its results.
New in version 2016.3.6.
non-zero return codes that should be considered a success. If the return code returned from the run matches any in the provided list, the return code will be overridden with zero.
New in version 2019.2.0.
Note
cmd.run supports the usage of reload_modules
. This functionality allows you to force Salt to reload all modules. You should only use reload_modules
if your cmd.run does some sort of installation (such as pip
), if you do not reload the modules future items in your state which rely on the software being installed will fail.
getpip:
cmd.run:
- name: /usr/bin/python /usr/local/sbin/get-pip.py
- unless: which pip
- require:
- pkg: python
- file: /usr/local/sbin/get-pip.py
- reload_modules: True
Download a script and execute it with specified arguments.
onlyif
option returns trueunless
option returns falseA list of environment variables to be set prior to execution. Example:
salt://scripts/foo.sh: cmd.script: - env: - BATCH: 'yes'
Warning
The above illustrates a common PyYAML pitfall, that yes, no, on, off, true, and false are all loaded as boolean True
and False
values, and must be enclosed in quotes to be used as strings. More info on this (and other) PyYAML idiosyncrasies can be found here.
Variables as values are not evaluated. So $PATH in the following example is a literal '$PATH':
salt://scripts/bar.sh: cmd.script: - env: "PATH=/some/path:$PATH"
One can still use the existing $PATH by using a bit of Jinja:
{% set current_path = salt['environ.get']('PATH', '/bin:/usr/bin') %}
mycommand:
cmd.run:
- name: ls -l /
- env:
- PATH: {{ [current_path, '/my/special/bin']|join(':') }}
base
Only run if the file or files specified by creates
do not exist.
New in version 2014.7.0.
New in version 2016.3.0.
Overrides default context variables passed to the template.
New in version 2016.3.0.
Default context passed to the template.
Control the loglevel at which the output from the command is logged to the minion log.
Note
The command being run will still be logged at the debug
loglevel regardless, unless quiet
is used for this value.
Suppress stdout and stderr in the state's results.
Note
This is separate from output_loglevel
, which only handles how Salt logs to the minion log.
New in version 2018.3.0.
non-zero return codes that should be considered a success. If the return code returned from the run matches any in the provided list, the return code will be overridden with zero.
New in version 2019.2.0.
Run the given command only if the watch statement calls it.
onlyif
option returns trueunless
option returns falseA list of environment variables to be set prior to execution. Example:
script-foo: cmd.wait: - env: - BATCH: 'yes'
Warning
The above illustrates a common PyYAML pitfall, that yes, no, on, off, true, and false are all loaded as boolean True
and False
values, and must be enclosed in quotes to be used as strings. More info on this (and other) PyYAML idiosyncrasies can be found here.
Variables as values are not evaluated. So $PATH in the following example is a literal '$PATH':
script-bar: cmd.wait: - env: "PATH=/some/path:$PATH"
One can still use the existing $PATH by using a bit of Jinja:
{% set current_path = salt['environ.get']('PATH', '/bin:/usr/bin') %}
mycommand:
cmd.run:
- name: ls -l /
- env:
- PATH: {{ [current_path, '/my/special/bin']|join(':') }}
Only run if the file or files specified by creates
do not exist.
New in version 2014.7.0.
Control the loglevel at which the output from the command is logged to the minion log.
Note
The command being run will still be logged at the debug
loglevel regardless, unless quiet
is used for this value.
Suppress stdout and stderr in the state's results.
Note
This is separate from output_loglevel
, which only handles how Salt logs to the minion log.
New in version 2018.3.0.
non-zero return codes that should be considered a success. If the return code returned from the run matches any in the provided list, the return code will be overridden with zero.
New in version 2019.2.0.
Download a script from a remote source and execute it only if a watch statement calls it.
onlyif
option returns trueunless
option returns falseA list of environment variables to be set prior to execution. Example:
salt://scripts/foo.sh: cmd.wait_script: - env: - BATCH: 'yes'
Warning
The above illustrates a common PyYAML pitfall, that yes, no, on, off, true, and false are all loaded as boolean True
and False
values, and must be enclosed in quotes to be used as strings. More info on this (and other) PyYAML idiosyncrasies can be found here.
Variables as values are not evaluated. So $PATH in the following example is a literal '$PATH':
salt://scripts/bar.sh: cmd.wait_script: - env: "PATH=/some/path:$PATH"
One can still use the existing $PATH by using a bit of Jinja:
{% set current_path = salt['environ.get']('PATH', '/bin:/usr/bin') %}
mycommand:
cmd.run:
- name: ls -l /
- env:
- PATH: {{ [current_path, '/my/special/bin']|join(':') }}
Control the loglevel at which the output from the command is logged to the minion log.
Note
The command being run will still be logged at the debug
loglevel regardless, unless quiet
is used for this value.
Suppress stdout and stderr in the state's results.
Note
This is separate from output_loglevel
, which only handles how Salt logs to the minion log.
New in version 2018.3.0.
non-zero return codes that should be considered a success. If the return code returned from the run matches any in the provided list, the return code will be overridden with zero.
New in version 2019.2.0.
© 2019 SaltStack.
Licensed under the Apache License, Version 2.0.
https://docs.saltstack.com/en/latest/ref/states/all/salt.states.cmd.html