Ansible プレイブックでのスクリプト出力の表示方法

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

はじめに

Ansible は、システム管理者や開発者がインフラストラクチャを効率的に管理するのに役立つ強力な自動化ツールです。Ansible プレイブックを通じてスクリプトやコマンドを実行する際、監視とトラブルシューティングのためにその出力をキャプチャして表示することが重要になることがよくあります。

この実践的な実験(Lab)では、Ansible プレイブックでスクリプト出力を効果的に表示する方法を学びます。まず、Ansible プレイブックの基本的な構造から始め、コマンド出力をキャプチャして表示するためのさまざまなテクニックを探求し、最後に、出力データをフォーマットおよびフィルタリングするためのいくつかの高度な方法をカバーします。

この実験(Lab)の終わりには、Ansible でスクリプト出力を処理するためのさまざまなアプローチに関する実践的な経験が得られ、より情報量が多く、デバッグしやすい自動化ワークフローを作成できるようになります。

最初の Ansible プレイブックの設定

スクリプト出力を表示する方法を探求する前に、基本的な Ansible 環境を設定し、最初のプレイブックを作成する必要があります。

Ansible のインストール

まず、システムに Ansible がインストールされていることを確認しましょう。

sudo apt update
sudo apt install -y ansible

このコマンドは、Ubuntu システムに Ansible をインストールします。インストールが完了したら、Ansible のバージョンを確認して検証します。

ansible --version

以下のような出力が表示され、Ansible が正しくインストールされていることを確認できます。

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 14 2023, 14:50:41) [GCC 11.3.0]
  jinja version = 3.0.3
  libyaml = True

Ansible インベントリの理解

Ansible は、接続先のホストを知っている必要があります。この実験(Lab)では、ローカルマシンのみを含むシンプルなインベントリファイルを使用します。

Ansible プロジェクト用のディレクトリを作成します。

mkdir -p ~/project/ansible-lab
cd ~/project/ansible-lab

次に、inventory.ini という名前のインベントリファイルを作成します。

echo "localhost ansible_connection=local" > inventory.ini

このインベントリファイルは、SSH を使用せずにローカルマシンでコマンドを実行するように Ansible に指示します。

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

次に、基本的な Ansible プレイブックを作成しましょう。WebIDE で、~/project/ansible-lab ディレクトリに first_playbook.yml という新しいファイルを作成し、次の内容を記述します。

---
- name: My First Ansible Playbook
  hosts: localhost
  gather_facts: yes

  tasks:
    - name: Display a simple message
      debug:
        msg: "Hello from Ansible!"

    - name: Display system information
      debug:
        msg: "You are running {{ ansible_distribution }} {{ ansible_distribution_version }}"

このシンプルなプレイブックには、2 つのタスクがあります。

  1. 簡単な挨拶メッセージを表示する
  2. 実行中のオペレーティングシステムに関する情報を表示する

このプレイブックを実行して、その動作を確認しましょう。

cd ~/project/ansible-lab
ansible-playbook -i inventory.ini first_playbook.yml

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

PLAY [My First Ansible Playbook] *********************************************************

TASK [Gathering Facts] *******************************************************************
ok: [localhost]

TASK [Display a simple message] **********************************************************
ok: [localhost] => {
    "msg": "Hello from Ansible!"
}

TASK [Display system information] ********************************************************
ok: [localhost] => {
    "msg": "You are running Ubuntu 22.04"
}

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

この出力は以下を示しています。

  • プレイブックが正常に実行されました
  • すべてのタスクが "ok" ステータスで完了しました
  • 各 debug タスクからの出力が表示されます

基本的なプレイブックが動作するようになったので、スクリプトを実行し、その出力をより詳細に表示する方法を探求できます。

スクリプトの実行と出力のキャプチャ

基本的な Ansible 環境が設定できたので、command モジュールと shell モジュールを使用してスクリプトを実行し、その出力をキャプチャする方法を探求しましょう。

Command モジュールと Shell モジュールの違い

Ansible は、コマンドを実行するための 2 つの主要なモジュールを提供します。

  • command: シェルを経由せずにリモートノードでコマンドを実行します。つまり、|><& などのシェル演算子は機能しません。
  • shell: シェルを介してコマンドを実行し、シェル演算子と環境変数を許可します。

実行するシンプルなスクリプトの作成

まず、Ansible で実行できるシンプルなシェルスクリプトを作成しましょう。~/project/ansible-lab ディレクトリに system_info.sh という名前のファイルを作成します。

cd ~/project/ansible-lab

WebIDE で、次の内容のファイルを作成します。

#!/bin/bash

echo "=== System Information ==="
echo "Hostname: $(hostname)"
echo "Kernel Version: $(uname -r)"
echo "CPU Info: $(grep 'model name' /proc/cpuinfo | head -1 | cut -d':' -f2 | xargs)"
echo "Memory Info: $(free -h | grep Mem | awk '{print $2 " total, " $3 " used, " $4 " free"}')"
echo "Disk Usage: $(df -h / | grep / | awk '{print $5 " of " $2 " used"}')"

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

