Ansible プレイブックでシェルコマンドの出力を表示する方法

AnsibleAnsibleIntermediate
オンラインで実践に進む

💡 このチュートリアルは英語版からAIによって翻訳されています。原文を確認するには、 ここをクリックしてください

はじめに

Ansible は、システム管理者や DevOps プロフェッショナルに広く利用されている、強力なオープンソースの自動化ツールです。その主要な機能の 1 つは、リモートホスト上でシェルコマンドを実行し、その出力を処理することです。この実践的なチュートリアルでは、Ansible プレイブックでシェルコマンドの出力を効果的にキャプチャ、表示、処理する方法を学びます。このスキルは、さまざまなシステムの状態に適応し、有用なフィードバックを提供する堅牢な自動化ワークフローを作成するために不可欠です。

これは Guided Lab です。学習と実践を支援するためのステップバイステップの指示を提供します。各ステップを完了し、実践的な経験を積むために、指示に注意深く従ってください。過去のデータによると、この 中級 レベルの実験の完了率は 53%です。学習者から 100% の好評価を得ています。

シェルコマンドを使用した最初の Ansible プレイブックの設定

このステップでは、シェルコマンドを実行し、その出力をキャプチャする基本的な Ansible プレイブックを設定します。これは、後のステップでより高度なテクニックの基礎となります。

Ansible のインストール

まず、システムに Ansible をインストールしましょう。

sudo apt update
sudo apt install -y ansible

次に、Ansible が正しくインストールされていることを確認します。

ansible --version

次のような出力が表示されるはずです。

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

インベントリファイルの作成

Ansible は、管理するホストを知るためにインベントリファイルを使用します。この実験(Lab)では、ローカルマシンのみを含むシンプルなインベントリを作成します。

  1. WebIDE を開き、/home/labex/project ディレクトリに inventory.ini という名前の新しいファイルを作成します。
  2. ファイルに次の内容を追加します。
[local]
localhost ansible_connection=local

このインベントリは、local というグループを定義し、localhost のみを含み、SSH なしで直接接続するように Ansible に指示します。

最初のプレイブックの作成

次に、シェルコマンドを実行するシンプルなプレイブックを作成しましょう。

  1. /home/labex/project ディレクトリに first_playbook.yml という名前の新しいファイルを作成します。
  2. ファイルに次の YAML コンテンツを追加します。
---
- 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 }}"

このプレイブックは、次のことを行います。

  • インベントリで定義した local グループをターゲットにします。
  • 事実(システム情報)の収集をスキップして、シンプルに保ちます。
  • グリーティングメッセージを出力するシェルコマンドを実行します。
  • register キーワードを使用して、出力を変数に保存します。
  • debug モジュールを使用して、出力を表示します。

プレイブックの実行

それでは、プレイブックを実行しましょう。

ansible-playbook -i inventory.ini first_playbook.yml

次のような出力が表示されるはずです。

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

出力は、プレイブックが正常に実行され、シェルコマンドを実行し、その出力を表示したことを示しています。

理解しておくべき重要な概念

この演習から、次の重要な概念に注意してください。

  1. shell モジュールを使用すると、シェルコマンドを実行できます。
  2. register ディレクティブは、タスクの出力を変数にキャプチャします。
  3. debug モジュールは、変数の値を表示するのに役立ちます。
  4. シェルコマンドの出力には、stdout (標準出力) と stderr (エラー出力) の両方が含まれます。

次のステップでは、シェルコマンドの出力をより効果的に処理およびフォーマットする方法を探ります。

構造化されたシェルコマンド出力の操作

Ansible でシェルコマンドを実行する基本を理解したところで、構造化されたコマンド出力を操作し、さまざまな形式で表示する方法を探ってみましょう。

システム情報の処理

システム情報を収集し、構造化された方法で提示する、より実践的なプレイブックを作成しましょう。

  1. /home/labex/project ディレクトリに system_info.yml という名前の新しいファイルを作成します。
  2. 次の内容を追加します。
---
- 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 }}"

このプレイブックは、次のことを行います。

  • さまざまなシステムの詳細を収集する複数行のシェルスクリプトを実行します。
  • 出力を system_info 変数に保存します。
  • 出力を最初に生の文字列として、次に行のリストとして表示します。

プレイブックを実行します。

ansible-playbook -i inventory.ini system_info.yml

次のような出力が表示されるはずです。

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

2 番目の表示タスクが、改行を含む文字列ではなく、リストとして出力を表示していることに注目してください。このリスト形式により、複数行の出力をより簡単に操作できます。

