シェル出力に基づく条件付き実行
Ansible の最も強力な機能の 1 つは、シェルコマンドの出力に基づいて意思決定を行う能力です。このステップでは、条件とフィルターを使用してシェルコマンド出力を処理し、プレイブックをより動的にする方法を学びます。
シェル出力での条件の使用
シェルコマンドの出力に基づいて意思決定を行うプレイブックを作成しましょう。
/home/labex/project
ディレクトリに conditional_playbook.yml
という名前の新しいファイルを作成します。
- 次の内容を追加します。
---
- 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 出力を処理するための組み込み機能があります。
/home/labex/project
ディレクトリに json_output.yml
という名前の新しいファイルを作成します。
- 次の内容を追加します。
---
- 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 を解析し、特定の情報を抽出し、条件に基づいてデータをフィルタリングしていることに注目してください。
シェルコマンドでのエラー処理
シェルコマンドを実行する場合、潜在的なエラーを適切に処理することが重要です。
/home/labex/project
ディレクトリに error_handling.yml
という名前の新しいファイルを作成します。
- 次の内容を追加します。
---
- 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
これは、シェルコマンドを実行するときに、さまざまなエラー状態をキャプチャして対応する方法を示しています。