When it comes to Ansible automation, registers allow you to capture and store outputs from shell commands, status messages, or a return code for later use in your playbook. An Ansible register provides a reliable way to store repeatable, reusable, and simple configuration management for a multi machine deployment mechanism, ideal for complicated applications.
By registering the task result, it gets easier for you to make real time decisions for executing data. Whether you’re working with shell commands, API responses, or module outputs, register makes your playbooks smarter, more adaptive, and context-aware.
Why Use register in Playbooks
Ansible register is crucial when you want to save task outputs and use them later on in your playbook. It allows you easy automation to adapt based on real-world conditions by storing data, such as:
- Command output (stdout, stderr)
- Return codes (rc)
- Execution status (changed, failed)
This is especially useful for:
- Running conditional tasks based on command results
- Debugging and logging
- Creating branching logic in workflows
- Reusing outputs without repeating expensive tasks
With register, your playbooks become more intelligent, reactive, and efficient.
Basic Syntax and Usage
Here’s how register is typically used:
Get exclusive access to all things tech-savvy, and be the first to receive
the latest updates directly in your inbox.
– name: Check if nginx is installed
command: which nginx
register: nginx_check
This stores the result of the nginx command in a variable called nginx_check. You can then reference parts of it like:
- nginx_check.stdout – The output of the command
- nginx_check.rc – The return code
- nginx_check.changed – Boolean indicating if the task made a change
Example With Conditional Logic:
– name: Restart nginx if installed
service:
name: nginx
state: restarted
when: nginx_check.rc == 0

