Инструментарий системного администратора: Распределенное администрирование при помощи SSH [2010]
Об этой серии статей
Обычно администратор UNIX® регулярно применяет ряд утилит, приемов и систем. Для упрощения различных процессов можно использовать основные утилиты, операторы командной строки и сценарии. Часть этих инструментов поставляется вместе с операционной системой, но бОльшая часть приемов нарабатывается на основе практического опыта и желания администратора упростить свою жизнь. Цель этой серии статей - рассказать о бОльшей части доступных инструментов для различных UNIX-систем, включая методы упрощения администрирования гетерогенных сред.
Упрощение удаленного входа в систему
Утилиты Secure Shell (SSH) обеспечивают безопасность входа в систему и обмена информацией с удаленным хостом. Существует множество подобных утилит, в том числе общего назначения (обеспечивающих удаленное терминальное подключение), SCP (безопасное решение для копирования между хостами) и SFTP (безопасное решение для копирования файлов, работающее подобно стандартным средствам FTP).
Безопасность работы всех этих утилит обеспечивает шифрование передаваемой информации. Кроме аутентификации, соединения защищены при помощи механизма открытых или закрытых ключей. Одно из основных преимуществ протокола SSH заключается в том, что он позволяет обойтись без обычного обмена логином и паролем, вместо этого копируя открытый ключ на удаленную машину.
Как бы ни был удобен SSH для входа на удаленную машину (поскольку исключает ввод пароля), он еще более удобен для удаленного администрирования. Необходимость ввода пароля может сделать автоматизацию удаленного администрирования (например, запуск команды при помощи планировщика cron) невозможной, поскольку вы, естественно, не захотите указывать пароль в скрипте.
При использовании SSH для запуска команд на множестве машин без передачи открытого ключа, потребуется ввод пароля на каждой машине.
Простой и быстрый способ автоматизации входа в систему заключается в создании открытого ключа:
$ ssh-keygen -t rsa
Следуйте инструкциям на экране, но не вводите пароль, когда он будет запрошен, иначе придется вводить его всякий раз при использовании этого ключа. Будут созданы файлы закрытого и открытого ключей. Теперь нужно только добавить содержимое файла открытого ключа в .ssh/id_rsa.pub и добавить его в файл .ssh/authorized_keys на удаленном хосте для учетной записи, которая используется для входа в систему. Необходимо добавить содержимое файла открытого ключа на каждый компьютер, на котором вы хотели бы входить в систему автоматически.
Удаленный запуск команд
Существует множество способов удаленного запуска команд.
Можно запускать удаленные команды по одной, добавляя их в SSH после информации об имени пользователя и хоста. Например, чтобы получить информацию о дисках удаленного хоста, можно использовать команду, приведенную листинге 1 ниже, которая возвращает соответствующую выдачу.
Листинг 1. Запуск простой команды в SSH
$ ssh mc@gentoo.vm df
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/hda3 14544820 3611520 10194464 27% /
udev 128044 564 127480 1% /dev
/dev/hdc1 1968872 50340 1818516 3% /var/tmp
/dev/hdc2 1968904 1482220 386668 80% /usr/portage
/dev/hdc3 1968904 35760 1833128 2% /home/build
shm 128044 0 128044 0% /dev/shm
Обратите внимание, что последовательность команд в листинге 1 потребует ввода пароля, если до этого на удаленный хост не был загружен открытый ключ.
Кроме того, можно выполнить последовательность команд, перечислив команды через точку с запятой, а затем, поместив всю цепочку команд в кавычки так, чтобы они определялись как единый аргумент.
Пример последовательного запуска поверки диска и времени работы показан в листинге 2.
Листинг 2. Проверка диска и времени работы
$ ssh mc@gentoo.vm "df;uptime"
Filesystem 1K-blocks Used Available Use% Mounted on
Можно указать столько команд, сколько нужно. Также возможно использование отбора при помощи grep или других программ, но необходимо убедиться в том, что вся последовательность удаленных команд заключена в кавычки (см. листинг 3).
Dec 17 18:05:37 localhost su[19218]: pam_authenticate: Permission denied
Dec 17 18:05:37 localhost su[19218]: FAILED su for root by mc
Dec 17 18:05:37 localhost su[19218]: - pts/1 mc:root
Dec 17 18:06:31 localhost su[19221]: pam_authenticate: Permission denied
Dec 17 18:06:31 localhost su[19221]: FAILED su for root by mc
Dec 17 18:06:31 localhost su[19221]: - pts/1 mc:root
Dec 17 18:06:40 localhost su[19222]: pam_authenticate: Permission denied
Dec 17 18:06:40 localhost su[19222]: FAILED su for root by mc
...
Первое, на что следует обратить внимание в листинге 3, - это то, что вход на удаленную машину осуществляется от имени суперпользователя root потому что файл, который необходимо просмотреть, доступен только суперпользователю. Для корректной работы убедитесь в том, что система поддерживает удаленный вход от имени root.
Вторым важным моментом этого примера является то, что команда grep выполняется удаленно. На самом деле в это нет необходимости. Стандартные устройства ввода и вывода удаленного хоста реплицируются с локальной машиной, поэтому выдача команды может быть отфильтрована локально, как показано в листинге 4.
Dec 17 18:05:37 localhost su[19218]: pam_authenticate: Permission denied
Dec 17 18:05:37 localhost su[19218]: FAILED su for root by mc
Dec 17 18:05:37 localhost su[19218]: - pts/1 mc:root
Dec 17 18:06:31 localhost su[19221]: pam_authenticate: Permission denied
Dec 17 18:06:31 localhost su[19221]: FAILED su for root by mc
Dec 17 18:06:31 localhost su[19221]: - pts/1 mc:root
Dec 17 18:06:40 localhost su[19222]: pam_authenticate: Permission denied
Dec 17 18:06:40 localhost su[19222]: FAILED su for root by mc
Dec 17 18:06:40 localhost su[19222]: - pts/1 mc:root
Естественно, результат будет одинаковым.
Тем не менее, использование цепочки команд при помощи вертикальной черты «|» является удобным, когда необходимо передать информацию удаленной команде. Например, можно использовать команду ls вместе с du для получения информации о размере нескольких каталогов, как показано в листинге 5.
Листинг 5. Определение размера нескольких каталогов
ssh root@gentoo.vm "ls -d /usr/local/* |xargs du -sh "
Password:
4.0K /usr/local/bin
4.0K /usr/local/games
4.0K /usr/local/lib
0 /usr/local/man
4.0K /usr/local/sbin
12K /usr/local/share
4.0K /usr/local/src
До того как приступить к использованию этих способов на множестве машин, рассмотрим простой трюк для запуска удаленного интерактивного сеанса на отдельном компьютере без необходимости входа в систему.
Интерактивное подключение к одному компьютеру
Как было сказано выше, на одном компьютере можно запускать несколько различных команд и цепочек команд. Одно из преимуществ SSH заключается в том, что хотя команда выполняется удаленно, устройства ввода и вывода находятся на локальном компьютере. Можно использовать это в качестве способа обмена информацией между двумя машинами для команд, которые нужно выполнить.
Таким образом, можно использовать почти все команды. Тем не менее, поскольку команды запускаются из командной строки, существуют некоторые ограничения. Например, попытка редактировать удаленный файл редактором, при помощи способов и приемов, показанных выше, как правило, заканчивается безуспешно (см. листинг 6).
Чтобы решить эту проблему, укажите SSH создавать псевдотерминал tty так, чтобы было возможно работать с удаленным приложением напрямую.
Запуск удаленной команды на множестве машин
До сих пор мы говорили о запуске одной команды или набора команд на одной удаленной машине. Хотя использование удаленного интерактивного сеанса удобно для администрирования отдельных компьютеров при помощи SSH, вы наверняка захотите автоматизировать этот процесс, что означает сокращение использования интерактивных элементов.
Для запуска удаленной команды на множестве компьютеров необходимо создать простую оболочку для команд SSH и удаленных команд, которые необходимо запустить так, чтобы этот процесс повторялся на всех удаленных машинах.
Это можно сделать при помощи очень простого цикла for, как показано в листинге 7.
Листинг 7. Цикл for для удаленного запуска команд
for remote in mc@gentoo.vm mc@redhat; do echo $remote; ssh $remote 'df -h'; done
mc@gentoo.vm
Filesystem Size Used Avail Use% Mounted on
/dev/hda3 14G 4.1G 9.2G 31% /
udev 126M 564K 125M 1% /dev
/dev/hdc1 1.9G 56M 1.8G 4% /var/tmp
/dev/hdc2 1.9G 1.3G 558M 70% /usr/portage
/dev/hdc3 1.9G 35M 1.8G 2% /home/build
shm 126M 0 126M 0% /dev/shm
mc@redhat
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/VolGroup00-LogVol00
7.1G 5.5G 1.3G 82% /
/dev/hda1 99M 13M 82M 14% /boot
none 125M 0 125M 0% /dev/shm
На основе этого несложно создать простой скрипт, приведенный в листинге 8.
Листинг 8. Сокращение цикла for до простой команды
#!/bin/bash
# Скрипт для запуска команд на множестве машин
# Общие параметры
TIMEOUT=10
ERRLOG=/tmp/remote-err-$$.log
OUTLOG=/tmp/remote-out-$$.log
# Extract the command line
MACHINES=$1;shift
COMMAND=$1;shift
for machine in $MACHINES
do
echo $machine
ssh -oConnectTimeout=$TIMEOUT $machine $
COMMAND >>$OUTLOG 2 >>$ERRLOG
done
cat $OUTLOG
cat $ERRLOG >&2
rm -f $OUTLOG $ERRLOG
MACHINES и COMMAND представляют собой переменные, обрабатываемые в командной строке. При использовании скрипта имя пользователя, хоста и выполняемую команду необходимо заключить в двойные кавычки, чтобы они определялись в качестве одного аргумента.
Единственным дополнением является параметр TIMEOUT. Он назначает для SSH параметр ConnectTimout, чтобы при запуске команды не пришлось напрасно ждать подключения к хосту, который может быть отключен. Значение по умолчанию указано в начале скрипта и гарантирует, что ждать слишком долго не придется.
При запуске команд, выдача отправляется в несколько файлов журналов, на одно стандартное устройство вывода и другое стандартное устройство вывода сообщений об ошибках. Затем можно выводить эту информацию по отдельности в соответствующие места. Это подчеркивает одно из преимуществ использования SSH – вывод от удаленных машин перенаправляются на одно устройстов (стандартное устройство вывода, стандартное устройство вывода сообщений об ошибках), поэтому можно перенаправить выдачу на локальное устройство.
Например, можно повторить проверку df при помощи скрипта:
$ runremote.sh "gentoo redhat" "df -h"
Поскольку стандартные устройства вывода и сообщений об ошибках перенаправлены, можно даже создать журнал всего процесса:
Использование удаленных команд для мониторинга производительности
При использовании скрипта runremote.sh возможно вам захочется поэкспериментировать со значением времени ожидания и изменить это значение в зависимости от своих задач. Например, если скрипт используется для получения снимка текущего состояния, проверяя время работы группы машин, не следует ждать подключения и выполнения команд слишком долго, иначе снимок будет неточным.
Кроме того, текущая версия скрипта выполняет команды последовательно. Это отнимает много времени не только, если происходит обращение к большому количеству машин, но также из-за задержки между выполнением указанных команд на первой и последней машинах, которое может оказаться настолько значительными, что сравнение между машинами будет невозможным.
Немного скорректированный скрипт runremote2 приведен в листинге 9. Он запускает удаленные команды почти одновременно (в фоновом режиме), а затем выполняет вывод в отдельные файлы журналов.
Листинг 9. Скрипт, выполняющий удаленные команды почти одновременно
#!/bin/bash
# Скрипт для запуска команд на множестве машин
# Общие параметры
TIMEOUT=10
ERRLOG=/tmp/remote-err-$$.log
OUTLOG=/tmp/remote-out-$$.log
# Обработка командной строки
MACHINES=$1;shift
COMMAND=$1;shift
for machine in $MACHINES
do
echo $machine >>$OUTLOG.$machine
ssh -oConnectTimeout=$TIMEOUT
$machine $COMMAND >>$OUTLOG.$machine
2>>$ERRLOG.$machine &
done
# Ждать завершения дочерних процессов
wait
cat $OUTLOG.*
cat $ERRLOG.* >&2
rm -f $OUTLOG.* $ERRLOG.*
Этот скрипт также выводит имя обрабатываемого компьютера в журнал (отдельный для каждой машины). Чтобы гарантировать, что скрипт не закроется до завершения всех удаленных команд, необходимо добавить команду wait для ожидания завершения дочерних процессов скрипта.
Теперь можно использовать этот скрипт для одновременной проверки множества машин (см. листинг 10).
Листинг 10. Использование скрипта для одновременной проверки множества машин
Этот вид мониторинга удобен, когда необходимо получить представление обо всей сети – например, для выявления проблемы с группой кластеров компьютеров, обслуживающих web-службы или базы данных, и выявить пиковые значения или проблемы, общие для группы машин.
Тем не менее, необходимо учитывать, что могут происходить задержки при подключении, особенно если машина загружена, а скорость выполнения команд на разных компьютерах будет отличаться.
Запуск одинаковых действий на множестве машин
Создание учетных записей пользователей на множестве машин может стать утомительной процедурой делом. Разумеется, существуют различные решения этой проблемы на основе средств единого входа, таких как Network Information Service (NIS) или решении на основе LDAP, но не всегда возможно синхронизировать учетные записи таким способом.
Для этого можно использовать SSH, запустив команду adduser на множестве машин. Но в ОС Solaris эта команда называется useradd. Параметры командной строки в основном совпадают, поэтому можно использовать скрипт run-remote.sh дважды (см. листинг 11).
Хотя вы создали одинакового пользователя на множестве машин, принадлежащего одной и той же группе и с одинаковым идентификатором, на практике такая регистрация пользователя редко применяется.
Намного лучше будет использовать совет, приведенный в статье Инструментарий системного администратора: Стандартизация инструментов командной строки UNIX (см. раздел Ресурсы) для использования одинаковой команды на множестве машин:
В этой статье вы познакомились с простым, но мощным методом запуска команд на удаленных машинах. Хотя основы этого процесса очевидны, можно расширить функциональность для выполнения некоторых задач удаленного администрирования (например, возможность перенаправлять и создавать цепочку из удаленного и локального ввода). При помощи некоторых простых приемов в скриптах можно использовать эту систему для одновременного удаленного администрирования множества машин, облегчая многие повторяющиеся задачи и мониторинг производительности.