Automatycznie uruchamiaj polecenia przez SSH na wielu serwerach

46

W pliku .txt znajduje się lista adresów IP, np .:

1.1.1.1
2.2.2.2
3.3.3.3

Za każdym adresem IP znajduje się serwer, a na każdym serwerze znajduje się sshd działający na porcie 22. Nie każdy serwer znajduje się na known_hostsliście (na moim komputerze, Ubuntu 10.04 LTS / bash).

Jak uruchomić polecenia na tych serwerach i zebrać dane wyjściowe?

Idealnie byłoby, gdyby polecenia były uruchamiane równolegle na wszystkich serwerach.

Będę używać uwierzytelniania za pomocą klucza publicznego na wszystkich serwerach.

Oto niektóre potencjalne pułapki:

  • Ssh monituje mnie o umieszczenie podanego klucza ssh serwera w moim known_hostspliku.
  • Podane polecenia mogą zwrócić niezerowy kod wyjścia, wskazując, że dane wyjściowe są potencjalnie nieprawidłowe. Muszę to rozpoznać.
  • Nie można nawiązać połączenia z danym serwerem, na przykład z powodu błędu sieci.
  • Powinien istnieć limit czasu na wypadek, gdyby polecenie działało dłużej niż oczekiwano lub serwer przestał działać podczas uruchamiania polecenia.

Serwery to AIX / ksh (ale myślę, że to naprawdę nie ma znaczenia.

LanceBaynes
źródło
1
Myślę, że to nie jest duplikat, ponieważ wspomniany link nie zawiera nawet SSH.
LanceBaynes
4
Jeśli jeszcze tego nie zrobiłeś, powinieneś skonfigurować serwery ssh na wszystkich komputerach, utworzyć parę klucz prywatny / publiczny na komputerze, z którego pracujesz i skopiować klucz publiczny na konta na serwerze, aby zapobiec dalszym kłopotom z hasłem. Dotyczy to mojej odpowiedzi, a także @ demure.
Anthon

Odpowiedzi:

14

Zakładając, że nie możesz zainstalować pssh lub innych, możesz zrobić coś podobnego do:

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"
Arcege
źródło
1
co dokładnie czeka w tym skrypcie? ty!
LanceBaynes
co się stanie, jeśli klucza serwera nie ma w moim pliku know_hosts?
LanceBaynes
5
umieszczanie skryptów w tle tworzy procesy potomne. Po zakończeniu procesu potomnego „gniazdo” procesu i zasoby pozostają w systemie, dopóki proces nadrzędny nie zakończy się lub proces nadrzędny „nie poczeka” na dziecko. Te procesy „zakończone przez wciąż obecne” są nazywane procesami „zombie”. Dobrym zachowaniem jest sprzątanie po procesie dziecka i odzyskiwanie zasobów.
Arcege,
1
Jeśli nie wiadomo, to może to zepsuć, ale możesz dodać, -o StrictHostKeyChecking=noaby tego uniknąć. Lepiej jednak najpierw przeskanować wszystkie serwery z wiersza polecenia, aby dodać klucze hosta.
Arcege,
1
Jak wspomniałem, po umieszczeniu programu ssh w tle i po jego zakończeniu zasoby są nadal przechowywane. waitKomenda odzyskuje te zasoby, w tym kodzie proces return (jak processs wyszły). Następnie, jeśli później w programie umieścisz inny proces, powiedzmy kompresję, w tle i trzeba na nią poczekać, to bez tej pętli oczekiwanie odzyska jeden z ukończonych programów ssh, a nie kompresję - co może nadal biegać. Otrzymasz status zwrotu niewłaściwego procesu potomnego. Dobrze jest posprzątać po sobie.
Arcege
61

Istnieje kilka narzędzi, które umożliwiają logowanie się i wykonywanie serii poleceń na wielu komputerach jednocześnie. Oto kilka:

Caleb
źródło
1
Możesz dodać pdsh do listy.
Riccardo Murri,
1
Uznałem, że klastrowanie jest dość intuicyjne w użyciu. Tylko moje 2 centy ...
josinalvo,
1
Często używam pssh. Działa bardzo dobrze, chociaż chciałbym powiedzieć, że niektóre zdalne polecenia będą miały niezerowy kod wyjścia, a to nie oznacza błędu. To jednak czysto kosmetyczne.
Anthony Clark
1
@AnthonyClark możesz dołączyć do tych poleceń coś w rodzaju „|| true”.
exic
16

Jeśli lubisz pisać w skryptach w Pythonie bardziej niż bashskrypty, to Fabric może być dla Ciebie narzędziem.

Ze strony głównej Fabric :

Fabric to biblioteka Pythona (w wersji 2.5 lub nowszej) i narzędzie wiersza polecenia do usprawnienia korzystania z SSH do wdrażania aplikacji lub zadań administracyjnych w systemie.

Zapewnia podstawowy zestaw operacji do wykonywania lokalnych lub zdalnych poleceń powłoki (normalnie lub przez sudo) i przesyłania / pobierania plików, a także funkcje pomocnicze, takie jak monitowanie działającego użytkownika o wprowadzenie danych lub przerywanie wykonywania.

Typowe zastosowanie polega na utworzeniu modułu Python zawierającego jedną lub więcej funkcji, a następnie uruchomieniu ich za pomocą narzędzia wiersza poleceń fab.

Riccardo Murri
źródło
Materiał v1 był niesamowity. Niestety, Fabric v2 usunął większość funkcji, które uczyniły go przydatnym w tym przypadku użycia - obecnie nie polecałby (czerwiec 2018).
Meekohi
11

Używam do tego GNU równoległego , szczególnie możesz użyć tego przepisu:

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

Z your.txtbycia plik z serwera adres IP / nazwami.

Anthon
źródło
nie ma innego sposobu, tylko używając ssh Ponieważ korzystam z serwerów mojej firmy, nie chcę instalować dodatkowych pakietów
Özzesh
Jasne, kiedyś to robiłem, zanim jeszcze sshistniałem, ale potrzebujesz sposobu, aby zalogować się na inne komputery, a te sposoby były mniej bezpieczne (jak rsh). Nie opisujesz tego, czego używasz teraz, aby przejść z maszyny na maszynę ( telnet?, rsh?).
Anthon
1
@ Özzesh tak tylko na kontrolerze
Anthon
1
@ Özzesh Sprawdź, czy powód, dla którego nie instalujesz GNU Parallel, znajduje się na stronie oletange.blogspot.dk/2013/04/why-not-install-gnu-parallel.html
Ole Tange
1
@OleTange Właśnie zdałem sobie sprawę, kto skomentował moją odpowiedź% -). Dzięki za to doskonałe oprogramowanie.
Anthon
8

