Skip to content
← DevOps foundations

Learning bite

Tasks, modules, and handlers

Describe desired state and react only to meaningful changes.

Documentation reviewed2026-10-01 · 3 min read
On this page

Ask a module for the desired result

A task invokes a module with arguments. copy manages file content, file manages paths and permissions, package manages packages, and service manages service state. Modules can compare the desired result with what exists. A shell command may need extra logic to decide whether it changed anything, and adds shell quoting and expansion to the problem.

Using the tested inventory.ini, save this complete site.yml:

yaml
- name: Place a study marker
  hosts: study
  gather_facts: true
  tasks:
    - name: Write a non-secret marker in the remote home
      ansible.builtin.copy:
        dest: "{{ ansible_facts['user_dir'] }}/learnwithsk-marker.txt"
        content: "environment=local\n"
        mode: '0600'
      notify: Report marker change
  handlers:
    - name: Report marker change
      ansible.builtin.debug:
        msg: Marker content or metadata changed.

gather_facts asks Ansible to collect information about the target. The user_dir fact identifies the remote user's home directory. The fully qualified name ansible.builtin.copy says which collection supplies the module, avoiding ambiguity with another module named copy. This file needs no root access.

Run from ansible-practice:

bash
ansible-playbook -i inventory.ini site.yml --list-hosts
ansible-playbook -i inventory.ini site.yml --limit study-vm
ansible-playbook -i inventory.ini site.yml --limit study-vm

If the marker was absent, expect the first copy task to report changed and the message handler to run. With matching content and mode, expect no change from that task on the second run and no handler notification. Actual recap totals depend on the initial state.

A handler reacts to change

Handlers are named tasks notified by other tasks that report changed. Repeated notifications are normally combined before the handler runs at its processing point. This is useful when several configuration edits should trigger one service reload. Here the handler prints a message so you can learn the timing without restarting a real service.

Handlers are not automatic validation. A changed invalid configuration could still notify a reload. A later task failure can also affect whether notified handlers run. Before adding flush points or forced handlers, understand the ordering you need and validate the application's configuration separately.

Read task outcomes accurately

ok means the module succeeded without reporting a change; changed means it reported an alteration; failed means task execution failed; unreachable means Ansible could not communicate as required. A skipped conditional task did not perform its operation. None of those alone describes the user's application experience.

For repeated data, a loop applies the same task to each item. A when condition decides whether a task applies. A register value stores a module's result for later decisions. Prefer those explicit structures to a large shell script that conceals individual outcomes. command runs a command without ordinary shell features; shell is needed only when you actually require shell behavior. Neither becomes idempotent because its name sounds harmless.

Try a controlled drift

Edit the marker's contents through the learning machine, then rerun the play. It should restore the line and notify the handler. Run once more and compare. If it keeps reporting changed, inspect the changing input or metadata rather than adding changed_when: false.

Checkpoint: does that setting prevent a command's side effects? No; it changes reporting. Why is copy appropriate here? It understands the desired file contents and permissions. Keep site.yml; next, replace its literal content with a template and validated variables.

References: handlers↗, copy↗, conditionals↗, and loops↗.

Your notes and evidence

Record observations, questions, or links to your work. Keep credentials out of your notes.

Loading saved progress…

Back up or restore this path

Progress and notes stay in this browser. A backup contains only this learning path.