Ansible shell Module: Run Commands with Pipes & Redirects (Complete Guide)
By Luca Berton · Published 2024-01-01 · Category: installation
How to run shell commands in Ansible with the shell module (ansible.builtin.shell). Use pipes, redirects, environment variables, chained commands. When to use shell vs command module.
Ansible Shell Module: Run Commands with Pipes & Redirects (Complete Guide)
The Ansible shell module (ansible.builtin.shell) executes commands through the shell (/bin/sh) on remote hosts, enabling pipes, redirects, environment variables, and all shell features. This guide covers when and how to use it effectively.
Shell vs Command Module: Key Difference
| Feature | shell | command | |---------|-------|---------| | Pipes (|) | ✅ Yes | ❌ No | | Redirects (>, >>) | ✅ Yes | ❌ No | | Environment variables ($HOME) | ✅ Yes | ❌ No | | Wildcards (.log) | ✅ Yes | ❌ No | | Chaining (&&, ||) | ✅ Yes | ❌ No | | Safer (no injection risk) | ❌ No | ✅ Yes |
Rule of thumb: Use command by default. Use shell only when you need shell features.
Basic Usage
Pipes and Redirects
Multi-Line Commands
Use YAML literal block scalar (|) for complex commands:
Environment Variables
Idempotency with creates and removes
Make shell commands idempotent:
Controlling changed_when
Prevent shell tasks from always showing "changed":
Choosing a Different Shell
Error Handling
Passing stdin Data
Security Best Practices
1. Prefer command over shell when possible
2. Use no_log for sensitive commands
3. Quote variables in shell commands
Common Patterns
Check-then-act
Pipeline with error checking
FAQ
When should I use Ansible shell vs command module?
Use ansible.builtin.shell when you need shell features like pipes (|), redirects (>), environment variable expansion ($HOME), or wildcards (.log). Use ansible.builtin.command for everything else — it's safer because it doesn't process shell metacharacters.
How do I make Ansible shell commands idempotent?
Use the creates parameter to skip the command if a file already exists, or removes to only run if a file exists. You can also use changed_when with conditions based on the command output to accurately report changes.
Why does Ansible shell always show "changed"?
The shell module defaults to changed: true because it can't know if the command actually modified anything. Use changed_when: false for read-only commands, or changed_when: "'specific text' in result.stdout" for conditional change detection.
Can I use bash-specific features in Ansible shell?
Yes, set executable: /bin/bash in the args section to use bash features like shopt, [[ ]] tests, process substitution, and associative arrays that aren't available in /bin/sh.
How do I prevent shell injection in Ansible?
Use the command module instead of shell when possible. If you must use shell, apply the quote filter to user-supplied variables: "{{ user_input | quote }}". Never pass untrusted data directly into shell commands.
Conclusion
The Ansible shell module is powerful for running complex commands with pipes, redirects, and shell features on remote hosts. Always prefer the command module for simple operations, and use shell only when you genuinely need shell capabilities. Apply changed_when, creates, and removes for idempotent automation.
Related Articles • Ansible command Module: Run Shell Commands on Remote Hosts • Ansible shell vs command vs raw: When to Use Each Module • Ansible script Module: Run Local Scripts on Remote Hosts
Category: installation