Одновременное управление несколькими серверами
Если вы администрируете несколько Linux-серверов, вы неизбежно столкнетесь с тем, что довольно часто приходиться проделывать одни и те же операции над всеми серверами. Например: вносить изменения в конфигурационные файлы (/etc/hosts, скрипты инициализации и т.п.), или производить разовую архивацию на всех серверах. После очередной пресной порции обезьяньей работы мы понимаем, что это не linux-way. Что можно сделать?
Задача # 1
Для примера: нужно поправить /etc/hosts на локальном компьютере и 8 серверах, список которых в файле
Стандартный подход
Обычно для решения этой задачи используем стандартные инструменты: любимый редактор (vim или nano) и scp (http://ru.wikipedia.org/wiki/SCP), который входит в состав пакета openssh и включен во все современные дистрибутивы.
1. Вносим необходимые правки в /etc/hosts.
2. Копируем на каждый из серверов:
3. Вводим пароль.
4. Опять выполняем команду копирования:
5. И снова вводим пароль.
.
17. И последний раз вводим пароль.
То есть выполняем 17 нудных действий. Пришло время подняться на первую ступень просвещения.
Ускоренный стандартный подход
Для начали избавимся от необходимости ввода пароля при входе по ssh или выполнения копирования посредством scp. Для этого мы сгенерируем пару ключей на локальной машине:
Несколько раз нажимаем Enter на все задаваемые вопросы. А затем скопируем этот ключ на все сервера стандартной командой ssh-copy-id, попутно вводя пароль. Можно копировать по одному:
1. Копируем ключ сначала на одну машину:
2. Вводим пароль.
3. Копируем ключ на слеующую машину:
16. Последний пароль.
А лучше в ускоренном режиме:
1. Копируем ключи поочередно на каждую из машин, список которых в файле
2. Вводим пароль.
3. Следующий пароль.
.
8. Последний пароль.
Все!
Это и правда все, то есть всего 2 (два) действия. Этой конструкцией можно горы свернуть, но не все, к сожалению. Например, мы сможем выполнить любую команду для каждого из серверов, но мы не увидим вывода этой команды. Можем смириться или двигаться на следующую ступень просветления.
Задача # 2
Нам просто нужно узнать время работы с последней перезагрузки стандартной командой uptime, но со всех серверов. Для этого нам придется воспользоваться одной из программ для параллельного выполнения комманд.
Программы для параллельного выполнения команд
Так как проблема существует не первый день, решений придумана масса, с довольно различными реализациями и подходом :
Из них бы я особо выделил pssh, pdsh, shmux. А из этих трех мне приглянулся pdsh, за то что: написан на С, давно разрабатывается, часто обновляется, и есть в репозиториях практически всех современных систем (кроме Slackware). И самое главное — не требуется установка на сервера, только на машине, откуда будете работать.
PDSH — высокопроизводительная, распараллеленная оболочка (по крайней мере так говорится на официальном сайте. Для доступа к серверам использует либо rsh, либо ssh, что предпочтительней. А так же использует модули расширения, которых мы касаться не будем. Установка, думаю, проблем не вызовет:
Синтаксис программы прост:
Решаем задачу # 2, а по ходу разбираемся:
Вот и все, задача решена. Правда вывод мы получили вразнобой, так как задачи выполняются параллельно, и вывод происходит по мере поступления (в shmux проблема решена). Но сама команда выглядит монструозной, не правда ли? Для решения этой проблемы у pdsh есть свой синтаксис, который отличается от синтаксиса bash из примера, думаю, будет понятно:
Получилось немного короче. А когда серверов 50, разница будет потрясающая.
Если мы хотим выполнить некий скрипт на всех серверах содержащий спецсимволы «; & && | || » обязательно возьмите всю выполняемую команду в кавычки. В противном случае интерпретатор (bash) решит, что команда, выполняемая после спецсимвола, предназначена для локальной машины. Например:
Интересно, что сделает скрипт, если мы кавычки забудем?
В комплекте с pdsh есть утилита pdcp схожая по функционалу с scp. Решим с ее помощью задачу # 1:
1. Редактируем /etc/hosts
2. Копируем все файлы hosts на удаленные машины в папку /etc:
Просто, да? Единственная трудность в том, что для этого pdsh должен быть установлен на всех машинах, но ведь теперь это не проблема:
А можно все это еще ускорить или упростить? Можно и нужно, последняя ступень просвещения и выход на космические скорости.
Редактируем .bashrc
Если мы управляем несколькими группами серверов, например хостинговыми (50шт) с Debian, сервера внутреннего проекта (24шт) со Slackware и офисные сервера (10шт) c Fedora. Тогда было бы удобно разделить их на группы. У pdsh на этот счет есть решение, но заставить его работать на Slackware я так и не сумел. Поэтому я пошел по linux-way и добавил в
/.bashrc вот такие строки:
Это позволило нам разделить сервера на группы, а так же обеспечило возможность автодополнения по табуляции. Для примера установим htop на всех машинах:
И, собственно, все. А если мы захотим узнать uptime на всех серверах, выполним следующее:
Что бы отчистить все сервера от бэкап-файлов, которые остаются после редактирования vim’ом, поступим так:
Думаю, нет необходимости подсчитывать количество сэкономленных телодвижений.
Итого
Если у вас до 10 нетребовательных к вниманию серверов, имеет смысл использовать ssh c аутентификацией по ключам и «ускоряющую конструкцию». Если более, то pdsh, pssh или shmux, дополненных .bashrc.
Источник
Урок 8. Объединение команд — последовательное и параллельное выполнение в bash
Символы групповых операций
Мы уже изучили достаточно команд и наверняка возникал вопрос как применить данные команды сразу к группе файлов. Например, за раз скопировать несколько файлов в каталог или наоборот удалить ненужные файлы. Делать одну и ту же операцию один за другим довольно утомительное и ненужное занятие.
Поэтому в Linux имеются специальные символы, которые позволяют проводить данные операции над несколькими файлами.
Символ “ * ” указывает на любой символ в любом количестве. Поясним на примере.
У нас имеются следующие файлы:
Необходимо скопировать файлы image в каталог photo/. Для этого достаточно выполнить:
Символ » * « в данном случае означает любые символы после слова image , то есть image1.jpg , image2.jpg и так далее, включая image1.txt , image2.txt и image.pdf .
Чтобы лучше понять данный принцип рассмотрим возможные применения данного символа в таблице:
Все файлы image1.jpg — image15.jpg, image1.txt, image2.txt image.pdf
cp image*.jpg photo/
Только файлы image1.jpg — image15.jpg
Все файлы jpg : image1.jpg — image15.jpg
Абсолютно все файлы в текущем каталоге
Символ “ ? ” указывает на любой одиночный символ. Например, команда cp image?.jpg photo/ скопирует файлы с image1.jpg по image9.jpg , то есть между image и .jpg рассматривается только один знак.
Рассмотрим возможные применения данного символа:
cp image?.jpg photo/
Только с image1.jpg по image9.jpg
cp image1?.jpg photo/
Только с image10.jpg по image15.jpg
В нашем случае выдаст ошибку, так такого файла или каталога не существует
image1.jpg — image9.jpg, image1.txt и image2.txt
Следующий символ групповых операций — это квадратные скобки []. Внутри скобок помещается определенной выражение.
Например, [12] означает, что в условии должен совпасть один из символов, указанных в скобках, то есть либо 1 либо 2. Также можно задать целый диапазон значений — 1, то есть любой символ из указанного диапазона.
Поясним сказанное на примерах:
cp image[12].jpg photo/
Только файлы image1.jpg и image2.jpg
cp image15.jpg photo/
Только файлы image11.jpg — image15.jpg
cp image[12]* photo/
image1.jpg, image2.jpg, image1.txt, image2.txt
cp image?[13].jpg photo/
Только файлы image11.jpg — image13.jpg
Как видно с помощью данных символов можно гибко управлять файлами. Данные символы можно использовать с любыми командами. В последующих разделам мы будем часто с ними встречаться.
Теперь рассмотрим, как можно объединить между собой сразу несколько команд, заставив их выполнять действие последовательно друг за другом либо параллельно.
Последовательное безусловное выполнение
Иногда при выполнении задач в Linux может потребоваться выполнить сразу целую последовательность команд.
Например, нам нужно создать каталог, скопировать группу файлов student*.jpg в данный каталог и проверить размер данного каталога в килобайтах.
Для этого мы выполним следующее:
cp student*.jpg photo/
Пришлось последовательно вводить команду, затем ждать ее завершения и вводить следующую. Однако данный процесс можно оптимизировать, введя все команды одну за другой, отделив каждую точкой с запятой:
mkdir photo; cp student*.jpg photo/; ls -lh
Результат будет тот же, но в данном случае мы все сделали гораздо быстрее. Это особенно актуально, если приходится использовать команды, на выполнение которых может уходить больше времени.
Следует помнить, что выполнение всегда передается следующей команде даже, если выполнение предыдущей команды завершилось с ошибкой.
Последовательное выполнение при соблюдении условия
Может возникнуть ситуация, когда от успешного выполнения первых команд зависит выполнение последующих команд. То есть, если первая команда завершилась с ошибкой, то вторую команду выполнять не будем.
Например, из каталога photo/ нам нужно скопировать файлы на внешний носитель, а затем удалить их из каталога photo/. В принципе можно воспользоваться указанной ниже последовательностью
cp student*.jpg /media/StudentFlash; rm student*.jpg
И все будет работать, однако здесь одно НО. Если мы забудем подключить флэшку и выполним вышеуказанную последовательность, то потеряем все файлы student*.jpg , так как несмотря на ошибку система все равно выполнит вторую команду.
Чтобы избежать подобных ситуаций можно воспользоваться конструкцией:
cp student*.jpg /media/StudentFlash && rm student*.jpg
То есть вместо символа » ; » (точка с запятой) мы используем » && » . Проще говоря, если первая команда завершилась с ошибкой (неважно какая), то система не выполнит вторую команду. Если первая команда завершилась успешно, то будет выполнена вторая команда.
Следующий символ объединения » || « используется, когда из 2-х (или более) команд нужно выполнить либо первую либо вторую команду. То есть, если первая команда завершилась с ошибкой, то ход переходит следующей команде, а если первая команда все же успешно завершилась, то вторая команда выполняться не будет.
Например, перейдем в каталог music/ , если его не существует то создадим его:
cd music/ || mkdir music
В нашем случае каталог music/ не существует и система выдала ошибку, поэтому будет выполнена команда mkdir music .
Передача выхода одной команды на вход другой команды
Иногда при работе с командой ls выводится слишком много информации, которая не помещается на всем экране и приходится прокручивать текст, чтобы увидеть начало
Чтобы постранично просматривать результат выполнения команд можно перенаправить вывод ls на вход команды less . Как мы уже знаем она используется для постраничного просмотра текстовых файлов. Для этого воспользуемся символом » | «:
Теперь попробуем в системе найти файл под названием icon с помощью команды locate (рассмотрим подробнее позже):
Система может выдать сотни и тысячи значений. Здесь тоже можем воспользоваться символом » | «:
locate * icon | less
Разумеется все это частные случаи. В процессе изучения новых команд и работе в Linux тебе придется не раз встречаться с ситуациями, когда будет необходимо воспользоваться символом » | « .
А можно результат работы locate записать в файл и уже потом просмотреть его содержимое с помощью less ?
Конечно можно. Для этого существует другой символ объединения команд » > « :
locate * icon > search_result.txt
В данном случаем символом » > » мы записываем результат выполнения locate в файл search_result.txt .
А файл search_result.txt нужно предварительно создавать?
Нет, если его нет, то система создаст его автоматически. А если он есть, то система перезапишет все его содержимое.
То есть мы можем все потерять по неосторожности?
Совершенно верно, но есть 2 способа избежать этого.
1-й способ. Можно установить специальную опцию noclobber :
set -o noclobber
Теперь, если файл существует, то система выдаст следующее сообщение:
Чтобы отключить эту опцию выполни
set +o noclobber
2-й способ. Вместо символа » > » воспользуйся символом » >> » . Когда указан этот символ система запишет данные в конец файла, тем самым сохранив предыдущие данные.
Подстановка вывода одной команды под аргумент второй команды
Некоторые команды не могут использоваться самостоятельно без указания аргументов. В качестве аргументов обычно выступают файлы, каталоги либо различные шаблоны и условия (об этом немного позже).
Вместо аргументов в некоторых случаях можно использовать и результаты выполнения некоторых команд.
К примеру, у нас имеется текстовый файл links.txt , где хранится следующая запись
Это простая текстовая строка. Попробуем подставить данную строку, чтобы создать каталоги согласно указанной строке. Для этого можно воспользоваться конструкцией типа $() :
mkdir $(cat links.txt)
Вывод команды cat был подставлен под аргумент команды mkdir .
Данная последовательность создает каталог по текущей дате.
Источник