Ansible で実行されるスクリプトの出力をキャプチャする方法

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

はじめに

Ansible は、複雑なインフラストラクチャとアプリケーションのデプロイメント管理を簡素化する、広く利用されている IT 自動化ツールです。このチュートリアルでは、Ansible プレイブックを通じて実行されるスクリプトの出力をキャプチャする方法を探求します。この機能は、自動化タスクの結果を監視、デバッグ、分析するために不可欠です。この実験(Lab)の終わりには、Ansible ワークフローでスクリプト出力をキャプチャし、利用するためのさまざまなテクニックを理解できるようになります。

Ansible 環境のセットアップ

Ansible でスクリプト出力をキャプチャし始める前に、基本的な Ansible 環境をセットアップする必要があります。これには、必要なディレクトリ構造と設定ファイルの作成が含まれます。

Ansible の基本を理解する

Ansible は、ターゲットホストに接続し、モジュールと呼ばれる小さなプログラムをプッシュすることで動作します。これらのモジュールはターゲットホスト上で実行され、完了すると削除されます。Ansible はエージェントレスであり、管理対象ノードに特別なソフトウェアをインストールする必要はありません。

まず、プロジェクトディレクトリと必要な Ansible ファイルを作成することから始めましょう。

mkdir -p ~/project/ansible-output-demo/scripts
cd ~/project/ansible-output-demo

次に、簡単なインベントリファイルを作成しましょう。Ansible では、インベントリファイルは、プレイブック内のコマンド、モジュール、およびタスクが動作するホストとホストグループを定義します。

コードエディタを使用してインベントリファイルを作成します。

  1. IDE の左上隅にある「File」メニューをクリックします。
  2. 「New File」を選択します。
  3. ~/project/ansible-output-demo ディレクトリに inventory として保存します。

inventory ファイルに次の内容を追加します。

[local]
localhost ansible_connection=local

このインベントリファイルは、ローカルマシン上で Ansible を実行することを指定しています。

次に、キャプチャする出力を生成する簡単なスクリプトを作成しましょう。このスクリプトは次のことを行います。

  1. いくつかのシステム情報を出力します。
  2. 標準出力を生成します。
  3. 標準エラー出力を生成します。

scripts ディレクトリに info.sh という名前の新しいファイルを作成します。

  1. 「File」メニューをクリックします。
  2. 「New File」を選択します。
  3. ~/project/ansible-output-demo ディレクトリに scripts/info.sh として保存します。

info.sh ファイルに次の内容を追加します。

#!/bin/bash

## Print system information
echo "=== System Information ==="
echo "Hostname: $(hostname)"
echo "Date: $(date)"
echo "Kernel: $(uname -r)"
echo "Memory:"
free -h

## Generate some standard output
echo "=== Standard Output ==="
echo "This is standard output"
echo "Hello from the script!"

## Generate some standard error
echo "=== Standard Error ===" >&2
echo "This is standard error" >&2
echo "An example error message" >&2

## Exit with a specific code
exit 0

次に、スクリプトを実行可能にします。

chmod +x ~/project/ansible-output-demo/scripts/info.sh

スクリプトを直接実行して、どのような出力が生成されるかを確認しましょう。

~/project/ansible-output-demo/scripts/info.sh

システム情報、標準出力メッセージ、および標準エラーメッセージを含む出力が表示されるはずです。

これで、基本的な環境がセットアップされました。次のステップでは、このスクリプトを実行し、その出力をキャプチャする Ansible プレイブックを作成します。

Ansible での基本的な出力キャプチャ

環境をセットアップしたので、スクリプトを実行し、その出力をキャプチャする簡単な Ansible プレイブックを作成しましょう。

基本的なプレイブックの作成

Ansible では、プレイブックは、リモートホストで実行される一連のタスクを定義する YAML ファイルです。info.sh スクリプトを実行し、register キーワードを使用してその出力をキャプチャするプレイブックを作成しましょう。

~/project/ansible-output-demo ディレクトリに capture_output.yml という名前の新しいファイルを作成します。

  1. 「File」メニューをクリックします。
  2. 「New File」を選択します。
  3. ~/project/ansible-output-demo ディレクトリに capture_output.yml として保存します。

