Статья, перевод которой мы сегодня публикуем, посвящена технологиям одновременного выполнения команд на нескольких 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
    18.10.2018 13:26

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


    1. ru_vds Автор
      18.10.2018 13:34

      Это один из вариантов мультитула в форм-факторе кредитки


    1. Taraflex
      18.10.2018 14:04

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


  1. Sovigod
    18.10.2018 13:38

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


  1. mikhailian
    18.10.2018 14:28

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


  1. kazenniy
    18.10.2018 15:45
    +2

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


  1. sardigital
    18.10.2018 16:01
    -1

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


  1. therb1
    18.10.2018 17:32
    -1

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


  1. heaveaxy
    18.10.2018 17:48

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


  1. miffo
    18.10.2018 17:48

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


  1. Acid_Jack
    18.10.2018 18:46

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


    1. ALexhha
      19.10.2018 00:09

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


      1. Acid_Jack
        19.10.2018 00:18

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


        1. ALexhha
          19.10.2018 11:41

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

          #!/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+ разница будет очень заметной.


          1. Acid_Jack
            19.10.2018 12:00

            Интересно. У меня на долгих операциях разница между -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, но теперь буду знать как сделать реально ОДНОВРЕМЕННО на всех хостах.


            1. ALexhha
              19.10.2018 12:16

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


              1. Acid_Jack
                19.10.2018 12:20

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


    1. Sovigod
      19.10.2018 12:09

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

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

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


      1. Acid_Jack
        19.10.2018 12:12

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


        1. Sovigod
          19.10.2018 12:19

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

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


  1. kt97679
    18.10.2018 20:23

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


  1. bormental
    18.10.2018 20:25

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

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


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

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



  1. nad_oby
    19.10.2018 14:53

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


  1. DmitriyPanteleev
    19.10.2018 14:54

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


  1. mishutka_ua
    19.10.2018 14:54

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


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


  1. hanix
    19.10.2018 14:54

    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…