Automatische Ausführung von Befehlen über SSH auf vielen Servern


46

In einer TXT-Datei befindet sich eine Liste mit IP-Adressen, z.

1.1.1.1
2.2.2.2
3.3.3.3

Hinter jeder IP-Adresse steht ein Server und auf jedem Server läuft ein SSHD auf Port 22. Nicht jeder Server ist in der known_hostsListe (auf meinem PC Ubuntu 10.04 LTS / bash).

Wie kann ich Befehle auf diesen Servern ausführen und die Ausgabe erfassen?

Idealerweise möchte ich die Befehle auf allen Servern parallel ausführen.

Ich verwende die Authentifizierung mit öffentlichem Schlüssel auf allen Servern.

Hier sind einige mögliche Fallstricke:

  • Der SSH fordert mich auf, den angegebenen SSH-Schlüssel des Servers in meine known_hostsDatei zu übernehmen.
  • Die angegebenen Befehle geben möglicherweise einen Exit-Code ungleich Null zurück, der angibt, dass die Ausgabe möglicherweise ungültig ist. Ich muss das erkennen.
  • Eine Verbindung zu einem bestimmten Server kann möglicherweise nicht hergestellt werden, z. B. aufgrund eines Netzwerkfehlers.
  • Es sollte eine Zeitüberschreitung geben, falls der Befehl länger als erwartet ausgeführt wird oder der Server während der Ausführung des Befehls ausfällt.

Die Server sind AIX / ksh (aber ich denke, das ist eigentlich egal.



1
Ich denke, es ist kein Duplikat, weil der Link, den Sie erwähnen, nicht einmal SSH enthält.
LanceBaynes

4
Wenn Sie dies nicht getan haben, sollten Sie ssh-Server auf allen Computern einrichten, auf dem Computer, auf dem Sie arbeiten, ein Paar aus privatem und öffentlichem Schlüssel erstellen und den öffentlichen Schlüssel auf die Konten auf dem Server kopieren, um weitere Probleme mit dem Kennwort zu vermeiden. Das gilt für meine Antwort und auch für @ demure.
Anthon

Antworten:


14

Angenommen, Sie sind nicht in der Lage, pssh oder andere zu installieren, können Sie Folgendes tun:

tmpdir=${TMPDIR:-/tmp}/pssh.$$
mkdir -p $tmpdir
count=0
while IFS= read -r userhost; do
    ssh -n -o BatchMode=yes ${userhost} 'uname -a' > ${tmpdir}/${userhost} 2>&1 &
    count=`expr $count + 1`
done < userhost.lst
while [ $count -gt 0 ]; do
    wait $pids
    count=`expr $count - 1`
done
echo "Output for hosts are in $tmpdir"

1
Was genau macht Warten in diesem Skript? ty!
LanceBaynes

Was passiert, wenn sich ein Serverschlüssel nicht in meiner Datei knows_hosts befindet?
LanceBaynes

5
Wenn Sie Skripte in den Hintergrund stellen, werden untergeordnete Prozesse erstellt. Wenn ein untergeordneter Prozess beendet wird, bleiben der 'Slot' und die Ressourcen des Prozesses im System, bis der übergeordnete Prozess beendet wird oder der übergeordnete Prozess auf das untergeordnete Prozess wartet. Diese Prozesse, die von noch vorhandenen beendet werden, werden als "Zombie" -Prozesse bezeichnet. Es ist ein gutes Verhalten, aufzuräumen, nachdem das Kind Ressourcen bearbeitet und zurückgefordert hat.
Arcege

1
Wenn es nicht bekannt ist, könnte das zu Problemen führen, aber Sie können hinzufügen -o StrictHostKeyChecking=no, um dies zu vermeiden. Es ist jedoch besser, zuerst alle Server über eine Befehlszeile zu scannen, damit die Hostschlüssel hinzugefügt werden können.
Arcege

1
Wie bereits erwähnt, bleiben die Ressourcen auch nach dem Einfügen des ssh-Programms in den Hintergrund und nach dem Beenden erhalten. Der waitBefehl fordert diese Ressourcen zurück, einschließlich des Rückkehrcodes des Prozesses (wie die Prozesse beendet wurden). Wenn Sie später im Programm einen anderen Prozess, zum Beispiel eine Komprimierung, in den Hintergrund stellen und darauf warten müssen, wird ohne diese Schleife eines der abgeschlossenen ssh-Programme zurückgefordert, nicht die Komprimierung - was möglicherweise immer noch der Fall ist in Betrieb sein. Sie erhalten einen Rückgabestatus für den falschen untergeordneten Prozess. Es ist gut, nach sich selbst aufzuräumen.
Arcege

61

Es gibt verschiedene Tools, mit denen Sie sich auf mehreren Computern gleichzeitig anmelden und eine Reihe von Befehlen ausführen können. Hier sind ein paar:


1
Möglicherweise möchten Sie pdsh zur Liste hinzufügen .
Riccardo Murri

1
Ich fand Clustersh ziemlich intuitiv zu bedienen. Nur meine 2 Cent ...
Josinalvo

1
Ich benutze pssh häufig. Es funktioniert sehr gut, obwohl ich wünschte, ich könnte es sagen, dass bestimmte Remote-Befehle einen Exit-Code ungleich Null haben, und das bedeutet keinen Fehler. Das ist aber rein kosmetisch.
Anthony Clark

1
@AnthonyClark Sie könnten an diese Befehle so etwas wie "|| true" anhängen.
Exic

16

Wenn Sie mehr mit Python- Skripten als mit bashSkripten zu tun haben , ist Fabric möglicherweise das richtige Werkzeug für Sie.

Von der Fabric-Homepage :

Fabric ist eine Python-Bibliothek (2.5 oder höher) und ein Befehlszeilentool zur Optimierung der Verwendung von SSH für die Anwendungsbereitstellung oder für Systemverwaltungsaufgaben.

Es bietet eine Reihe grundlegender Vorgänge zum Ausführen von lokalen oder Remote-Shell-Befehlen (normalerweise oder über sudo) und zum Hochladen / Herunterladen von Dateien sowie zusätzliche Funktionen, z. B. das Auffordern des aktiven Benutzers zur Eingabe oder das Abbrechen der Ausführung.

In der Regel wird ein Python-Modul erstellt, das eine oder mehrere Funktionen enthält, und diese dann über das Befehlszeilentool fab ausgeführt.


Fabric v1 war unglaublich. Leider hat Fabric v2 die meisten Funktionen entfernt, die es für diesen Anwendungsfall nützlich gemacht haben - derzeit nicht empfohlen (Juni 2018).
Meekohi

11

Ich benutze GNU parallel dazu , insbesondere können Sie dieses Rezept verwenden:

parallel --tag --nonall --slf your.txt command

Mit your.txtder Datei mit der Server-IP-Adresse / Namen.


gibt es keine andere Möglichkeit nur mit ssh Da ich meine Unternehmensserver verwende, möchte ich keine zusätzlichen Pakete installieren
Özzesh

Natürlich habe ich das sshauch schon früher gemacht, aber Sie müssen sich auf eine Art und Weise bei den anderen Computern anmelden und diese Art und Weise war früher weniger sicher (wie rsh). Sie beschreiben nicht, was Sie jetzt verwenden, um von Maschine zu Maschine zu gelangen ( telnet?, rsh?).
Anthon

1
@ Özzesh ja nur auf dem Controller
Anthon

1
@ Özzesh Sehen Sie, ob Ihr Grund, GNU Parallel nicht zu installieren, auf oletange.blogspot.dk/2013/04/why-not-install-gnu-parallel.html
Ole Tange

1
@OleTange Hab gerade gemerkt, wer meine Antwort% -) kommentiert hat. Vielen Dank für diese hervorragende Software.
Anthon

