Einführung
Ansible ist ein leistungsstarkes Open-Source-Automatisierungstool, das von Systemadministratoren und DevOps-Experten weit verbreitet ist. Eine seiner wichtigsten Fähigkeiten ist das Ausführen von Shell-Befehlen auf Remote-Hosts und die Verarbeitung ihrer Ausgabe. In diesem praktischen Tutorial erfahren Sie, wie Sie die Ausgabe von Shell-Befehlen in Ansible-Playbooks effektiv erfassen, anzeigen und verarbeiten können. Diese Fähigkeit ist unerlässlich für die Erstellung robuster Automatisierungs-Workflows, die sich an unterschiedliche Systembedingungen anpassen und nützliches Feedback liefern können.
Einrichten Ihres ersten Ansible-Playbooks mit Shell-Befehlen
In diesem Schritt richten wir ein einfaches Ansible-Playbook ein, das Shell-Befehle ausführt und deren Ausgabe erfasst. Dies bildet die Grundlage für fortgeschrittenere Techniken in späteren Schritten.
Installieren von Ansible
Zuerst installieren wir Ansible auf unserem System:
sudo apt update
sudo apt install -y ansible
Überprüfen Sie nun, ob Ansible korrekt installiert wurde:
ansible --version
Sie sollten eine ähnliche Ausgabe wie diese sehen:
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
Erstellen einer Inventory-Datei
Ansible verwendet eine Inventory-Datei, um zu wissen, welche Hosts verwaltet werden sollen. Für dieses Lab erstellen wir ein einfaches Inventory, das nur die lokale Maschine enthält:
- Öffnen Sie Ihre WebIDE und erstellen Sie eine neue Datei namens
inventory.iniim Verzeichnis/home/labex/project. - Fügen Sie der Datei den folgenden Inhalt hinzu:
[local]
localhost ansible_connection=local
Dieses Inventory definiert eine Gruppe namens local, die nur den localhost enthält, und weist Ansible an, sich direkt ohne SSH zu verbinden.
Erstellen Ihres ersten Playbooks
Erstellen wir nun ein einfaches Playbook, das Shell-Befehle ausführt:
- Erstellen Sie eine neue Datei namens
first_playbook.ymlim Verzeichnis/home/labex/project. - Fügen Sie der Datei den folgenden YAML-Inhalt hinzu:
---
- 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 }}"
Dieses Playbook macht Folgendes:
- Zielt auf die Gruppe
localab, die wir in unserem Inventory definiert haben - Überspringt das Sammeln von Fakten (Systeminformationen), um die Dinge einfach zu halten
- Führt einen Shell-Befehl aus, der eine Grußnachricht ausgibt
- Speichert die Ausgabe in einer Variable mithilfe des Schlüsselworts
register - Zeigt die Ausgabe mithilfe des
debug-Moduls an
Ausführen Ihres Playbooks
Führen wir nun das Playbook aus:
ansible-playbook -i inventory.ini first_playbook.yml
Sie sollten eine ähnliche Ausgabe wie diese sehen:
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
Die Ausgabe zeigt, dass unser Playbook erfolgreich ausgeführt wurde, den Shell-Befehl ausführte und dessen Ausgabe anzeigte.
Wichtige Konzepte zum Verständnis
Beachten Sie aus dieser Übung diese wichtigen Konzepte:
- Das
shell-Modul ermöglicht die Ausführung von Shell-Befehlen - Die
register-Direktive erfasst die Ausgabe einer Aufgabe in einer Variable - Das
debug-Modul hilft beim Anzeigen von Variablenwerten - Die Ausgabe von Shell-Befehlen enthält sowohl
stdout(Standardausgabe) als auchstderr(Fehlerausgabe)
Im nächsten Schritt werden wir untersuchen, wie man die Ausgabe von Shell-Befehlen effektiver verarbeitet und formatiert.
Arbeiten mit strukturierter Shell-Befehlsausgabe
Nachdem Sie die Grundlagen der Ausführung von Shell-Befehlen in Ansible verstanden haben, wollen wir uns damit befassen, wie man mit strukturierter Befehlsausgabe arbeitet und diese in verschiedenen Formaten anzeigt.
Verarbeiten von Systeminformationen
Erstellen wir ein praktischeres Playbook, das Systeminformationen sammelt und strukturiert darstellt:
- Erstellen Sie eine neue Datei namens
system_info.ymlim Verzeichnis/home/labex/project. - Fügen Sie den folgenden Inhalt hinzu:
---
- 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 }}"
Dieses Playbook:
- Führt ein mehrzeiliges Shell-Skript aus, das verschiedene Systemdetails sammelt
- Speichert die Ausgabe in der Variable
system_info - Zeigt die Ausgabe zuerst als rohe Zeichenkette und dann als Liste von Zeilen an
Führen Sie das Playbook aus:
ansible-playbook -i inventory.ini system_info.yml
Sie sollten eine Ausgabe sehen, die so aussieht:
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
Beachten Sie, wie die zweite Anzeigaufgabe die Ausgabe als Liste anstelle einer Zeichenkette mit Zeilenumbrüchen anzeigt. Dieses Listenformat erleichtert die Arbeit mit mehrzeiliger Ausgabe.
Arbeiten mit Befehlsergebnissen und Rückgabecodes
Shell-Befehle in Linux geben Exit-Codes zurück, um Erfolg (0) oder Fehler (ungleich 0) anzuzeigen. Ansible erfasst diese im Attribut rc (Return Code) der registrierten Variable.
Erstellen wir ein Playbook, das zeigt, wie man mit Rückgabecodes arbeitet:
- Erstellen Sie eine neue Datei namens
command_results.ymlim Verzeichnis/home/labex/project. - Fügen Sie den folgenden Inhalt hinzu:
---
- 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 }}
Dieses Playbook:
- Führt zwei Testbefehle aus, um zu überprüfen, ob Dateien existieren
- Verwendet
ignore_errors: yes, um zu verhindern, dass das Playbook anhält, wenn ein Befehl fehlschlägt - Zeigt detaillierte Informationen zum Befehlsergebnis an, einschließlich des Rückgabecodes und des Erfolgs-/Fehlerstatus
Führen Sie das Playbook aus:
ansible-playbook -i inventory.ini command_results.yml
Sie sollten eine ähnliche Ausgabe wie diese sehen:
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
Beachten Sie, dass der Rückgabecode 0 für die vorhandene Datei und 1 für die nicht vorhandene Datei ist. Dies zeigt, wie Sie Rückgabecodes verwenden können, um Entscheidungen in Ihren Playbooks zu treffen.
Verstehen der Struktur der registrierten Variable
Die Variable, die von einem Shell-Befehl registriert wird, enthält mehrere nützliche Attribute:
stdout: Die Standardausgabe als einzelne Zeichenkettestdout_lines: Die Standardausgabe aufgeteilt in eine Liste von Zeilenstderr: Die Standardfehlerausgabe als einzelne Zeichenkettestderr_lines: Die Standardfehlerausgabe aufgeteilt in eine Liste von Zeilenrc: Der Rückgabecode (0 für Erfolg, ungleich 0 für Fehler)cmd: Der Befehl, der ausgeführt wurdestartundend: Zeitstempel für den Beginn und das Ende des Befehlsdelta: Die Dauer der Befehlsausführung
Das Verständnis dieser Struktur ist entscheidend für die effektive Arbeit mit der Ausgabe von Shell-Befehlen in Ansible.
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.ymlim 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
whenbasierend 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.ymlim 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.ymlim 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.
Erstellen eines praktischen Tools zur Verarbeitung der Shell-Ausgabe
In diesem letzten Schritt werden wir alles, was wir gelernt haben, zusammenführen, um ein praktisches Ansible-Playbook zu erstellen, das Systeminformationen sammelt, verarbeitet und einen Bericht generiert. Dies stellt ein reales Szenario dar, in dem die Fähigkeiten von Ansible zur Verarbeitung von Shell-Befehlen äußerst nützlich sein können.
Erstellen eines Tools zur Erstellung von Systeminformationsberichten
Erstellen wir ein umfassendes Tool zur Erfassung von Systeminformationen:
- Erstellen Sie eine neue Datei namens
system_report.ymlim Verzeichnis/home/labex/project. - Fügen Sie den folgenden Inhalt hinzu:
---
- 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
Dieses Playbook:
- Sammelt umfassende Systeminformationen mithilfe einer Reihe von Shell-Befehlen
- Schreibt die Informationen in eine Berichtdatei
- Überprüft, ob der Bericht erfolgreich erstellt wurde
- Zeigt den Inhalt des Berichts an
- Analysiert die Festplattenauslastungsdaten
- Generiert entsprechende Warnungen basierend auf der Analyse
Führen Sie das Playbook aus:
ansible-playbook -i inventory.ini system_report.yml
Sie sehen eine umfassende Ausgabe, die die Ausführung des Playbooks und den vollständigen Systembericht zeigt. Die Ausgabe ist recht lang, daher hier nur ein Beispiel dafür, was Sie sehen könnten:
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",
...
Untersuchen des Berichts
Untersuchen wir den von uns generierten Systembericht:
cat /tmp/system_report.txt
Dadurch wird der vollständige Bericht angezeigt, der von unserem Playbook generiert wurde.
Erstellen eines benutzerdefinierten Shell-Skripts und Aufrufen aus Ansible
Für komplexere Operationen ist es manchmal einfacher, ein dediziertes Shell-Skript zu erstellen und es von Ansible aus aufzurufen:
- Erstellen Sie eine neue Datei namens
disk_analyzer.shim Verzeichnis/home/labex/project. - Fügen Sie den folgenden Inhalt hinzu:
#!/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
- Machen Sie das Skript ausführbar:
chmod +x /home/labex/project/disk_analyzer.sh
- Erstellen Sie ein neues Playbook, um dieses Skript aufzurufen:
touch /home/labex/project/call_script.yml
- Fügen Sie den folgenden Inhalt zum Playbook hinzu:
---
- 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")
- Führen Sie das Playbook aus:
ansible-playbook -i inventory.ini call_script.yml
Sie sollten eine ähnliche Ausgabe wie diese sehen:
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
Dieser Ansatz kombiniert die Leistungsfähigkeit von Shell-Skripten mit den Automatisierungsfunktionen von Ansible. Das Shell-Skript übernimmt die komplexe Logik für die Festplattenanalyse, während Ansible die Ausführung und weitere Verarbeitung der Ergebnisse verwaltet.
Wichtige Erkenntnisse
Durch dieses Lab haben Sie mehrere wichtige Techniken für die Arbeit mit der Ausgabe von Shell-Befehlen in Ansible gelernt:
- Wie man Shell-Befehle ausführt und deren Ausgabe erfasst
- Wie man die Befehlsausgabe zur Anzeige verarbeitet und formatiert
- Wie man die bedingte Ausführung basierend auf Befehlsergebnissen verwendet
- Wie man JSON-Ausgabe und Fehlerbedingungen behandelt
- Wie man praktische Tools erstellt, die Shell-Befehle mit den Automatisierungsfunktionen von Ansible kombinieren
Diese Fähigkeiten sind von unschätzbarem Wert, wenn Sie komplexere Automatisierungslösungen mit Ansible erstellen.
Zusammenfassung
In diesem Lab haben Sie gelernt, wie man effektiv mit der Ausgabe von Shell-Befehlen in Ansible-Playbooks arbeitet. Beginnend mit den Grundlagen der Ausführung von Shell-Befehlen und der Erfassung ihrer Ausgabe, sind Sie zu fortgeschritteneren Techniken wie bedingter Ausführung, Fehlerbehandlung und der Verarbeitung strukturierter Datenformate wie JSON übergegangen.
Sie haben mehrere wichtige Fähigkeiten gemeistert:
- Ausführen von Shell-Befehlen in Ansible-Playbooks mit dem
shell-Modul - Erfassen der Befehlsausgabe mit der Direktive
register - Anzeigen der Ausgabe mit dem
debug-Modul - Verarbeiten der Ausgabe mit Jinja2-Filtern und -Bedingungen
- Erstellen praktischer Automatisierungstools, die Ansible mit Shell-Skripten kombinieren
Diese Techniken ermöglichen es Ihnen, dynamischere und reaktionsfähigere Automatisierungs-Workflows zu erstellen, die sich an unterschiedliche Systembedingungen anpassen und nützliches Feedback über die durchgeführten Operationen geben können.
Denken Sie auf Ihrer Ansible-Reise daran, dass die integrierten Module von Ansible oft eine robustere und portablere Lösung für gängige Aufgaben darstellen, auch wenn Shell-Befehle eine große Flexibilität bieten. Verwenden Sie Shell-Befehle, wenn Sie vorhandene Shell-Skripte nutzen oder komplexe Operationen durchführen müssen, die nicht einfach von Ansible-Modulen gehandhabt werden können.


