⌨️ Daily Life Commands
Updated 18 August 2026
Every command marked ⭐ across Modules 01–14, collected into one working reference — organised by what you are trying to do, not by which module taught it.
If you only memorise one section, make it 🚦 Before You Run Anything.
🚦 Before you run anything
ansible-playbook site.yml --syntax-check # does it parse?
ansible-playbook site.yml --list-hosts # what is the blast radius?
ansible-playbook site.yml --list-tasks # what will it do, in order?
ansible-playbook site.yml --check --diff --limit web01 # what WOULD change?# And when the pattern matters more than the playbook
ansible 'prod:&web:!web01' --list-hosts # verify BEFORE anything destructive🔎 Orientation — an unfamiliar repository or host
ansible --version # version AND which ansible.cfg won
ansible-config dump --only-changed # every non-default setting, with its source
ansible-galaxy collection list # what collections are installed
ansible-galaxy install -r requirements.yml # get the pinned dependencies
ansible-inventory -i inventory/ --graph # the group tree
ansible-inventory -i inventory/ --graph --vars # tree plus variables
ansible-inventory -i inventory/ --host web01 # everything resolved for one host
ansible-playbook site.yml --list-tasks # the full ordered scope🔌 Connectivity
ansible all -m ansible.builtin.ping # SSH + auth + Python, all at once
ansible all -m ansible.builtin.ping -o # one line per host
ansible web01 -m ansible.builtin.ping -vvv # the exact ssh command built
ansible web01 -m ping -vvv 2>&1 | grep -o 'IdentityFile=[^]*' # WHICH key was offered?
ansible web01 -m ansible.builtin.command -a "id" # who am I after login?
ansible web01 -m ansible.builtin.command -a "id" -b # who am I after become?When it fails
ssh -vvv [email protected] # ALWAYS reproduce outside Ansible
ssh web01 'ls -ld ~ ~/.ssh ~/.ssh/authorized_keys' # target-side permissions
ssh web01 'sudo journalctl -u sshd -n 50' # THE REAL REASON for auth failures
ssh-keygen -R web01 # clear a changed host key
ssh-keyscan -H web01 >> ~/.ssh/known_hosts
ssh-keygen -t ed25519 -f ~/.ssh/ansible_ed25519
ssh-copy-id -i ~/.ssh/ansible_ed25519.pub [email protected]
ssh-add ~/.ssh/ansible_ed25519 # load a passphrase-protected keyAnd check whether someone ran it under sudo — that changes $HOME to /root, so Ansible reads /root/.ssh and your key is never offered.
🏃 Running playbooks
ansible-playbook site.yml
ansible-playbook site.yml --limit web01 # one host first, always
ansible-playbook site.yml --limit @site.retry # only the hosts that failed
ansible-playbook site.yml --check --diff # the closest thing to terraform plan
ansible-playbook site.yml --tags deploy # run one slice
ansible-playbook site.yml --skip-tags slow
ansible-playbook site.yml --list-tags # what tags exist?
ansible-playbook site.yml --start-at-task "Deploy config" # resume after a fix
ansible-playbook site.yml --step # confirm each task
ansible-playbook site.yml -e app_version=2.4.1 # extra vars always win
ansible-playbook site.yml -e '{"debug": false}' # JSON preserves real types
ansible-playbook site.yml -e "@vars/production.yml" # load a whole file
ansible-playbook site.yml --flush-cache # discard cached facts
ansible-playbook site.yml -f 50 # forks for this run
ansible-playbook site.yml -vvv # connection-level debuggingMulti-environment
ansible-playbook -i inventories/staging playbooks/site.yml
ansible-playbook -i inventories/production playbooks/site.yml⚡ Ad-hoc operations
ansible all -m ansible.builtin.setup # every fact
ansible all -m ansible.builtin.setup -a 'filter=ansible_distribution*' # filtered
ansible all -m ansible.builtin.setup -a 'filter=ansible_local' # custom facts
ansible all -m ansible.builtin.shell -a "uptime" -o # quick fleet check
ansible all -m ansible.builtin.shell -a "df -h /" -o # who is out of disk?
ansible web -m ansible.builtin.service -a "name=nginx state=restarted" -b
ansible all -m ansible.builtin.package -a "name=htop state=present" -b --check -o # AUDIT🔍 Debugging
The three-step variable diagnosis
- ansible.builtin.debug: var=hostvars[inventory_hostname] # 1. what DOES this host have?
- ansible.builtin.debug: var=myvar # 2. what is the value?
- ansible.builtin.debug: msg="{{ myvar | type_debug }}" # 3. what TYPE is it?Other inspection
- ansible.builtin.debug: var=result # a full registered object
- ansible.builtin.debug: var=ansible_facts # all gathered facts
- ansible.builtin.debug: var=groups # the whole inventory
- ansible.builtin.debug: var=group_names # groups THIS host is in
- ansible.builtin.assert: # fail early, fail clearly
that: [app_port | int > 1024]
fail_msg: "app_port={{ app_port }} type={{ app_port | type_debug }}"The interactive debugger
strategy: debug # play level - debugger on any failure
debugger: on_failed # task level(debug) p task.args # arguments AFTER templating
(debug) p task_vars['myvar']
(debug) p result._result # the full failure object
(debug) task.args['_raw_params'] = '...' # modify in place
(debug) r # REDO just this task
(debug) c # continueLogging and timing
ANSIBLE_LOG_PATH=/tmp/run.log ansible-playbook site.yml
grep -n 'FAILED\|UNREACHABLE\|rescued' /tmp/run.log
ANSIBLE_CALLBACKS_ENABLED=profile_tasks,timer ansible-playbook site.yml # where time goes"What changed?"
git log --since="last Tuesday" --oneline -- playbooks/ roles/ inventory/
git log -p -- requirements.yml # an unpinned collection bump
git diff HEAD~1 -- group_vars/
ansible-galaxy collection list # what versions are actually installed📚 Finding things
ansible-doc ansible.builtin.copy # full module docs
ansible-doc -s ansible.builtin.copy # PASTE-READY task skeleton
ansible-doc -l # every module available
ansible-doc -l | grep -i firewall # find the right module
ansible-doc -t filter -l # every Jinja2 filter
ansible-doc -t filter ansible.builtin.combine # docs for one filter
ansible-doc -t lookup -l
ansible-doc -t callback -l
ansible-doc -t role mycompany.platform.webserver # a role's argument_specs
ansible-doc -l mycompany.platform # modules in one collection# Test a filter or expression instantly
ansible localhost -m ansible.builtin.debug -a "msg={{ 'test' | upper }}"
ansible localhost -m ansible.builtin.debug -a "msg={{ myvar | type_debug }}"📦 Collections and roles
ansible-galaxy install -r requirements.yml # roles AND collections
ansible-galaxy collection install -r requirements.yml -p ./collections --force
ansible-galaxy collection install community.general:==8.3.0 # exact version
ansible-galaxy collection list
ansible-galaxy role init roles/myrole # scaffold a role
ansible-galaxy collection init mycompany.platform # scaffold a collection
ansible-galaxy collection build --output-path ./dist --force
ansible-galaxy collection install ./dist/mycompany-platform-0.1.0.tar.gz -p ./collections🔐 Vault
ansible-vault create secrets.yml # new encrypted file
ansible-vault edit secrets.yml # decrypt, edit, re-encrypt
ansible-vault view secrets.yml # read WITHOUT modifying
ansible-vault rekey secrets.yml # change the password
ansible-vault encrypt_string 'SuperSecret' --name 'vault_db_password'
ansible-vault encrypt_string --stdin-name 'vault_api_token' # keeps it out of shell history
ansible-playbook site.yml --vault-password-file ~/.vault-pass
ansible-playbook site.yml --vault-id prod@~/.vault-prod
export ANSIBLE_VAULT_PASSWORD_FILE=~/.vault-passThe secret audit
# What IS encrypted
grep -rl 'ANSIBLE_VAULT;1.1' . --include='*.yml'
# What SHOULD be - plaintext credentials in version control
git grep -nE '(password|passwd|secret|token|api_key)\s*:\s*[^"{ ]' -- ':!*vault.yml'
# Every secret the project consumes, without decrypting anything
grep -rhoE 'vault_[a-z0-9_]+' --include='vars.yml' . | sort -u🧪 Testing
yamllint .
ansible-lint # lint everything discoverable
ansible-lint --profile production # the strictest profile
ansible-lint --fix # auto-fix the mechanical rules
ansible-lint --list-rules
molecule converge # create + run the role, LEAVE IT UP
molecule login -h ubuntu2204 # shell in and look around
molecule idempotence # run again, fail on any change
molecule verify
molecule test # full lifecycle - what CI runs
molecule test -s tls # a named scenario
cd ~/collections/ansible_collections/mycompany/platform
ansible-test sanity --docker default
ansible-test sanity --docker --test validate-modules
pre-commit install
pre-commit run --all-filesyamllint .
ansible-lint --profile moderate
ansible-playbook playbooks/site.yml --syntax-check
cd roles/<changed-role> && molecule testIf those pass, CI will almost certainly pass — and you have not burned a pipeline slot discovering a missing quote.
☁️ Dynamic inventory
ansible-inventory -i inventory/prod.aws_ec2.yml --graph
ansible-inventory -i inventory/ --graph --flush-cache # bypass a stale cache
ansible-inventory -i inventory/ --list --output /tmp/inv.json
ansible -i inventory/ role_web --list-hosts # does the pattern match?
ansible -i inventory/ needs_attention --list-hosts # tagging audit
# When it returns nothing
ansible-inventory -i inventory/x.yml --graph -vvvv 2>&1 | grep -i 'declined\|parse'
ls inventory/ # does the filename end in aws_ec2.yml?
aws sts get-caller-identity # are credentials working at all?🎛️ AWX
export CONTROLLER_HOST=https://awx.internal
export CONTROLLER_OAUTH_TOKEN="$AWX_TOKEN" # a SCOPED token, not admin
awx job_templates list
awx job_templates launch "Deploy Web Tier" --monitor # CI-safe
awx job_templates launch "Deploy Web Tier" \
--extra_vars '{"app_version":"2.4.1"}' --monitor
awx jobs list --status failed --order_by '-finished' --count 5
awx jobs stdout 4821
awx projects update "Platform Automation" --monitor # force an SCM pull
awx inventory_sources update "AWS Production" --monitor # refresh inventory
awx export --organization Engineering > org.json # config backup
awx roles list --team "Support Desk" # who can do what⚙️ Configuration worth having
# ansible.cfg
[defaults]
inventory = ./inventories/staging # NOT production, deliberately
roles_path = ./roles:./galaxy_roles
collections_path = ./collections
remote_user = deploy
forks = 25 # default 5 is far too low
stdout_callback = yaml
callbacks_enabled = profile_tasks, timer
interpreter_python = auto_silent
gathering = smart # REQUIRED for fact caching to help
fact_caching = jsonfile
fact_caching_connection = /tmp/ansible_facts
fact_caching_timeout = 7200
vault_password_file = ~/.ansible-vault-pass # the PATH is committed, not the file
[privilege_escalation]
become = True
become_method = sudo
become_user = root
[ssh_connection]
pipelining = True # ~40% fewer SSH ops per task
ssh_args = -o ControlMaster=auto -o ControlPersist=60s
control_path_dir = /tmp/.acp # fixes 'socket path too long'
[inventory]
enable_plugins = auto, yaml, ini, amazon.aws.aws_ec2, constructed
cache = True
cache_plugin = jsonfile
cache_timeout = 900inventory points at staging, so a forgotten -i is harmless rather than an incident. Some teams set no default at all, forcing every command to be explicit.
pipelining = True requires requiretty disabled in sudoers on the managed nodes. Verify across the fleet before enabling it globally:
ansible all -m ansible.builtin.shell -a "grep -r requiretty /etc/sudoers /etc/sudoers.d/ 2>/dev/null || echo OK" -o🎯 The six patterns worth knowing by heart
serial: [1, 5, "25%"] # canary, then progressive batches
max_fail_percentage: 0 # halt at the first failure
# plus block / rescue / always, where the rescue ENDS with `fail`Without that fail, a successful rescue clears the failure state, max_fail_percentage never fires, and the rollout continues through a broken release.
1. Inspect current state. Matches? -> exit_json(changed=False)
2. if module.check_mode: -> exit_json(changed=True)
3. Make the change -> exit_json(changed=True)Reverse steps 2 and 3 and your module modifies production during a dry run.
- ansible.builtin.meta: flush_handlers # BEFORE any task that verifies the handler's effectWithout it you verify the old state and get a confusing failure.
{% for host in groups['web'] | sort %} {# sort = stable = idempotent #}
{% for k, v in settings | dictsort %} {# same reason #}Unstable ordering makes the render differ between runs — a false changed and a needless restart, every time.
when: enable_feature | bool # -e passes STRINGS; "false" is truthyowner: "{{ file_owner | default(omit) }}" # omit = do not pass the argument AT ALLdefault('') passes an empty string, which the module then tries to act on and fails.
🚩 The flags that prevent incidents
| Flag or setting | What it prevents |
|---|---|
| --check --diff | Applying a change you have not seen |
| --limit web01 | Learning about a bug on 500 hosts instead of one |
| --list-hosts | Discovering your pattern matched production |
| validate: nginx -t -c %s | Writing a broken config and reloading into an outage |
| no_log: true | A password in your CI log forever |
| loop_control: label: | The whole credential dict echoed per iteration |
| max_fail_percentage: 0 | A bad release reaching every host in the fleet |
| tags: always on include_vars | A tagged run skipping setup and failing mysteriously |
| apply: on include_role | A tagged run that silently does nothing at all |
| Pinned requirements.yml | A collection upgrading underneath you with no commit |