コマンド結果とリターンコードの操作

Linux のシェルコマンドは、成功 (0) または失敗 (非ゼロ) を示す終了コードを返します。Ansible は、登録された変数の rc (リターンコード) 属性でこれらをキャプチャします。

リターンコードを操作する方法を示すプレイブックを作成しましょう。

  1. /home/labex/project ディレクトリに command_results.yml という名前の新しいファイルを作成します。
  2. 次の内容を追加します。
---
- 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 }}

このプレイブックは、次のことを行います。

  • ファイルが存在するかどうかを確認するために、2 つのテストコマンドを実行します。
  • コマンドが失敗した場合にプレイブックが停止しないように、ignore_errors: yes を使用します。
  • リターンコードと成功/失敗ステータスを含む、詳細なコマンド結果情報を表示します。

プレイブックを実行します。

ansible-playbook -i inventory.ini command_results.yml

次のような出力が表示されるはずです。

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

既存のファイルのリターンコードが 0 で、存在しないファイルのリターンコードが 1 であることに注目してください。これは、リターンコードを使用してプレイブックで意思決定を行う方法を示しています。

登録された変数の構造を理解する

シェルコマンドから登録された変数には、いくつかの便利な属性が含まれています。

  • stdout: 単一の文字列としての標準出力
  • stdout_lines: 行のリストに分割された標準出力
  • stderr: 単一の文字列としての標準エラー出力
  • stderr_lines: 行のリストに分割された標準エラー出力
  • rc: リターンコード (成功の場合は 0、失敗の場合は非ゼロ)
  • cmd: 実行されたコマンド
  • start および end: コマンドが開始および終了したタイムスタンプ
  • delta: コマンド実行の期間

この構造を理解することは、Ansible でシェルコマンド出力を効果的に操作するために不可欠です。

シェル出力に基づく条件付き実行

Ansible の最も強力な機能の 1 つは、シェルコマンドの出力に基づいて意思決定を行う能力です。このステップでは、条件とフィルターを使用してシェルコマンド出力を処理し、プレイブックをより動的にする方法を学びます。

シェル出力での条件の使用

シェルコマンドの出力に基づいて意思決定を行うプレイブックを作成しましょう。

  1. /home/labex/project ディレクトリに conditional_playbook.yml という名前の新しいファイルを作成します。
  2. 次の内容を追加します。
---
- 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

このプレイブックは、次のことを行います。

  • ルートファイルシステムの使用率をパーセンテージで確認するシェルコマンドを実行します。
  • コマンド出力に基づいて when 条件を使用します。
  • 比較のために、文字列出力を整数に変換するために int フィルターを使用します。

プレイブックを実行します。

ansible-playbook -i inventory.ini conditional_playbook.yml

出力は実際のディスク使用量によって異なりますが、次のようになります。

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

Ansible が、実際のディスク使用量に基づいて条件付きタスクの 1 つだけを実行したことに注目してください。

コマンドからの JSON 出力の処理

多くの最新の CLI ツールは、JSON 形式でデータを返します。Ansible には、JSON 出力を処理するための組み込み機能があります。

  1. /home/labex/project ディレクトリに json_output.yml という名前の新しいファイルを作成します。
  2. 次の内容を追加します。
---
- 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"

このプレイブックは、次のことを行います。

  • デモンストレーション用のサンプル JSON ファイルを作成します。
  • シェルコマンドで JSON ファイルを読み取ります。
  • from_json フィルターを使用して、JSON 文字列をデータ構造に解析します。
  • データ構造をループして情報を表示します。
  • 条件付きロジックを使用して、実行中のサービスのみをフィルタリングします。

プレイブックを実行します。

ansible-playbook -i inventory.ini json_output.yml

次のような出力が表示されるはずです。

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

プレイブックが JSON を解析し、特定の情報を抽出し、条件に基づいてデータをフィルタリングしていることに注目してください。

シェルコマンドでのエラー処理

シェルコマンドを実行する場合、潜在的なエラーを適切に処理することが重要です。

  1. /home/labex/project ディレクトリに error_handling.yml という名前の新しいファイルを作成します。
  2. 次の内容を追加します。
---
- 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' }}

このプレイブックは、次のことを行います。

  • 失敗すると予想されるコマンドを実行します。
  • コマンドが失敗した場合でもプレイブックの実行を続行するために、ignore_errors: yes を使用します。
  • エラー情報を処理および表示するためのさまざまな方法を示します。