capture_output.yml ファイルに次の内容を追加します。

---
- name: Capture Script Output
  hosts: local
  gather_facts: no

  tasks:
    - name: Execute the info.sh script
      command: "{{ playbook_dir }}/scripts/info.sh"
      register: script_output

    - name: Display the script output
      debug:
        var: script_output.stdout

このプレイブックを見てみましょう。

  1. プレイブックは、インベントリで定義された local グループをターゲットにしています。
  2. 最初のタスクは、command モジュールを使用して info.sh スクリプトを実行します。
  3. register キーワードは、コマンドの出力を script_output という名前の変数に格納します。
  4. 2 番目のタスクは、debug モジュールを使用して、スクリプトの標準出力 (stdout) を表示します。

プレイブックの実行

次に、プレイブックを実行して、スクリプトの出力がどのようにキャプチャされ、表示されるかを確認しましょう。

cd ~/project/ansible-output-demo
ansible-playbook -i inventory capture_output.yml

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

PLAY [Capture Script Output] *******************************************

TASK [Execute the info.sh script] **************************************
changed: [localhost]

TASK [Display the script output] ***************************************
ok: [localhost] => {
    "script_output.stdout": "=== System Information ===\nHostname: ubuntu\nDate: Tue Oct 17 12:34:56 UTC 2023\nKernel: 5.15.0-1031-aws\nMemory:\n              total        used        free      shared  buff/cache   available\nMem:          7.7Gi       1.2Gi       5.2Gi        12Mi       1.3Gi       6.3Gi\nSwap:            0B          0B          0B\n=== Standard Output ===\nThis is standard output\nHello from the script!"
}

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

標準出力のみが表示されていることに注意してください。標準エラー (stderr) 出力は、script_output.stdout の表示のみを要求したため、表示されません。

出力の可読性の向上

出力は、単一の文字列としては少し読みにくいです。stdout_lines 属性を使用して、出力をより読みやすい形式で表示するようにプレイブックを変更しましょう。stdout_lines 属性は、出力を行のリストとして表示します。

capture_output.yml ファイルを編集し、2 番目のタスクを次のように変更します。

- name: Display the script output
  debug:
    var: script_output.stdout_lines

プレイブックをもう一度実行します。

ansible-playbook -i inventory capture_output.yml

これで、出力はより読みやすくなり、各行が個別に表示されます。

TASK [Display the script output] ***************************************
ok: [localhost] => {
    "script_output.stdout_lines": [
        "=== System Information ===",
        "Hostname: ubuntu",
        "Date: Tue Oct 17 12:34:56 UTC 2023",
        "Kernel: 5.15.0-1031-aws",
        "Memory:",
        "              total        used        free      shared  buff/cache   available",
        "Mem:          7.7Gi       1.2Gi       5.2Gi        12Mi       1.3Gi       6.3Gi",
        "Swap:            0B          0B          0B",
        "=== Standard Output ===",
        "This is standard output",
        "Hello from the script!"
    ]
}

この形式により、出力が非常に読みやすく、扱いやすくなります。次のステップでは、さまざまな種類の出力をキャプチャして表示する方法を探求します。

さまざまな種類の出力のキャプチャ

前のステップでは、スクリプトの標準出力をキャプチャして表示しました。ただし、スクリプトを実行する際には、キャプチャしたい出力がいくつかあります。

  1. 標準出力 (stdout): スクリプトの通常の出力
  2. 標準エラー (stderr): エラーメッセージと警告
  3. リターンコード (rc): スクリプトの終了ステータス (通常、0 は成功を意味し、0 以外の値はエラーを示します)

3 種類のすべての出力をキャプチャして表示する新しいプレイブックを作成しましょう。

~/project/ansible-output-demo ディレクトリに capture_all_output.yml という名前の新しいファイルを作成します。

  1. 「File」メニューをクリックします。
  2. 「New File」を選択します。
  3. capture_all_output.yml として保存します。

capture_all_output.yml ファイルに次の内容を追加します。

