Wartungsbefehle ausführen und Fehler behandeln

AnsibleBeginner
Jetzt üben

Einführung

Bestehende Wartungsprogramme benötigen sorgfältige Einbindung in deklarative Automatisierung. Sie unterscheiden command, shell und script, übergeben einen Pfad mit Leerzeichen sicher, klassifizieren ausschließlich lesende Ergebnisse und schützen eine tatsächliche Skriptausgabe vor unnötiger Wiederholung. Eine Pipeline und delegierte Controller-Belege machen Ausführungsort und Fehlerweitergabe beobachtbar. Außerdem lösen Sie einen tatsächlichen Fehler wegen fehlender Eingabe aus und beheben ihn.

Einen direkten Befehl mit sicheren Argumenten ausführen

In diesem Schritt untersuchen Sie verwaltete Eingaben mit command, erhalten einen Pfad mit Leerzeichen und klassifizieren die ausschließlich lesende Operation korrekt.

Bevorzugen Sie deklarative Module wie copy und file zur Zustandsverwaltung. Command, shell und script sind nützlich bei der Einbindung bestehender ausführbarer Dateien oder Wartungsprogramme. command führt eine verwaltete ausführbare Datei ohne Shell aus, sodass Pipes und Umleitungen nicht interpretiert werden. Seine Form argv hält jedes Argument separat, einschließlich eines Pfads mit Leerzeichen.

Die vorbereiteten Ziele besitzen jeweils /home/automation/maintenance input.txt mit einer Zeile freigegebener Daten sowie eine Voraussetzung maintenance-ready. Der Controller stellt für die spätere Verwendung ein bestehendes Skript unter scripts/ bereit. Erhalten Sie diese Eingaben.

Wechseln Sie ins Controller-Projekt:

cd /home/labex/project

Erstellen Sie ein Playbook mit argv. Der Pfad mit Leerzeichen ist ein YAML-Listeneintrag. register erfasst das Ergebnis der ausführbaren Datei einschließlich stdout und des numerischen Rückgabecodes rc. Null bedeutet normalerweise Erfolg; ein Befehlsrückgabecode ungleich null lässt die Aufgabe normalerweise fehlschlagen.

cat > maintenance.yml <<'YAML'
- name: Inspect maintenance inputs safely
  hosts: all
  gather_facts: false
  tasks:
    - name: Read the managed input with a space-safe argument list
      ansible.builtin.command:
        argv:
          - /usr/bin/cat
          - /home/automation/maintenance input.txt
      register: input_result
      changed_when: false

    - name: Retain the inspected input in a managed record
      ansible.builtin.copy:
        dest: /home/automation/command-result.txt
        content: "{{ input_result.stdout }}\n"
        mode: "0640"
YAML

Der Befehl cat liest ausschließlich, daher klassifiziert changed_when false sein Ergebnis als unverändert. Diese Einstellung ändert die Meldung, nicht die tatsächliche Wirkung eines Befehls; sie darf nicht zum Verbergen von Änderungen eines verändernden Programms verwendet werden. Die copy-Aufgabe verwendet die zurückgegebene stdout und schreibt einen tatsächlichen verwalteten Datensatz mit ausdrücklichem abschließendem Zeilenumbruch.

Prüfen Sie das Playbook und führen Sie es aus:

ansible-playbook maintenance.yml --syntax-check
ansible-playbook maintenance.yml

Beide Leseaufgaben sollten ok melden, während die erste Datensatzkopie jedes Ziel ändert. Untersuchen Sie die tatsächlichen Datensätze:

ansible all -m ansible.builtin.command -a 'cat /home/automation/command-result.txt'

Jeder sollte Approved maintenance data enthalten. In dieser Core-Version kann command Umgebungsvariablenargumente durch Python expandieren, obwohl es keine Shell aufruft. Verwenden Sie expand_argument_vars false, wenn wörtliche Argumente mit vorangestelltem Dollarzeichen erforderlich sind; für diesen festen Pfad ist dies unnötig.

Ein Controller-Skript übertragen und seine tatsächliche Ausgabe schützen