8

Sehr einfaches Setup:

for host in $(cat hosts.txt); do ssh "$host" "$command" >"output.$host"; done

Die Authentifizierung mit Name / Passwort ist wirklich keine gute Idee. Sie sollten dafür einen privaten Schlüssel einrichten:

ssh-keygen && for host in $(cat hosts.txt); do ssh-copy-id $host; done

1
das ist das, wonach ich gesucht habe !!!!! Thanks michas
Özzesh

Das obige Skript funktioniert gut für mich, aber nach der Ausführung auf 10 Servern reagiert das Skript nicht mehr. Wie kann ich mich vom SSH-Server abmelden, mit dem ich verbunden bin?
Özzesh

Sie müssen sich nicht explizit abmelden. Dieses "Skript" wird nur ssh $host $commandfür jeden Host ausgeführt. Versuchen Sie, diese Befehle manuell auszuführen, um herauszufinden, was gerade passiert.
Michas


2

Ich denke, Sie suchen nach pssh und den zugehörigen parallelen Versionen des üblichen scp, rsync usw.


Dies ist eine Stimme von der Löschung entfernt, aber diese spätere Antwort ist bei +10. Sinnvoll
Michael Mrozek

@MichaelMrozek Es ist schlimmer als du weißt. Der zweite der beiden VTDs ist meiner wegen eines Click-Happy-Unfalls. Ich habe diese Registerkarte für ein paar Tage geöffnet, um Sie zu markieren oder zu pingen, um meine VTD zurückzusetzen, wenn sie gelöscht wurde. Vielleicht können Sie es jetzt einfach umdrehen, um die Stimmen zu löschen.
Caleb