プレイブックを実行します。

ansible-playbook -i inventory.ini error_handling.yml

次のような出力が表示されるはずです。

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

これは、シェルコマンドを実行するときに、さまざまなエラー状態をキャプチャして対応する方法を示しています。

実用的なシェル出力処理ツールの作成

この最後のステップでは、これまで学習したすべてのことを組み合わせて、システム情報を収集し、処理し、レポートを生成する実用的な Ansible プレイブックを作成します。これは、Ansible のシェルコマンド処理機能が非常に役立つ可能性のある現実世界のシナリオを表しています。

システム情報レポートツールの構築

包括的なシステム情報収集ツールを作成しましょう。

  1. /home/labex/project ディレクトリに system_report.yml という名前の新しいファイルを作成します。
  2. 次の内容を追加します。
---
- 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

このプレイブックは、次のことを行います。

  • 一連のシェルコマンドを使用して、包括的なシステム情報を収集します。
  • 情報をレポートファイルに書き込みます。
  • レポートが正常に作成されたことを確認します。
  • レポートの内容を表示します。
  • ディスク使用量データを分析します。
  • 分析に基づいて適切なアラートを生成します。

プレイブックを実行します。

ansible-playbook -i inventory.ini system_report.yml

プレイブックの実行と完全なシステムレポートを示す包括的な出力が表示されます。出力は非常に長いため、表示される可能性のある内容のサンプルを次に示します。

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",
        ...

レポートの確認

生成されたシステムレポートを確認しましょう。

cat /tmp/system_report.txt

これにより、プレイブックによって生成された完全なレポートが表示されます。

カスタムシェルスクリプトの作成と Ansible からの呼び出し

より複雑な操作を行うには、専用のシェルスクリプトを作成し、Ansible からそれを呼び出す方が簡単な場合があります。

  1. /home/labex/project ディレクトリに disk_analyzer.sh という名前の新しいファイルを作成します。
  2. 次の内容を追加します。
#!/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. スクリプトを実行可能にします。
chmod +x /home/labex/project/disk_analyzer.sh
  1. このスクリプトを呼び出す新しいプレイブックを作成します。
touch /home/labex/project/call_script.yml
  1. プレイブックに次の内容を追加します。
---
- 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. プレイブックを実行します。
ansible-playbook -i inventory.ini call_script.yml

次のような出力が表示されるはずです。

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

このアプローチは、シェルスクリプトの力と Ansible の自動化機能を組み合わせたものです。シェルスクリプトはディスク分析の複雑なロジックを処理し、Ansible は結果の実行とさらなる処理を管理します。

主なポイント

この実験を通して、Ansible でシェルコマンド出力を操作するためのいくつかの重要なテクニックを学びました。

  1. シェルコマンドを実行し、その出力をキャプチャする方法
  2. コマンド出力を表示用に処理およびフォーマットする方法
  3. コマンドの結果に基づいて条件付き実行を使用する方法
  4. JSON 出力とエラー状態を処理する方法
  5. シェルコマンドと Ansible の自動化機能を組み合わせた実用的なツールを作成する方法

これらのスキルは、Ansible でより複雑な自動化ソリューションを構築する際に非常に役立ちます。

まとめ

この実験では、Ansible プレイブックでシェルコマンド出力を効果的に操作する方法を学びました。シェルコマンドの実行と出力のキャプチャの基本から始めて、条件付き実行、エラー処理、JSON などの構造化データ形式の処理など、より高度なテクニックに進みました。

いくつかの重要なスキルを習得しました。

  • shell モジュールを使用して Ansible プレイブックでシェルコマンドを実行する
  • register ディレクティブを使用してコマンド出力をキャプチャする
  • debug モジュールを使用して出力を表示する
  • Jinja2 フィルターと条件を使用して出力を処理する
  • Ansible とシェルスクリプトを組み合わせた実用的な自動化ツールを作成する

これらのテクニックにより、さまざまなシステム状態に適応し、実行されている操作に関する有用なフィードバックを提供する、より動的で応答性の高い自動化ワークフローを作成できます。

Ansible の旅を続ける中で、シェルコマンドは優れた柔軟性を提供しますが、Ansible の組み込みモジュールは、一般的なタスクに対してより堅牢でポータブルなソリューションであることが多いことを覚えておいてください。既存のシェルスクリプトを活用する必要がある場合や、Ansible モジュールでは簡単に処理できない複雑な操作を実行する必要がある場合は、シェルコマンドを使用してください。