Come posso automatizzare l'esecuzione in remoto dei comandi su SSH su più server in parallelo?

StackOverflow https://stackoverflow.com/questions/243750

  •  04-07-2019
  •  | 
  •  

Domanda

Ho cercato un po 'domande simili, ma a parte l'esecuzione di un comando o forse alcuni comandi con elementi come:

ssh user@host -t sudo su -

Tuttavia, cosa succede se essenzialmente devo eseguire uno script su (diciamo) 15 server contemporaneamente. È possibile in bash? In un mondo perfetto, devo evitare di installare applicazioni, se possibile, per riuscirci. Per ragioni di cose, diciamo solo che devo fare quanto segue su 10 host:

  1. Distribuisci un nuovo contenitore Tomcat
  2. Distribuire un'applicazione nel contenitore e configurarla
  3. Configura un vhost Apache
  4. Ricarica Apache

Ho uno script che fa tutto questo, ma dipende da me accedere a tutti i server, estrarre uno script da un repository e quindi eseguirlo. Se ciò non è possibile in bash, quali alternative suggerisci? Ho bisogno di un martello più grande, come Perl (Python potrebbe essere preferito poiché posso garantire che Python sia su tutte le scatole in un ambiente RHEL grazie a yum / up2date)? Se qualcuno può indicarmi qualsiasi informazione utile, sarebbe molto apprezzato, specialmente se è fattibile in bash. Mi accontenterò di Perl o Python, ma non li conosco nemmeno (ci sto lavorando). Grazie!

È stato utile?

Soluzione

Spesso userò solo la versione Tcl originale di Expect. Devi solo averlo sul computer locale. Se sono all'interno di un programma che utilizza Perl, lo faccio con Net :: SSH :: Aspettatevi . Altre lingue hanno & Quot simili; prevedono & Quot; strumenti.

Altri suggerimenti

Puoi eseguire uno script locale come mostrato da che e Yang, e / o puoi usare un documento Qui:

ssh root@server /bin/sh <<\EOF  
wget http://server/warfile    # Could use NFS here  
cp app.war /location  
command 1  
command 2  
/etc/init.d/httpd restart  
EOF 

Il problema di come eseguire comandi su più server contemporaneamente è emerso l'altro giorno in una mailing list Perl e darò la stessa raccomandazione Ho dato lì , che deve usare gsh:

http://outflux.net/unix/software/gsh

gsh è simile al " for box in box1_name box2_name box3_name " soluzione già fornita ma trovo che gsh sia più conveniente. Si configura un file / etc / ghosts contenente i propri server in gruppi come web, db, RHEL4, x86_64 o qualsiasi altra cosa (man ghosts) quindi si usa quel gruppo quando si chiama gsh.

[pdurbin@beamish ~]$ gsh web "cat /etc/redhat-release; uname -r"
www-2.foo.com: Red Hat Enterprise Linux AS release 4 (Nahant Update 7)
www-2.foo.com: 2.6.9-78.0.1.ELsmp
www-3.foo.com: Red Hat Enterprise Linux AS release 4 (Nahant Update 7)
www-3.foo.com: 2.6.9-78.0.1.ELsmp
www-4.foo.com: Red Hat Enterprise Linux Server release 5.2 (Tikanga)
www-4.foo.com: 2.6.18-92.1.13.el5
www-5.foo.com: Red Hat Enterprise Linux Server release 5.2 (Tikanga)
www-5.foo.com: 2.6.18-92.1.13.el5
[pdurbin@beamish ~]$

Puoi anche combinare o dividere gruppi fantasma, usando web + db o web-RHEL4, per esempio.

Menzionerò anche che mentre non ho mai usato shmux, il suo sito web contiene un elenco di software (incluso gsh) che consente di eseguire comandi su molti server contemporaneamente. Capistrano è già stato menzionato e (da quello che ho capito) potrebbe anche essere in quella lista.

Dai un'occhiata a Expect (man expect)

Ho svolto attività simili in passato utilizzando Expect.