---
- name: Capture All Types of Script Output
  hosts: local
  gather_facts: no

  tasks:
    - name: Execute the info.sh script
      command: "{{ playbook_dir }}/scripts/info.sh"
      register: script_output

    - name: Display standard output
      debug:
        msg: "Standard Output (stdout):"

    - name: Display stdout content
      debug:
        var: script_output.stdout_lines

    - name: Display standard error
      debug:
        msg: "Standard Error (stderr):"

    - name: Display stderr content
      debug:
        var: script_output.stderr_lines

    - name: Display return code
      debug:
        msg: "Return Code: {{ script_output.rc }}"

このプレイブックは、スクリプトを実行し、次に以下を表示します。

  1. script_output.stdout_lines を使用した標準出力
  2. script_output.stderr_lines を使用した標準エラー
  3. script_output.rc を使用したリターンコード

拡張プレイブックの実行

新しいプレイブックを実行しましょう。

cd ~/project/ansible-output-demo
ansible-playbook -i inventory capture_all_output.yml

3 種類のすべての出力が包括的に表示されるはずです。

PLAY [Capture All Types of Script Output] *****************************

TASK [Execute the info.sh script] *************************************
changed: [localhost]

TASK [Display standard output] ****************************************
ok: [localhost] => {
    "msg": "Standard Output (stdout):"
}

TASK [Display stdout content] *****************************************
ok: [localhost] => {
    "script_output.stdout_lines": [
        "=== System Information ===",
        "Hostname: ubuntu",
        "Date: Tue Oct 17 12:40:22 UTC 2023",
        "Kernel: 5.15.0-1031-aws",
        "Memory:",
        "              total        used        free      shared  buff/cache   available",
        "Mem:          7.7Gi       1.2Gi       5.2Gi        12Mi       1.3Gi       6.3Gi",
        "Swap:            0B          0B          0B",
        "=== Standard Output ===",
        "This is standard output",
        "Hello from the script!"
    ]
}

TASK [Display standard error] *****************************************
ok: [localhost] => {
    "msg": "Standard Error (stderr):"
}

TASK [Display stderr content] *****************************************
ok: [localhost] => {
    "script_output.stderr_lines": [
        "=== Standard Error ===",
        "This is standard error",
        "An example error message"
    ]
}

TASK [Display return code] ********************************************
ok: [localhost] => {
    "msg": "Return Code: 0"
}

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

これで、スクリプトからのすべての種類の出力を見ることができます。

  • 標準出力には、システム情報と通常のメッセージが表示されます。
  • 標準エラーには、エラーメッセージが表示されます。
  • リターンコードは 0 で、正常な実行を示しています。

エラーのあるスクリプトの作成

エラーを生成し、0 以外の終了コードを返すスクリプトを作成して、Ansible がそれをどのように処理するかを確認しましょう。

scripts ディレクトリに error.sh という名前の新しいファイルを作成します。

  1. 「File」メニューをクリックします。
  2. 「New File」を選択します。
  3. scripts/error.sh として保存します。

error.sh ファイルに次の内容を追加します。

#!/bin/bash

## Print some standard output
echo "Starting error demonstration script"
echo "This will appear in stdout"

## Print some standard error
echo "This will appear in stderr" >&2
echo "Error: Something went wrong!" >&2

## Exit with a non-zero code to indicate error
exit 1

スクリプトを実行可能にします。

chmod +x ~/project/ansible-output-demo/scripts/error.sh

次に、このスクリプトを実行してエラーを処理するプレイブックを作成しましょう。 handle_errors.yml という名前の新しいファイルを作成します。

  1. 「File」メニューをクリックします。
  2. 「New File」を選択します。
  3. handle_errors.yml として保存します。

handle_errors.yml ファイルに次の内容を追加します。

---
- name: Handle Script Errors
  hosts: local
  gather_facts: no

  tasks:
    - name: Execute the error script
      command: "{{ playbook_dir }}/scripts/error.sh"
      register: script_output
      ignore_errors: yes

    - name: Display standard output
      debug:
        var: script_output.stdout_lines

    - name: Display standard error
      debug:
        var: script_output.stderr_lines

    - name: Display return code
      debug:
        msg: "Return Code: {{ script_output.rc }}"

    - name: Check if script failed
      debug:
        msg: "The script failed with return code {{ script_output.rc }}"
      when: script_output.rc != 0

