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

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

  •  04-07-2019
  •  | 
  •  

Вопрос

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

ssh user@host -t sudo su -

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

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

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

Это было полезно?

Решение

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

Другие советы

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

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 или что-то еще (man Ghosts), а затем используете эту группу при вызове 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

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

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

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

Чтобы дать вам структуру, без реального кода.

<Ол>
  • Используйте scp, чтобы скопировать ваш скрипт установки / настройки в целевое окно.
  • Используйте ssh для вызова вашего скрипта в удаленном окне.
  • pssh может быть интересным, поскольку, в отличие от большинства упомянутых здесь решений, команды выполняются параллельно .

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

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

    Для тех, кто сталкивается с этим вопросом, я включу ответ, который использует Fabric , который решает именно описанную проблему выше: Запуск произвольных команд на нескольких хостах через 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.

    Вы можете сделать это так же, как и раньше, просто сделайте сценарий вместо того, чтобы делать это вручную. Следующий код удален к машине с именем '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 .

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

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

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

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

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

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

    $ 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.

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top