chmod +x ~/project/ansible-lab/system_info.sh

次に、このスクリプトを手動で実行して、どのような出力が生成されるかを確認します。

./system_info.sh

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

=== System Information ===
Hostname: labex-xxxxxxxx
Kernel Version: 5.15.0-xx-generic
CPU Info: Intel(R) Xeon(R) xxxxxx
Memory Info: 8.0G total, 1.2G used, 5.8G free
Disk Usage: 15% of 50G used

Ansible でのスクリプトの実行

次に、このスクリプトを実行してその出力をキャプチャする新しいプレイブックを作成しましょう。~/project/ansible-lab ディレクトリに script_output.yml という名前のファイルを作成します。

---
- name: Run Script and Capture Output
  hosts: localhost
  gather_facts: no

  tasks:
    - name: Run system info script
      command: ./system_info.sh
      register: script_result

    - name: Display script output
      debug:
        msg: "{{ script_result.stdout }}"

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

  1. command モジュールを使用して、system_info.sh スクリプトを実行します。
  2. register キーワードを使用して、出力を script_result という変数に格納します。
  3. debug モジュールを使用して、キャプチャされた出力を表示します。

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

cd ~/project/ansible-lab
ansible-playbook -i inventory.ini script_output.yml

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

PLAY [Run Script and Capture Output] ***************************************************

TASK [Run system info script] ***********************************************************
changed: [localhost]

TASK [Display script output] ************************************************************
ok: [localhost] => {
    "msg": "=== System Information ===\nHostname: labex-xxxxxxxx\nKernel Version: 5.15.0-xx-generic\nCPU Info: Intel(R) Xeon(R) xxxxxx\nMemory Info: 8.0G total, 1.2G used, 5.8G free\nDisk Usage: 15% of 50G used"
}

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

出力が改行文字 (\n) を含む単一の文字列として表示されることに注意してください。次のセクションでは、表示を改善します。

Register 変数の理解

register キーワードは、コマンドの出力だけでなく、いくつかの属性を含む変数を生成します。これらの属性を探求するために、新しいプレイブックを作成しましょう。

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

---
- name: Explore Register Variable
  hosts: localhost
  gather_facts: no

  tasks:
    - name: Run system info script
      command: ./system_info.sh
      register: script_result

    - name: Display all register properties
      debug:
        var: script_result

    - name: Display just stdout
      debug:
        var: script_result.stdout

    - name: Display stdout as a list of lines
      debug:
        var: script_result.stdout_lines

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

ansible-playbook -i inventory.ini register_details.yml

script_result 変数のすべてのプロパティを示す、より詳細な出力が表示されます。これには以下が含まれます。

  • stdout: 標準出力(単一の文字列として)
  • stderr: 標準エラー(存在する場合)
  • rc: リターンコード(0 は成功を意味します)
  • stdout_lines: 標準出力が改行で分割されたリスト

最後のタスクは、出力を行のリストとしてフォーマットするため、非常に読みやすくなります。

高度な出力処理技術

スクリプト出力をキャプチャする基本を理解したので、Ansible プレイブックで出力を処理および表示するための、より高度な技術を探求しましょう。

スクリプトエラーの処理

スクリプトを実行する際には、エラー状態を適切に処理することが重要です。Ansible は、コマンドがゼロ以外の終了コードを返した場合、タスクを失敗としてマークします。エラー処理を実演するプレイブックを作成しましょう。

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

---
- name: Handling Script Errors
  hosts: localhost
  gather_facts: no

  tasks:
    - name: Run a command that might fail
      command: ls /nonexistent_directory
      register: cmd_result
      ignore_errors: yes

    - name: Show error message if command failed
      debug:
        msg: "Command failed with error: {{ cmd_result.stderr }}"
      when: cmd_result.rc != 0

    - name: Show success message if command succeeded
      debug:
        msg: "Command succeeded with output: {{ cmd_result.stdout }}"
      when: cmd_result.rc == 0

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

  1. 存在しないディレクトリをリストしようとします。
  2. コマンドが失敗した場合にプレイブックが停止しないように、ignore_errors: yes を使用します。
  3. 戻りコード (cmd_result.rc) を確認して、コマンドが成功したか失敗したかを判断します。
  4. 結果に基づいて適切なメッセージを表示します。

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

cd ~/project/ansible-lab
ansible-playbook -i inventory.ini error_handling.yml

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

PLAY [Handling Script Errors] ***********************************************************

TASK [Run a command that might fail] ***************************************************
fatal: [localhost]: FAILED! => {"changed": true, "cmd": ["ls", "/nonexistent_directory"], "delta": "0:00:00.003398", "end": "2023-09-15 12:34:56.789012", "msg": "non-zero return code", "rc": 2, "start": "2023-09-15 12:34:56.785614", "stderr": "ls: cannot access '/nonexistent_directory': No such file or directory", "stderr_lines": ["ls: cannot access '/nonexistent_directory': No such file or directory"], "stdout": "", "stdout_lines": []}
...ignoring