ignore_errors: yes が追加されていることに注意してください。これは、コマンドが失敗した場合 (0 以外の終了コードを返した場合) でも、Ansible にプレイブックの実行を続行するように指示します。

このプレイブックを実行しましょう。

ansible-playbook -i inventory handle_errors.yml

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

PLAY [Handle Script Errors] *******************************************

TASK [Execute the error script] ***************************************
changed: [localhost]

TASK [Display standard output] ****************************************
ok: [localhost] => {
    "script_output.stdout_lines": [
        "Starting error demonstration script",
        "This will appear in stdout"
    ]
}

TASK [Display standard error] *****************************************
ok: [localhost] => {
    "script_output.stderr_lines": [
        "This will appear in stderr",
        "Error: Something went wrong!"
    ]
}

TASK [Display return code] ********************************************
ok: [localhost] => {
    "msg": "Return Code: 1"
}

TASK [Check if script failed] *****************************************
ok: [localhost] => {
    "msg": "The script failed with return code 1"
}

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

この例では、次の方法を示しています。

  1. エラーを生成するスクリプトからの出力をキャプチャする
  2. エラーが発生してもプレイブックの実行を続行する
  3. スクリプトのリターンコードに基づいてタスクを条件付きで実行する

次のステップでは、Ansible でスクリプト出力を操作するための、より高度なユースケースとベストプラクティスを探求します。

高度な出力処理と実用的なユースケース

さまざまな種類の出力をキャプチャする方法を理解したので、Ansible でスクリプト出力を処理し、利用するためのより高度なテクニックを探求しましょう。

フィルターを使用した出力の解析

Ansible には、スクリプト出力から特定の情報を操作および抽出できるさまざまなフィルターが用意されています。このセクションでは、いくつかの一般的なフィルタリングテクニックを見ていきます。

~/project/ansible-output-demo ディレクトリに parse_output.yml という名前の新しいファイルを作成します。

  1. 「File」メニューをクリックします。
  2. 「New File」を選択します。
  3. parse_output.yml として保存します。

まず、解析できる構造化された出力を生成するスクリプトを作成しましょう。 system_stats.sh という名前の新しいファイルを作成します。

  1. 「File」メニューをクリックします。
  2. 「New File」を選択します。
  3. scripts/system_stats.sh として保存します。

system_stats.sh ファイルに次の内容を追加します。

#!/bin/bash

## Display CPU info
echo "CPU_MODEL: $(grep 'model name' /proc/cpuinfo | head -1 | cut -d ':' -f2 | xargs)"
echo "CPU_CORES: $(grep -c 'processor' /proc/cpuinfo)"

## Display memory info in GB
mem_total=$(free -g | grep Mem | awk '{print $2}')
echo "MEMORY_GB: $mem_total"

## Display disk usage
disk_usage=$(df -h / | tail -1 | awk '{print $5}' | tr -d '%')
echo "DISK_USAGE_PCT: $disk_usage"

## Display load average
load_avg=$(uptime | awk -F'load average: ' '{print $2}' | cut -d, -f1)
echo "LOAD_AVG: $load_avg"

exit 0

スクリプトを実行可能にします。

chmod +x ~/project/ansible-output-demo/scripts/system_stats.sh

次に、このスクリプトを実行し、その出力をキャプチャし、それを解析して特定の情報を抽出するプレイブックを作成しましょう。

parse_output.yml ファイルに次の内容を追加します。