Bardzo podstawowa konfiguracja:

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

Uwierzytelnianie za pomocą nazwy / hasła nie jest naprawdę dobrym pomysłem. W tym celu należy skonfigurować klucz prywatny:

ssh-keygen && for host in $(cat hosts.txt); do ssh-copy-id $host; done
michas
źródło
1
tego szukałem !!!!! Dzięki michas
Özzesh
powyższy skrypt działa dobrze dla mnie, ale po uruchomieniu na 10 serwerach skrypt nie odpowiada. Jak mogę się wylogować z serwera ssh, z którym jestem połączony?
Özzesh
Nie musisz jawnie się wylogowywać. Ten „skrypt” będzie działał tylko ssh $host $commanddla każdego hosta. Spróbuj uruchomić te polecenia ręcznie, aby dowiedzieć się, co się dzieje.
michas
4

Sugeruję Ansible.cc . To menedżer konfiguracji i dyspozytor poleceń.

Tomek
źródło
2

Myślę, że szukasz pssh i powiązanych równoległych wersji zwykłego scp, rsync itp.

unclejamil
źródło
To jeden głos od usunięcia, ale ta późniejsza odpowiedź to +10. Ma sens
Michael Mrozek
@MichaelMrozek Jest gorzej niż wiesz. Drugi z dwóch VTD jest mój na wypadek szczęśliwego kliknięcia. Od kilku dni mam tę kartę otwartą i mam zamiar oflagować Cię lub pingować, aby przywrócić mój VTD, jeśli został usunięty. Być może możesz po prostu odwrócić go teraz, aby wyczyścić głosy.
Caleb
@Caleb Naprawiono
Michael Mrozek
2

Zbudowałem narzędzie typu open source o nazwie Overcast, aby ułatwić tego typu rzeczy.

