AnsiblePilot — Master Ansible Automation

AnsiblePilot is the leading resource for learning Ansible automation, DevOps, and infrastructure as code. Browse over 1,100 tutorials covering Ansible modules, playbooks, roles, collections, and real-world examples. Whether you are a beginner or an experienced engineer, our step-by-step guides help you automate Linux, Windows, cloud, containers, and network infrastructure.

Popular Topics

About Luca Berton

Luca Berton is an Ansible automation expert, author of "Ansible for VMware by Examples" and "Ansible for Kubernetes by Example" published by Apress, and creator of the Ansible Pilot YouTube channel. He shares practical automation knowledge through tutorials, books, and video courses to help IT professionals and DevOps engineers master infrastructure automation.

Ansible command Module: Run Shell Commands on Remote Hosts (ansible.builtin.command)

By Luca Berton · Published 2024-01-01 · Category: installation

How to run commands on remote hosts with Ansible command module (ansible.builtin.command). Execute binaries, use creates/removes guards. Practical YAML playbook examples.

The ansible.builtin.command module runs commands on remote hosts without shell processing. This means no pipes, redirects, or variable expansion — making it more secure than shell for most tasks. Here's everything you need to know.

Basic Usage

Key Parameters

| Parameter | Description | Example | |-----------|-------------|---------| | cmd | Command string to execute | cmd: ls -la /tmp | | argv | Command as list (safer) | argv: [ls, -la, /tmp] | | chdir | Change to directory first | chdir: /opt/app | | creates | Skip if file exists | creates: /opt/app/installed | | removes | Skip if file doesn't exist | removes: /tmp/lock.pid | | stdin | Pass data to stdin | stdin: "yes" | | stdin_add_newline | Add newline to stdin | stdin_add_newline: true | | strip_empty_ends | Strip empty lines from output | strip_empty_ends: true |

Idempotent Command Execution

The biggest problem with command is it always reports changed. Use creates and removes for idempotency:

Using argv for Safe Arguments

When arguments contain spaces or special characters, use argv:

Working Directory

Environment Variables

Capturing Output

Handling Return Codes

command vs shell vs raw

| Feature | command | shell | raw | |---------|-----------|---------|-------| | Shell processing | ❌ No | ✅ Yes | ✅ Yes | | Pipes & redirects | ❌ | ✅ \|, >, >> | ✅ | | Variable expansion | ❌ | ✅ $HOME | ✅ | | Glob patterns | ❌ | ✅ .log | ✅ | | Python required | ✅ | ✅ | ❌ | | Security | 🟢 Safest | 🟡 Injection risk | 🔴 Most risk |

Rule of thumb: Use command unless you specifically need shell features. Use shell for pipes and redirects. Use raw only for hosts without Python.

Common Patterns

Check Before Acting

Suppress Changed Status

Pipeline Alternative Without Shell

Warnings and Ansible-Lint

Ansible-lint flags command when a built-in module exists:

Common replacements:

| Command | Use This Module Instead | |---------|----------------------| | mkdir | ansible.builtin.file (state: directory) | | rm | ansible.builtin.file (state: absent) | | chmod | ansible.builtin.file (mode) | | chown | ansible.builtin.file (owner, group) | | cp | ansible.builtin.copy | | ln -s | ansible.builtin.file (state: link) | | systemctl | ansible.builtin.service or ansible.builtin.systemd | | apt install | ansible.builtin.apt | | yum install | ansible.builtin.yum or ansible.builtin.dnf |

FAQ

When should I use command instead of shell?

Always prefer command unless you need shell features like pipes (|), redirects (>), variable expansion ($VAR), or glob patterns (.log). The command module is more secure because it doesn't pass through a shell interpreter, eliminating shell injection risks.

How do I make command idempotent?

Use the creates parameter to skip execution when a file already exists, or removes to skip when a file doesn't exist. For more complex idempotency, use register + changed_when with a conditional check.

Why does command always show "changed"?

The command module has no way to know if the command actually changed anything. Use changed_when: false for read-only commands, or changed_when with a condition based on the registered output.

Can I use command with sudo?

Yes, use Ansible's become mechanism instead of putting sudo in the command:

Conclusion

Use ansible.builtin.command as your default for running commands on remote hosts. It's safer than shell because it skips shell processing. Make your commands idempotent with creates/removes, suppress false changed results with changed_when: false, and consider native modules before reaching for command.

Related ArticlesAnsible shell vs commandAnsible Builtin Command ModuleAnsible error handling

Category: installation

Browse all Ansible tutorials · AnsiblePilot Home