it-swarm.com.ru

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

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

ssh [email protected] -t Sudo su -

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

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

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

18
f4nt

Часто я просто использую оригинальную Tcl версию Expect. Это нужно только на локальной машине. Если я нахожусь внутри программы, использующей Perl, я делаю это с Net :: SSH :: Expect . Другие языки имеют аналогичные «ожидаемые» инструменты.

9
brian d foy

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

ssh [email protected] /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 
11
Bash

Вопрос о том, как запускать команды на многих серверах одновременно, возник в списке рассылки 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 или что-то еще (man ghosts), а затем используете эту группу при вызове gsh.

[[email protected] ~]$ 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
[[email protected] ~]$

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

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

9
Philip Durbin

Посмотрите на Expect (man expect)

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

6
antik

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

Смотрите это отличная статья о том, как его использовать.

4
Christopher Mahan

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

ssh -t [email protected] 'sh' < path_to_script

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

4
Yang Zhao

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

  1. Используйте scp, чтобы скопировать ваш скрипт установки/настройки в целевое окно.
  2. Используйте ssh для вызова вашего скрипта на удаленной машине.
3
Darron

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

2
Keltia

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

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

from fabric.api import env, run

env.hosts = ['[email protected]', '[email protected]']

def reload():
    """ Reload Apache """
    run("Sudo /etc/init.d/Apache2 reload")

Затем на локальном компьютере запустите fab reload, и команда Sudo /etc/init.d/Apache2 reload будет запущена на всех хостах, указанных в env.hosts.

2
Brad Montgomery

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

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

2
bortzmeyer

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

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

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

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

1
Steve Baker

Хотя это сложная тема, я очень рекомендую Capistrano .

1
m104

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

che @ ovecka ~ $ ssh loca 'uname -a; echothing_else '
 Linux loca 2.6.25.9 # 1 (бла-бла))

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

для коробки в поле имя_1 имя_блока имя_3 имя_3 
 делать 
 ssh $ box 'commmands_to_run_everywhere' 
 done

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

1
che

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

1
David Locke

Существует инструмент под названием FLATT (FLexible Automation and Устранение неполадок) , который позволяет выполнять скрипты на нескольких хостах Unix/Linux одним нажатием кнопки. Это настольное приложение с графическим интерфейсом, которое работает на Mac и Windows, но есть и клиент Java из командной строки.
Вы можете создавать пакетные задания и повторно использовать их на нескольких хостах.
Требуется Java 1.6 или выше.

1
Andy M

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

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

Другие посты показали вам, что делать, и я, вероятно, тоже буду использовать sh, но у меня будет соблазн использовать Perl наподобие ssh [email protected] Perl -e 'do-everything-on-one-line;', или вы можете сделать это:

либо scp the_package.tbz [email protected]:the_place/.
ssh [email protected] /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

1
dlamblin

Создает команду hostname 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
1
Quierati

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

$ cat your_script.sh | ssh your_Host bash

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

0
Jeremy Cantrell

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

0
David Ritchie

Просто прочитайте новый блог using 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"
0
user3438301