4 инструмента для одновременного выполнения команд на нескольких Linux-серверах +26


Статья, перевод которой мы сегодня публикуем, посвящена технологиям одновременного выполнения команд на нескольких Linux-серверах. Речь здесь пойдёт о нескольких широко известных инструментах, реализующих подобный функционал. Этот материал пригодится системным администраторам, которым, например, регулярно приходится проверять состояние множества удалённых систем. Предполагается, что у читателя уже имеется несколько серверов, к которым организован доступ по SSH. Кроме того, при одновременной работе с несколькими машинами весьма полезно настроить SSH-доступ к ним по ключу, без пароля. Такой подход, с одной стороны, повышает безопасность сервера, а с другой — облегчает работу с ним.



1. PSSH — Parallel SSH


PSSH — это опенсорсный набор инструментов командной строки, написанный на Python и предназначенный для параллельного выполнения SSH-команд на множестве Linux-систем. Он быстро работает и лёгок в освоении. PSSH включает в себя такие средства, как parallel-ssh, parallel-scp, parallel-rsync, parallel-slurp и parallel-nuke (подробности об этих средствах можно посмотреть в man).

Перед установкой parallel-ssh в Linux-системе сначала надо установить pip. Вот как это делается в разных дистрибутивах:

$ sudo apt install python-pip python-setuptools   #Debian/Ubuntu 
# yum install python-pip python-setuptools        #RHEL/CentOS 
# dnf install python-pip python-setuptools        #Fedora 22+

Затем parallel-ssh устанавливают с использованием pip:

$ sudo pip install parallel-ssh

Далее, нужно внести имена хостов или IP-адреса удалённых Linux-серверов и сведения о портах в файл hosts (на самом деле, назвать его можно как угодно). Тут нам пригодится такая команда:

$ vim hosts

Вот пример содержимого такого файла:

192.168.0.10:22
192.168.0.11:22
192.168.0.12:22

После того, как в файл будет внесено всё необходимое, пришло время запустить parallel-ssh, передав этой утилите имя файла с использованием опции -h, а также — команды, которые нужно выполнить на всех серверах, адреса которых имеются в файле hosts. Флаг -i утилиты используется для того, чтобы вывести на экран то, что попадёт в стандартные потоки вывода и ошибок после завершения выполнения команд на серверах.

Команда запуска parallel-ssh может выглядеть так:

$ parallel-ssh -h hosts "uptime; df -h"

На следующем рисунке показано использование утилиты при работе с тремя серверами.


Утилита parallel-ssh выполняет команды на нескольких серверах

2. Pdsh — Parallel Remote Shell Utility


Pdsh — это, опять же, опенсорсное решение, представляющее собой оболочку для одновременного выполнения команд на нескольких Linux-серверах.

Вот как установить pdsh в различных дистрибутивах:

$ sudo apt install pdsh         #Debian/Ubuntu 
# yum install pdsh              #RHEL/CentOS 
# dnf install pdsh              #Fedora 22+

Для того чтобы выполнять команды на нескольких серверах, адреса этих серверов, как и при использовании parallel-ssh, надо добавить в файл, который тоже можно назвать hosts. Затем нужно запустить pdsh в следующем виде:

$ pdsh -w ^hosts -R ssh "uptime; df -h"

Здесь флаг -w используется для указания файла со списком серверов, флаг -R применяется для указания модуля удалённых команд (среди доступных модулей удалённых команд имеются ssh, rsh, exec; по умолчанию используется rsh). Обратите внимание на значок ^ перед именем файла со списком серверов.

Вот как выглядит работа с этой командой.


Выполнение команд на нескольких серверах с использованием pdsh

Если вы, при вызове pdsh, не указали список команд, которые надо выполнить на серверах, эта утилита запустится в интерактивном режиме. Подробности о pdsh можно узнать на соответствующей странице man.

3. ClusterSSH