In diesem Schritt rufen Sie das bereitgestellte controllerseitige Wartungsskript auf beiden Zielen auf und vermeiden unnötige wiederholte Ausführung.

Untersuchen Sie das bereitgestellte Programm vor seiner Ausführung:

cat scripts/host-maintenance.sh

Es prüft die Eingabe maintenance-ready des Ziels, bevor es Ausgabe erstellt. Fehlende Bereitschaft gibt einen Fehler aus und endet mit 42. Andernfalls schreibt es einen geschützten Bericht mit dem tatsächlichen Zielhostnamen und seinem Bezeichnungsargument. Seine kleine Shell-Implementierung ist eine bestehende Integrationseingabe; verwenden Sie deklarative Module für gewöhnliche Dateikonfiguration.

Das script-Modul überträgt eine Controller-Quelle zum Ziel und führt sie dort aus. Dies unterscheidet sich von command, dessen ausführbare Datei bereits auf dem verwalteten Knoten existieren muss. Die folgende Bezeichnung in Anführungszeichen bleibt ein Argument mit Leerzeichen. Der Pfad creates wird auf dem verwalteten Ziel geprüft: Wenn dieser Bericht bereits existiert, wird das Skript übersprungen.

Hängen Sie die Skriptaufgabe an:

cat >> maintenance.yml <<'YAML'

    - name: Run the supplied controller script once per target report
      ansible.builtin.script:
        cmd: /home/labex/project/scripts/host-maintenance.sh 'Maintenance checked'
        creates: /home/automation/maintenance-run/report.txt
      register: maintenance_result
      failed_when: maintenance_result.rc is defined and maintenance_result.rc != 0
YAML

rc des registrierten Ergebnisses steuert failed_when. Die Prüfung is defined berücksichtigt Ergebnisse ohne Ausführungsrückgabecode. Verwenden Sie weder ignore_errors noch failed_when false, um einen tatsächlichen Skriptfehler in scheinbaren Erfolg zu verwandeln.

Führen Sie das erweiterte Playbook aus:

ansible-playbook maintenance.yml

Beide Ziele sollten Berichte erstellen. Lesen Sie die tatsächlichen Ausgaben:

ansible all -m ansible.builtin.command -a 'cat /home/automation/maintenance-run/report.txt'

Jede sollte ihren eigenen Hostnamen und label=Maintenance checked enthalten. Wiederholen Sie dasselbe Playbook:

ansible-playbook maintenance.yml

Das Skript sollte übersprungen werden, da sein Zielbericht existiert, und beide Zusammenfassungen sollten changed=0 ohne fehlgeschlagene/unerreichbare Ziele melden. Creates ist eine Existenzprüfung, kein Mechanismus zur Inhaltsangleichung: Es repariert keinen beschädigten vorhandenen Bericht und erzeugt ihn bei geänderten Skripteingaben nicht automatisch neu.

Fehler weitergeben und Controller-Belege delegieren

In diesem Schritt verwenden Sie shell nur für eine tatsächliche Pipeline, speichern separate Controller-Belege und erproben einen sichtbaren Skriptfehler, ohne ihn zu unterdrücken.

Eine Pipe verbindet die Ausgabe eines Befehls mit der Eingabe eines anderen und benötigt daher shell. Bash-pipefail lässt einen fehlschlagenden Befehl innerhalb einer Pipeline einen Fehler erzeugen, statt ihn durch einen erfolgreichen letzten Befehl wc verbergen zu lassen. Die folgende Pipeline zählt nur Eingabezeilen; changed_when false ist angemessen, weil sie ohne Änderung des Zielzustands liest. failed_when verwirft außerdem eine unerwartete Zeilenzahl.

Erstellen Sie ein Controller-Belegverzeichnis. Jede delegierte Kopie verwendet den ursprünglichen Inventarnamen in einem separaten Dateinamen und verhindert so, dass Hosts einen gemeinsamen Beleg überschreiben:

mkdir -p receipts

