Keywords: Ansible | Shell Output | Playbook Debugging
Abstract: This technical article provides an in-depth analysis of obtaining clean, readable output formats when executing shell commands within Ansible Playbooks. By examining the differences between direct ansible command execution and Playbook-based approaches, it details the optimal solution using register variables and the debug module with stdout_lines attribute, effectively resolving issues with lost newlines and messy dictionary structures in Playbook output for system monitoring and operational tasks.
Problem Background and Challenges
In automated operations scenarios, Ansible as a mainstream configuration management tool frequently requires executing system monitoring commands to gather host status information. Users typically employ commands like ps -eo pcpu,user,args | sort -r -k1 | head -n5 to monitor processes with highest CPU utilization. Direct usage of the ansible command-line tool perfectly outputs formatted results:
localhost | success | rc=0 >>
0.0 root /sbin/init
0.0 root [kthreadd]
0.0 root [ksoftirqd/0]
0.0 root [migration/0]However, when migrating the same command to Playbook execution, the output becomes difficult to read:
changed: [localhost] => {"changed": true, "cmd": "ps -eo pcpu,user,args | sort -r -k1 head -n5 ", "delta": "0:00:00.015337", "end": "2013-12-13 10:57:25.680708", "rc": 0, "start": "2013-12-13 10:57:25.665371", "stderr": "", "stdout": "47.3 xxx Xvnc4 :24 -desktop xxx:24 (xxx) -auth /home/xxx/.Xauthority -geometry 1920x1200\n...."Core Solution
Through in-depth analysis of Ansible module working principles, we identify the root cause lies in Playbook's default output format handling mechanism. When using the shell module to execute commands, the returned result is a dictionary object containing complete execution information, where the stdout field stores the command's standard output content, but this field converts newlines into \n escape characters, causing formatting issues during direct output.
The optimal solution leverages Ansible's variable registration functionality and specific attributes of the debug module:
- hosts: all
gather_facts: no
tasks:
- shell: ps -eo pcpu,user,args | sort -r -k1 | head -n5
register: ps
- debug: var=ps.stdout_linesTechnical Principle Analysis
The register keyword saves the shell module's execution result to a specified variable, which contains several important fields:
stdout: Raw standard output stringstdout_lines: Line-separated list formatstderr: Standard error outputrc: Return code
The key advantage of the stdout_lines attribute is its automatic splitting of output content into a Python list based on newline characters, with each list element corresponding to one line of original output. When outputting this attribute using the debug module, Ansible displays the list content in a structured manner, preserving the original line formatting.
Practical Application Results
After implementing this solution, the output format shows significant improvement:
ok: [host1] => {
"ps.stdout_lines": [
"%CPU USER COMMAND",
" 1.0 root /usr/bin/python",
" 0.6 root sshd: root@notty ",
" 0.2 root java",
" 0.0 root sort -r -k1"
]
}This format not only preserves the original layout of command output but also provides clear hierarchical structure for quick identification of key information.
Extended Application Scenarios
This technical approach can be widely applied to various system monitoring scenarios:
- Process monitoring: Combining
ps,topand other commands for real-time system resource monitoring - Performance analysis: Using
dstat,iostatand other tools to collect performance metrics - Log inspection: Filtering critical log information through
grep,tailand other commands - Configuration verification: Executing specific commands to validate system configuration status
By reasonably combining different Shell commands and output processing techniques, powerful automated monitoring systems can be constructed.
Best Practice Recommendations
In actual production environments, we recommend following these best practices:
- For critical monitoring tasks, always use the
registerandstdout_linescombination to ensure output readability - Add appropriate error handling logic in Playbooks, checking the
rcreturn code - For complex outputs, consider preprocessing with tools like
sed,awk - Consider using
lineinfileorcopymodules to save important outputs to files
The advantage of this method lies in maintaining the elegance of Ansible's declarative configuration while providing necessary flexibility to handle command-line tool output format requirements.