What you'll learn
- What is the difference between `command` vs `shell` Ansible modules?
- command vs shell
- command module
- shell module
- Links
- command code
- command execution
- shell execution
- wrong module code
- wrong module execution
What is the difference between `command` vs `shell` Ansible modules?
`ansible.builtin.command` executes a binary directly on the target host — no shell involvement, so pipes, redirects, and environment variable expansion are unavailable, but execution is more predictable and secure. `ansible.builtin.shell` routes the command through `/bin/sh`, enabling pipes (`|`), redirects (`>`), and shell built-ins at the cost of less predictable behavior. Use `command` when possible; reach for `shell` only when you genuinely need shell features.
command vs shell
command
- execute commands against the target Unix-based hosts
- it bypasses the shell
- always set changed to True
shell
- execute shell commands against the target Unix-based hosts
- redirections and shell's inbuilt functionality
- always set changed to True
The `command` and `shell` Ansible modules execute commands on the target node.
Generally speaking, is always better to use a specialized Ansible module to execute a task.
However, sometimes the only way is to execute a Linux `command` via command or `shell` module.
Let me reinforce again, you should avoid as much as possible the usage of command/shell instead of a better module.
Both modules execute commands on target nodes but in a sensible different way.
The `command` modules execute commands on the target machine without using the target shell, it simply executes the command. The target shell is for example the popular `bash`, `zsh`, or `sh`. As a side effect user environment, variable expansions, output redirections, stringing two commands together, and other shell features are not available. On the other side, every command executed using `shell` module has all shell features so it could be expanded in runtime. From the security point of view`command` module is more robust and has a more predictable outcome because it bypasses the `shell`.
Both modules returned **always** changed status because Ansible is not able to predict if the execution has or has not altered the target system.
command module
- Execute commands on targets
The "command" module is the default module in Ansible Ad-hoc mode. The command module is able to execute only the binaries on remote hosts. The `command` module won't be impacted by local shell variables because it bypasses the shell. At the same time, it may not be able to run "shell" built-in features and redirections.
shell module
- Execute shell commands on targets
The `shell` Ansible module is potentially more dangerous than the command module and should only be used when you actually really need the shell functionality. So if you're not stringing two commands together (using pipes or even just `&&` or `;`), you don't really need the shell module. Similarly, expanding shell variables or file global requires the shell module. If you're not using these features, don't use the shell module. Sometimes it's the only way, I know.
Links
- [ansible.builtin.shell](https://docs.ansible.com/ansible/latest/