如何在Ansible剧本中显示shell命令的输出

AnsibleAnsibleBeginner
立即练习

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

Introduction

Ansible is a powerful open-source automation tool widely used by system administrators and DevOps professionals. One of its key capabilities is running shell commands on remote hosts and processing their output. In this hands-on tutorial, you will learn how to effectively capture, display, and process the output of shell commands in Ansible playbooks. This skill is essential for creating robust automation workflows that can adapt to different system conditions and provide useful feedback.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL ansible(("Ansible")) -.-> ansible/ModuleOperationsGroup(["Module Operations"]) ansible/ModuleOperationsGroup -.-> ansible/command("Execute Commands") ansible/ModuleOperationsGroup -.-> ansible/debug("Test Output") ansible/ModuleOperationsGroup -.-> ansible/shell("Execute Shell Commands") subgraph Lab Skills ansible/command -.-> lab-415017{{"如何在Ansible剧本中显示shell命令的输出"}} ansible/debug -.-> lab-415017{{"如何在Ansible剧本中显示shell命令的输出"}} ansible/shell -.-> lab-415017{{"如何在Ansible剧本中显示shell命令的输出"}} end

Setting Up Your First Ansible Playbook with Shell Commands

In this step, we will set up a basic Ansible playbook that executes shell commands and captures their output. This will provide the foundation for more advanced techniques in later steps.

Installing Ansible

First, let's install Ansible on our system:

sudo apt update
sudo apt install -y ansible

Now, verify that Ansible is installed correctly:

ansible --version

You should see output similar to this:

ansible [core 2.12.x]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/labex/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3/dist-packages/ansible
  ansible collection location = /home/labex/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible
  python version = 3.10.x (default, Mar 15 2022, 12:22:08) [GCC 11.2.0]
  jinja version = 3.0.3
  libyaml = True

Creating an Inventory File

Ansible uses an inventory file to know which hosts to manage. For this lab, we'll create a simple inventory that includes only the local machine:

  1. Open your WebIDE and create a new file called inventory.ini in the /home/labex/project directory.
  2. Add the following content to the file:
[local]
localhost ansible_connection=local

This inventory defines a group called local that contains just the localhost, and tells Ansible to connect directly without SSH.

Creating Your First Playbook

Now, let's create a simple playbook that executes shell commands:

  1. Create a new file called first_playbook.yml in the /home/labex/project directory.
  2. Add the following YAML content to the file:
---
- name: Shell Command Example
  hosts: local
  gather_facts: no

  tasks:
    - name: Run a simple shell command
      shell: echo "Hello from Ansible shell command"
      register: hello_output

    - name: Display the output
      debug:
        msg: "{{ hello_output.stdout }}"

This playbook does the following:

  • Targets the local group we defined in our inventory
  • Skips gathering facts (system information) to keep things simple
  • Runs a shell command that echoes a greeting message
  • Stores the output in a variable using the register keyword
  • Displays the output using the debug module

Running Your Playbook

Now let's run the playbook:

ansible-playbook -i inventory.ini first_playbook.yml

You should see output similar to this:

PLAY [Shell Command Example] **************************************************

TASK [Run a simple shell command] *********************************************
changed: [localhost]

TASK [Display the output] *****************************************************
ok: [localhost] => {
    "msg": "Hello from Ansible shell command"
}

PLAY RECAP ********************************************************************
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

The output shows that our playbook ran successfully, executing the shell command and displaying its output.

Key Concepts to Understand

From this exercise, note these important concepts:

  1. The shell module allows you to run shell commands
  2. The register directive captures the output of a task into a variable
  3. The debug module helps display variable values
  4. Shell command output contains both stdout (standard output) and stderr (error output)

In the next step, we'll explore how to process and format shell command output more effectively.

Working with Structured Shell Command Output

Now that you understand the basics of executing shell commands in Ansible, let's explore how to work with structured command output and display it in different formats.

Processing System Information

Let's create a more practical playbook that gathers system information and presents it in a structured way:

  1. Create a new file called system_info.yml in the /home/labex/project directory.
  2. Add the following content:
---
- name: Gather and Display System Information
  hosts: local
  gather_facts: no

  tasks:
    - name: Gather system information
      shell: |
        echo "OS Information: $(cat /etc/os-release | grep PRETTY_NAME | cut -d= -f2)"
        echo "Kernel Version: $(uname -r)"
        echo "CPU Information: $(grep "model name" /proc/cpuinfo | head -1 | cut -d: -f2 | xargs)"
        echo "Memory Information: $(free -h | grep Mem | awk '{print $2}')"
      register: system_info

    - name: Display raw system information
      debug:
        msg: "{{ system_info.stdout }}"

    - name: Display information as a list
      debug:
        msg: "{{ system_info.stdout_lines }}"

