Наши партнеры

UnixForum






Книги по Linux (с отзывами читателей)

Библиотека сайта rus-linux.net

На главную -> MyLDP -> Тематический каталог -> Решение административных задач в Linux

Одновременное управление несколькими серверами

Автор: Жольнай Кирилл,
Дата: 21 февраля 2009

Если вы администрируете несколько Linux-серверов, вы неизбежно столкнетесь с тем, что довольно часто приходиться проделывать одни и те же операции над всеми серверами. Например: вносить изменения в конфигурационные файлы (/etc/hosts, скрипты инициализации и т.п.), или производить разовую архивацию на всех серверах. После очередной пресной порции обезьяньей работы мы понимаем, что это не linux-way. Что можно сделать?

Задача # 1

Для примера: нужно поправить /etc/hosts на локальном компьютере и 8 серверах, список которых в файле ~/servers.list.

$ cat servers.list
192.168.0.1
192.168.0.2
192.168.0.3
192.168.4.44
192.168.0.5
192.168.0.6
192.168.0.7
192.168.8.88

$ cat /etc/hosts
127.0.0.1       localhost.localdomain localhost
192.168.0.1   gate
192.168.0.2   megahost1
192.168.0.3   megahost2
192.168.4.44  megahost3
192.168.0.5   megahost4
192.168.0.6   megahost5
192.168.0.7   megahost6
192.168.8.88  megahost7

Стандартный подход