Najpierw zdefiniuj swoje serwery:

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

Następnie możesz uruchamiać na nich wiele poleceń i plików skryptów, sekwencyjnie lub równolegle, na przykład:

overcast run vm.* uptime "free -m" /path/to/script --parallel
Andrew Childs
źródło
2

W projekcie Hypertable niedawno dodano narzędzie ssh dla wielu hostów. To narzędzie jest zbudowane przy pomocy libssh i ustanawia połączenia oraz wydaje polecenia asynchronicznie i równolegle dla uzyskania maksymalnej równoległości. Aby uzyskać pełną dokumentację, zobacz Narzędzie SSH dla wielu hostów . Aby uruchomić polecenie na zestawie hostów, uruchom je w następujący sposób:

$ ht ssh 1.1.1.1,2.2.2.2,3.3.3.3 uptime

Możesz także podać nazwę hosta lub wzorzec IP, na przykład:

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

Obsługuje również --random-start-delay <millis>opcję, która opóźnia uruchomienie polecenia na każdym hoście o losowy przedział czasu od 0 do <millis>milisekund. Tej opcji można użyć, aby uniknąć problemów ze stadem grzmotów, gdy uruchamiane polecenie uzyskuje dostęp do zasobu centralnego.

Doug ocenił
źródło
2

Opracowałem Collectnode Bardzo prosty i skuteczny do wykonywania zadań na kilku serwerach (w tym Windows)

Jak korzystać z CollectNode:

  1. Utwórz listę serwerów, aby pracować z:

    # cat hosts.file
    server1
    server2
    server3
    server4
    server5
    
  2. Wykonaj CollectNode, przekazując listę serwów:

    collectnode --file servers.txt --command='cat /etc/httpd/conf/httpd.conf |grep ^User'
    
  3. Opcjonalnie możliwe jest filtrowanie wyników, na przykład to polecenie wyświetla tylko serwer, na którym warunek jest spełniony.

    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/

fvidalmolina
źródło
1
Wygląda na to, że jesteś programistą CollectNode. W takim przypadku należy ujawnić, że w odpowiedzi jest to spam.
muru
przepraszam, to nie był mój zamiar, odpowiedź zmodyfikowana, by była bardziej szczegółowa.
fvidalmolina
1

Tylko heads-up na naprawdę miłe pytanie:

Najlepsze rozwiązanie, jakie znalazłem, to nie tak zaskakujące tmux.

Możesz zrobić Ctrl-B: setw panele synchronizacji w tmux dla niesamowitego resut. W tym celu musisz mieć otwarte wszystkie połączenia ssh, w różnych oknach 1 okna Tmux.

Michaił Krutow
źródło
0

Może coś takiego działa, aby uruchomić polecenie na wielu hostach? załóżmy, że wszystkie hosty są skonfigurowane w .ssh / config do logowania bez hasła.

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

Y0NG
źródło
0

Utwórz plik / etc / sxx / hosts

wypełnić się tak:

[grp_ips]
1.1.1.1
2.2.2.2
3.3.3.3

udostępnij klucz ssh na wszystkich komputerach.

Zainstaluj sxx z pakietu:

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

Następnie uruchom polecenie tak:

sxx username@grp_ips "whatever bash command"
ericcurtin
źródło
Gdzie jest zapisany wynik? Jak obsługiwane są niezerowe stany wyjścia? Proszę nie odpowiadać w komentarzach; edytuj swoją odpowiedź, aby była jaśniejsza i bardziej kompletna.
G-Man mówi „Przywróć Monikę”
0

Użyj Paramiko http://www.paramiko.org/ i równoległości opartej na wątku https://docs.python.org/3/library/threading.html. Poniżej kod pozwala na wykonywanie wielu poleceń na każdym serwerze równolegle!

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()

Uwaga: powtórz powyższe instrukcje dla każdego serwera.

Sharma
źródło
0

Myślę, że „oczekuj” jest tym, czego potrzebujesz.
Wiele osób nawet nie wie, że istnieje. Jest to program oparty na tcl, który zadaje pytania i możliwe odpowiedzi w Twoim imieniu. Zajrzyj na https://wiki.tcl-lang.org/page/Expect

Łaskawy
źródło