@Caleb Behoben
Michael Mrozek

2

Ich habe ein Open-Source-Tool namens Overcast entwickelt , um dies zu vereinfachen.

Zuerst definieren Sie Ihre Server:

overcast import vm.01 --ip 1.1.1.1 --ssh-key /path/to/key
overcast import vm.02 --ip 2.2.2.2 --ssh-key /path/to/key

Anschließend können Sie mehrere Befehle und Skriptdateien nacheinander oder parallel ausführen.

overcast run vm.* uptime "free -m" /path/to/script --parallel

2

Das Hypertable- Projekt hat kürzlich ein Multi-Host-SSH-Tool hinzugefügt. Dieses Tool wurde mit libssh erstellt und stellt Verbindungen her und gibt Befehle asynchron und parallel aus, um maximale Parallelität zu erzielen . Eine vollständige Dokumentation finden Sie unter SSH-Tool für mehrere Hosts . Um einen Befehl auf einer Reihe von Hosts auszuführen, führen Sie ihn wie folgt aus:

$ ht ssh 1.1.1.1,2.2.2.2,3.3.3.3 uptime

Sie können auch einen Hostnamen oder ein IP-Muster angeben, zum Beispiel:

$ ht ssh 1.1.1.[1-99] uptime
$ ht ssh host[00-99] uptime

Es wird auch eine --random-start-delay <millis>Option unterstützt , die den Start des Befehls auf jedem Host um ein zufälliges Zeitintervall zwischen 0 und <millis>Millisekunden verzögert . Diese Option kann verwendet werden, um donnernde Probleme mit der Herde zu vermeiden, wenn der ausgeführte Befehl auf eine zentrale Ressource zugreift.


2

Ich habe collectnode entwickelt . Sehr einfach und effektiv, um Aufgaben auf mehreren Servern auszuführen (Fenster eingeschlossen).

So verwenden Sie CollectNode:

  1. Erstellen Sie die Liste der Server, mit denen Sie arbeiten möchten:

    # cat hosts.file
    server1
    server2
    server3
    server4
    server5
    
  2. Führen Sie CollectNode aus, indem Sie die Liste der Serves übergeben:

    collectnode --file servers.txt --command='cat /etc/httpd/conf/httpd.conf |grep ^User'
    
  3. Optional können die Ergebnisse gefiltert werden. Dieser Befehl zeigt beispielsweise nur den Server an, auf dem die Bedingung erfüllt ist.

    collectnode --file servers.txt --command='cat /etc/httpd/conf/httpd.conf |grep ^User' --where="command contain User"
    

https://collectnode.com/5-tasks-collectnode-can-help-managing-servers/


1
Sie scheinen der Entwickler von CollectNode zu sein. In diesem Fall sollten Sie dies in der Antwort offenlegen, da es sich sonst nur um Spam handelt.
muru

Entschuldigung, das war nicht meine Absicht.
Fvidalmolina

1

Nur ein Headsup für eine wirklich schöne Frage:

Die beste Lösung, die ich gefunden habe, ist, nicht überraschend, tmux.

Sie können Strg-B: Synchronisieren-Fenster in tmux für erstaunliche Ergebnisse setzen. Dazu müssen Sie alle Ihre ssh-Verbindungen in verschiedenen Fenstern von Tmux geöffnet haben.


0

Vielleicht funktioniert so etwas, um Befehl auf mehreren Hosts auszuführen? Angenommen, alle Hosts sind in .ssh / config eingerichtet, um sich ohne Kennwort anzumelden.

$ < hosts.txt xargs -I {} ssh {} command


0

Erstellen Sie eine Datei / etc / sxx / hosts

bevölkern wie folgt:

[grp_ips]
1.1.1.1
2.2.2.2
3.3.3.3

Teilen Sie den SSH-Schlüssel auf allen Computern.

Installieren Sie sxx aus dem Paket:

https://github.com/ericcurtin/sxx/releases

Dann führe den Befehl wie folgt aus:

sxx username@grp_ips "whatever bash command"

Wo steht die Ausgabe? Wie werden Exit-Status ungleich Null behandelt? Bitte antworten Sie nicht in Kommentaren; Bearbeiten Sie Ihre Antwort, um sie klarer und vollständiger zu gestalten.
G-Man sagt, dass Monica am

0

Verwenden Sie Paramiko http://www.paramiko.org/ und Thread-basierte Parallelität https://docs.python.org/3/library/threading.html. Der folgende Code ermöglicht die parallele Ausführung mehrerer Befehle auf jedem Server!

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.load_system_host_keys()
ssh.connect(hostname, port, username, password)
t = threading.Thread(target=tasks[index], args=(ssh, box_ip,))
t.start()

Hinweis: Wiederholen Sie die obigen Anweisungen für jeden Server.


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.