Обычно для решения этой задачи используем стандартные инструменты: любимый редактор (vim или nano) и scp (http://ru.wikipedia.org/wiki/SCP), который входит в состав пакета openssh и включен во все современные дистрибутивы.

1. Вносим необходимые правки в /etc/hosts.
2. Копируем на каждый из серверов:

$ scp /etc/hosts root@192.168.0.1

3. Вводим пароль.
4. Опять выполняем команду копирования:

$ scp /etc/hosts root@192.168.0.2

5. И снова вводим пароль.
...
17. И последний раз вводим пароль.
То есть выполняем 17 нудных действий. Пришло время подняться на первую ступень просвещения.

Ускоренный стандартный подход

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

$ ssh-keygen -q

Несколько раз нажимаем Enter на все задаваемые вопросы. А затем скопируем этот ключ на все сервера стандартной командой ssh-copy-id, попутно вводя пароль. Можно копировать по одному:

1. Копируем ключ сначала на одну машину:

$ ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.0.1

2. Вводим пароль.

3. Копируем ключ на слеующую машину:

$ ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.0.2
...

16. Последний пароль.

А лучше в ускоренном режиме:
1. Копируем ключи поочередно на каждую из машин, список которых в файле ~/servers.list:

$ cat ~/servers.list | while read i ; do ssh-copy-id -i ~/.ssh/id_rsa.pub root@"$i" ; done

2. Вводим пароль.
3. Следующий пароль.
...
8. Последний пароль.

После копирования ключей ни ssh, ни scp пароль не попросит. А вот теперь опять решаем нашу задачу # 1:
1. Редактируем /etc/hosts
2. И копируем на все машины, список которых в файле ~/servers.list:
cat ~/servers.list | while read i ; do scp /etc/hosts root@"$i":/etc/ ; done

Все!
Это и правда все, то есть всего 2 (два) действия. Этой конструкцией можно горы свернуть, но не все, к сожалению. Например, мы сможем выполнить любую команду для каждого из серверов, но мы не увидим вывода этой команды. Можем смириться или двигаться на следующую ступень просветления.

Задача # 2

Нам просто нужно узнать время работы с последней перезагрузки стандартной командой uptime, но со всех серверов. Для этого нам придется воспользоваться одной из программ для параллельного выполнения комманд.

Программы для параллельного выполнения команд

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

Из них бы я особо выделил pssh, pdsh, shmux. А из этих трех мне приглянулся pdsh, за то что: написан на С, давно разрабатывается, часто обновляется, и есть в репозиториях практически всех современных систем (кроме Slackware). И самое главное - не требуется установка на сервера, только на машине, откуда будете работать.

pdsh

PDSH - высокопроизводительная, распараллеленная оболочка (по крайней мере так говорится на официальном сайте. Для доступа к серверам использует либо rsh, либо ssh, что предпочтительней. А так же использует модули расширения, которых мы касаться не будем. Установка, думаю, проблем не вызовет:

$ sudo apt-get install pdsh -y
$ yum install pdsh -y

Синтаксис программы прост:

pdsh -w [user@]host,host,... command

Решаем задачу # 2, а по ходу разбираемся:

Вот и все, задача решена. Правда вывод мы получили вразнобой, так как задачи выполняются параллельно, и вывод происходит по мере поступления (в shmux проблема решена). Но сама команда выглядит монструозной, не правда ли? Для решения этой проблемы у pdsh есть свой синтаксис, который отличается от синтаксиса bash из примера, думаю, будет понятно:

$ pdsh -w root@192.168.0.[1-3,5-7],root@192.168.8.88,root@192.168.4.44 uptime

Получилось немного короче. А когда серверов 50, разница будет потрясающая.

Если вывод многострочный, да еще и задерживается, мы получим кашу, то есть строки будут поступать на экран по мере формирования. Частично решить проблему можно такой конструкцией:
$ pdsh -w hosts command | sort -n

Если мы хотим выполнить некий скрипт на всех серверах содержащий спецсимволы "; & && | || " обязательно возьмите всю выполняемую команду в кавычки. В противном случае интерпретатор (bash) решит, что команда, выполняемая после спецсимвола, предназначена для локальной машины. Например:

$ pdsh -w hosts "i=~ ; rm -rf *$i"

Интересно, что сделает скрипт, если мы кавычки забудем?

В комплекте с pdsh есть утилита pdcp схожая по функционалу с scp. Решим с ее помощью задачу # 1:
1. Редактируем /etc/hosts
2. Копируем все файлы hosts на удаленные машины в папку /etc:

$ pdcp -w root@192.168.0.[1-3,5-7],root@192.168.8.88,root@192.168.4.44 /etc/hosts /etc/

Просто, да? Единственная трудность в том, что для этого pdsh должен быть установлен на всех машинах, но ведь теперь это не проблема:

$ pdsh -w root@192.168.0.[1-3,5-7],root@192.168.8.88,root@192.168.4.44 yum install pdsh -y

А можно все это еще ускорить или упростить? Можно и нужно, последняя ступень просвещения и выход на космические скорости.

Редактируем .bashrc

Если мы управляем несколькими группами серверов, например хостинговыми (50шт) с Debian, сервера внутреннего проекта (24шт) со Slackware и офисные сервера (10шт) c Fedora. Тогда было бы удобно разделить их на группы. У pdsh на этот счет есть решение, но заставить его работать на Slackware я так и не сумел. Поэтому я пошел по linux-way и добавил в ~/.bashrc вот такие строки:

Это позволило нам разделить сервера на группы, а так же обеспечило возможность автодополнения по табуляции. Для примера установим htop на всех машинах:

$ pdsh-to-servers apt-get install htop -y
$ pdsh-to-project "wget http://repos.example.org/htop.tgz && installpkg htop.tgz ; rm htop.tgz"
$ pdsh-to-office yum install htop -y

И, собственно, все. А если мы захотим узнать uptime на всех серверах, выполним следующее:

$ pdsh-to-all uptime

Что бы отчистить все сервера от бэкап-файлов, которые остаются после редактирования vim'ом, поступим так:

$ pdsh-to-all "find /etc -name *~ -exec rm -f {} \;"

Думаю, нет необходимости подсчитывать количество сэкономленных телодвижений.

Итого

Если у вас до 10 нетребовательных к вниманию серверов, имеет смысл использовать ssh c аутентификацией по ключам и "ускоряющую конструкцию". Если более, то pdsh, pssh или shmux, дополненных .bashrc.