Table of Contents
Go from Ansible beginner to Ansible pro with this full video course.
What does the Ansible command
module do?
Ansible’s command
module executes simple shell commands on remote hosts.
- name: precompile assets with asdf in $PATH and $RAILS_ENV set to production
command: "rails assets:precompile"
args:
chdir: /opt/my_app
environment:
PATH: "/opt/asdf/bin:/opt/asdf/shims:{{ ansible_env.PATH }}"
RAILS_ENV: production
Ansible command
Module Video Tutorial
If you prefer watching to reading, here’s a full video tutorial from the TopTechSkills YouTube channel covering a many of the points and examples from this article. Feel free to comment on this article or the video if you have any questions.
When to use the command
module vs shell
module
The command
and shell
modules are almost identical, except that command
cannot use special shell operators such as <
>
|
;
&
or access user-specific environment variables like $HOME
. According to the docs, the command
module is more secure and predictable, so my personal preference is to default to using command
unless I need the extended functionality of shell
.
# If your command looks like this, use `command`:
/path/to/program arg1 arg2
# If your command looks like this, use `shell`:
java -version 2>&1 | grep OpenJDK
Examples
How to run command
only if a file doesn’t exist
Use the creates
argument to run the command only if a file doesn’t exist already.
- name: create a new test file only if it doesn't already exist
command: touch /tmp/test_file
args:
creates: /tmp/test_file
How to run command
only if a file does exist
Use the removes
argument to run the command only if a file already exists.
- name: remove /tmp/test_file only if it already exists
command: rm /tmp/test_file
args:
removes: /tmp/test_file
How to run command
in a different directory
Use the chdir
argument to run command
inside the specified directory.
- name: precompile assets after changing to the app directory
command: "rails assets:precompile"
args:
chdir: /opt/my_app
How to run command
with custom environment variables
Use the environment
keyword to set environment variables for the command. This is commonly used to alter the $PATH
or set framework-specific ENV
s such as RAILS_ENV
.
- name: precompile assets with asdf in $PATH and $RAILS_ENV set to production
command: "rails assets:precompile"
args:
chdir: /opt/my_app
environment:
PATH: "/opt/asdf/bin:/opt/asdf/shims:{{ ansible_env.PATH }}"
RAILS_ENV: production
How to run command
multiple times in a loop
Use the loop
keyword to run command
multiple times in a loop.
- name: run commands with asdf in $PATH and $RAILS_ENV set to production
command: "{{ item }}"
args:
chdir: /opt/my_app
environment:
PATH: "/opt/asdf/bin:/opt/asdf/shims:{{ ansible_env.PATH }}"
RAILS_ENV: production
loop:
- "rake db:migrate"
- "rails assets:precompile"
How to capture command
module output
Use the register
keyword to capture the output of any commands you run.
- name: make a test file with command module
command: touch /tmp/test_file
register: command_output
- debug: var=command_output
The debug
task above will output the following:
ok: [123.123.123.123] => {
"touch_output": {
"changed": true,
"cmd": [
"touch",
"/tmp/test_file"
],
"delta": "0:00:00.003577",
"end": "2018-12-26 05:45:17.411042",
"failed": false,
"rc": 0,
"start": "2018-12-26 05:45:17.407465",
"stderr": "",
"stderr_lines": [],
"stdout": "",
"stdout_lines": [],
"warnings": [...]
}
}
How to capture command
module output from a loop
When using the command
module in a loop, the output of each item in the loop will go into the results
key of the registered variable.
- name: make multiple test files with command module
command: "touch /tmp/test_file_{{ item }}"
register: command_output
loop:
- 1
- 2
- debug: var=command_output
ok: [123.123.123.123] => {
"command_output": {
"changed": true,
"msg": "All items completed",
"results": [
{
...
"changed": true,
"cmd": [
"touch",
"/tmp/test_file_1"
],
"delta": "0:00:00.003201",
"end": "2018-12-26 05:51:46.044893",
"failed": false,
"invocation": {...},
"item": "1",
"rc": 0,
"start": "2018-12-26 05:51:46.041692",
"stderr": "",
"stderr_lines": [],
"stdout": "",
"stdout_lines": []
},
{
...
"changed": true,
"cmd": [
"touch",
"/tmp/test_file_2"
],
"delta": "0:00:00.003118",
"end": "2018-12-26 05:51:46.360661",
"failed": false,
"invocation": {...},
"item": "2",
"rc": 0,
"start": "2018-12-26 05:51:46.357543",
"stderr": "",
"stderr_lines": [],
"stdout": "",
"stdout_lines": []
}
],
"warnings": [...]
}
}
Further reading
Ansible command
Module on Ansible Docs