Ausführen von Befehlen auf Remote-Servern mit dem Ansible-Shell-Modul
Ansible ist ein weit verbreitetes Konfigurationsmanagement-Tool, das die Verwaltung mehrerer Server vereinfacht. Es optimiert Aufgaben wie die Serverkonfiguration und die Installation von Anwendungen durch Automatisierung, sodass Sie zahlreiche Remote-Server verwalten und Aufgaben nacheinander von einem zentralen Kernknoten aus ausführen können. Außerdem ist Ansible wegen seiner zahlreichen Module und seiner Fähigkeit beliebt, nahtlos über SSH zu arbeiten, ohne dass zusätzliche Software auf den Zielservern installiert werden muss.
In diesem Tutorial lernen wir, wie man mit dem Ansible-Shell-Modul Befehle auf Remote-Servern ausführt. Darüber hinaus werden wir uns damit befassen, wie man Ansible-Ad-hoc-Befehle ausführt und ein Playbook erstellt, um verschiedene Shell-Befehle auszuführen.
Voraussetzungen
Sie müssen die folgenden Voraussetzungen erfüllen, um das Ansible-Shell-Modul nutzen zu können:
1. In dieser Anleitung verwenden wir Ubuntu 22.04. Ansible sollte also auf Ihrem Ubuntu-System installiert und konfiguriert sein.
2. Es sollte ein Remote-Host konfiguriert sein, auf dem Sie die Befehle mithilfe des Ansible-Shell-Moduls ausführen werden.
Was ist das Ansible-Shell-Modul?
Das Ansible-Shell-Modul ermöglicht es Benutzern, Befehle auf der Shell der Zielsysteme auszuführen. Es ermöglicht Benutzern, komplexe Befehle mit Pipes und Umleitungen auf Remote-Zielen auszuführen, wobei die Originalität der Befehlsausführung gewahrt bleibt.
Bei der Ausführung von Befehlen im Ansible-Shell-Modul werden der Befehlsname sowie Parameter oder Argumente, die durch Leerzeichen getrennt sind, übernommen und diese Befehle auf den Remote-Hosts ausgeführt.
Unterschied: Ansible-Shell-Modul vs. Befehlsmodul
Sowohl das Ansible-Shell-Modul als auch das Befehlsmodul sind sich recht ähnlich und liefern die gleichen Ergebnisse. Es bestehen jedoch einige Unterschiede zwischen diesen beiden Modulen, die wir nachfolgend aufgeführt haben:
- Das Ansible-Shell-Modul unterstützt alle speziellen Operatoren, Umgebungsvariablen, Pipes und Umleitungen. Das Befehlsmodul hingegen unterstützt die Operatoren (<, >, &,;, | |), Umgebungsvariablen und Pipes nicht.
- Das Befehlsmodul erlaubt es Benutzern nicht, Befehle direkt in der Shell auszuführen. In diesem Fall bietet das Ansible-Shell-Modul mehr Flexibilität als das Befehlsmodul. Mit dem Shell-Modul können Sie Befehle direkt in der Shell der Zielhosts ausführen. Es verwendet standardmäßig die „/bin/sh“-Shell, um Befehle auszuführen. Sie können auch andere Shells für die Ausführung von Befehlen auf Remote-Hosts konfigurieren.
- Ansible-Benutzer bevorzugen aus Sicherheitsgründen die Verwendung von Befehlsmodulen bei der Ausführung von Befehlen auf Zielsystemen. Ansible-Run-Befehle im Befehlsmodul sind sicherer und bieten besser vorhersehbare Optionen als das Ansible-Shell-Modul. Darüber hinaus hat das Befehlsmodul keinen Einfluss auf die Remote-Shell-Umgebung des Benutzers.
Erste Schritte mit Ansible-Shell-Befehlen: Ad-hoc-Befehle ausführen
Ad-hoc-Befehle sind Einzeiler-Befehle, die in Zukunft nicht wiederverwendbar sind. Sie können jedoch die Ansible-Ad-hoc-Shell-Befehle verwenden, um einzelne Aufgaben schnell auszuführen. Die grundlegende Syntax von Ad-hoc-Befehlen ist unten angegeben:
ansible [pattern] -m [ansible-module] -a "[Befehl mit Optionen]"
In der obigen Syntax steht das Muster für den Host oder die Hostgruppe aus dem Inventar. Die Option -m gibt das Modul an, und die Option -a nimmt die Befehlsargumente entgegen.
Sehen wir uns ein Beispiel an, um die Syntax der Ansible-Ad-hoc-Befehle zu erläutern. In diesem Beispiel versuchen wir, Datum und Uhrzeit des Zielhosts anzuzeigen. Hier haben wir nur eine Verbindung zu einem Host hergestellt und einen separaten Benutzer namens „ansible“ angelegt. Verwenden Sie den folgenden Befehl, um Datum und Uhrzeit des Remote-Hosts anzuzeigen:
$ ansible 192.168.1.14 -u ansible -m shell -a "timedatectl"
Der oben genannte Ansible-Ad-hoc-Befehl stellt über SSH eine Verbindung zum Remote-Host mit der IP-Adresse „192.168.1.14“ unter Verwendung des Benutzernamens „ansible“ her. Anschließend wird auf dem Remote-Host der Befehl „timedatectl“ ausgeführt, der dazu dient, Informationen über die Datums- und Uhrzeiteinstellungen des Systems anzuzeigen.
$ ansible <ip-address> -u ansible -m shell -a "timedatectl | grep Time"
Mit dem obigen Ansible-Ad-hoc-Befehl wird der Befehl „timedatectl“ ausgeführt und anschließend mithilfe des Befehls „grep“ werden Zeilen gefiltert und angezeigt, die „Time“ enthalten.
Ebenso können Sie Systeminformationen mithilfe des Befehls „uptime“ und der durchschnittlichen Auslastung anzeigen. Verwenden Sie dazu den folgenden Befehl:
$ ansible <ip-address> -u ansible -m shell -a "uptime"
Wenn Sie den obigen Ansible-Shell-Befehl ausführen, wird der Befehl „uptime“ ausgeführt, nachdem eine Verbindung zum Remote-Host hergestellt wurde.
$ ansible <ip-address> -u ansible -m setup
Der obige Befehl verwendet statt des Shell-Moduls das Modul setup und erfasst damit Systemdaten und Informationen (Facts) über den Remote-Host.
Wie verwendet man das Ansible-Shell-Modul?
Bevor Sie die Ansible-Shell-Befehle ausführen, ist es wichtig, dass Sie die grundlegenden Shell-Parameter kennen, die Sie bei der Verwendung des Ansible-Shell-Moduls übergeben müssen:
chdir – Ändert das aktuelle Verzeichnis vor der Befehlsausführung.
cmd – Eine Zeichenkette enthält den auszuführenden Befehl sowie alle zugehörigen Argumente.
executable – Erfordert einen absoluten Pfad, um die vom Benutzer verwendete Shell zu ändern.
removes – Nimmt den Dateinamen entgegen und wird verwendet, um Schritte auszuschließen, wenn eine Datei nicht existiert.
stdin – Ermöglicht es dem Benutzer, die „stdin“ eines Befehls auf einen bestimmten Wert zu setzen.
warn – Aktivierte oder deaktivierte Aufgabenwarnungen. Der Parameter wurde in neueren Ansible-Versionen (ab ansible-core 2.14) entfernt.
Nachdem dies geklärt ist, sehen wir uns einige Beispiele für die Verwendung der Ansible-Shell an.
Ansible-Befehle mit dem Shell-Modul ausführen
Die wahre Stärke von Ansible liegt in der Verwendung von Playbooks, mit denen Sie komplexe Aufgaben auf Zielhosts ausführen können. Neben Ad-hoc-Befehlen können Sie auch das Ansible-Shell-Modul innerhalb von Playbooks nutzen, um Aufgaben für Remote-Hosts zu definieren.
Einen einzelnen Befehl mit dem Ansible-Shell-Modul ausführen
Sie können mit dem Ansible-Shell-Modul auch einen einzelnen Befehl ausführen. Erstellen Sie dazu ein Playbook, zum Beispiel die Datei environment_var.yml, und fügen Sie die folgenden Codezeilen ein:
---
- name: Shell module example
hosts: database_servers
tasks:
- name: Check system information
shell: "df -h"
register: os_info
- debug:
msg: "{{ os_info.stdout_lines }}"
Speichern Sie nun die Änderungen in dieser Datei und beenden Sie den Editor mit „Strg+X“. Führen Sie anschließend dieses Playbook mit dem folgenden Befehl aus:
$ ansible-playbook --ask-become-pass -i hosts environment_var.yml
Nach Ausführung des obigen Befehls zeigt Ansible im Terminal die Ausgabe von df -h für jeden Host und am Ende eine Zusammenfassung wie diese an:
PLAY RECAP ********************************************************************* 192.168.1.14 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Ansible: Ausführen mehrerer Befehle mit dem Shell-Modul
Mit Ansible können Sie mehrere Aufgaben nacheinander ausführen. Um ein Ansible-Playbook zu erstellen, erstellen Sie eine leere Datei in Ihrem Quellcode-Editor. In dieser Anleitung verwenden wir den Nano-Editor, um ein Playbook zu erstellen.
$ sudo nano testplaybook.yml
Fügen Sie den folgenden Inhalt ein:
---
- name: Mehrere Befehle mit dem Shell-Modul ausführen
hosts: database_servers
become: yes
vars:
new_user: deploy
package_name: nginx
tasks:
- name: Benutzer anlegen
shell: id {{ new_user }} || useradd -m {{ new_user }}
- name: Paket-Cache aktualisieren
shell: apt-get update
- name: Paket installieren oder aktualisieren
shell: apt-get install -y {{ package_name }}
- name: Installierte Version anzeigen
shell: nginx -v 2>&1
register: nginx_version
- debug:
msg: "{{ nginx_version.stdout }}"
Das obige Playbook führt mehrere Aufgaben nacheinander aus: Es legt einen Benutzer an, aktualisiert den Paket-Cache und installiert oder aktualisiert das Nginx-Paket auf dem Zielhost. Die Variablen machen das Playbook flexibler und wiederverwendbarer. Für solche Aufgaben gibt es in Ansible auch eigene Module (user, apt), die in der Praxis vorzuziehen sind. Hier dienen sie als Beispiel für das Shell-Modul.
Speichern Sie die Datei mit „Strg+O“ und verlassen Sie den Editor mit „Strg+X“.
Hier verwenden wir die benutzerdefinierte Inventardatei „hosts“. Um dieses Playbook auszuführen, verwenden Sie den folgenden Befehl:
$ ansible-playbook --ask-become-pass -i hosts testplaybook.yml
Im obigen Befehl fordert --ask-become-pass Sie auf, das sudo-Passwort einzugeben. Am Ende zeigt Ansible eine Zusammenfassung wie diese an:
PLAY RECAP ********************************************************************* 192.168.1.14 : ok=6 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Installieren eines Pakets mit dem Ansible-Shell-Modul
Sie können auch ein Paket auf dem Ziel-Remote-Host installieren.
Betrachten Sie das folgende Playbook, um das Paket „apache2“ auf dem Zielhost zu installieren. Hier wird das spezialisierte apt-Modul verwendet:
---
- name: Install apache2
hosts: database_servers
become: yes
tasks:
- name: Update apt cache
apt:
update_cache: yes
- name: Install apache2 package
apt:
name: apache2
state: present
Nach Ausführung des obigen Playbooks werden Sie feststellen, dass apache2 auf den Remote-Servern installiert ist.
Verhindern von Shell-Befehlsinjektionen
Wie bereits erwähnt, gilt das command-Modul in Ansible als sicherere Wahl für die Ausführung von Befehlen auf Remote-Systemen. Es weist jedoch gewisse Einschränkungen hinsichtlich der Funktionalität auf.
Um das shell-Modul sicher zu verwenden, können Sie den Filter quote einsetzen, um Variablen vor potenziellen Befehlsinjektionen zu schützen. Das folgende Beispiel zeigt, wie der Filter angewendet wird:
---
- name: Ansible Quote Filter Example
hosts: database_servers
become: yes
vars:
database_name: mydb
table_name: "my table"
tasks:
- name: Create a table in the {{ database_name }} database
shell: >
mysql -u root -psecret {{ database_name | quote }}
-e "CREATE TABLE `{{ table_name }}` (id INT, name VARCHAR(255));"
In diesem Playbook schützt der Filter quote den Datenbanknamen als Shell-Argument, der Tabellenname wird für MySQL zusätzlich in Backticks gesetzt. Allgemein gilt: Wenn Variablen direkt als Shell-Argumente verwendet werden, schützen Sie sie mit dem Filter quote, zum Beispiel shell: ls -l {{ dir_name | quote }}. So werden Leer- und Sonderzeichen korrekt maskiert und Befehlsinjektionen verhindert.
Fazit
Das Ansible-Shell-Modul ist ein flexibles und robustes Werkzeug, das die Benutzerkontrolle verbessert und die Konfiguration von Remote-Servern vereinfacht. In diesem Artikel haben wir untersucht, wie das Ansible-Shell-Modul verwendet wird, welche Parameter es bietet und welche Argumente erforderlich sind. Wir hoffen, dass Sie mit diesem Wissen das Ansible-Shell-Modul auf Ihrem Linux-System effektiv nutzen können.
Blog