Ad-hoc commands answer quick questions across a fleet, and they teach the modules playbooks are made of.
An ad-hoc command runs one module on a set of hosts:
ansible <pattern> -i inventory.yml -m <module> -a "<arguments>"
Add -b (become) to run as root via sudo, -K to prompt for the sudo password, -f 20 for 20 parallel hosts, and --check for a dry run.
Core modules worth knowing (all in ansible.builtin):
ping: checks connectivity and Python, not ICMP.commandruns a program without a shell;shellruns through/bin/sh(pipes, redirects). Both always report changed unless told otherwise, so prefer real modules.package/apt/dnf: install packages;service/systemd_service: manage services.copy,template,file,lineinfile,blockinfile: files and their contents.user,group: accounts;ansible.posix.authorized_key(a collection module) for SSH keys.get_url,unarchive,git: fetch things.setup: gathers facts;debug: prints values.
Use fully qualified collection names (FQCN) like ansible.builtin.copy; short names still work but FQCNs are unambiguous and what linters expect.
ansible-doc ansible.builtin.lineinfile shows any module's documentation with examples, offline.
Example
ansible all -i inventory.yml -m ansible.builtin.ping
ansible web -i inventory.yml -m ansible.builtin.command -a "uptime"
ansible web -i inventory.yml -b -m ansible.builtin.apt -a "name=htop state=present update_cache=true"
ansible db -i inventory.yml -m ansible.builtin.setup -a "filter=ansible_distribution*"
# db1 | SUCCESS => { "ansible_facts": { "ansible_distribution": "Ubuntu",
# "ansible_distribution_version": "24.04", ... } }
ansible all -i inventory.yml -b -m ansible.builtin.service -a "name=nginx state=restarted" --limit web1
ansible-doc -s ansible.builtin.copy # short argument summaryRemember
- ansible <pattern> -m module -a args; -b for sudo
- Prefer specific modules over command/shell
- Use FQCNs and ansible-doc
Watch out for
- Using shell for everything, losing idempotence and change reporting.