This task only runs if nginx was found on the system (rc == 0).
Accessing Registered Variables
Once you have saved an output in using the register keyword, it is stored in a structured variable. These variables hold multiple different attributes that you can access in later tasks.
Attribute | Description |
stdout | The standard output of the command (as a single string) |
stdout_lines | The same output, split into a list of lines |
stderr | The error output (if any) |
rc | The return code of the task |
changed | Boolean indicating if the task made changes |
failed | Boolean indicating if the task failed |
Access Example:
– debug:
msg: “Nginx path is: {{ nginx_check.stdout }}”
You can use these attributes in when conditions, debug tasks, or even to define other variables using set_fact.
Examples of Ansible register in Action
- Registering Command Output
– name: Get the current user
command: whoami
register: current_user
– name: Show the user
debug:
msg: “This playbook is running as: {{ current_user.stdout }}”
- Using register with shell and Parsing Output
– name: Check available disk space
shell: df -h / | awk ‘NR==2 {print $5}’
register: disk_usage
– name: Warn if disk usage is above 80%
debug:
msg: “Warning: High disk usage – {{ disk_usage.stdout }}”
when: disk_usage.stdout | regex_replace(‘%’,”) | int > 80
- Conditional Task Based on Command Output
– name: Check if apache2 is running
shell: pgrep apache2
register: apache_status
ignore_errors: yes
– name: Restart Apache if running
service:
name: apache2
state: restarted
when: apache_status.rc == 0
Working with Complex Output (stdout, stderr, rc)
Structured dictionary is extremely useful when the command or the module produces complex output that you want to parse or use in decisions, for example:
Task:
– name: Run a shell script
shell: ./health_check.sh
register: health_output
Now health_output contains:
- stdout: The main output (e.g., status report)
- stderr: Error messages (if any)
- rc: Return code (0 = success, non-zero = error)
- changed: Boolean that reflects if changes occurred
- failed: True if the task failed
Accessing the values:
– name: Show the script result
debug:
msg:
– “Output: {{ health_output.stdout }}”
– “Errors: {{ health_output.stderr }}”
– “Exit Code: {{ health_output.rc }}”
This gives a full view of what happened during the task.
Handling Lists and Dictionaries from Output
Some tasks, such as those that require using modules like uri, command -json, or setup, return lists or dictionaries. You can access these nested structures very easily in your playbooks.
Example: Register JSON Output
– name: Get user details in JSON
shell: cat user_info.json
register: user_json
changed_when: false
Assuming the JSON is:
{
“name”: “admin”,
“roles”: [“sysadmin”, “devops”]
}
You can parse it using from_json:
– set_fact:
user_data: “{{ user_json.stdout | from_json }}”
– debug:
msg: “Username: {{ user_data.name }}, Role 1: {{ user_data.roles[0] }}”
Example: Looping Over Output Lines
– name: List all users
command: cut -d: -f1 /etc/passwd
register: users
– name: Show each user
debug:
msg: “{{ item }}”
loop: “{{ users.stdout_lines }}”
Common Use Cases for Ansible register
There are multiple use cases for using Ansible registers. To give you an idea, here are some of the most common ones.
- Check if a Package is Installed
You can use an Ansible register to capture the result of a check, then perform actions based on it.
– name: Check if nginx is installed
shell: dpkg -l | grep nginx
register: nginx_installed
ignore_errors: true
– name: Install nginx if not present
apt:
name: nginx
state: present
when: nginx_installed.rc != 0
Explanation: The return code shows us if the package was found and if not, then we shall proceed with the installation.
- Capture and Reuse API Response
Register results from an API call and use the response data later.
– name: Get user details from API
uri:
url: “https://api.example.com/users/1”
method: GET
return_content: yes
register: api_response
– name: Parse and use the user name
set_fact:
user_data: “{{ api_response.json }}”
– name: Show username
debug:
msg: “Username is {{ user_data.name }}”
Explanation: The output that the uri module shows includes json, which you can directly access from the registered variable.
- Conditionally Restart Services
Only restart a service if a config file was changed.
– name: Update nginx config
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
register: config_result
– name: Restart nginx if config changed
service:
name: nginx
state: restarted
when: config_result.changed
Explanation: Ansible sets changed to true if the template task made changes, which we use to decide if the service needs to be reset.
Best Practices When Using register in Ansible
An Ansible register is super easy to manage, however, these best practices will help you even more:
- Don’t register outputs unless you plan on using them later on. Unnecessarily storing them will increase memory usage and make logs noisy.
- Use ignore_errors: true when a failure is expected and pair it with conditionals like when: result.rc != 0.
- Check result.rc instead of assuming success based on stdout. when: result.rc == 0
- Use changed_when: false for Read-Only Tasks
- Know Your Output Structure
Use:
- stdout for raw text output
- stdout_lines for lists (line-by-line)
- json for API results from the uri module
- Use debug to view registered variables for troubleshooting.
– debug:
var: result
Troubleshooting Ansible Register Issues
Issue | Cause | Solution |
undefined variableerror | Trying to use a registered variable before it’s created | Ensure the task that sets the variable runs before the one using it |
stdout is empty | The command didn’t return any output | Check the command syntax and add debug to inspect output |
Task marked as “changed” unexpectedly | Registered task returns output even though nothing changed | Use changed_when: false to override the change status |
Task fails but you want to continue | The task returns non-zero exit code | Add ignore_errors: true and handle the result with conditionals |
Cannot parse output as JSON | Using json filter on invalid format | Ensure the command returns proper JSON or wrap it with ` |
Confusion between stdout and stdout_lines | Using the wrong structure in loops or templates | Use stdout_lines for iterating, stdout for full string |
Wrapping Up – Managing An Ansible Register
The Ansible register is a powerful tool that allows you to capture and reuse tasks results dynamically. Make sure to use it purposefully, understand the structure, and debug effectively. Using smart use of Ansible register, you can build more responsive and intelligent automation workflows that adapt in real time.
Can I use registered variables across different plays?
By default, registered variables are available only within the play they were created. To pass them across plays, you’ll need to use facts or write them to a file.
Can I register multiple outputs in a single Ansible task?
No, each register
captures the output of only one task. However, you can use structured outputs like dictionaries or lists to handle complex data.
What is the register
keyword in Ansible?
The register
keyword in Ansible is used to capture the output or result of a task and save it to a variable for use later in the playbook.