ClusterSSH — это инструмент командной строки, предназначенный для администрирования кластеров серверов. Он запускает консоль администратора и, для каждого сервера, отдельное окно xterm. После этого на всех этих серверах можно одновременно выполнять одни и те же команды.

Установим clusterssh:

$ sudo apt install clusterssh    #Debian/Ubuntu 
# yum install clusterssh         #RHEL/CentOS 
$ sudo dnf install clusterssh    #Fedora 22+

Теперь, для подключения к серверам, нужно выполнить команду следующего вида:

$ clusterssh linode cserver contabo

Можно воспользоваться и такой конструкцией:

$ clusterssh username@server1 username@server2 username@server3

После этого вы увидите нечто, подобное тому, что показано на следующем рисунке.


Работа с несколькими серверами с помощью clusterssh

Команды, введённые в консоли администратора, выполняются на всех серверах. Для выполнения команд на отдельном сервере нужно вводить их в окне, открытом для него.

4. Ansible


Ansible — это популярный опенсорсный инструмент для автоматизации IT-процессов. Он используется для настройки систем и для управления ими, для установки приложений и для решения других задач.

Установим ansible:

$ sudo apt install ansible       #Debian/Ubuntu 
# yum install ansible            #RHEL/CentOS 
$ sudo dnf install ansible       #Fedora 22+

После этого надо добавить адреса серверов в файл /etc/ansible/hosts.

$ sudo vim /etc/ansible/hosts

Вот пример фрагмента подобного файла с несколькими системами, объединёнными в группу webservers:

# Ex 2: A collection of hosts belonging to the 'webservers' group
[webservers]
139.10.100.147
139.20.40.90
192.30.152.186

Теперь, для того, чтобы получить сведения команды uptime и узнать, какие пользователи подключены к хостам, входящим в группу webservers, можно воспользоваться следующей конструкцией:

$ ansible webservers -a "w " -u admin

Здесь опция -a используется для указания аргументов, передаваемых модулю, а флаг -u позволяет задать имя пользователя по умолчанию, применяемое для подключения к удалённым серверам по SSH.

Обратите внимание на то, что интерфейс командной строки ansible позволяет выполнять команды лишь по одной.


Взаимодействие с несколькими серверами средствами ansible

Итоги


В этом материале мы рассказали об инструментах, которые предназначены для одновременного выполнения команд на нескольких серверах, работающих под управлением Linux. Если вы подумываете об автоматизации задач по управлению множеством серверов — надеемся, вы найдёте здесь что-нибудь такое, что вам подойдёт.

Уважаемые читатели! Знаете ли вы о каких-нибудь полезных утилитах, упрощающих администрирование большого количества серверов?

Вы можете помочь и перевести немного средств на развитие сайта