---
- name: Parse Script Output
  hosts: local
  gather_facts: no

  tasks:
    - name: Execute the system_stats.sh script
      command: "{{ playbook_dir }}/scripts/system_stats.sh"
      register: stats_output

    - name: Display raw output
      debug:
        var: stats_output.stdout_lines

    - name: Parse CPU model
      set_fact:
        cpu_model: "{{ stats_output.stdout | regex_search('CPU_MODEL: (.+)', '\\1') | first }}"

    - name: Parse CPU cores
      set_fact:
        cpu_cores: "{{ stats_output.stdout | regex_search('CPU_CORES: (\\d+)', '\\1') | first }}"

    - name: Parse memory
      set_fact:
        memory_gb: "{{ stats_output.stdout | regex_search('MEMORY_GB: (\\d+)', '\\1') | first }}"

    - name: Parse disk usage
      set_fact:
        disk_usage: "{{ stats_output.stdout | regex_search('DISK_USAGE_PCT: (\\d+)', '\\1') | first }}"

    - name: Parse load average
      set_fact:
        load_avg: "{{ stats_output.stdout | regex_search('LOAD_AVG: ([0-9.]+)', '\\1') | first }}"

    - name: Display parsed information
      debug:
        msg: |
          Parsed system information:
          - CPU Model: {{ cpu_model }}
          - CPU Cores: {{ cpu_cores }}
          - Memory (GB): {{ memory_gb }}
          - Disk Usage (%): {{ disk_usage }}
          - Load Average: {{ load_avg }}

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

  1. system_stats.sh スクリプトを実行します。
  2. 生の出力を表示します。
  3. regex_search フィルターを使用して、出力から特定の情報を抽出します。
  4. 抽出された情報を変数に格納します。
  5. 解析された情報を構造化された形式で表示します。

このプレイブックを実行しましょう。

cd ~/project/ansible-output-demo
ansible-playbook -i inventory parse_output.yml

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

PLAY [Parse Script Output] ********************************************

TASK [Execute the system_stats.sh script] *****************************
changed: [localhost]

TASK [Display raw output] *********************************************
ok: [localhost] => {
    "stats_output.stdout_lines": [
        "CPU_MODEL: Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz",
        "CPU_CORES: 2",
        "MEMORY_GB: 7",
        "DISK_USAGE_PCT: 58",
        "LOAD_AVG: 0.08"
    ]
}

TASK [Parse CPU model] ************************************************
ok: [localhost]

TASK [Parse CPU cores] ************************************************
ok: [localhost]

TASK [Parse memory] ***************************************************
ok: [localhost]

TASK [Parse disk usage] ***********************************************
ok: [localhost]

TASK [Parse load average] *********************************************
ok: [localhost]

TASK [Display parsed information] *************************************
ok: [localhost] => {
    "msg": "Parsed system information:\n- CPU Model: Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz\n- CPU Cores: 2\n- Memory (GB): 7\n- Disk Usage (%): 58\n- Load Average: 0.08"
}

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

出力に基づく意思決定

スクリプト出力をキャプチャする最も強力な側面の 1 つは、それを使用して Ansible プレイブックで意思決定を行うことです。スクリプト出力に基づいて条件付き実行を示すプレイブックを作成しましょう。

~/project/ansible-output-demo ディレクトリに conditional_actions.yml という名前の新しいファイルを作成します。

  1. 「File」メニューをクリックします。
  2. 「New File」を選択します。
  3. conditional_actions.yml として保存します。

次の内容を追加します。

---
- name: Conditional Actions Based on Script Output
  hosts: local
  gather_facts: no

  tasks:
    - name: Execute the system_stats.sh script
      command: "{{ playbook_dir }}/scripts/system_stats.sh"
      register: stats_output

    - name: Parse disk usage
      set_fact:
        disk_usage: "{{ stats_output.stdout | regex_search('DISK_USAGE_PCT: (\\d+)', '\\1') | first | int }}"

    - name: Parse load average
      set_fact:
        load_avg: "{{ stats_output.stdout | regex_search('LOAD_AVG: ([0-9.]+)', '\\1') | first | float }}"

    - name: Display system status
      debug:
        msg: "Current system status: Disk usage: {{ disk_usage }}%, Load average: {{ load_avg }}"

    - name: Warn about high disk usage
      debug:
        msg: "WARNING: Disk usage is high at {{ disk_usage }}%. Consider cleaning up disk space."
      when: disk_usage > 50

    - name: Warn about high load average
      debug:
        msg: "WARNING: Load average is high at {{ load_avg }}. Check for resource-intensive processes."
      when: load_avg > 1.0

    - name: Report healthy system
      debug:
        msg: "System is healthy. All metrics within normal ranges."
      when: disk_usage <= 50 and load_avg <= 1.0

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

  1. system_stats.sh スクリプトを実行します。
  2. ディスク使用量と負荷平均値を解析します。
  3. 値に基づいてさまざまなメッセージを表示します。
    • ディスク使用量が 50% を超えている場合は警告
    • 負荷平均が 1.0 を超えている場合は警告
    • すべてのメトリックが正常範囲内にある場合は「正常なシステム」メッセージ