This playbook:

  • Executes a multi-line shell script that gathers various system details
  • Stores the output in the system_info variable
  • Displays the output first as a raw string and then as a list of lines

Run the playbook:

ansible-playbook -i inventory.ini system_info.yml

You should see output that looks like this:

PLAY [Gather and Display System Information] **********************************

TASK [Gather system information] **********************************************
changed: [localhost]

TASK [Display raw system information] *****************************************
ok: [localhost] => {
    "msg": "OS Information: \"Ubuntu 22.04.1 LTS\"\nKernel Version: 5.15.0-1023-azure\nCPU Information: Intel(R) Xeon(R) Platinum 8171M CPU @ 2.60GHz\nMemory Information: 4.0Gi"
}

TASK [Display information as a list] *****************************************
ok: [localhost] => {
    "msg": [
        "OS Information: \"Ubuntu 22.04.1 LTS\"",
        "Kernel Version: 5.15.0-1023-azure",
        "CPU Information: Intel(R) Xeon(R) Platinum 8171M CPU @ 2.60GHz",
        "Memory Information: 4.0Gi"
    ]
}

PLAY RECAP ********************************************************************
localhost                  : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Notice how the second display task shows the output as a list instead of a string with newlines. This list format makes it easier to work with multi-line output.

Working with Command Results and Return Codes

Shell commands in Linux return exit codes to indicate success (0) or failure (non-zero). Ansible captures these in the rc (return code) attribute of the registered variable.

Let's create a playbook that demonstrates how to work with return codes:

  1. Create a new file called command_results.yml in the /home/labex/project directory.
  2. Add the following content:
---
- name: Working with Command Results
  hosts: local
  gather_facts: no

  tasks:
    - name: Check if a file exists
      shell: test -f /etc/hosts
      register: file_check
      ignore_errors: yes

    - name: Show command result details
      debug:
        msg: |
          Return code: {{ file_check.rc }}
          Succeeded: {{ file_check.rc == 0 }}
          Failed: {{ file_check.rc != 0 }}

    - name: Check if a non-existent file exists
      shell: test -f /file/does/not/exist
      register: missing_file
      ignore_errors: yes

    - name: Show command result for missing file
      debug:
        msg: |
          Return code: {{ missing_file.rc }}
          Succeeded: {{ missing_file.rc == 0 }}
          Failed: {{ missing_file.rc != 0 }}

This playbook:

  • Runs two test commands to check if files exist
  • Uses ignore_errors: yes to prevent the playbook from stopping if a command fails
  • Displays detailed command result information, including the return code and success/failure status

Run the playbook:

ansible-playbook -i inventory.ini command_results.yml

You should see output similar to this:

PLAY [Working with Command Results] *******************************************

TASK [Check if a file exists] *************************************************
changed: [localhost]

TASK [Show command result details] ********************************************
ok: [localhost] => {
    "msg": "Return code: 0\nSucceeded: True\nFailed: False\n"
}