Комментарии (27):

  1. claygod
    /#19250661

    Инструмент на первой иллюстрации мне напомнил одновременно УШС (универсальный шаблон сварщика) и квадрат для метания (холодное оружие). Что же это на самом деле?

    • Taraflex
      /#19250851

      del. Я буду обновлять страницу.

  2. Sovigod
    /#19250727

    Это больше выполнение сценариев/скриптов/плейбуков. Просто потыкать команды и красиво увидеть их ответ — удобней будет tmux c кучкой панелей на одном экране. Или iTerm для тех у кого macos. В обоих есть broadcast input и горизонатльное/вертикальное разделение экрана.

  3. mikhailian
    /#19250971

    А как же знаменитый в узких кругах paexec?

  4. kazenniy
    /#19251371 / +2

    Ansible отсюда стоит убрать, он из другой оперы. Им конечно тоже можно выполнить конкретную команду на нескольких серверах, но задуман он не для этого. Сюда скорее чтонить типа python-fabric подойдет, хотя тоже не вполне.

  5. sardigital
    /#19251455 / -1

    ну ок, под венду есть Superputty, например
    и вот такое еще есть — WinSSHTerm

  6. therb1
    /#19251903 / -1

    Если есть анчибле то почему бы не добавить соль папки и иже с ними.

  7. heaveaxy
    /#19251973

    Линуксовый терминатор тоже такое может. Делим окно на необходимое количество частей, заходим в каждом на свой сервер, создаём на этих частях терминала широковещательный ввод и пишем команды. По результатам выполнения команд, в каждом «отсеке» терминала виден свой результат. Если что не так, можно шир. ввод выключить, поправить, потом продолжить. Тоже удобно

  8. miffo
    /#19251975

    TMUX'a забыли.
    Регулярно рулю виртуалками и серверами в консоли с одновременным вводом. Вся прелесть в том, что режим одновременного ввода включается и выключается по хоткею. Тмукс позволяет очень удобно сравнивать STDOUT на сплитскрине на 2-3 машины.

  9. Acid_Jack
    /#19252237

    for HOST in `cat hosts.txt`; do ssh -f "uptime; df -h" $HOST; done

    • ALexhha
      /#19253349

      Хосты будут обрабатываться последовательно, а не параллельно. А теперь представьте что у вас 1к+ хостов и в среднем ваша команда выполняется 10 минут. Вот и посчитайте сколько уйдёт времени при вашем способе

      • Acid_Jack
        /#19253367

        -f Requests ssh to go to background just before command execution. This is useful if ssh is going to ask for passwords or passphrases, but the user wants it in the background. This implies -n. The recommended way to start X11 programs at a remote site is with something like ssh -f host xterm.

        • ALexhha
          /#19254545

          Ради интереса проверил простенький скрипт

          #!/bin/bash
          
          for HOST in $(cat hosts.txt)
          do
              ssh -f ansible@$HOST "date; hostname";
          done
          


          На выходе получил
          $ time./test.sh > debug.log
          real	0m26.477s
          user	0m0.408s
          sys	0m0.084s
          
          $ cat debug.log 
          Fri Oct 19 08:16:48 UTC 2018
          edge-eplus-main-3klf
          Fri Oct 19 08:16:48 UTC 2018
          edge-eplus-main-2x1g
          Fri Oct 19 08:16:49 UTC 2018
          edge-eplus-main-6t1g
          Fri Oct 19 08:16:53 UTC 2018
          edge-eplus-main-720h
          Fri Oct 19 08:16:54 UTC 2018
          edge-eplus-main-86hf
          Fri Oct 19 08:16:55 UTC 2018
          edge-eplus-main-8jf2
          Fri Oct 19 08:16:56 UTC 2018
          edge-eplus-main-d8w0
          Fri Oct 19 08:16:58 UTC 2018
          edge-eplus-main-jkjr
          Fri Oct 19 08:17:01 UTC 2018
          edge-eplus-main-nsj9
          Fri Oct 19 08:17:03 UTC 2018
          edge-eplus-main-ph9j
          Fri Oct 19 08:17:05 UTC 2018
          edge-eplus-main-t2g1
          Fri Oct 19 08:17:06 UTC 2018
          edge-eplus-main-t9jb
          Fri Oct 19 08:17:07 UTC 2018
          edge-eplus-main-x3c4
          Fri Oct 19 08:17:10 UTC 2018
          edge-eplus-main-x5q0
          


          из того, что я вижу, команды выполняются последовательно. Для сравнения ansible
          $ time ansible habrahabr -u ansible -m shell -a "date; hostname" > debug.log
          real	0m15.962s
          user	0m3.820s
          sys	0m1.768s
          
          
          $ time ansible habrahabr -u ansible -f 15 -m shell -a "date; hostname" > debug.log
          real	0m8.568s
          user	0m3.012s
          sys	0m1.328s
          


          Как бы разница налицо. И это было всего лишь 15 хостов. На 500+ разница будет очень заметной.

          • Acid_Jack
            /#19254637

            Интересно. У меня на долгих операциях разница между -f и без форка весьма заметна. Решил проверить ещё раз.

            Итак, эталон с последовательным выполнением:
            $ for HOST in `cat hosts.txt`; do ssh $HOST "sleep 5s; date"; done
            19 октября 2018 г., 10:51:58 CEST
            19 октября 2018 г., 10:52:06 CEST
            19 октября 2018 г., 10:52:11 CEST
            19 октября 2018 г., 10:52:17 CEST
            19 октября 2018 г., 10:52:23 CEST
            19 октября 2018 г., 10:52:29 CEST
            19 октября 2018 г., 10:52:35 CEST
            19 октября 2018 г., 10:52:40 CEST
            19 октября 2018 г., 10:52:47 CEST
            19 октября 2018 г., 10:52:53 CEST
            19 октября 2018 г., 10:52:59 CEST
            19 октября 2018 г., 10:53:04 CEST
            19 октября 2018 г., 10:53:10 CEST
            19 октября 2018 г., 10:53:16 CEST
            19 октября 2018 г., 10:53:22 CEST
            19 октября 2018 г., 10:53:27 CEST
            19 октября 2018 г., 10:53:33 CEST
            19 октября 2018 г., 10:53:39 CEST
            19 октября 2018 г., 10:53:45 CEST
            19 октября 2018 г., 10:53:50 CEST
            19 октября 2018 г., 10:53:56 CEST


            Теперь с форком:
            $ for HOST in `cat hosts.txt`; do ssh -f $HOST "sleep 5s; date"; done
            19 октября 2018 г., 10:55:58 CEST
            19 октября 2018 г., 10:55:58 CEST
            19 октября 2018 г., 10:55:59 CEST
            19 октября 2018 г., 10:55:59 CEST
            19 октября 2018 г., 10:56:00 CEST
            19 октября 2018 г., 10:56:01 CEST
            19 октября 2018 г., 10:56:01 CEST
            19 октября 2018 г., 10:56:02 CEST
            19 октября 2018 г., 10:56:02 CEST
            19 октября 2018 г., 10:56:03 CEST
            19 октября 2018 г., 10:56:03 CEST
            19 октября 2018 г., 10:56:04 CEST
            19 октября 2018 г., 10:56:04 CEST
            19 октября 2018 г., 10:56:05 CEST
            19 октября 2018 г., 10:56:06 CEST
            19 октября 2018 г., 10:56:06 CEST
            19 октября 2018 г., 10:56:07 CEST
            19 октября 2018 г., 10:56:07 CEST
            19 октября 2018 г., 10:56:08 CEST
            19 октября 2018 г., 10:56:08 CEST
            19 октября 2018 г., 10:56:09 CEST


            Как видим, есть примерно секундная задержка на запуск нового фонового процесса. На пяти сотнях хостов это, возможно, будет критично. Таки да, согласен. Посыпаю голову пеплом.
            Но теперь сделаем финт ушами:

            $ for HOST in `cat hosts.txt`; do ssh -f $HOST "sleep 5s; date"& done
            19 октября 2018 г., 10:58:43 CEST
            19 октября 2018 г., 10:58:43 CEST
            19 октября 2018 г., 10:58:43 CEST
            19 октября 2018 г., 10:58:43 CEST
            19 октября 2018 г., 10:58:43 CEST
            19 октября 2018 г., 10:58:43 CEST
            19 октября 2018 г., 10:58:43 CEST
            19 октября 2018 г., 10:58:43 CEST
            19 октября 2018 г., 10:58:43 CEST
            19 октября 2018 г., 10:58:43 CEST
            19 октября 2018 г., 10:58:43 CEST
            19 октября 2018 г., 10:58:43 CEST
            19 октября 2018 г., 10:58:43 CEST
            19 октября 2018 г., 10:58:43 CEST
            19 октября 2018 г., 10:58:43 CEST
            19 октября 2018 г., 10:58:43 CEST
            19 октября 2018 г., 10:58:43 CEST
            19 октября 2018 г., 10:58:43 CEST
            19 октября 2018 г., 10:58:43 CEST
            19 октября 2018 г., 10:58:43 CEST
            19 октября 2018 г., 10:58:43 CEST


            Спасибо за наводку. До сих пор мне хватало просто -f, но теперь буду знать как сделать реально ОДНОВРЕМЕННО на всех хостах.

            • ALexhha
              /#19254739

              Думаю сильно будет зависеть от удаленности хостов. Если у вас, например, все тестовые хосты в пределах локальной сети, то разница будет не такой заметной. У меня тестовые хосты были распределены по всем регионам в пределах GCP

              • Acid_Jack
                /#19254767

                Не локалка. Расстояние до хостов ~1700 км. Пинг ~70мс.

    • Sovigod
      /#19254689

      Фоновое выполнение не сильно удобно когда хостов очень много. Удобней ограничить количество потоков. Например завернув параллельность в xars

      #!/bin/bash
      
      rcmd () {
        ssh root@$1 "date;hostname;"
      }
      export -f rcmd
      cat hosts.txt | xargs -n1 -P20 -I {} bash -c 'rcmd "$@"' _ {}
      

      тут параметр -P20 — ограничивает выполнение 20 потоками.

      • Acid_Jack
        /#19254707

        Тоже интересно, но я предпочитаю простые однострочники. Чем проще, тем лучше.
        Иначе получаются велосипеды, описанные в статье.

        • Sovigod
          /#19254757

          вот вам однострочник

          cat hosts.txt | xargs -n1 -P20 -I {} ssh root@{} "date;hostname"
          

  10. kt97679
    /#19252639

    Я пользовался parallel-ssh, было не удобно, в результате написал вот это: github.com/kt97679/one-ssh

  11. bormental
    /#19252645

    Обратите внимание на то, что интерфейс командной строки ansible позволяет выполнять команды лишь по одной.

    Ansible, как написали выше, инструмент несколько другой направленности. Но тем не менее, лично я его использую в т.ч. и для кейса данной статьи.
    Поэтому хочется скорректировать выделенное выше утверждение.
    В Ansible куча модулей (-m module_name) со своими аргументами (-a arguments).
    Поэтому легко и просто выполнить и несколько команд.
    Например:


    ansible the_cluster -f 4 -m shell -a "free -h; df -h /"

    "-f X" — полезный параметр, делает "fork", т.е. порождает X параллельных процессов и команды выполняются параллельно на хостах.

  12. nad_oby
    /#19255705

    GNU parallel в сочетании с xargs можно для этих целей использовать.
    Для нестандартног использования типа выстрелил и забыл или если нужно обрабатывать/агрегировать выхлоп команд я пишу обычно на связке python + paramiko небольшой скрипт.
    Очень неплохо выходит.

  13. DmitriyPanteleev
    /#19255707

    Есть супер утилита PAC manager. Фантастически удобная. По удаленному управлению умеет все и еще чуть-чуть:)! В том числе в ней очень удобно делать различную оркестрацию. Интеграция с кипасам и прочая и прочая…
    Жалко только с 2016-го она не обновляется. Со временем, в системе обновилось пара-тройка зависимостей (например xfreerdp) и некоторый функционал стал глючить. Дописать-то, наверное, легко. Вот только Perl знать надо, а мне он все никак не дается…

  14. mishutka_ua
    /#19255709

    Такой подход, с одной стороны, повышает безопасность сервера, а с другой — облегчает работу с ним.


    Понимать как написано или if {} else {}?

  15. hanix
    /#19255711

    github.com/reconquest/orgalorg
    Zero-configuration.
    Running SSH commands or shell scripts on any number of hosts in parallel.
    Synchronizing files and directories across cluster with prior global cluster locking.
    and more…