Hängen Sie Pipeline- und Belegaufgaben an. delegate_to localhost führt ausschließlich die Belegaufgabe auf dem Controller aus; inventory_hostname identifiziert weiterhin das ursprüngliche Ziel. become false hält Controller-Dateierstellung unter dem gewöhnlichen Konto labex.

cat >> maintenance.yml <<'YAML'

    - name: Count managed input lines with explicit pipeline failure propagation
      ansible.builtin.shell: |
        set -o pipefail
        cat '/home/automation/maintenance input.txt' | wc -l
      args:
        executable: /bin/bash
      register: line_result
      changed_when: false
      failed_when: line_result.rc != 0 or (line_result.stdout | trim) != '1'

    - name: Store a per-target receipt on the controller
      ansible.builtin.copy:
        dest: "/home/labex/project/receipts/{{ inventory_hostname }}.txt"
        content: |
          host={{ inventory_hostname }}
          input_lines={{ line_result.stdout | trim }}
        mode: "0640"
      delegate_to: localhost
      become: false
YAML

Führen Sie den vollständigen Wartungsablauf aus:

ansible-playbook maintenance.yml

Untersuchen Sie beide Controller-Belege. Jeder muss seinen eigenen ursprünglichen Host und input_lines=1 identifizieren:

cat receipts/web1.txt receipts/web2.txt

Erproben Sie nun den tatsächlichen Fehlerzweig des Skripts auf web1. Entfernen Sie seinen durch creates geschützten Bericht und seine Bereitschaftseingabe mit dem file-Modul; dies sind absichtliche temporäre Änderungen innerhalb des Schulungsknotens:

ansible web1 -m ansible.builtin.file -a 'path=/home/automation/maintenance-run/report.txt state=absent'
ansible web1 -m ansible.builtin.file -a 'path=/home/automation/maintenance-ready state=absent'

Die nächste Ausführung sollte die Skriptaufgabe auf web1 mit rc 42 und der Meldung zur fehlenden Eingabe fehlschlagen lassen. || lässt den Terminalablauf nach diesem erwarteten Playbook-Rückgabewert ungleich null weiterlaufen; es ändert die Fehlerklassifizierung von Ansible nicht:

ansible-playbook maintenance.yml || printf 'Expected missing-readiness failure\n'

Untersuchen Sie den Berichtspfad; web1 darf nach dem fehlgeschlagenen Skript keinen erfundenen Erfolgsbericht besitzen:

ansible web1 -m ansible.builtin.stat -a 'path=/home/automation/maintenance-run/report.txt'

Stellen Sie die Bereitschaftseingabe aus einer exakten Controller-Quelle wieder her und führen Sie den vollständigen Ablauf erneut aus:

printf 'Ready\n' > ready.txt
ansible web1 -m ansible.builtin.copy -a 'src=/home/labex/project/ready.txt dest=/home/automation/maintenance-ready mode=0644'
ansible-playbook maintenance.yml

Web1 sollte seinen Bericht erfolgreich neu erzeugen. Die letzte Wiederholung sollte keine Änderungen, unerreichbaren Ziele oder Fehler haben:

ansible-playbook maintenance.yml

Ausschließlich lesende Untersuchungen laufen weiterhin, das geschützte Skript überspringt bestehende Berichte, und jeder delegierte Beleg bleibt auf dem Controller. Dies erhält tatsächliche Fehlersignale und hält erfolgreiche wiederholte Ausführung zugleich stabil.

Zusammenfassung

Sie haben argv für direkte verwaltete Ausführung, script für Programmübertragung vom Controller zum Ziel und shell ausschließlich für eine tatsächliche Pipeline mit ausdrücklicher Fehlerweitergabe verwendet. Wahrheitsgetreue Änderungsmeldung für Leseoperationen, eine tatsächliche creates-Prüfung und nicht unterdrückte Rückgabecodes hielten Ergebnisse aussagekräftig. Delegierte hostspezifische Belege zeigten Controller-Ausführung, und die Übung mit fehlender Eingabe endete in einem wiederhergestellten stabilen Ablauf.