TASK [Check if a non-existent file exists] ************************************
fatal: [localhost]: FAILED! => {"changed": true, "cmd": "test -f /file/does/not/exist", "delta": "0:00:00.003183", "end": "2023-07-14 15:24:33.931406", "msg": "non-zero return code", "rc": 1, "start": "2023-07-14 15:24:33.928223", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
...ignoring

TASK [Show command result for missing file] ***********************************
ok: [localhost] => {
    "msg": "Return code: 1\nSucceeded: False\nFailed: True\n"
}

PLAY RECAP ********************************************************************
localhost                  : ok=4    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=1

Notice how the return code is 0 for the existing file and 1 for the non-existent file. This demonstrates how you can use return codes to make decisions in your playbooks.

Understanding The Registered Variable Structure

The variable registered from a shell command contains several useful attributes:

  • stdout: The standard output as a single string
  • stdout_lines: The standard output split into a list of lines
  • stderr: The standard error output as a single string
  • stderr_lines: The standard error output split into a list of lines
  • rc: The return code (0 for success, non-zero for failure)
  • cmd: The command that was executed
  • start and end: Timestamps for when the command started and finished
  • delta: The duration of the command execution

Understanding this structure is crucial for effectively working with shell command output in Ansible.

Conditional Execution Based on Shell Output

One of the most powerful capabilities in Ansible is the ability to make decisions based on the output of shell commands. In this step, we'll learn how to use conditions and filters to process shell command output and make playbooks more dynamic.

Using Conditions with Shell Output

Let's create a playbook that makes decisions based on shell command output:

  1. Create a new file called conditional_playbook.yml in the /home/labex/project directory.
  2. Add the following content:
---
- name: Conditional Tasks Based on Command Output
  hosts: local
  gather_facts: no

  tasks:
    - name: Check disk space
      shell: df -h / | grep -v Filesystem | awk '{print $5}' | sed 's/%//'
      register: disk_usage

    - name: Display disk usage
      debug:
        msg: "Current disk usage: {{ disk_usage.stdout }}%"

    - name: Disk usage warning
      debug:
        msg: "WARNING: Disk usage is high"
      when: disk_usage.stdout|int > 50

    - name: Disk usage normal
      debug:
        msg: "Disk usage is normal"
      when: disk_usage.stdout|int <= 50

This playbook:

  • Runs a shell command to check disk usage percentage on the root filesystem
  • Uses the when conditional based on the command output
  • Uses the int filter to convert the string output to an integer for comparison

Run the playbook:

ansible-playbook -i inventory.ini conditional_playbook.yml

The output will vary depending on your actual disk usage, but will look something like this:

PLAY [Conditional Tasks Based on Command Output] ******************************

TASK [Check disk space] *******************************************************
changed: [localhost]

TASK [Display disk usage] *****************************************************
ok: [localhost] => {
    "msg": "Current disk usage: 38%"
}

TASK [Disk usage warning] *****************************************************
skipped: [localhost]

TASK [Disk usage normal] ******************************************************
ok: [localhost] => {
    "msg": "Disk usage is normal"
}

PLAY RECAP ********************************************************************
localhost                  : ok=3    changed=1    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0

Notice how Ansible executed only one of the conditional tasks based on the actual disk usage value.

Handling JSON Output from Commands

Many modern CLI tools return data in JSON format. Ansible has built-in capabilities to handle JSON output:

  1. Create a new file called json_output.yml in the /home/labex/project directory.
  2. Add the following content:
---
- name: Handling JSON Output
  hosts: local
  gather_facts: no

  tasks:
    - name: Create a JSON file for testing
      copy:
        dest: /tmp/services.json
        content: |
          {
            "services": [
              {
                "name": "web",
                "status": "running",
                "port": 80
              },
              {
                "name": "database",
                "status": "stopped",
                "port": 5432
              },
              {
                "name": "cache",
                "status": "running",
                "port": 6379
              }
            ]
          }

    - name: Read JSON file with shell
      shell: cat /tmp/services.json
      register: json_output

    - name: Parse and display JSON content
      debug:
        msg: "{{ json_output.stdout | from_json }}"

    - name: Extract and display service information
      debug:
        msg: "Service: {{ item.name }}, Status: {{ item.status }}, Port: {{ item.port }}"
      loop: "{{ (json_output.stdout | from_json).services }}"

    - name: Show only running services
      debug:
        msg: "Running service: {{ item.name }} on port {{ item.port }}"
      loop: "{{ (json_output.stdout | from_json).services }}"
      when: item.status == "running"

This playbook:

  • Creates a sample JSON file for demonstration
  • Reads the JSON file with a shell command
  • Uses the from_json filter to parse the JSON string into a data structure
  • Loops through the data structure to display information
  • Uses conditional logic to filter only running services

Run the playbook:

ansible-playbook -i inventory.ini json_output.yml

You should see output similar to this:

PLAY [Handling JSON Output] ***************************************************

TASK [Create a JSON file for testing] *****************************************
changed: [localhost]

TASK [Read JSON file with shell] **********************************************
changed: [localhost]

TASK [Parse and display JSON content] *****************************************
ok: [localhost] => {
    "msg": {
        "services": [
            {
                "name": "web",
                "port": 80,
                "status": "running"
            },
            {
                "name": "database",
                "port": 5432,
                "status": "stopped"
            },
            {
                "name": "cache",
                "port": 6379,
                "status": "running"
            }
        ]
    }
}

TASK [Extract and display service information] ********************************
ok: [localhost] => (item={'name': 'web', 'status': 'running', 'port': 80}) => {
    "msg": "Service: web, Status: running, Port: 80"
}
ok: [localhost] => (item={'name': 'database', 'status': 'stopped', 'port': 5432}) => {
    "msg": "Service: database, Status: stopped, Port: 5432"
}
ok: [localhost] => (item={'name': 'cache', 'status': 'running', 'port': 6379}) => {
    "msg": "Service: cache, Status: running, Port: 6379"
}

TASK [Show only running services] *********************************************
ok: [localhost] => (item={'name': 'web', 'status': 'running', 'port': 80}) => {
    "msg": "Running service: web on port 80"
}
skipped: [localhost] => (item={'name': 'database', 'status': 'stopped', 'port': 5432})
ok: [localhost] => (item={'name': 'cache', 'status': 'running', 'port': 6379}) => {
    "msg": "Running service: cache on port 6379"
}

PLAY RECAP ********************************************************************
localhost                  : ok=5    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Notice how the playbook parses the JSON, extracts specific information, and filters the data based on conditions.

Error Handling with Shell Commands

When running shell commands, it's important to handle potential errors gracefully:

  1. Create a new file called error_handling.yml in the /home/labex/project directory.
  2. Add the following content:
---
- name: Error Handling with Shell Commands
  hosts: local
  gather_facts: no

  tasks:
    - name: Run a potentially failing command
      shell: grep "nonexistent_pattern" /etc/passwd
      register: command_result
      ignore_errors: yes

    - name: Display success or failure
      debug:
        msg: "Command {{ 'succeeded' if command_result.rc == 0 else 'failed with return code ' + command_result.rc|string }}"

    - name: Run a custom failing command
      shell: exit 3
      register: exit_command
      ignore_errors: yes

    - name: Display detailed error information
      debug:
        msg: |
          Return code: {{ exit_command.rc }}
          Error message: {{ exit_command.stderr if exit_command.stderr else 'No error message' }}

This playbook:

  • Runs commands that are expected to fail
  • Uses ignore_errors: yes to continue the playbook execution even when commands fail
  • Shows different methods for handling and displaying error information

Run the playbook:

ansible-playbook -i inventory.ini error_handling.yml

You should see output similar to this:

PLAY [Error Handling with Shell Commands] *************************************

TASK [Run a potentially failing command] **************************************
fatal: [localhost]: FAILED! => {"changed": true, "cmd": "grep \"nonexistent_pattern\" /etc/passwd", "delta": "0:00:00.002916", "end": "2023-07-14 16:10:23.671519", "msg": "non-zero return code", "rc": 1, "start": "2023-07-14 16:10:23.668603", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
...ignoring

TASK [Display success or failure] *********************************************
ok: [localhost] => {
    "msg": "Command failed with return code 1"
}

TASK [Run a custom failing command] *******************************************
fatal: [localhost]: FAILED! => {"changed": true, "cmd": "exit 3", "delta": "0:00:00.002447", "end": "2023-07-14 16:10:23.906121", "msg": "non-zero return code", "rc": 3, "start": "2023-07-14 16:10:23.903674", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
...ignoring

TASK [Display detailed error information] *************************************
ok: [localhost] => {
    "msg": "Return code: 3\nError message: No error message\n"
}

PLAY RECAP ********************************************************************
localhost                  : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=2

This demonstrates how to capture and respond to different error conditions when running shell commands.

Creating a Practical Shell Output Processing Tool

In this final step, we'll bring together everything we've learned to create a practical Ansible playbook that collects system information, processes it, and generates a report. This represents a real-world scenario where Ansible's shell command processing capabilities can be extremely useful.

Building a System Information Report Tool

Let's create a comprehensive system information gathering tool:

  1. Create a new file called system_report.yml in the /home/labex/project directory.
  2. Add the following content:
---
- name: Comprehensive System Report
  hosts: local
  gather_facts: no

  vars:
    report_file: /tmp/system_report.txt

  tasks:
    - name: Collect basic system information
      shell: |
        echo "SYSTEM REPORT" > {{ report_file }}
        echo "=============" >> {{ report_file }}
        echo "" >> {{ report_file }}

        echo "HOSTNAME: $(hostname)" >> {{ report_file }}
        echo "TIMESTAMP: $(date)" >> {{ report_file }}
        echo "" >> {{ report_file }}

        echo "SYSTEM INFORMATION" >> {{ report_file }}
        echo "------------------" >> {{ report_file }}
        echo "OS: $(cat /etc/os-release | grep PRETTY_NAME | cut -d= -f2)" >> {{ report_file }}
        echo "KERNEL: $(uname -r)" >> {{ report_file }}
        echo "UPTIME: $(uptime -p)" >> {{ report_file }}
        echo "" >> {{ report_file }}

        echo "RESOURCE UTILIZATION" >> {{ report_file }}
        echo "-------------------" >> {{ report_file }}
        echo "CPU LOAD: $(uptime | awk -F'load average:' '{print $2}')" >> {{ report_file }}
        echo "MEMORY USAGE:" >> {{ report_file }}
        free -h >> {{ report_file }}
        echo "" >> {{ report_file }}
        echo "DISK USAGE:" >> {{ report_file }}
        df -h >> {{ report_file }}
        echo "" >> {{ report_file }}

        echo "NETWORK INFORMATION" >> {{ report_file }}
        echo "-------------------" >> {{ report_file }}
        echo "IP ADDRESSES:" >> {{ report_file }}
        ip addr | grep "inet " | awk '{print $2}' >> {{ report_file }}
        echo "" >> {{ report_file }}

        echo "PROCESS INFORMATION" >> {{ report_file }}
        echo "-------------------" >> {{ report_file }}
        echo "TOP 5 CPU CONSUMING PROCESSES:" >> {{ report_file }}
        ps aux --sort=-%cpu | head -6 >> {{ report_file }}
        echo "" >> {{ report_file }}
        echo "TOP 5 MEMORY CONSUMING PROCESSES:" >> {{ report_file }}
        ps aux --sort=-%mem | head -6 >> {{ report_file }}
      register: report_generation

    - name: Check if report was generated successfully
      stat:
        path: "{{ report_file }}"
      register: report_stat

    - name: Display report generation status
      debug:
        msg: "Report generated successfully at {{ report_file }}"
      when: report_stat.stat.exists

    - name: Display report content
      shell: cat {{ report_file }}
      register: report_content
      when: report_stat.stat.exists

    - name: Show report content
      debug:
        msg: "{{ report_content.stdout_lines }}"
      when: report_stat.stat.exists

    - name: Analyze disk usage
      shell: df -h / | grep -v Filesystem | awk '{print $5}' | sed 's/%//'
      register: disk_usage
      when: report_stat.stat.exists

    - name: Generate disk usage alert if needed
      debug:
        msg: "ALERT: Disk usage on / is {{ disk_usage.stdout }}% which exceeds the 80% threshold!"
      when:
        - report_stat.stat.exists
        - disk_usage.stdout|int > 80

    - name: Generate disk usage warning if needed
      debug:
        msg: "WARNING: Disk usage on / is {{ disk_usage.stdout }}% which exceeds the 60% threshold."
      when:
        - report_stat.stat.exists
        - disk_usage.stdout|int > 60
        - disk_usage.stdout|int <= 80

    - name: Confirm normal disk usage
      debug:
        msg: "Disk usage on / is normal at {{ disk_usage.stdout }}%."
      when:
        - report_stat.stat.exists
        - disk_usage.stdout|int <= 60

This playbook:

  • Collects comprehensive system information using a series of shell commands
  • Writes the information to a report file
  • Verifies the report was created successfully
  • Displays the content of the report
  • Analyzes the disk usage data
  • Generates appropriate alerts based on the analysis

Run the playbook:

ansible-playbook -i inventory.ini system_report.yml

You'll see comprehensive output showing the playbook execution and the full system report. The output is quite long, so here's just a sample of what you might see:

PLAY [Comprehensive System Report] ********************************************

TASK [Collect basic system information] ***************************************
changed: [localhost]

TASK [Check if report was generated successfully] *****************************
ok: [localhost]

TASK [Display report generation status] ***************************************
ok: [localhost] => {
    "msg": "Report generated successfully at /tmp/system_report.txt"
}

TASK [Display report content] *************************************************
changed: [localhost]

TASK [Show report content] ****************************************************
ok: [localhost] => {
    "msg": [
        "SYSTEM REPORT",
        "=============",
        "",
        "HOSTNAME: ubuntu-vm",
        "TIMESTAMP: Fri Jul 14 16:35:42 UTC 2023",
        "",
        "SYSTEM INFORMATION",
        "------------------",
        "OS: \"Ubuntu 22.04.1 LTS\"",
        "KERNEL: 5.15.0-1023-azure",
        "UPTIME: up 3 hours, 25 minutes",
        ...

Examining the Report

Let's examine the system report we generated:

cat /tmp/system_report.txt

This will display the full report that was generated by our playbook.

Creating a Custom Shell Script and Calling It from Ansible

For more complex operations, it's sometimes easier to create a dedicated shell script and call it from Ansible:

  1. Create a new file called disk_analyzer.sh in the /home/labex/project directory.
  2. Add the following content:
#!/bin/bash

## disk_analyzer.sh - A simple script to analyze disk usage

echo "DISK USAGE ANALYSIS"
echo "------------------"

## Get overall disk usage
ROOT_USAGE=$(df -h / | grep -v Filesystem | awk '{print $5}' | sed 's/%//')
echo "Root filesystem usage: ${ROOT_USAGE}%"

## Categorize the usage
if [ $ROOT_USAGE -gt 80 ]; then
  echo "STATUS: CRITICAL - Immediate action required"
elif [ $ROOT_USAGE -gt 60 ]; then
  echo "STATUS: WARNING - Consider cleaning up disk space"
else
  echo "STATUS: OK - Disk usage is within normal parameters"
fi

echo ""

## Find largest directories
echo "Top 5 largest directories in /var:"
du -h /var --max-depth=1 2> /dev/null | sort -hr | head -5

echo ""

## Find largest files
echo "Top 5 largest files in /var/log:"
find /var/log -type f -exec du -h {} \; 2> /dev/null | sort -hr | head -5

exit 0
  1. Make the script executable:
chmod +x /home/labex/project/disk_analyzer.sh
  1. Create a new playbook to call this script:
touch /home/labex/project/call_script.yml
  1. Add the following content to the playbook:
---
- name: Call Custom Shell Script
  hosts: local
  gather_facts: no

  tasks:
    - name: Run disk analyzer script
      shell: /home/labex/project/disk_analyzer.sh
      register: script_output

    - name: Display script output
      debug:
        msg: "{{ script_output.stdout_lines }}"

    - name: Check for critical status
      debug:
        msg: "CRITICAL DISK USAGE DETECTED! Immediate action required."
      when: script_output.stdout is search("STATUS: CRITICAL")
  1. Run the playbook:
ansible-playbook -i inventory.ini call_script.yml

You should see output similar to this:

PLAY [Call Custom Shell Script] ***********************************************

TASK [Run disk analyzer script] ***********************************************
changed: [localhost]

TASK [Display script output] **************************************************
ok: [localhost] => {
    "msg": [
        "DISK USAGE ANALYSIS",
        "------------------",
        "Root filesystem usage: 38%",
        "STATUS: OK - Disk usage is within normal parameters",
        "",
        "Top 5 largest directories in /var:",
        "60M\t/var/lib",
        "60M\t/var/cache",
        "12M\t/var/log",
        "4.0K\t/var/tmp",
        "4.0K\t/var/mail",
        "",
        "Top 5 largest files in /var/log:",
        "4.0M\t/var/log/journal/c75af53674ce472fb9654a1d5cf8cc37/system.journal",
        "2.3M\t/var/log/auth.log",
        "1.3M\t/var/log/syslog",
        "724K\t/var/log/kern.log",
        "428K\t/var/log/cloud-init.log"
    ]
}

TASK [Check for critical status] **********************************************
skipped: [localhost]

PLAY RECAP ********************************************************************
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0

This approach combines the power of shell scripts with Ansible's automation capabilities. The shell script handles the complex logic for disk analysis, while Ansible manages the execution and further processing of the results.

Key Takeaways

Through this lab, you've learned several important techniques for working with shell command output in Ansible:

  1. How to execute shell commands and capture their output
  2. How to process and format command output for display
  3. How to use conditional execution based on command results
  4. How to handle JSON output and error conditions
  5. How to create practical tools that combine shell commands with Ansible's automation capabilities

These skills will be invaluable as you build more complex automation solutions with Ansible.

Summary

In this lab, you learned how to effectively work with shell command output in Ansible playbooks. Starting with the basics of executing shell commands and capturing their output, you progressed to more advanced techniques like conditional execution, error handling, and processing structured data formats like JSON.

You've mastered several key skills:

  • Running shell commands in Ansible playbooks using the shell module
  • Capturing command output with the register directive
  • Displaying output using the debug module
  • Processing output with Jinja2 filters and conditionals
  • Creating practical automation tools that combine Ansible with shell scripts

These techniques enable you to create more dynamic and responsive automation workflows that can adapt to different system conditions and provide useful feedback about the operations being performed.

As you continue your Ansible journey, remember that while shell commands provide great flexibility, Ansible's built-in modules are often a more robust and portable solution for common tasks. Use shell commands when you need to leverage existing shell scripts or perform complex operations that aren't easily handled by Ansible modules.