Как автоматизировать запуск команд удаленно через SSH на несколько серверов параллельно?

Я немного искал подобные вопросы, но кроме выполнения одной команды или, возможно, нескольких команд с такими элементами, как:

ssh user@host -t sudo su -

однако, что, если мне по существу нужно запустить скрипт на (скажем) 15 серверах сразу. Это выполнимо в Баш? В идеальном мире мне нужно избегать установки приложений, если это вообще возможно. Ради аргумента, давайте просто скажем, что мне нужно сделать следующее Через 10 хостов:

  1. развернуть a новый контейнер Tomcat
  2. разверните приложение в контейнере и настройте его
  3. настройка Apache vhost
  4. Перезагрузить Apache

У меня есть скрипт, который делает все это, но он полагается на то, что я войду во все серверы, вытащив скрипт из РЕПО, а затем запустив его. Если это не выполнимо в bash, какие альтернативы вы предлагаете? Нужен ли мне больший молоток, такой как Perl (Python может быть предпочтительным, поскольку я могу гарантировать Python находится на всех коробках в среде RHEL благодаря yum / up2date)? Если кто-то может указать мне на какую-либо полезную информацию, это было бы очень полезно, особенно если это выполнимо в bash. Я соглашусь на Perl или Python, но я просто не знаю их (работая над этим). Спасибо!

21 ответов


часто, я просто буду использовать оригинальную версию Tcl Expect. Вам нужно только иметь это на локальном компьютере. Если я внутри программы, использующей Perl, я делаю это с Net:: SSH:: Expect. Другие языки имеют аналогичные инструменты" expect".


вы можете запустить локальный скрипт, как показано che и Yang, и / или вы можете использовать здесь документ:

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 

вопрос о том, как запускать команды на многих серверах сразу появился в списке рассылки Perl на днях, и я дам ту же рекомендацию Я есть С помощью gsh:

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

gsh похож на "for box in box1_name box2_name box3_name" решением уже дал но я нахожу gsh более удобным. Вы настраиваете файл/etc / ghosts, содержащий ваши серверы в таких группах, как web, db, RHEL4, x86_64 или что-то еще (призраки человека), то вы используете эту группу при вызове 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 ~]$

вы также можете комбинировать или разбивать группы призраков, используя, например, web+db или web-RHEL4.

Я также упомяну, что, хотя я никогда не использовал shmux,сайте содержит список программного обеспечения (включая gsh), которое позволяет запускать команды сразу на многих серверах. Капистрано уже упоминалось, и (насколько я понимаю) может быть в этом списке как что ж.


взгляните на Expect (man expect)

Я выполнял подобные задачи в прошлом, используя Expect.


вы можете передать локальный скрипт на удаленный сервер и выполнить его одной командой:

ssh -t user@host 'sh' < path_to_script

Это можно дополнительно автоматизировать, используя аутентификацию открытого ключа и обертывание скриптами для параллельного выполнения.


вы можете попробовать парамико. Это чисто-python ssh-клиент. Вы можете запрограммировать сеансы ssh. Ничего не устанавливать на удаленных машинах.

посмотреть этот большая статья о том, как использовать его.


чтобы дать вам структуру, без фактического кода.

  1. используйте scp для копирования сценария установки/установки в целевое поле.
  2. используйте ssh для вызова скрипта в удаленном окне.

pssh может быть интересно, так как, в отличие от большинства решений, упомянутых здесь, команды выполняются параллельно.