このプレイブックを実行しましょう。

ansible-playbook -i inventory conditional_actions.yml

出力はシステムの現在の状態によって異なりますが、ディスク使用量と負荷平均に基づく条件付きメッセージが含まれるはずです。

これらの例は、次の方法を示しています。

  1. スクリプト出力から特定の情報を解析して抽出する
  2. その情報を使用して、Ansible プレイブックで意思決定を行う
  3. スクリプト出力に基づいてさまざまなアクションを実行する

これらのテクニックは、さまざまな条件やシナリオに適応できる、動的で応答性の高い自動化ワークフローを作成するために不可欠です。

実用的なユースケース - システムヘルスチェック

この最終ステップでは、Ansible でスクリプト出力をキャプチャして処理することについて学んだすべてのことをまとめた、完全な実用的な例を作成します。以下を行うシステムヘルスチェックツールを構築します。

  1. さまざまなシステムメトリックを収集する
  2. メトリックを分析して潜在的な問題を特定する
  3. ヘルスレポートを生成する
  4. 必要に応じて是正措置を講じる

ヘルスチェックスクリプトの作成

まず、さまざまなシステムメトリックを収集する包括的なヘルスチェックスクリプトを作成しましょう。

scripts ディレクトリに health_check.sh という名前の新しいファイルを作成します。

  1. 「File」メニューをクリックします。
  2. 「New File」を選択します。
  3. scripts/health_check.sh として保存します。

health_check.sh ファイルに次の内容を追加します。

#!/bin/bash

## System Health Check Script

echo "HEALTH_CHECK_START: $(date)"

## CPU load
cpu_load=$(uptime | awk -F'load average: ' '{print $2}' | cut -d, -f1)
echo "CPU_LOAD: $cpu_load"
if (($(echo "$cpu_load > 1.0" | bc -l))); then
  echo "CPU_STATUS: WARNING"
else
  echo "CPU_STATUS: OK"
fi

## Memory usage
mem_total=$(free | grep Mem | awk '{print $2}')
mem_used=$(free | grep Mem | awk '{print $3}')
mem_pct=$(echo "scale=2; $mem_used / $mem_total * 100" | bc)
echo "MEM_USAGE_PCT: $mem_pct"
if (($(echo "$mem_pct > 80" | bc -l))); then
  echo "MEM_STATUS: WARNING"
else
  echo "MEM_STATUS: OK"
fi

## Disk usage
disk_usage=$(df -h / | tail -1 | awk '{print $5}' | tr -d '%')
echo "DISK_USAGE_PCT: $disk_usage"
if [ "$disk_usage" -gt 80 ]; then
  echo "DISK_STATUS: WARNING"
else
  echo "DISK_STATUS: OK"
fi

## Check for zombie processes
zombie_count=$(ps aux | grep -c Z)
echo "ZOMBIE_PROCESSES: $zombie_count"
if [ "$zombie_count" -gt 0 ]; then
  echo "ZOMBIE_STATUS: WARNING"
else
  echo "ZOMBIE_STATUS: OK"
fi

## Check system uptime
uptime_days=$(uptime | awk '{print $3}')
echo "UPTIME_DAYS: $uptime_days"

## Check last 5 log entries for errors
echo "RECENT_ERRORS: $(grep -i error /var/log/syslog 2> /dev/null | tail -5 | wc -l)"

echo "HEALTH_CHECK_END: $(date)"

スクリプトを実行可能にします。

chmod +x ~/project/ansible-output-demo/scripts/health_check.sh

ヘルスチェックプレイブックの作成

次に、ヘルスチェックスクリプトを実行し、結果を分析し、その結果に基づいて適切なアクションを実行する包括的なプレイブックを作成しましょう。

~/project/ansible-output-demo ディレクトリに system_health_check.yml という名前の新しいファイルを作成します。

  1. 「File」メニューをクリックします。
  2. 「New File」を選択します。
  3. system_health_check.yml として保存します。

