AnsiblePilot — Master Ansible Automation

AnsiblePilot is the leading resource for learning Ansible automation, DevOps, and infrastructure as code. Browse over 1,400 tutorials covering Ansible modules, playbooks, roles, collections, and real-world examples. Whether you are a beginner or an experienced engineer, our step-by-step guides help you automate Linux, Windows, cloud, containers, and network infrastructure.

Popular Topics

About Luca Berton

Luca Berton is an Ansible automation expert, author of 8 Ansible books published by Apress and Leanpub including "Ansible for VMware by Examples" and "Ansible for Kubernetes by Example", and creator of the Ansible Pilot YouTube channel. He shares practical automation knowledge through tutorials, books, and video courses to help IT professionals and DevOps engineers master infrastructure automation.

Ansible register: Save Task Output to Variables (Complete Guide)

By Luca Berton · Published 2024-01-01 · Category: installation

Complete guide to Ansible register. Save task output to variables, access stdout, stderr, return codes, and use registered results in conditions, loops.

The register keyword captures a task's output into a variable for use in subsequent tasks. It's one of the most used Ansible features — essential for conditional logic, debugging, chaining tasks, and building dynamic playbooks.

Basic Syntax

- name: Run a command
  ansible.builtin.command: whoami
  register: result

- name: Show the output ansible.builtin.debug: var: result

The registered variable result is a dictionary containing the task's full return data.

See also: Ansible Variable Precedence: Complete Order of Priority (2026)

Registered Variable Structure

Every registered variable contains at minimum:

result:
  changed: true/false        # Whether the task made changes
  failed: false               # Whether the task failed
  msg: ""                     # Module message (if any)
  # For command/shell modules:
  cmd: "whoami"               # The command that ran
  stdout: "root"              # Standard output
  stdout_lines: ["root"]      # Stdout split by newlines
  stderr: ""                  # Standard error
  stderr_lines: []            # Stderr split by newlines
  rc: 0                       # Return code
  start: "2026-04-12 ..."     # Start timestamp
  end: "2026-04-12 ..."       # End timestamp
  delta: "0:00:00.003"        # Execution time

Access Registered Data

stdout and stderr

- name: Get hostname
  ansible.builtin.command: hostname -f
  register: hostname_result
  changed_when: false

- name: Use the hostname ansible.builtin.debug: msg: "This server is {{ hostname_result.stdout }}"

Return Code

- name: Check if file exists
  ansible.builtin.command: test -f /etc/app/config.yml
  register: file_check
  failed_when: false
  changed_when: false

- name: Create config if missing ansible.builtin.template: src: config.yml.j2 dest: /etc/app/config.yml when: file_check.rc != 0

stdout_lines (List)

- name: List running services
  ansible.builtin.command: systemctl list-units --type=service --state=running --no-pager --plain
  register: services
  changed_when: false

- name: Show service count ansible.builtin.debug: msg: "{{ services.stdout_lines | length }} services running"

- name: Check if nginx is running ansible.builtin.debug: msg: "nginx is running" when: services.stdout_lines | select('search', 'nginx') | list | length > 0

See also: Ansible default() Filter: Set Fallback Values for Undefined Variables

Use in Conditions (when)

- name: Get OS release
  ansible.builtin.command: cat /etc/os-release
  register: os_release
  changed_when: false

- name: Ubuntu-specific task ansible.builtin.debug: msg: "This is Ubuntu" when: "'Ubuntu' in os_release.stdout"

- name: RHEL-specific task ansible.builtin.debug: msg: "This is RHEL" when: "'Red Hat' in os_release.stdout"

Check Success or Failure

- name: Try to connect to database
  ansible.builtin.command: pg_isready -h {{ db_host }}
  register: db_check
  failed_when: false
  changed_when: false

- name: Database is available ansible.builtin.debug: msg: "Database is ready" when: db_check is success

- name: Database is down ansible.builtin.debug: msg: "Cannot reach database" when: db_check is failed

Register with Loops

When used with loops, the registered variable contains a results list:

- name: Check multiple services
  ansible.builtin.command: "systemctl is-active {{ item }}"
  register: service_status
  loop:
    - nginx
    - redis
    - postgresql
  failed_when: false
  changed_when: false

- name: Show stopped services ansible.builtin.debug: msg: "{{ item.item }} is {{ item.stdout }}" loop: "{{ service_status.results }}" when: item.stdout != 'active'

Loop Results Structure

service_status:
  results:
    - item: nginx           # The loop item
      stdout: "active"
      rc: 0
      changed: false
    - item: redis
      stdout: "inactive"
      rc: 3
      changed: false

See also: Ansible vars_files: Load Variables from External YAML Files (Guide)

Register Module-Specific Data

File Module (stat)

- name: Check file details
  ansible.builtin.stat:
    path: /etc/nginx/nginx.conf
  register: nginx_conf