(для моего собственного использования я написал более простой небольшой скрипт, очень похожий на Gavincattell's one, это документально здесь-на французском языке).


вы смотрели на вещи, как кукол или Cfengine. Они могут делать то, что вы хотите, и, вероятно, гораздо больше.


для тех, кто натыкается на этот вопрос, я включу ответ, который использует ткани, который решает точно описанную выше проблему: запуск произвольных команд на нескольких хостах через ssh.

после установки fabric вы создадите fabfile.py, и реализовать задачи это можно запустить на удаленных хостах. Например, задача Перезагрузить Apache может выглядеть так:

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 и sudo /etc/init.d/apache2 reload команда будет запущена на всех хостах, указанных в env.hosts.


вы можете сделать это так же, как и раньше, просто напишите его вместо того, чтобы делать это вручную. Следующий код remotes к машине с именем "loca" и выполняет две команды там. Что вам нужно сделать, это просто вставить команды, которые вы хотите работать там.

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

затем, чтобы перебрать все машины, сделайте что-то вроде:

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

для того, чтобы эта вещь ssh работала без ввода паролей все время, вам нужно будет настроить аутентификацию ключа. Вы можете читать об этом IBM developerworks.


вы можете запустить одну и ту же команду на нескольких серверах одновременно с помощью такого инструмента, как кластер ssh. Ссылка на обсуждение кластерного ssh в Debian-пакете дневного блога.


Ну, для шага 1 и 2 нет веб-интерфейса tomcat manager; вы можете написать это с помощью curl или zsh с помощью плагина libwww.

для SSH вы ищете: 1) не получить запрос на пароль (используйте ключи) 2) передайте команду(ы) в командной строке SSH, это похоже на rsh в доверенной сети.

другие сообщения показали вам, что делать, и я бы, вероятно, использовал sh тоже, но у меня будет соблазн использовать perl как ssh tomcatuser@server perl -e 'do-everything-on-one-line;' или вы могли бы сделать это:

или scp the_package.tbz tomcatuser@server:the_place/.
ssh tomcatuser@server /bin/sh <<\EOF
определить такие вещи, как TOMCAT_WEBAPPS=/usr/local/share/tomcat/webapps
tar xj the_package.tbz или 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 [обычно вам не нужно перезапускать tomcat]
mv $THE_PLACE/vhost_file $APACHE_VHOST_DIR/vhost_file
$APACHECTL restart [возможно, потребуется войти в систему как пользователь apache, чтобы переместить этот файл и перезапустить]
EOF


вы хотите DSH или распределенную оболочку, которая часто используется в кластерах. Вот ссылка: dsh

у вас в основном есть группы узлов (файл со списками узлов в них), и вы указываете, в какой группе узлов вы хотите запускать команды, тогда вы будете использовать dsh, как и ssh для запуска команд на них.

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

он будет запускать команду на всех машинах одновременно и возвращать выходные данные с префиксом имени хоста. Команда или скрипт присутствуйте в системе, поэтому общий каталог NFS может быть полезен для таких вещей.


создает команду ssh имени хоста всех доступных машин. по 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

существует инструмент под названием FLATT (гибкий инструмент автоматизации и устранения неполадок) это позволяет выполнять скрипты на нескольких хостах Unix/Linux одним нажатием кнопки. Это настольное приложение GUI, которое работает на Mac и Windows, но есть также клиент java командной строки.
Можно создавать пакетные задания и повторно использовать их на нескольких узлах.
Требует Java 1.6 или выше.


хотя это сложная тема, я могу очень рекомендовать Капистрано.


Я не уверен, что этот метод будет работать для всего, что вы хотите, но вы можете попробовать что-то вроде этого:

$ cat your_script.sh | ssh your_host bash

запустить скрипт (который находится локально) на удаленном сервере.


Multixterm круто для этого, и позволяет легко поставить 1 из N машины обратно в последовательности.


просто прочитайте новый блог используя setsid без какой-либо дополнительной установки/конфигурации, кроме основного ядра. Испытана/проверена в соответствии с Ubuntu14.04.

хотя у автора есть очень четкое объяснение и пример кода, вот волшебная часть для быстрого взгляда:

#----------------------------------------------------------------------
# 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"

вот скрипт для выполнения команды SSH на нескольких машинах, это может помочь:

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

можно даже сделать это так, что это на своем пути, называют это что-то вроде sshAll, то просто команда sshAll типа.