Puoi reindirizzare lo script locale al server remoto ed eseguirlo con un comando:

ssh -t user@host 'sh' < path_to_script

Questo può essere ulteriormente automatizzato utilizzando l'autenticazione con chiave pubblica e il wrapping con script per eseguire l'esecuzione parallela.

Puoi provare paramiko . È un client SSH di Python puro. Puoi programmare le tue sessioni ssh. Nulla da installare su macchine remote.

Vedi questo ottimo articolo su come usarlo.

Per darti la struttura, senza codice reale.

  1. Usa scp per copiare lo script di installazione / configurazione nella casella di destinazione.
  2. Usa ssh per invocare il tuo script nella casella remota.

pssh può essere interessante poiché, a differenza della maggior parte delle soluzioni menzionate qui, i comandi vengono eseguiti in parallelo .

(Per uso personale, ho scritto una piccola sceneggiatura più semplice molto simile a quella di GavinCattell, è documentato qui - in francese ).

Hai visto cose come Puppet o Cfengine . Possono fare quello che vuoi e probabilmente molto di più.

Per coloro che si imbattono in questa domanda, includerò una risposta che utilizza Fabric , che risolve esattamente il problema descritto sopra: esecuzione di comandi arbitrari su più host tramite ssh.

Una volta installato fabric, creeresti un fabfile.py e implementerai task che possono essere eseguiti sui tuoi host remoti. Ad esempio, un'attività per Ricaricare Apache potrebbe apparire così:

from fabric.api import env, run

env.hosts = ['host1@example.com', 'host2@example.com']

def reload():
    """ Reload Apache """
    run("sudo /etc/init.d/apache2 reload")

Quindi, sul tuo computer locale, esegui fab reload e il comando sudo /etc/init.d/apache2 reload verrebbe eseguito su tutti gli host specificati in env.hosts.

Puoi farlo come facevi prima, basta copiarlo invece di farlo manualmente. Il codice seguente si riferisce alla macchina denominata 'loca' ed esegue due comandi lì. Quello che devi fare è semplicemente inserire i comandi che vuoi eseguire lì.

che@ovecka ~ $ ssh loca 'uname -a; echo something_else'
Linux loca 2.6.25.9 #1 (blahblahblah)
something_else

Quindi, per scorrere tutte le macchine, fai qualcosa del tipo:

for box in box1_name box2_name box3_name
do
   ssh $box 'commmands_to_run_everywhere'
done

Per far funzionare questa cosa ssh senza inserire password per tutto il tempo, devi impostare l'autenticazione con chiave. Puoi leggerlo a IBM developerworks .

Puoi eseguire lo stesso comando su più server contemporaneamente con uno strumento come cluster ssh . Il link è una discussione di cluster ssh sul pacchetto Debian del blog del giorno.

Bene, per i passaggi 1 e 2 non esiste un'interfaccia web di Tomcat Manager; potresti copiarlo con curl o zsh con il plug-in libwww.

Per SSH stai cercando di: 1) non viene richiesta una password (utilizzare i tasti) 2) passare i comandi sulla riga di comando di SSH, questo è simile a rsh in una rete fidata.

Altri post ti hanno mostrato cosa fare e probabilmente userò anche sh ma sarei tentato di usare perl come ssh tomcatuser@server perl -e 'do-everything-on-one-line;' o potresti farlo:

scp the_package.tbz tomcatuser@server:the_place/.
ssh tomcatuser@server /bin/sh <<\EOF
definisci cose come TOMCAT_WEBAPPS=/usr/local/share/tomcat/webapps
tar xj the_package.tbz o rsync rsync://repository/the_package_place
mv $TOMCAT_WEBAPPS/old_war $TOMCAT_WEBAPPS/old_war.old
mv $THE_PLACE/new_war $TOMCAT_WEBAPPS/new_war
touch $TOMCAT_WEBAPPS/new_war [normalmente non è necessario riavviare tomcat]
mv $THE_PLACE/vhost_file $APACHE_VHOST_DIR/vhost_file
$APACHECTL restart [potrebbe essere necessario accedere come utente apache per spostare quel file e riavviare]
EOF

