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

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

ssh [email protected] -t sudo su -

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

  • Разверните новый контейнер Tomcat
  • Разверните приложение в контейнере и настройте его
  • Настройка Apache vhost
  • Обновить Apache

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

Ответы

Ответ 1

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

Ответ 2

Вы можете запустить локальный script, как показано 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 

Ответ 3

Вопрос о том, как запускать команды на многих серверах сразу, появился в списке рассылки 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.

[[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 уже упоминался и (из того, что я понимаю) также мог быть в этом списке.

Ответ 4

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

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

Ответ 5

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

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

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

Ответ 6

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

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

Ответ 7

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

  • Используйте scp для копирования вашей установки/настройки script в целевое поле.
  • Используйте ssh для вызова вашего script в удаленном поле.

Ответ 8

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

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

Ответ 9

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

Ответ 10

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

После установки ткани вы создадите fabfile.py и реализуете задачи, которые могут выполняться на ваших удаленных хостах. Например, задача Reload 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.

Ответ 11

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

Ответ 12

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

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

Ответ 13

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

Ответ 14

Ну, для шага 1 и 2 нет веб-интерфейса менеджера tomcat; вы могли бы script с помощью 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

Ответ 15

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

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

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

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

Ответ 16

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

Ответ 17

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

Ответ 18

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

$ cat your_script.sh | ssh your_host bash

Запустится script (локально локально) на удаленном сервере.

Ответ 19

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

Ответ 20

Просто прочитайте новый блог, используя 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"

Ответ 21

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

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

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