- name: Show file info ansible.builtin.debug: msg: | Exists: {{ nginx_conf.stat.exists }} Size: {{ nginx_conf.stat.size | default('N/A') }} Owner: {{ nginx_conf.stat.pw_name | default('N/A') }} Modified: {{ nginx_conf.stat.mtime | default('N/A') }}

Package Module

- name: Install nginx
  ansible.builtin.package:
    name: nginx
    state: present
  register: install_result

- name: Notify if newly installed ansible.builtin.debug: msg: "nginx was just installed" when: install_result.changed

URI Module (API calls)

- name: Call API
  ansible.builtin.uri:
    url: https://api.example.com/users
    return_content: true
  register: api_response

- name: Process API response ansible.builtin.debug: msg: "Found {{ api_response.json | length }} users"

- name: Use specific field ansible.builtin.debug: msg: "First user: {{ api_response.json[0].name }}"

Service Facts

- name: Gather service facts
  ansible.builtin.service_facts:
  register: services

- name: Check specific service ansible.builtin.debug: msg: "nginx state: {{ services.ansible_facts.services['nginx.service'].state }}" when: "'nginx.service' in services.ansible_facts.services"

Register with set_fact

Store extracted data for use across plays:

- name: Get app version
  ansible.builtin.command: /opt/myapp/bin/version
  register: version_output
  changed_when: false

- name: Store version as fact ansible.builtin.set_fact: app_version: "{{ version_output.stdout | trim }}" cacheable: true

- name: Use the version later ansible.builtin.debug: msg: "Running version {{ app_version }}"

Register with Templates

- name: Get server info
  ansible.builtin.command: uname -a
  register: uname_result
  changed_when: false

- name: Generate report ansible.builtin.template: src: report.j2 dest: /tmp/server_report.txt vars: server_info: "{{ uname_result.stdout }}"

Common Patterns

Parse JSON Output

- name: Get docker info
  ansible.builtin.command: docker info --format '{{ '{{' }}json .{{ '}}' }}'
  register: docker_info
  changed_when: false

- name: Parse JSON ansible.builtin.set_fact: docker_data: "{{ docker_info.stdout | from_json }}"

- name: Show containers ansible.builtin.debug: msg: "Running containers: {{ docker_data.ContainersRunning }}"

Conditional Task Chain

- name: Check if app is installed
  ansible.builtin.command: which myapp
  register: app_installed
  failed_when: false
  changed_when: false

- name: Install app ansible.builtin.package: name: myapp when: app_installed.rc != 0

- name: Get current version ansible.builtin.command: myapp --version register: current_version changed_when: false when: app_installed.rc == 0

- name: Upgrade if old version ansible.builtin.package: name: myapp state: latest when: - app_installed.rc == 0 - current_version.stdout is version('2.0', '<')

Common Mistakes

Using Undefined Register

# Bug: result not defined if when is false
- name: Conditional task
  ansible.builtin.command: echo "hello"
  register: result
  when: run_task | default(false)

# Fix: check if defined - name: Use result safely ansible.builtin.debug: msg: "{{ result.stdout | default('task was skipped') }}" when: result is defined and result is not skipped

Forgetting changed_when for Read-Only Commands

# Bug: always reports "changed"
- name: Check version
  ansible.builtin.command: python3 --version
  register: py_version

# Fix: mark as read-only - name: Check version ansible.builtin.command: python3 --version register: py_version changed_when: false

FAQ

What does register do in Ansible?

The register keyword saves a task's complete output (stdout, stderr, return code, changed status, and module-specific data) into a variable. You can then use this variable in subsequent tasks for conditions, templates, or debugging.

How do I access stdout from a registered variable?

Use result.stdout for the full output as a string, or result.stdout_lines for a list split by newlines: msg: "{{ result.stdout }}".

Can I register variables in a loop?

Yes, when used with loop, the registered variable contains a results list. Each item has the loop value in item.item and the task output in the usual fields (item.stdout, item.rc, etc.).

How do I check if a registered task failed?

Use when: result is failed or when: result is success. For command/shell tasks, you can also check result.rc != 0.

Does register work with all modules?

Yes, every Ansible module returns data that can be registered. The exact fields vary by module — command/shell return stdout/stderr/rc, uri returns json/status, stat returns file info, etc.

Conclusion

register is fundamental to dynamic Ansible playbooks: • Capture output: register: result on any task • Access data: result.stdout, result.rc, result.json, result.statUse in conditions: when: result is success or when: "'text' in result.stdout"Loop results: Access via result.results[].itemAlways add changed_when: false to read-only command/shell tasks

Related Articles

Ansible set_fact Module: Set Variables DynamicallyAnsible changed_when & failed_when: Control Task StatusPrint Text or Variable: Ansible debug ModuleAnsible when Conditionals: Complete Guide

Category: installation

Browse all Ansible tutorials · AnsiblePilot Home