TASK [Show error message if command failed] *********************************************
ok: [localhost] => {
    "msg": "Command failed with error: ls: cannot access '/nonexistent_directory': No such file or directory"
}

TASK [Show success message if command succeeded] ****************************************
skipping: [localhost]

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

コマンドが失敗したにもかかわらず、プレイブックが実行を継続し、エラーメッセージが表示されることに注意してください。

マルチライン出力のフォーマット

マルチライン出力を生成する、より複雑なスクリプトを作成し、プレイブックでそれを適切にフォーマットしましょう。

~/project/ansible-lab ディレクトリに package_info.sh という名前のファイルを作成します。

#!/bin/bash

echo "TOP 5 LARGEST INSTALLED PACKAGES"
echo "================================"
dpkg-query -W -f='${Installed-Size}\t${Package}\n' | sort -n -r | head -5

実行可能にします。

chmod +x ~/project/ansible-lab/package_info.sh

次に、このスクリプトを実行して出力を適切にフォーマットするプレイブックを作成します。formatted_output.yml という名前のファイルを作成します。

---
- name: Format Script Output
  hosts: localhost
  gather_facts: no

  tasks:
    - name: Run package info script
      shell: ./package_info.sh
      register: pkg_info

    - name: Display raw output
      debug:
        msg: "{{ pkg_info.stdout }}"

    - name: Display formatted output with a title
      debug:
        msg: |
          Below is the package information:
          --------------------------------
          {% for line in pkg_info.stdout_lines %}
          {{ line }}
          {% endfor %}
          --------------------------------
          Total lines: {{ pkg_info.stdout_lines | length }}

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

  1. package_info.sh スクリプトを実行します。
  2. 生の出力を表示します。
  3. Jinja2 テンプレートを使用して、タイトルとフッターで出力をフォーマットします。

実行してみましょう。

ansible-playbook -i inventory.ini formatted_output.yml

次のように適切にフォーマットされた出力が表示されるはずです。

PLAY [Format Script Output] ***********************************************************

TASK [Run package info script] ********************************************************
changed: [localhost]

TASK [Display raw output] *************************************************************
ok: [localhost] => {
    "msg": "TOP 5 LARGEST INSTALLED PACKAGES\n================================\n112233\tsome-large-package\n99887\tanother-package\n...\n"
}

TASK [Display formatted output with a title] ******************************************
ok: [localhost] => {
    "msg": "Below is the package information:\n--------------------------------\nTOP 5 LARGEST INSTALLED PACKAGES\n================================\n112233\tsome-large-package\n99887\tanother-package\n...\n--------------------------------\nTotal lines: 7"
}

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

条件付きでの出力表示

場合によっては、詳細モードで実行する場合など、特定の条件下でのみ出力を表示したいことがあります。これを行う方法を見てみましょう。

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

---
- name: Conditional Output Display
  hosts: localhost
  gather_facts: yes

  tasks:
    - name: Get disk usage information
      shell: df -h
      register: disk_info

    - name: Display disk usage (always shown)
      debug:
        msg: "{{ disk_info.stdout_lines[0:2] }}"

    - name: Display detailed disk usage (only in verbose mode)
      debug:
        msg: "{{ disk_info.stdout_lines }}"
        verbosity: 1

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

  1. ディスク使用量情報をキャプチャします。
  2. 常に要約(最初の 2 行)を表示します。
  3. 詳細モード(-v フラグを使用)で実行する場合にのみ、詳細情報を表示します。

まず、通常モードで実行してみましょう。

ansible-playbook -i inventory.ini conditional_output.yml

次に、詳細モードで実行してみましょう。

ansible-playbook -i inventory.ini conditional_output.yml -v

詳細モードでは、完全なディスク使用量情報が表示され、通常モードでは要約のみが表示されることに注意してください。

この技術は、デフォルトでは潜在的に機密性の高い、または圧倒的な出力を非表示にし、デバッグに必要な場合にのみ利用できるようにする場合に役立ちます。

まとめ

この実験では、Ansible プレイブックでスクリプト出力をキャプチャして表示するためのさまざまな技術を学びました。

  1. 基本的な Ansible 環境をセットアップし、最初のプレイブックを作成しました。
  2. command モジュールと shell モジュールを使用してスクリプトを実行する方法を学びました。
  3. register ディレクティブを使用してスクリプト出力をキャプチャしました。
  4. さまざまな形式で debug モジュールを使用して出力を表示しました。
  5. エラー状態を処理し、条件付き出力表示を実装しました。
  6. 出力をより読みやすくするために、フォーマット技術を適用しました。

これらのスキルにより、実行中に明確なフィードバックを提供する、より有益な Ansible プレイブックを作成できます。この可視性は、自動化されたプロセスの監視と、問題が発生した場合のトラブルシューティングの両方にとって重要です。

これらの出力処理技術を活用することで、タスクを実行するだけでなく、各ステップで何が起こっているかを明確に伝える、より堅牢な自動化ワークフローを構築できます。これにより、自動化がより透明になり、特にチーム環境や複雑なインフラストラクチャで作業する場合に、保守が容易になります。