Bedingte Ausführung basierend auf Shell-Ausgabe
Eine der leistungsstärksten Fähigkeiten in Ansible ist die Möglichkeit, Entscheidungen basierend auf der Ausgabe von Shell-Befehlen zu treffen. In diesem Schritt lernen wir, wie man Bedingungen und Filter verwendet, um die Ausgabe von Shell-Befehlen zu verarbeiten und Playbooks dynamischer zu gestalten.
Verwenden von Bedingungen mit Shell-Ausgabe
Erstellen wir ein Playbook, das Entscheidungen basierend auf der Ausgabe von Shell-Befehlen trifft:
- Erstellen Sie eine neue Datei namens
conditional_playbook.yml
im Verzeichnis /home/labex/project
.
- Fügen Sie den folgenden Inhalt hinzu:
---
- 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
Dieses Playbook:
- Führt einen Shell-Befehl aus, um den Festplattenauslastungsprozentsatz auf dem Root-Dateisystem zu überprüfen
- Verwendet die Bedingung
when
basierend auf der Befehlsausgabe
- Verwendet den
int
-Filter, um die Zeichenkettenausgabe zur Vergleichszwecken in eine Ganzzahl umzuwandeln
Führen Sie das Playbook aus:
ansible-playbook -i inventory.ini conditional_playbook.yml
Die Ausgabe variiert je nach Ihrer tatsächlichen Festplattenauslastung, sieht aber in etwa so aus:
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
Beachten Sie, wie Ansible nur eine der bedingten Aufgaben basierend auf dem tatsächlichen Festplattenauslastungswert ausgeführt hat.
Umgang mit JSON-Ausgabe von Befehlen
Viele moderne CLI-Tools geben Daten im JSON-Format zurück. Ansible verfügt über integrierte Funktionen zur Verarbeitung von JSON-Ausgaben:
- Erstellen Sie eine neue Datei namens
json_output.yml
im Verzeichnis /home/labex/project
.
- Fügen Sie den folgenden Inhalt hinzu:
---
- 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"
Dieses Playbook:
- Erstellt eine Beispiel-JSON-Datei zur Demonstration
- Liest die JSON-Datei mit einem Shell-Befehl
- Verwendet den
from_json
-Filter, um die JSON-Zeichenkette in eine Datenstruktur zu parsen
- Durchläuft die Datenstruktur, um Informationen anzuzeigen
- Verwendet bedingte Logik, um nur laufende Dienste zu filtern
Führen Sie das Playbook aus:
ansible-playbook -i inventory.ini json_output.yml
Sie sollten eine ähnliche Ausgabe wie diese sehen:
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
Beachten Sie, wie das Playbook das JSON parst, bestimmte Informationen extrahiert und die Daten basierend auf Bedingungen filtert.
Fehlerbehandlung mit Shell-Befehlen
Bei der Ausführung von Shell-Befehlen ist es wichtig, potenzielle Fehler ordnungsgemäß zu behandeln:
- Erstellen Sie eine neue Datei namens
error_handling.yml
im Verzeichnis /home/labex/project
.
- Fügen Sie den folgenden Inhalt hinzu:
---
- 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' }}
Dieses Playbook:
- Führt Befehle aus, von denen erwartet wird, dass sie fehlschlagen
- Verwendet
ignore_errors: yes
, um die Ausführung des Playbooks fortzusetzen, auch wenn Befehle fehlschlagen
- Zeigt verschiedene Methoden zur Behandlung und Anzeige von Fehlerinformationen
Führen Sie das Playbook aus:
ansible-playbook -i inventory.ini error_handling.yml
Sie sollten eine ähnliche Ausgabe wie diese sehen:
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
Dies zeigt, wie man auf verschiedene Fehlerbedingungen reagieren kann, wenn Shell-Befehle ausgeführt werden.