Ansible Output — register
Facts tell you about a host before anything runs. register tells you about the result of a task you just ran — capturing it into a variable you can use for the rest of the play. This is one of the most commonly used variable sources in real playbooks, and it’s the promise made back in the playbook chapter finally paid off.
register — Capturing A Task’s Result
Attach register: name to any task, and its entire result gets stored under that name:
- name: Register Demo
hosts: servers
tasks:
- name: Get uptime
ansible.builtin.command: uptime
register: uptime_result
- name: Print the captured result
ansible.builtin.debug:
var: uptime_resultNote var: uptime_result here instead of msg: — var dumps a variable’s raw structure exactly as it is, which is the fastest way to see what’s actually inside something you’ve just registered for the first time.
ok: [ubuntu] => {
"uptime_result": {
"changed": true,
"cmd": ["uptime"],
"rc": 0,
"stdout": " 14:32:01 up 2 days, 3:14, 0 users, load average: 0.00, 0.01, 0.05",
"stderr": "",
...
}
}What’s Inside A Registered Variable?
A registered result isn’t just the command’s output — it’s a full structure, with fields like stdout, stderr, rc (return code), cmd, and changed, for a command/shell task specifically. Different modules populate somewhat different fields, which is exactly why dumping the whole thing with var: the first time you register something new is worth doing before assuming what’s inside it.
Using A Registered Result In A Later Task
Once you know the field you want, reference it directly:
- name: Print just the uptime line
ansible.builtin.debug:
msg: "System has been up for: {{ uptime_result.stdout }}"ok: [ubuntu] => {
"msg": "System has been up for: 14:32:01 up 2 days, 3:14, 0 users, load average: 0.00, 0.01, 0.05"
}Registered results are frequently combined with conditional logic — running a later task only if a registered result looks a certain way — but conditionals (when:) haven’t been covered yet in this course, so we’re stopping at capturing and printing for now. Expect to see the two paired together constantly once you get there.
A Gotcha: register Doesn’t Grant Idempotency
Registering a task’s result has nothing to do with whether that task itself is idempotent. The command task above still reports changed on every single run, exactly as covered in the idempotency chapter — register just captures whatever happened, whether that was a genuine change or not. Wrapping a command in register doesn’t make it smarter about detecting real change; that still depends entirely on which module you’re using, command/shell included.
A second detail worth knowing: a registered variable is scoped per host, not shared globally across your whole run. On a multi-host play, uptime_result genuinely holds a different value for ubuntu than it does for fedora — the same variable name, quietly holding different content depending on which host’s turn it currently is.
Best Practices
- Use
debug: var: name, notmsg:, the first time you inspect a newly registered result — you want to see its full structure before deciding which field to actually use. - Reference specific fields (
.stdout,.rc) in later tasks, rather than dumping the entire registered structure again once you know what you need. - Don’t assume
registerimplies idempotency. The underlying module’s own behavior — covered back in the playbook chapter — still determines whether a task reportschangedaccurately or unconditionally.