system_health_check.yml ファイルに次の内容を追加します。

---
- name: System Health Check
  hosts: local
  gather_facts: no

  tasks:
    - name: Execute health check script
      command: "{{ playbook_dir }}/scripts/health_check.sh"
      register: health_check

    - name: Display raw health check output
      debug:
        var: health_check.stdout_lines

    ## Parse metrics from the health check output
    - name: Parse CPU load
      set_fact:
        cpu_load: "{{ health_check.stdout | regex_search('CPU_LOAD: ([0-9.]+)', '\\1') | first | float }}"
        cpu_status: "{{ health_check.stdout | regex_search('CPU_STATUS: (\\w+)', '\\1') | first }}"

    - name: Parse memory usage
      set_fact:
        mem_usage: "{{ health_check.stdout | regex_search('MEM_USAGE_PCT: ([0-9.]+)', '\\1') | first | float }}"
        mem_status: "{{ health_check.stdout | regex_search('MEM_STATUS: (\\w+)', '\\1') | first }}"

    - name: Parse disk usage
      set_fact:
        disk_usage: "{{ health_check.stdout | regex_search('DISK_USAGE_PCT: (\\d+)', '\\1') | first | int }}"
        disk_status: "{{ health_check.stdout | regex_search('DISK_STATUS: (\\w+)', '\\1') | first }}"

    - name: Parse zombie processes
      set_fact:
        zombie_count: "{{ health_check.stdout | regex_search('ZOMBIE_PROCESSES: (\\d+)', '\\1') | first | int }}"
        zombie_status: "{{ health_check.stdout | regex_search('ZOMBIE_STATUS: (\\w+)', '\\1') | first }}"

    ## Generate a health status summary
    - name: Generate health status summary
      set_fact:
        health_status:
          cpu:
            load: "{{ cpu_load }}"
            status: "{{ cpu_status }}"
          memory:
            usage_percent: "{{ mem_usage }}"
            status: "{{ mem_status }}"
          disk:
            usage_percent: "{{ disk_usage }}"
            status: "{{ disk_status }}"
          processes:
            zombie_count: "{{ zombie_count }}"
            status: "{{ zombie_status }}"

    ## Display health summary
    - name: Display health summary
      debug:
        var: health_status

    ## Check overall system status
    - name: Determine overall system status
      set_fact:
        overall_status: "{{ 'WARNING' if (cpu_status == 'WARNING' or mem_status == 'WARNING' or disk_status == 'WARNING' or zombie_status == 'WARNING') else 'OK' }}"

    - name: Display overall system status
      debug:
        msg: "Overall System Status: {{ overall_status }}"

    ## Take remedial actions if necessary
    - name: Recommend actions for CPU issues
      debug:
        msg: "Action recommended: Check for resource-intensive processes using 'top' or 'htop'"
      when: cpu_status == "WARNING"

    - name: Recommend actions for memory issues
      debug:
        msg: "Action recommended: Free up memory by restarting services or clearing cache"
      when: mem_status == "WARNING"

    - name: Recommend actions for disk issues
      debug:
        msg: "Action recommended: Clean up disk space using 'du -sh /* | sort -hr' to identify large directories"
      when: disk_status == "WARNING"

    - name: Recommend actions for zombie processes
      debug:
        msg: "Action recommended: Identify and restart parent processes of zombies"
      when: zombie_status == "WARNING"

    ## Generate health report file
    - name: Create health report directory
      file:
        path: "{{ playbook_dir }}/reports"
        state: directory

    - name: Get current timestamp
      command: date "+%Y%m%d_%H%M%S"
      register: timestamp

    - name: Create health report file
      copy:
        content: |
          System Health Report - {{ timestamp.stdout }}
          ----------------------------------------------

          CPU:
            Load Average: {{ cpu_load }}
            Status: {{ cpu_status }}

          Memory:
            Usage: {{ mem_usage }}%
            Status: {{ mem_status }}

          Disk:
            Usage: {{ disk_usage }}%
            Status: {{ disk_status }}

          Processes:
            Zombie Count: {{ zombie_count }}
            Status: {{ zombie_status }}

          Overall Status: {{ overall_status }}

          Recommendations:
          {% if cpu_status == "WARNING" %}
          - CPU: Check for resource-intensive processes using 'top' or 'htop'
          {% endif %}
          {% if mem_status == "WARNING" %}
          - Memory: Free up memory by restarting services or clearing cache
          {% endif %}
          {% if disk_status == "WARNING" %}
          - Disk: Clean up disk space using 'du -sh /* | sort -hr' to identify large directories
          {% endif %}
          {% if zombie_status == "WARNING" %}
          - Processes: Identify and restart parent processes of zombies
          {% endif %}
          {% if overall_status == "OK" %}
          - System is healthy. No actions required.
          {% endif %}
        dest: "{{ playbook_dir }}/reports/health_report_{{ timestamp.stdout }}.txt"

    - name: Display report location
      debug:
        msg: "Health report saved to {{ playbook_dir }}/reports/health_report_{{ timestamp.stdout }}.txt"

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

  1. ヘルスチェックスクリプトを実行します。
  2. スクリプト出力からさまざまなメトリックを解析します。
  3. システムのヘルスに関する構造化された概要を作成します。
  4. 個々のコンポーネントのステータスに基づいて、システムの全体的なステータスを決定します。
  5. 検出された問題に対する具体的な推奨事項を提供します。
  6. タイムスタンプ付きの詳細なヘルスレポートファイルを生成します。