Volete DSH o shell distribuita, che viene usata molto nei cluster. Ecco il link: dsh

Fondamentalmente si hanno gruppi di nodi (un file con liste di nodi in essi) e si specifica su quale gruppo di nodi si desidera eseguire i comandi, quindi si utilizzerà dsh, come se si eseguisse i comandi su di essi.

dsh -a /path/to/some/command/or/script

Eseguirà il comando su tutte le macchine contemporaneamente e restituirà l'output con prefisso con il nome host. Il comando o lo script deve essere presente sul sistema, quindi una directory NFS condivisa può essere utile per questo genere di cose.

Crea il comando ssh hostname di tutte le macchine a cui si accede. di Quierati http://pastebin.com/pddEQWq2

#Use in .bashrc
#Use "HashKnownHosts no" in ~/.ssh/config or /etc/ssh/ssh_config 
# If known_hosts is encrypted and delete known_hosts

[ ! -d ~/bin ] && mkdir ~/bin
for host in `cut -d, -f1 ~/.ssh/known_hosts|cut -f1 -d " "`;
  do
    [ ! -s ~/bin/$host ] && echo ssh $host '$*' > ~/bin/$host
done
[ -d ~/bin ] && chmod -R 700 ~/bin
export PATH=$PATH:~/bin 

Ex Execute:

$for i in hostname{1..10}; do $i who;done

Esiste uno strumento chiamato FLATT (strumento di automazione e risoluzione dei problemi FLexible) che consente di eseguire script su più Unix / Linux host con un clic di un pulsante. È un'app GUI desktop che funziona su Mac e Windows, ma esiste anche un client Java da riga di comando.
È possibile creare processi batch e riutilizzarli su più host.
Richiede Java 1.6 o successivo.

Sebbene sia un argomento complesso, posso consigliare vivamente Capistrano .

Non sono sicuro che questo metodo funzionerà per tutto quello che vuoi, ma puoi provare qualcosa del genere:

$ cat your_script.sh | ssh your_host bash

Che eseguirà lo script (che risiede localmente) sul server remoto.

Multixterm è utile per farlo e ti consente di inserire facilmente 1 di n macchina in sequenza.

Basta leggere un nuovo blog usando setsid senza ulteriori installazioni / configurazioni oltre al kernel mainstream. Testato / verificato su Ubuntu14.04.

Mentre l'autore ha una spiegazione molto chiara e anche un codice di esempio, ecco la parte magica per una rapida occhiata:

#----------------------------------------------------------------------
# Create a temp script to echo the SSH password, used by SSH_ASKPASS
#----------------------------------------------------------------------
SSH_ASKPASS_SCRIPT=/tmp/ssh-askpass-script
cat > ${SSH_ASKPASS_SCRIPT} <<EOL
#!/bin/bash
echo "${PASS}"
EOL
chmod u+x ${SSH_ASKPASS_SCRIPT}

# Tell SSH to read in the output of the provided script as the password.
# We still have to use setsid to eliminate access to a terminal and thus avoid
# it ignoring this and asking for a password.
export SSH_ASKPASS=${SSH_ASKPASS_SCRIPT}
......
......
# Log in to the remote server and run the above command.
# The use of setsid is a part of the machinations to stop ssh 
# prompting for a password.
setsid ssh ${SSH_OPTIONS} ${USER}@${SERVER} "ls -rlt"

Ecco uno script per eseguire un comando SSH su più macchine, può essere d'aiuto:

#!/bin/bash
MACHINES="machine1 machine2 machine3 machine4 machine5 machine6"
for m in $MACHINES
do
        cmd="ssh $m '$*'"
        eval $cmd
done

Potresti anche metterlo in modo che sia sul tuo percorso, chiamarlo in qualche modo come sshAll, quindi basta digitare il comando sshAll.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top