Como posso automatizar executando comandos remotamente por SSH para vários servidores em paralelo?
Pergunta
Eu procurei em torno de um bocado para perguntas semelhantes, mas diferente do que correr um comando ou talvez um comando poucos com itens como:
ssh user@host -t sudo su -
No entanto, o que se eu basicamente precisa executar um script em (digamos de LET) 15 servidores ao mesmo tempo. É este factível em bash? Em um mundo perfeito eu preciso para evitar a instalação de aplicativos, se possível para puxar esta off. Por causa do argumento, vamos apenas dizer que eu preciso fazer o seguinte em 10 exércitos:
- Implantar um novo recipiente Tomcat
- implantar um aplicativo no recipiente, e configurá-lo
- Configurar um Apache vhost
- Recarregar Apache
Eu tenho um script que faz tudo isso, mas depende de mim fazer login em todos os servidores, puxando um script para baixo de um repo, e depois executá-lo. Se isto não é factível em bash, que alternativas você sugere? Preciso de um martelo maior, como Perl (Python pode ser preferido desde que eu posso garantir Python é em todas as caixas em um ambiente RHEL graças a yum / up2date)? Se alguém pode apontar-me a qualquer informação útil seria muito apreciada, especialmente se é factível em bash. Eu vou resolver para Perl ou Python, mas eu só não sei as também (trabalhando nisso). Obrigado!
Solução
Muitas vezes, eu só vou usar a versão original Tcl de esperar. Você só precisa ter essa na máquina local. Se eu estou dentro de um programa usando Perl, eu faço isto com Net :: SSH :: esperar . Outras línguas têm similar "esperar" ferramentas.
Outras dicas
Você pode executar um script local como mostrado por che e Yang, e / ou você pode usar um documento aqui:
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
A questão de como executar comandos em vários servidores ao mesmo tempo surgiu em uma lista Perl no outro dia e eu vou dar a mesma recomendação Eu dei lá , que é a utilização gsh
:
http://outflux.net/unix/software/gsh
GSH é semelhante à solução "for box in box1_name box2_name box3_name
" dada mas acho GSH a ser mais conveniente. Você configurar um arquivo / etc / fantasmas contendo os servidores em grupos tais como web, db, RHEL4, x86_64, ou qualquer outra coisa (homem fantasmas), então você usar esse grupo quando você chamar 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 ~]$
Você também pode combinar ou grupos de fantasmas de divisão, usando web + db ou web-RHEL4, por exemplo.
Eu também vou mencionar que, embora eu nunca usei shmux, seu site contém uma lista de software (incluindo GSH) que permite executar comandos em vários servidores ao mesmo tempo. Capistrano já foi mencionado e (pelo que entendi) poderia estar nessa lista também.
Dê uma olhada em esperar (man expect
)
Eu tenho feito tarefas semelhantes no passado usando Espere.
Você pode canalizar o script local para o servidor remoto e executá-lo com um comando:
ssh -t user@host 'sh' < path_to_script
Isto pode ser ainda mais automatizado usando autenticação de chave pública e envolvimento com scripts para executar a execução paralela.
Você pode tentar paramiko . É um cliente ssh puro-python. Você pode programar suas sessões SSH. Nada a instalar em máquinas remotas.
Veja este ótimo artigo sobre como usá-lo.
Para dar-lhe a estrutura, sem código real.
- Use scp para copiar o script de instalação / configuração para a caixa alvo.
- Use ssh para chamar o script na caixa remoto.
phsss pode ser interessante uma vez que, ao contrário da maioria das soluções mencionadas aqui, os comandos são executados em paralelo .
(Para meu próprio uso, eu escrevi um pequeno script simples muito semelhante à própria GavinCattell, é documentado aqui -. em francês )
Para aqueles que tropeçar através desta pergunta, eu vou incluir uma resposta que usos Tecido , que resolve exatamente o problema descrito acima:. Executar comandos arbitrários em vários hosts sobre ssh
Uma vez que tecido é instalado, você criar um fabfile.py
, e implementar tarefas que pode ser executado em seus hosts remotos. Por exemplo, uma tarefa a Recarregar Apache pode ter esta aparência:
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")
fab reload
Então, em sua máquina local, correr e o comando sudo /etc/init.d/apache2 reload
iria se executar em todos os hosts especificados no env.hosts
.
Você pode fazê-lo da mesma forma que fez antes, apenas escrevê-lo em vez de fazê-lo manualmente. Os seguintes controles remotos código a máquina chamada 'loca' e corre dois comandos. O que você precisa fazer é simplesmente inserir comandos que você deseja executar lá.
che@ovecka ~ $ ssh loca 'uname -a; echo something_else' Linux loca 2.6.25.9 #1 (blahblahblah) something_else
Então, para percorrer todas as máquinas, fazer algo como:
for box in box1_name box2_name box3_name do ssh $box 'commmands_to_run_everywhere' done
A fim de fazer isso ssh coisa trabalho sem digitar senhas o tempo todo, você precisa configurar a autenticação de chave. Você pode ler sobre ele em IBM developerWorks .
Você pode executar o mesmo comando em vários servidores ao mesmo tempo com uma ferramenta como aglomerado ssh . O link é para uma discussão sobre ssh cluster no pacote Debian do dia blog.
Bem, para o passo 1 e 2 não existe uma interface de gerenciamento web tomcat; você poderia script que com a onda ou zsh com o plug libwww em.
Para SSH você está olhando para:
1) não se for solicitada uma senha (use as teclas)
2) passar o comando (s) na linha de comando do SSH, este é semelhante ao rsh
em uma rede confiável.
Outras mensagens têm mostrado o que fazer, e eu provavelmente usaria sh
também, mas eu ficaria tentado a utilização perl
como ssh tomcatuser@server perl -e 'do-everything-on-one-line;'
ou você poderia fazer isso:
qualquer scp the_package.tbz tomcatuser@server:the_place/.
ssh tomcatuser@server /bin/sh <<\EOF
definir coisas como TOMCAT_WEBAPPS=/usr/local/share/tomcat/webapps
tar xj the_package.tbz
ou 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
[você normalmente não é necessário reiniciar tomcat]
mv $THE_PLACE/vhost_file $APACHE_VHOST_DIR/vhost_file
$APACHECTL restart
[ser necessário fazer login como apache usuário mover o arquivo e reiniciar]
EOF
Você quer DSH ou distributed shell, que é usado em aglomerados muito. Aqui está o link: dsh
Você tem basicamente grupos de nós (um arquivo com listas de nós em-los) e você especificar qual grupo nó que você deseja executar comandos em seguida, você usaria dsh, como se fosse ssh para executar comandos sobre eles.
dsh -a /path/to/some/command/or/script
Ele será executado o comando em todas as máquinas ao mesmo tempo e retorna a saída prefixado com o nome do host. O comando ou script tem de estar presente no sistema, de modo que um diretório NFS compartilhado pode ser útil para esses tipos de coisas.
Cria hostname comando ssh de todas as máquinas acessados. por 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 Executar:
$for i in hostname{1..10}; do $i who;done
Há uma ferramenta chamada Flatt (flexível Automação e Solução de Problemas Tool) que lhe permite executar scripts em múltiplos Unix / Linux hosts com um clique de um botão. É um aplicativo GUI desktop que roda em Mac e Windows, mas há também um cliente de linha de comando java.
Você pode criar trabalhos em lote e reutilização em vários hosts.
Requer Java 1.6 ou superior.
Embora seja um tema complexo, recomendo Capistrano .
Eu não tenho certeza se este método irá funcionar para tudo o que quiser, mas você pode tentar algo como isto:
$ cat your_script.sh | ssh your_host bash
O que irá executar o script (que reside no local) no servidor remoto.
Multixterm é legal para fazer isso, e permite que você fez facilmente o 1 de n volta máquina em sequência.
Basta ler um novo usando setsid sem qualquer outra instalação / configuração além do kernel do mainstream. Testado / Verificado sob Ubuntu14.04.
Enquanto o autor tem uma explicação muito clara e código de exemplo, bem, aqui é a parte mágica para uma rápida olhada:
#----------------------------------------------------------------------
# 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"
Aqui está um script para fazer um comando SSH em várias máquinas, pode ajudar:
#!/bin/bash
MACHINES="machine1 machine2 machine3 machine4 machine5 machine6"
for m in $MACHINES
do
cmd="ssh $m '$*'"
eval $cmd
done
Você pode até mesmo colocar isso por isso é no seu caminho, chamá-lo de algo como sshAll, em seguida, basta digitar o comando sshAll.