ヘルスチェックの実行

システムヘルスチェックプレイブックを実行しましょう。

cd ~/project/ansible-output-demo
ansible-playbook -i inventory system_health_check.yml

システムのヘルスステータスを示す詳細な出力と、必要な改善に関する推奨事項が表示されるはずです。出力は、システムの現在の状態によって異なります。

プレイブックを実行した後、レポートディレクトリを確認して、生成されたヘルスレポートを確認します。

ls -l ~/project/ansible-output-demo/reports/

health_report_[timestamp].txt という名前のファイルが表示されるはずです。このファイルの内容を表示します。

cat ~/project/ansible-output-demo/reports/health_report_*.txt

これまで学んだことのまとめ

このチュートリアル全体を通して、次のことを学びました。

  1. Ansible によって実行されるスクリプトから、さまざまな種類の出力 (stdout、stderr、リターンコード) をキャプチャする方法
  2. Ansible フィルターを使用して、スクリプト出力から特定の情報を解析して抽出する方法
  3. スクリプト出力を使用して、意思決定を行い、条件付きアクションを実行する方法
  4. システムヘルス監視にスクリプト出力を活用する、完全な実用的なソリューションを実装する方法

これらのテクニックは、Ansible 自動化ツールキットの強力なツールであり、洗練された、動的で応答性の高い自動化ワークフローを作成できます。

まとめ

この実験では、Ansible を介して実行されるスクリプトの出力を効果的にキャプチャして利用する方法を探求しました。 register キーワードを使用した基本的な出力キャプチャから始め、フィルターを使用した出力の解析や、スクリプトの結果に基づいた意思決定などのより高度なテクニックに進みました。

このチュートリアルからの主なポイントは次のとおりです。

  1. Ansible によって実行されるスクリプトから、さまざまな種類の出力 (stdout、stderr、リターンコード) をキャプチャする機能
  2. スクリプト出力から特定の情報を解析して抽出するためのテクニック
  3. スクリプト出力に基づいてタスクを条件付きで実行するための方法
  4. Ansible を使用してシステムヘルス監視ソリューションを構築する方法を示す、包括的な実用的な例

これらのテクニックを習得することで、さまざまな条件やシナリオに適応できる、より洗練された、動的で応答性の高い自動化ワークフローを作成できます。この機能は、Ansible を使用した効果的なインフラストラクチャ管理、アプリケーションデプロイメント、およびシステム管理に不可欠です。

Ansible の旅を続ける中で、スクリプト出力のキャプチャは、Ansible が提供する多くの強力な機能の 1 つにすぎないことを忘れないでください。ロール、テンプレート、および vault などの他の Ansible 機能を探求することで、自動化ツールキットがさらに強化されます。