Skip to content

Паралельне виконання команд на кожному сервері у кластері за допомогою onall

onall - це скрипт на Perl5, котрий фактично є зручною обгорткою над ssh, який дозволяє зручно копіювати файл, виконувати команди та скрипти на віддалених серверах, список котрих можна передати onall як у вигляді текстового файлу, так і просто через стандартний потік введення (stdin).

Сам по собі скрипт невеличкий і не має додаткових залежностей окрім встановленого клієнта ssh та інтерпретатора perl5 (на момент написання статті perl5 предвстановлений на кожному десктоп дистрибутиві лінукс). Тож якщо у вас вже встановлені пакети git та make виконуємо наступні команди для інсталяції onall:

$ git clone https://github.com/ticketmaster/onall.git
$ cd onall
~/onall$ sudo make install

І ми готові перейти до практичних прикладів. Якщо просто набрати в терміналі команду onall, то побачимо мінімальні приклади використання команди:

$ onall

onall v2.11 -- A parallelized system-administration tool.
Usage: onall [<options>] <command>
       onall [<options>] --script <script> <script_args>
       onall [<options>] --copy <file> <dest_path>

ERROR: Nothing to do. Exiting.

Припустимо, нам потрібно виконати команду date на root@server1.local, root@server2.local та root@server3.local, аби впевнитись, що час налаштовано правильно на всіх трьох серверах. Створюємо файл cluster1.list зі списком серверів та запускаємо команду onall використовуючи наступну конструкцію:

$ onall -f /tmp/cluster1.list date

3 Target(s):

root@server1.local root@server2.local
root@server3.local

The following command will be executed:
	date
Continue (Y/N):y

root@server2.local: Sat Dec 25 13:03:04 UTC 2021
root@server1.local: Sat Dec 25 13:03:04 UTC 2021
root@server3.local: Sat Dec 25 13:03:04 UTC 2021

Оскільки назви серверів побудовані за певним шаблоном, ми можемо згенерувати список серверів за допомогою bash так передати їх на вхід команди onall у наступний спосіб:

$ echo root@server{1..3}.local | onall -q date
root@server2.local: Sat Dec 25 13:04:37 UTC 2021
root@server3.local: Sat Dec 25 13:04:37 UTC 2021
root@server1.local: Sat Dec 25 13:04:37 UTC 2021

Як бачите, я ще додав параметр -q, щоб onall не перепитував чи хочу я виконати команду на запропонованому списку серверів, тому маємо компактніший вивід.

Аби не додавати до кожного сервера “root@”, можна передати onall ім’я користувача через параметр -u:

$ echo server{1..3}.local | onall -u root -q date
server2.local: Sat Dec 25 13:05:19 UTC 2021
server3.local: Sat Dec 25 13:05:19 UTC 2021
server1.local: Sat Dec 25 13:05:19 UTC 2021

Ускладнимо завдання, скажімо нам потрібно дізнатися на якому сервері яка материнська плата встановлена, а також яка загальна їх кількість у кластері:

$ echo server{1..3}.local | onall -u root -q 'dmidecode -s baseboard-product-name'
server1.local: X9DRT
server2.local: X9DRT
server3.local: X10DRT-P
$ echo server{1..3}.local | onall -u root -q 'dmidecode -s baseboard-product-name' | awk '{print $2}' | sort | uniq -c
      1 X10DRT-P
      2 X9DRT

Як бачите, команду dmidecode з додатковими параметрами я взяв в лапки, аби onall не намагався розібрати його параметри як свої. Втім, інколи буває ситуація, коли через використання одинарних та подвійних лапок неможливо виконати команду, тому залишається лише створити скрипт, та виконати його на всіх серверах ось таким чином:

$ echo server{1..3}.local | onall -u root -q --script cron_status.sh
server1.local: cron is active (running)
server2.local: cron is active (running)
server3.local: cron is active (running)
$ echo server{1..3}.local | onall -u root -q --script cron_status.sh stop
$ echo server{1..3}.local | onall -u root -q --script cron_status.sh
server1.local: cron is not active (stopped)
server2.local: cron is not active (stopped)
server3.local: cron is not active (stopped)

У наведеному прикладі містичний скрипт cron_status.sh може працювати як з параметрами, так і без них. Яким має бути ваш скрипт і чи повинен він підтримувати якісь параметри - залежить лише від ваших потреб та уяви.

Останній приклад, копіювання файлів. У моїй практиці була ситуація, коли потрібно було синхронізувати файл /etc/hosts на 50+ серверах, для цього я використовував параметр --copy:

$ echo server{1..3}.local | onall -u root -q --copy /etc/hosts /etc/hosts
$

На додаток додам, що за замовченням onall запускає максимум 20 одночасних ssh клієнтів, що можна змінити параметром -r. І він не перевіряє, чи сервери онлайн, що можна виправити додавши параметр -p, але треба ще буде довстановити у систему fping. Ознайомитись з повним списком параметрів можна виконавши команду: onall -h

Корисне

  1. GRUB2: Перезавантажити систему у іншу ОС з меню завантаження
  2. Завантажуємо внутрішні посилання для списку доменів з Common Crawl API
  3. Розбиваємо файл на декілька інших файлів за фільтром
  4. Пошук по історії bash за допомогою курсорних клавіш
  5. Ізолюємо процес від доступу до мережі
  6. Пряма трансляція з авторизацією за допомогою Nginx-RTMP
  7. Емулятор груп в Mastodon та Pleroma