ansible/ansible
Shell plugins (and a note on strategy)
Shell plugins handle the platform-specific logic for quoting commands, joining environment variables, and choosing how to wrap shell invocations on a remote target. Strategy plugins (covered in their own dedicated Strategy page) decide when to dispatch tasks; shell plugins decide how to format the commands the connection plugin then sends.
Shell plugins
ansible-core ships shell plugins for each major remote shell:
lib/ansible/plugins/shell/
├── __init__.py # ShellBase
├── sh.py # POSIX sh — the common case
├── cmd.py # Windows cmd.exe
├── powershell.py # Windows PowerShell
├── csh.py
└── fish.pyThe shell plugin is selected based on the target's ansible_shell_type (set automatically based on connection plugin and gathered facts). Action plugins use it to:
- Build environment-prefixed commands:
ENV_VAR=value /bin/sh -c 'cmd'. - Quote arguments correctly for the shell.
- Generate temp directory creation/removal commands.
- Build the AnsiBallZ wrapper invocation.
- Format chmod/chown calls.
ShellBase contract
| Attribute / method | Purpose |
|---|---|
COMPATIBLE_SHELLS |
Set of shell types this plugin handles |
SHELL_FAMILY |
sh, csh, powershell, cmd |
quote(arg) |
Shell-quote a single argument |
join_path(*args) |
Join paths with the shell's separator |
mkdtemp(...) |
Build a mktemp -d command |
expand_user(path) |
Build a ~user expansion command |
set_user_facl(path, user, mode) |
ACL helper |
chmod(paths, mode), chown(paths, user, group) |
|
env_prefix(env_dict) |
KEY=val ANOTHER=val ... |
pwd() |
Print working directory command |
command_sep |
; for sh, \n for PowerShell |
sh
lib/ansible/plugins/shell/sh.py is the workhorse. POSIX-compliant quoting (single-quotes with embedded '\'' escapes), mktemp -d, chmod $mode $path, etc.
powershell
lib/ansible/plugins/shell/powershell.py is the Windows equivalent and significantly more involved than sh.py. It handles:
- PowerShell-specific quoting (
'value'vs"value"rules). New-Item -ItemType Directoryformkdir.Get-ItemPropertyfor stat-equivalent operations.- The full PowerShell wrapper boilerplate that
lib/ansible/executor/powershell/references.
PowerShell is unique because the AnsiBallZ-equivalent flow is different: instead of a Python script, it's a PowerShell script with embedded C# helper assemblies (compiled by PowerShell at runtime). The shell plugin is part of the wrapper-construction pipeline.
cmd
lib/ansible/plugins/shell/cmd.py is for cmd.exe. Mostly a fallback for older Windows targets that don't have PowerShell available; modern Windows automation uses the powershell shell.
csh, fish
Niche but supported. Useful for the rare target running a non-POSIX login shell where the executor needs to syntax-match.
Why shell plugins matter
Without a correct shell plugin:
- Quoting bugs → injection vulnerabilities.
- Environment variables don't propagate.
mkdir/chmod/rmcommands fail in subtle ways.- AnsiBallZ wrappers don't execute correctly.
The bulk of platform-specific quirks for "running a command on a remote target" live here. When porting Ansible to a new shell or shell-flavor, the shell plugin is the bulk of the work.
A note on strategy
The strategy plugin and the shell plugin are independent — one decides which task to run next, the other decides how to format the command for that task. They don't interact directly. The strategy hands a task to a worker; the worker's TaskExecutor instantiates an action plugin; the action plugin calls into the connection plugin; the connection plugin uses the shell plugin to build the actual remote command line.
For the deep dive on strategies — linear, free, host_pinned, debug — see Strategy.
Integration points
- Imported by: action plugins (when building exec commands), connection plugins (when wrapping
exec_command),lib/ansible/executor/module_common.py(when building AnsiBallZ wrapper invocations). - Selected by:
ansible_shell_typeper host. Set automatically; can be overridden in inventory. - Loaded by:
shell_loaderinlib/ansible/plugins/loader.py.
Entry points for modification
- Quoting bug for an unusual shell — fix in the relevant
lib/ansible/plugins/shell/*.pyfile. - A new shell — write a plugin in a collection. Subclass
ShellBase. SetCOMPATIBLE_SHELLSandSHELL_FAMILY. Implement quoting and the path/file-handling commands.
Cross-links
- Strategy — the dispatch-side counterpart.
- Connection — what passes the formatted command over the wire.
- Module execution and AnsiBallZ — where shell-plugin-built command lines surround the AnsiBallZ wrapper invocation.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.