Поиск по этому блогу

среда, 20 января 2010 г.

Удалённый доступ Linux-to-Linux, или ...

Удалённый доступ Linux-to-Linux, или Просто об SSH и VNC.



Когда пришлось решать проблему удалённого доступа между правильными ОС,
встал вполне логичный вопрос о том, как это осуществить. В голову сразу
пришёл протокол SSH, о
котором уже как-то читал, но не решался попробовать в действии, т.к.
полагал что всё будет нудно и сложно, да и вообще мне это было не
нужно. На самом деле, в простейшем случае, это совсем не так. Итак,
если у вас и на обоих ПК установлен дистрибутив Ubuntu Linux, то
получить графический доступ к рабочему столу, но по протоколу VNC, можно вообще в пару кликов мыши.

VNC

     Для
этого сначала на удалённом ПК зайдите в "Система -> Параметры ->
Удалённый рабочий стол" или в терминале выполните (сразу условимся: "$"
перед командой - достаточно прав пользователя, а "#" означает, что
нужны привилегии рута):

$ vino-preferences

После этого откроется окно настроек.
     Итак,
для предоставления доступа нужно отметить пункт "Позволять другим
пользователям видеть ваш рабочий стол". На этом можно и остановиться,
но посмотрим, что предложили нам в дополнительных настройках. Здесь
можно обратить внимание на разделы "Безопасность" вкладки "Общие" и
"Уведомления" вкладки "Дополнительно". Можно вообще отключить
какое-либо уведомление о подключении, убрав отметки пунктов в разделе
"Безопасность", а в "Уведомления" отметив "Никогда не показывать
значок". В принципе, настройки не нуждаются в комментариях, всё
элементарно. После произведения настроек жмём "Закрыть". Так же
необходимо убедиться, что открыты порты диапазона 5000-5006. Всё, ПК
готов к соединению.
     Теперь, когда настройки удалённого ПК завершены, перейдём к осуществлению подключения. Для этого уже на рабочем ПК наберём:

$ vncviewer 111.111.111.111:0

Где
"111.111.111.111" - IP удалённого ПК, а "0" (нуль) после двоеточия -
номер дисплея удалённого ПК. Всё. Если в настройках не были указаны
подтверждение или ввод пароля, то сразу откроется окно, в котором и
будет отображён рабочий стол удалённого ПК. Можно пользоваться не
только управлением мышью, но и клавиатурой. Хочу отметить, что если
запустить вот так:

$ vncviewer FullScreen=1 111.111.111.111:0

то
рабочий стол будет отображён в полноэкранном режиме, а не в окне. Если
вы захотите выйти из полноэкранного режима, то нажмите F8 и уберите
соответствующую галочку. Так же здесь имеются дополнительные настройки
соединения в меню "Settings", которые так же доступны в виде свойств
при запуске vncviewer (в терминале: $ vncviewer --help).
     Данный
метод есть смысл использовать только в случае достаточно быстрого
Интернет-соединения и на десктоп-ориентированных ПК с X Window System.
А так как сам по себе этот протокол всё-таки не отличается особой
безопасностью, то работать с ПК, содержащим важные данные, не
рекомендуется. В случае работы с важными данными гораздо лучше
запускать VNC-сессию через SSH-тоннель. Но это не входит в данный
обзор, поэтому пока ограничимся шифрованным доступом к командной
оболочки удалённого ПК.

SSH

     С
помощью SSH всё не так красочно, но зато быстро и надёжно. Используя
SSH можно без проблем организовать надёжный и шифрованный канал между
двумя машинами. Приступим.
     Для начала необходимо убедится, что на удалённом ПК работает SSH-сервер:

$ ps -ax|grep sshd

Должна появится строка вроде "5437 ? Ss 0:00 /usr/sbin/sshd". Если это не так, то запускаем

# /etc/init.d/ssh start

или устанавливаем его (демон запустится автоматически):

# apt-get install openssh-server

Убедитесь, что порт 22 для TCP-соединений не закрыт. С удалённой машиной всё :)
     Теперь переходим к поднятию соединения. Убедитесь, что у вас установлен SSH-клиент:

$ aptitude search openssh-client

В начале строки должна стоять буква "i". Если это не так, то:

# apt-get install openssh-client


     Осуществлять
аутентификацию будем по двум ключам - приватному (шифрованный) и
публичному. Это просто и удобно, лучше чем по паролю на удалённом ПК.
Для этого нужно сначала создать эти два ключа:

$ ssh-keygen

Будет
задана как минимум пара вопросов. Место расположения ключа оставьте по
умолчанию, т.е. на первый вопрос просто нажмите Ввод, а вот потом
введите ключевую фразу и в следующем шаге подтвердите ввод. Фраза
должна быть более 4-х байт, но лучше с запасом. 6-8 символов вполне
подойдут. После этого скопируем публичный ключ на тот самый удалённый
ПК через Сеть (трафик шифруется):

$ ssh-copy-id user@ip

Где
"user" - название учётной записи пользователя удалённого ПК, от имени
которого вы будете работать, а "ip" - IP того ПК. После установления
соединения ответьте "yes" на подтверждение передачи публичного ключа
через интернет, а потом введите пароль этого аккуанта. Всё, ключ
скопирован на удалённый ПК. С этого момента вы сможете заходить на него
без ввода пароля пользователя, а лишь вводя свою ключевую фразу для
расшифровки своего же (приватного) ключа. Делается это очень просто:

$ ssh user@ip

Таким
образом, если вы будет работать под чьим-то аккуантом, то его владелец
сможет сменить пароль после передачи ключа, а вы этого даже не заметите.
     Итак,
после подключения у вас в терминале/консоли будет выведено
информационное сообщение, а строка приглашения изменится на
user@server, где "server" - уже имя удалённой машины.

Устанавливаем и настраиваем систему м...

Устанавливаем и настраиваем систему мониторинга сети OpenNMS (opennms monitoring)

1. Cайт OpenNMS - http://www.opennms.org.
2. Документация OpenNMS - http://www.opennms.org/index.php/Docu-overview




Когда количество активного оборудования и серверов в сети неуклонно
растет, а контролировать работоспособность и качество предоставляемых
сервисов становится все сложнее, на помощь приходит система
мониторинга сети OpenNMS.

Кратко о системе мониторинга OpenNMS

OpenNMS - система мониторинга сетевой инфраструктуры уровня
предприятия, распространяемая по модели свободного программного
обеспечения (Open Source). Кроме обычной для Open Source-проектов
поддержки сообществом пользователей, производитель предоставляет
многоуровневое коммерческое сопровождение продукта: от внедрения до
обеспечения технической поддержки 24х7 и обучения персонала.

Данная система реализована на Java, поэтому появляется такое
положительное качество, как кроссплатформенность.

Поддерживаются ОС:

* Linux:
* Debian Etch и Lenny (x86 и x86_64);
* Red Hat Enterprise Linux/CentOS (3, 4 и 5; x86 и x86_64);
* Fedora Core (версии с 2 по 8, x86 и x86_64);
* Mandriva 2007 и 2008;
* SuSE (9 и 10).
* Solaris 8, 9, и 10 (SPARC и x86);
* Mac OS X (10.4+, PowerPC и x86);
* Windows 2000, XP, 2003 (Vista и Server 2008 не тестировались).


Теоретически OpenNMS может запуститься на любой платформе,
поддерживающей Java SDK 1.4 и выше. Также к положительным качествам
можно отнести модульность системы и возможность развертывания частей
системы на раздельных серверах (СУБД, демоны сбора статистики и
веб-интерфейс могут быть разнесены). Конечно, можно добавить и ложку
дегтя: за Java-реализацию, обеспечившую кроссплатформенность, пришлось
заплатить увеличением потребления ресурсов.

Система OpenNMS отвечает за мониторинг функционирующих в сетевой
инфраструктуре сервисов, таких как Web, DNS, DHCP, сервисы СУБД
(Oracle, MSSQL, PostgreSQL и др.), однако информация о состоянии
сетевых устройств также доступна.

В системе упрощены способы добавления новых сетевых устройств для
мониторинга, и общий принцип работы основан на автоматическом
обнаружении (discovery) сетевых устройств. Обнаружение состоит из двух
частей - определение интерфейсов (IP-адресов) и определение
функционирующих на этих интерфейсах сервисов. Определение интерфейсов
осуществляется на основе протокола ICMP (Ping), а определение сервисов
- с помощью сборщиков (collectors). На данный момент существует
несколько сборщиков, но далее мы подробно рассмотрим сбор статистики,
основанный на протоколе SNMP.

Основной единицей мониторинга системы является интерфейс (interface),
который уникально определяется на основе IP-адреса. Сервисы (services)
привязаны к интерфейсам, а интерфейсы, расположенные на одном
устройстве, группируются в узел (node).

Что ж, давайте не будем упускать шанс оценить качество системы и
удобство работы с ней самостоятельно, не полагаясь на рекламные
строчки и чужие мнения. Приступим к установке.


Установка в дистрибутиве Fedora 8 Linux

Перед началом установки хотелось бы предупредить вас о некоторых
тонкостях. Во-первых, для текущей версии OpenNMS 1.5.90 сервер
PostgreSQL ветки 8.3.Х не поддерживается, так что устанавливать
будем сервер ветки 8.2. Во-вторых, начиная с версии OpenNMS 1.3.6 в
составе дистрибутива отсутствует библиотека jicmp, которую необходимо
будет загрузить отдельно.

Также для работы системы нам понадобится JDK. Уточню, что
необходима именно версия JDK (Java Developer Kit), а не JRE (Java
Runtime Environment), так как веб-интерфейс написан на Java/JSP, а для
компиляции JSP в сервлет необходим компилятор Java, который
отсутствует в JRE.

Установка JDK

Java Development Kit (JDK) можно скачать с сайта компании Sun либо
установить с помощью yum из репозитория Tigro.

Если данный репозиторий у вас не подключен, то можно установить его
через RPM-менеджер:

rpm -ihv http://mirror.yandex.ru/fedora/tigro/8/i386/tigro-release-8-1.i386.rpm


После установки репозитория можно воспользоваться yum:

yum install jdk


Хочу упомянуть об одном неприятном моменте: после установки JDK в
Fedora 8 необходимо выполнить ряд дополнительных шагов, чтобы
заставить работать виртуальную машину. Дело в том, что при попытке
запуска любого Java-приложения выдается ошибка следующего вида:

java: xcb_xlib.c:50: xcb_xlib_unlock: Assertion `c->xlib.lock' failed


Проблема всем давно известная (попробуйте поискать в Google строку с
ошибкой) и решается в Fedora 8 следующим образом:

sed -i 's/XINERAMA/FAKEEXTN/g' /usr/java/jdk1.6.0_05/jre/lib/i386/xawt/libmawt.so


Возможно, ваш путь к файлу libmawt.so будет отличаться от приведенного
выше.

Установка PostgreSQL

Если у вас еще не установлен PostgreSQL [4], то установим с помошью
yum:

yum install postgresql-server


Теперь выполним начальную инициализацию:

/sbin/service postgresql initdb


Далее необходимо задать базовые настройки сервера. Для этого нужно
отредактировать файлы pg_hba.conf и postgresql.conf, находящиеся в
/var/lib/pgsql/dat.

Правим файл pg_hba.conf:

local all all trust
host all all 127.0.0.1/32 trust
host all all ::1/128 trust


Файл postgresql.conf:

listen_addresses = 'localhost'


Еще раз напомню, что это тестовая установка и конфигурационные файлы
очень упрощены, проблемы безопасности полностью игнорируются и доступ
к серверу БД никак не защищен.

Запускаем сервер:

/sbin/service postgresql start


и переходим к следующему шагу.


Установка OpenNMS

Есть несколько веток программы для установки: stable, development и
nightly snapshot, причем разработчикам рекомендуется использовать
ветку development. На момент написания статьи была доступна версия
1.5.90.

Для установки можно скачать установочный jar-файл, но проще будет
установить дополнительный репозиторий OpenNMS для yum:

rpm -Uvh http://yum.opennms.org/repofiles/opennms-repo-unstable-fc8.noarch.rpm


Данной командой мы установили репозиторий yum для development-ветки
OpenNMS. Теперь необходимо установить пакет opennms с помошью yum:

yum install opennms


Дополнительно необходимо установить пакеты jrrd (опционально вместо
rrd), jicmp и iplike:

yum install jrrd
yum install jicmp
yum install iplike


По умолчанию устанавливается веб-интерфейс opennms-webapp-jetty для
встроенного в OpenNMS контейнера сервлетов Jetty, но есть также версия
веб-интерфейса для Tomcat и называется opennms-webapp-standalone.

После успешной установки необходимо запустить скрипт поиска
установленной виртуальной машины Java:

cd /opt/opennms/bin
./runjava -s


Если по какой-то причине скрипт отработает некорректно (например, вы
установили JDK по нестандартному пути), либо у вас установлено
несколько разных JDK и вы хотите указать скрипту конкретную, то можно
задать явный путь:

./runjava -S /usr/java/jdk1.6.0_5/bin/java


Теперь можно запускать скрипт начальной конфигурации:

./install -dis


Итак, если мы ничего не упустили, то скрипт отработает без ошибок.
После завершения установочного скрипта не забываем посмотреть, все ли
прошло хорошо:

- searching for jicmp:
- trying to load /usr/lib/libjicmp.so: OK
- searching for jrrd:
- trying to load /usr/lib/libjrrd.so: OK
- checking database version... 8.2


Должны быть найдены библиотеки jicmp и jrrd. Если что-то пошло не так,
то можно явно задать пути поиска:

./install -disU -l /usr/lib/jni:/usr/lib


Также не забываем, что если мы устанавливаем базу данных OpenNMS на
свежую инсталляцию СУБД PostgreSQL, то пароль пользователя postgres
пока пустой. Если же у вас уже был установлен сервер PostgreSQL, то
вам могут понадобиться опциональные аргументы для скрипта инсталляции:

-A,--admin-password <arg>
// Пароль администратора сервера postgres (по умолчанию: '')

-a,--admin-username <arg>
// Имя администратора сервера postgres (по умолчанию: 'postgres')

-c,--clean-database
// Очистить существующую базу при создании

-D,--database-url <arg>
// JDBC УРЛ базы данных (по умолчанию: jdbc:postgresql://localhost:5432/)

-P,--database-name <arg>
// Имя базы данных PostgreSQL (по умолчанию: opennms)

-p,--password <arg>
// Пароль для базы данных opennms (по умолчанию: 'opennms')

-u,--username <arg>
// Имя пользователя БД opennms (по умолчанию: 'opennms')


Список всех возможных атрибутов можно просмотреть, набрав:

./install -help


После успешной начальной установки и конфигурации можно запускать
OpenNMS:

./opennms start


Теперь набираем в браузере строку http://127.0.0.1:8980/opennms/ и
вводим имя пользователя "admin" и пароль "admin".


Установка в Windows XP

Установка для Windows не должна вызвать каких-либо затруднений и
сводится к запуску файла opennms-installer-1.5.90.jar и следованию
указаниям графического установщика, поэтому подробно описывать процесс
не имеет смысла. Перед установкой необходимо предварительно
инсталлировать JDK не ниже 5 версии и PostgreSQL ветки 8.2 (8.3 не
поддерживается). Также отдельно устанавливается библиотека jicmp,
и путь к ней должен содержаться в переменной окружения PATH.


Описание сетевой инфраструктуры для мониторинга

Для более наглядного описания системы представим себе, что мы
настраиваем ее для мониторинга корпоративной сети предприятия с
головным офисом и небольшой сетью филиалов. Каждый из филиалов
объединен с головным офисом в единую сеть (см. рис. 1).


Рисунок 1. Общая схема сети организации с удаленными офисами


Пусть адресное пространство корпоративной сети будет задано следующим
образом:

* 10.10.10.0/24 - адресное пространство головного офиса, выделенное
для серверов, маршрутизаторов, коммутаторов, сетевых принтеров и т.
п.;


* 10.10.11.0/24 - адресное пространство головного офиса для рабочих
станций пользователей;


* 10.10.12.0/24 - адресное пространство офиса No.1;


* 10.10.13.0/24 - адресное пространство офиса No.2;


* 10.10.14.0/24 - адресное пространство офиса No.3.


Наша сеть состоит из достаточного количества маршрутизаторов (например
Cisco 2800 серии в головном офисе и маршрутизаторов попроще - Cisco
серий 2600, 1800 и т. п.). На маршрутизаторах настроены SNMP-агенты
различных версий, включая третью. Кроме того, имеются также серверы,
среди которых терминальные, серверы баз данных, почтовые и т. п., на
многих из которых также установлены SNMP-агенты (например, с помощью
Net-SNMP).


Настройка диапазонов сетевого обнаружения (Discovery)

Параметры обнаружения устройств описываются в файле
discovery-cofiguration.xml. Уточню, что все конфигурационные файлы
хранятся в каталоге openNMS-install-path\etc, где openNMS-install-path
- путь установки OpenNMS. Ниже представлен пример файла
discovery-cofiguration.xml для нашего варианта сетевой инфраструктуры:

<discovery-configuration threads="1" packets-per-second="1"
initial-sleep-time="30000"
restart-sleep-time="86400000"
retries="3" timeout="800">

<include-range retries="2" timeout="1500">
<begin>10.10.10.1</begin>
<end>10.10.14.254</end>
</include-range>
<exclude-range>
<begin>10.10.11.1</begin>
<end>10.10.11.254</end>
</exclude-range>
<specific>10.10.11.1</specific>
<include-url>file:/opt/OpenNMS/etc/moreip.txt</include-url>
</discovery-configuration>


Согласно приведенному файлу, будет осуществляться опрос (посылаться
ICMP ping) диапазона адресов 10.10.10.0/24, 10.10.12.0/24,
10.10.13.0/24 и 10.10.14.0/24, а также одиночного IP-адреса 10.10.11.1
и списка IP-адресов, указанных в файле /opt/OpenNMS/etc/moreip.txt.

Опишем некоторые глобальные атрибуты по умолчанию, задаваемые в теге
<discovery-configuration>:

* threads - количество потоков для опроса.


* packets-per-second - количество генерируемых ICMP-пакетов в
секунду. Не стоит указывать слишком большое число, если задержки в
вашей сети велики.


* initial-sleep-time - время перед стартом процесса обнаружения (в
миллисекундах, значение по умолчанию - 5 минут). Задержка необходима
для полного старта системы, перед тем как начнут генерироваться
события (events).


* restart-sleep-time - время после окончания процесса обнаружения,
через которое процесс будет повторно запущен (в миллисекундах,
значение по умолчанию - 24 часа).


* timeout - время ожидания ответа от обнаруживаемого IP-адреса.


* retries - количество попыток обнаружения, если с первой попытки
ничего не обнаружено.



Глобальные атрибуты можно переопределить внутри вложенных в тег
<discovery-configuration> тегов.

* Тег <specific> - указывает определенный IP-адрес, включенных в
процесс обнаружения.


* Тег <include-range> - указывает диапазон IP-адресов, включенных в
процесс обнаружения.


* Тег <exclude-range> - указывает диапазон IP-адресов, исключенных из
процесса обнаружения.


* Тег <include-url> - определяет файл со списком включенных в процесс
обнаружения IP-адресов, один IP-адрес в каждой строке.


Все вложенные теги необязательны, но возможно также их множественное
добавление. Так, можно задать несколько диапазонов с помощью
<include-range>, определить несколько тегов <specific> и
<include-url>.

Итак, при запуске системы OpenNMS по истечении времени
initial-sleep-time запускается процесс обнаружения интерфейсов. Если
получен ответ на ICMP-запрос, то для обнаруженного интерфейса
регистрируется событие (event) newSuspect, на основе которого в
дальнейшем будет осуществлена попытка обнаружения сервисов,
функционирующих на данном интерфейсе. А что делать, если ICMP-запросы
блокируются сетевым экраном? Для таких случаев существует
альтернативный метод для регистрации событий newSuspect. В подкаталоге
bin установленной системы openNMS находится Perl-скрипт send-event.pl,
который можно использовать для самостоятельной регистрации данного
события:

/opt/opennms/bin/send-event.pl --interface ip-address uei.opennms.org/internal/discovery/newSuspect


где "ip-address" - нужный IP-адрес.

Посмотреть на ход процесса обнаружения можно, заглянув в файл
discovery.log, находящийся в подкаталоге logs установленной системы
openNMS.


Настройка процесса обнаружения сервисов (Capabilities daemon)

После того как зарегистрированы события newSuspect для обнаруженных
интерфейсов, приходит время работы демона capsd (capabilities daemon).
Его задачей является распознавание всех функционирующих на интерфейсе
сервисов. Рассмотрим пример конфигурационного файла
capsd-configuration.xml. Конфигурация файла позволяет очень гибко
управлять ходом процесса обнаружения сервисов. В первых строчках
определяются глобальные параметры функционирования сервиса:

<capsd-configuration rescan-frequency="86400000"
initial-sleep-time="300000"
management-policy="managed"
max-suspect-thread-pool-size="6"
max-rescan-thread-pool-size="3"
abort-protocol-scans-if-no-route="false">


где:

* rescan-frequency - время, через которое происходит повторное
сканирование интерфейса на предмет обнаружения сервисов.


* initial-sleep-time - время задержки после запуска openNMS перед
началом сканирования сервисов.


* management-policy - контролирует процесс сканирования сервисов.


Если установлен в "managed" - то все события newSuspect будут
обработаны, если же параметр установлен в значение "unmanaged", то
все события newSuspect будут проигнорированы, и сканирование не
произойдет. Параметр можно переопределить в теге
<protocol-configuration>, о котором будет рассказано дальше.

* max-suspect-thread-pool-size - количество одновременных потоков
сканирования при первоначальном обходе адресов. Увеличение значения
ускоряет сканирование ценой потребляемых ресурсов.


* max-rescan-thread-pool-size - количество создаваемых потоков на
интерфейсах с уже обнаруженными сервисами при повторном сканировании.


* abort-protocol-scans-if-no-route - если параметр выставлен в
"false", то попытки сканирования сервисов при получении сообщения
"no route to host" продолжатся, так как это сообщение может быть в
некоторых случаях вызвано наличием межсетевого экрана. Если параметр
примет значение "true", то сканирование интерфейса будет
остановлено.


Далее в конфигурационном файле идет описание сервисов (protocols).
Определение сервисов основано на установлении TCP-подключения на
определенный порт, но есть также специальные классы для некоторых
сервисов. Список сервисов, поддерживаемых "из коробки" можно
просмотреть в конфигурационном файле (возможно также добавление
дополнительных сервисов с помощью тега <protocol-plugin>).

При обработке события newEvent, в случае, если IP-адрес определен как
"managed" демон capsd начинает сканирование сервисов в порядке их
следования в конфигурационном файле. Первым в конфигурационном файле
указан протокол ICMP:

<protocol-plugin protocol="ICMP"
class-name="org.opennms.netmgt.capsd.IcmpPlugin"
scan="on" user-defined="false">
<property key="timeout" value="2000"/>
<property key="retry" value="2"/>
</protocol-plugin>


Описание каждого сервиса заключено внутри тега <protocol-plugin>.
Данный тег содержит следующие атрибуты:

* protocol - название сервиса;


* class-name - определяет класс, который будет использоваться для
сканирования сервиса;


* scan - признак включения сканирования данного сервиса ("on" -
сканирование сервиса включено, "off" - сервис не будет
сканироваться);


* user-defined - добавление новых сервисов возможно через
веб-интерфейс. В таком случае атрибут примет значение "true".


В каждом сервисе можно указывать дополнительные параметры,
определяемые через значения key и value внутри тега <property>. Кроме
того, применительно к каждому сервису можно применять дополнительный
тег <protocol-configuration>, в котором можно описывать группы
IP-адресов, исключенные (или включенные) из сканирования. Например:

<protocol-plugin protocol="SNMP"
class-name="org.opennms.netmgt.capsd.plugins.SnmpPlugin" scan="on"
user-defined="false">

<protocol-configuration scan="off" user-defined="false">
<range begin="10.10.12.1" end="10.10.14.254"/>
<property key="timeout" value="4000"/>
<property key="retry" value="3"/>
</protocol-configuration>
<protocol-configuration scan="on" user-defined="false">
<specific>10.10.11.1</specific>
</protocol-configuration>

<property key="timeout" value="2000" />
<property key="retry" value="1" />
</protocol-plugin>


В приведенном выше примере мы переопределили группу адресов
(10.10.12.1 -10.10.14.254), для которых определение сервиса SNMP будет
отключено, и добавили адрес 10.10.11.1, для которого наличие сервиса
будет определяться. Также можно переопределить общие для всех
настройки обнаружения, заданные в головном теге <capsd-configuration>
с помощью тега <ip-management>:

<ip-management policy="managed">
<range begin="10.10.10.1" end="10.10.14.254"/>
<include-url>file:/opt/OpenNMS/etc/include</include-url>
</ip-management>


где значение атрибута policy может принимать значение "managed" и
"unmanaged".

Данные настройки действуют на все указанные в capsd-configuration
сервисы, если только диапазон адресов для какого-либо сервиса (в нашем
случае - SNMP) не переопределен c помощью тега
<protocol-configuration>.

Необходимо заметить, что если в процессе обнаружения (discovery)
интерфейс по каким-то причинам не был определен, и не было
зарегистрировано событие newSuspect, демон capsd для такого интерфейса
не будет запущен, даже если указать IP-адрес в файле конфигурации
capsd явно.


Настройка периодичности опросов (polling)

После сбора информации об узлах, интерфейсах и функционирующих на них
сервисах приходит время мониторинга. Информация о состоянии сервисов,
интерфейсов и узлов собирается двумя основными способами.

Первый способ основан на периодических опросах (polling).
Процессы-мониторы подключаются к ресурсу и производят простой тест,
чтобы определить текущее состояние ресурса. Если ресурс недоступен -
генерируется определенное событие.

Настройка периодичности опросов описывается в файле
poller-configuration.xml. Для удобства введено понятие пакета
(package) сервисов. В файле можно описать несколько пакетов, в каждом
из которых можно указать собственную периодичность опросов, а также
определить уникальное подмножество опрашиваемых сервисов. Кроме того,
в каждом пакете можно задавать собственную модель действий при
недоступности сервиса. Период опроса в случае недоступности сервиса
меняется динамически и может гибко настраиваться. Также для каждого
пакета можно задать время простоя, когда не будет производиться опрос
сервисов. Глобально периоды простоя для всех пакетов можно задать в
файле poll-outages.xml.

Данные опросов собираются с помощью библиотеки jrrd - Java-реализации
всем известной RRD (Round Robin Database).

Рассмотрим файл poller-configuration.xml:

<poller-configuration threads="30"
serviceUnresponsiveEnabled="false"
nextOutageId="SELECT nextval('outageNxtId')" xmlrpc="false">
<node-outage status="on" pollAllIfNoCriticalServiceDefined="true">
<critical-service name="ICMP" />
</node-outage>


Параметр threads определяет максимальное количество потоков для
опроса. Варьируется в зависимости от количества опрашиваемых устройств
и мощности сервера. Будьте внимательны с данным параметром, при
большом количестве опрашиваемых устройств может потребоваться
увеличить количество потоков для опроса, так как демон может не успеть
опросить все устройства в течение заданного времени. Узнать, успевает
ли демон опросить все устройства и сервисы, можно, заглянув в файл
logs/daemon/poller.log. В файле нужно найти строку, содержащую
максимальное значение параметра alive:

2008-05-15 17:01:16,201 DEBUG [PollerScheduler-40 Pool]
RunnableConsumerThreadPool$SizingFifoQueue:
adjust: started fiber PollerScheduler-40 Pool-fiber21
ratio = 1.0476191, alive = 21


Если значение параметра alive+1 (так как есть еще родительский поток)
близко к значению параметра threads, то есть смысл увеличить
количество потоков опроса.

Параметр serviceUnresponsiveEnabled определяет, какое событие будет
генерироваться в случае кратковременного сбоя - "выход из строя"
(outage) или только "сервис не отвечает" (unresponsive).

Чтобы не генерировать событие "выход из строя" при кратковременной
недоступности, нужно выставить этот параметр в "true".

Тег <node-outage> определяет поведение в случае недоступности всех
интерфейсов на узле.

Если во время опроса какой-либо сервис на интерфейсе не отвечает,
генерируется событие NodeLostService, если все сервисы на интерфейсе
не отвечают, то генерируется событие InterfaceDown. Если параметру
status присвоено значение "on", то в случае недоступности всех
интерфейсов узла не генерируется множество событий NodeLostService и
InterfaceDown, а лишь одно событие - NodeDown. Во время недоступности
узла, в случае, если с помощью тега <critical-service> определен
критический сервис (в нашем случае ICMP), будет опрашиваться только
критический сервис. После того как критический сервис будет
восстановлен, начнут опрашиваться все остальные сервисы. Если тег
<critical-service> не задан, то опрос всех сервисов определяется
параметром pollAllIfNoCriticalServiceDefined. Если данное свойство
имеет значение "false", то будет опрашиваться только первый сервис в
пакете, иначе - все. Для удобства создадим на основе уже готового
пакета exmaple1 пакет ICMP-PKG и поместим туда единственный сервис
ICMP, так как хотим опрашивать устройства по данному протоколу чаще,
чем, например, собирать статистику по SNMP:


<package name="ICMP-PKG">
<filter>IPADDR != '0.0.0.0'</filter>
<include-range begin="1.1.1.1" end="254.254.254.254" />
<rrd step="60">
<rra>RRA:AVERAGE:0.5:1:89280</rra>
<rra>RRA:AVERAGE:0.5:60:8784</rra>
<rra>RRA:AVERAGE:0.5:1440:366</rra>
<rra>RRA:MAX:0.5:1440:366</rra>
<rra>RRA:MIN:0.5:1440:366</rra>
</rrd>
<service name="ICMP" interval="30000"
user-defined="false" status="on">
<parameter key="retry" value="2" />
<parameter key="timeout" value="3000" />
<parameter key="rrd-repository"
value="D:/PROGRA~1/OpenNMS/share/rrd/response" />
<parameter key="rrd-base-name" value="icmp" />
<parameter key="ds-name" value="icmp" />
</service>
<downtime interval="20000" begin="0" end="300000"/>
<!-- 20s, 0, 5m -->
<downtime interval="120000" begin="300000" end="3600000"/>
<!-- 2m, 5m, 1h -->
<downtime interval="300000" begin="3600000" end="432000000"/>
<!-- 5m, 1h, 5d -->
<downtime begin="432000000" delete="true" />
<!-- anything after 5 days delete -->
</package>




Обратите внимание на тег <filter>. Внутри пакета он может быть задан в
единственном числе. В теге можно задать фильтрацию IP-адресов по
маскам. Например, так: <filter>IPADDR = '10.*.*.*'</filter> - будут
опрашиваться лишь адреса 10.0.0.0/8. Также можно задавать диапазоны
адресов с помощью уже известного тега <include-range>, внутри которого
задан диапазон IP-адресов для опроса. Напомню, что опрашиваться будут
лишь сервисы на интерфейсах, найденных в процессе обнаружения. То есть
сервисов на интерфейсе может быть найдено множество, однако сбор
статистики будет происходить лишь по сервисам, указанным в пакетах
файла poller-configuration. Внутри пакета с помощью тега <service>
может быть определено несколько сервисов (в нашем пакете только сервис
ICMP). Рассмотрим атрибуты и вложенные теги тега <service>:

Атрибут status может принимать значения "on" - статистика собирается
и "off" - сбор статистики отключен.

В тегах <parameter> с помощью атрибутов key и value задаются
дополнительные параметры, среди которых следует обратить внимание на
параметр rrd-repository, в котором задается путь для хранения данных
опросов. Учтите, что этот параметр связан с параметром rrd.base.dir в
файле opennms.properties. Не забывайте об этом, если будете переносить
конфигурационные файлы с сервера на сервер.

В тегах <downtime> описывается поведение опроса сервиса в случае его
недоступности:

* Атрибут interval - задает периодичность опроса при недоступности;


* Атрибут begin - время начала заданного периода опроса
миллисекундах;


* Атрибут end - время с окончания заданного периода опроса в
миллисекундах.


То есть в строке:

interval="20000" begin="0" end="300000"/>


указано, что в случае недоступности сервиса производить опрос каждые
20 секунд, начиная с нулевой секунды и по достижении 5 минут времени
недоступности. Начиная с пяти минут недоступности сервиса можно
увеличить интервал опроса до 2 минут, таким образом уменьшив нагрузку
на вычислительные ресурсы:

<downtime interval="120000" begin="300000" end="3600000"/>


а после недоступности сервиса в течение часа увеличить интервал опроса
еще больше.

Тег <rrd>, в котором задаются параметры сбора и хранения данных,
заслуживает более пристального изучения и будет рассмотрен позже.

Второй способ сбора статистики основан на коллекторах (collectors). Он
немного сложнее в настройке, но может дать больше информации.
Существует возможность использования нескольких коллекторов, мы
остановимся подробнее на сборе статистики с помощью опросов
SNMP-агентов.


Настройка сбора статистики по протоколу SNMP

При настройках по умолчанию в OpenNMS 1.5.90 для сбора статистики на
основе коллекторов используется протокол SNMP версии 1 и 2(с). Однако
существует также возможность использовать протокол SNMP-версии 3. Для
активации возможности сбора информации по SNMPv3 необходимо
использовать библиотеку SNMP4J [1], поддерживающую протокол SNMPv3 (по
умолчанию используется библиотека JoeSNMP). Однако для большинства
случаев достаточно SNMPv1 и SNMPv2. Для активации SNMPv3 необходимо
раскомментировать строчку:

org.opennms.snmp.strategyClass=org.opennms.netmgt.snmp.snmp4j.Snmp4JStrategy


в файле opennms.properties и поставить символ комментария перед
строчкой с JoeSNMP.

Теперь следует возвратиться к файлу capsd-configuration.xml и добавить
для удобства новый сервис с названием SNMPv3 (название может быть
любым, удобным вам). В будущем это поможет отличать узлы с
обнаруженными SNMP-агентами разных версий:

<protocol-plugin protocol="SNMPv3"
class-name="org.opennms.netmgt.capsd.SnmpPlugin"
scan="on" user-defined="false">
<property key="force version" value="SNMPv3"/>
<property key="timeout" value="2000"/>
<property key="retry" value="3"/>
</protocol-plugin>


Также необходимо добавить сервис с таким же именем в файл
poller-configuration.xml, если этого не сделать, сервис определится,
но опрашиваться не будет. Здесь есть одна тонкость - если не указывать
конкретную версию протокола и вообще исключить строчку <property
key="force version" value="SNMPv3"/> (как это сделано в конфигурации
по умолчанию), то будут найдены SNMP-агенты версий, указанных в файле
snmp-config.xml.

При сканировании сервиса SNMP демон capsd обращается за дополнительной
информацией в файл snmp-config.xml:

<?xml version="1.0"?>
<snmp-config port="161" retry="3" timeout="1500"
read-community="public" write-community="private">
<definition version="v3" security-name="myname"
auth-protocol="MD5" auth-passphrase="yourmd5pass">
<specific>10.10.10.1</specific>
<specific>10.10.11.1</specific>
</definition>
<definition version="v1" read-community="charoday">
<specific>10.10.14.1</specific>
</definition>
</snmp-config>


В файле находится дополнительная информация для опроса SNMP-агентов.

Корневой тег файла называется <snmp-config> и содержит следующие
атрибуты:

* port - порт, через который идет обращение к SNMP-агенту;
* retry - количество попыток подключения к SNMP-агенту;
* timeout - время ожидания ответа от агента;
* read-community - строка для доступа на чтение к SNMP-агенту;
* write-community - строка для доступа на запись к SNMP-агенту;
* version - версия SNMP-протокола.


Можно переопределить атрибуты, указанные в корневом теге, описав
внутри него тег <definition>. В нашем случае в первом вложенном теге
<definition> мы переопределили версию протокола SNMP. Внутри этого
тега также можно определять диапазоны IP-адресов с помощью тегов
<include-range>, <specific> и <exclude-range>.

Для определения протокола SNMPv3 существуют дополнительные атрибуты:

* security-name - имя для аутентификации;


* auth-protocol - протокол шифрования пароля аутентификации (SHA или MD5);


* auth-passphrase - пароль аутентификации (шифруется MD5 или SHA);


* privacy-protocol - протокол шифрования данных (DES);


* privacy-passphrase - пароль шифрования данных.


Протокол SNMPv3 поддерживает три типа аутентификации: noAuthNoPriv,
authNoPriv и authPriv.

Если указать все атрибуты - получим тип authPriv (самый защищенный
тип: шифруются данные авторизации и все передаваемые данные).

Если не указывать атрибуты privacy-protocol и privacy-passphrase, то
получим тип authNoPriv, когда в защищенном виде передаются лишь
аутентификационные данные, остальные данные не шифруются.

Если указать только атрибут security-name, то получим самый
незащищенный тип noAuthNoPriv.

Подробнее о модели безопасности SNMPv3 (User-Based Security Model -
USM и VACM - View-based Access-Control Model) можно найти в RFC3414 и
RFC3415.

Обратите внимание, что библиотека SNMP4J [8] ревностно относится к
соблюдению стандартов, согласно которым auth-passphrase должен быть не
менее 8 символов, то же касается и privacy-passphrase. Поэтому не
советую испытывать судьбу коротким паролем. Подробнее о настройке
SNMPv3 на оборудовании фирмы Cisco можно узнать из [9].

Что дальше?

После осуществления всех приведенных выше настроек можно запустить
openNMS:

./opennms start


или для Windows:

opennms.bat start


Через некоторое время после запуска в списке узлов появятся первые
обнаруженные устройства с найденными интерфейсами и сервисами. Это уже
работающая система. Через веб-интерфейс мы можем получать информацию о
событиях, таких как доступность сервисов и устройств, просматривать
графики загрузки каналов связи и ряд других, уже внесенных в типовую
конфигурацию графиков. На рис. 2 показана основная страница
веб-интерфейса OpenNMS.



Рисунок 2. Главная страница веб-интерфейса

Однако многие вопросы дополнительной настройки остались неосвещенными,
например, настройка уведомлений о событиях на e-mail, кастомизация
веб-интерфейса, отвечающая требованиям вашей сети, тонкая настройка
хранимых в базах RRD данных, а также настройка параметров отображения
графиков и создание отчетов о состоянии сервисов и устройств.



Что ж, вопросы с установкой решены (см. No.5 за 2008 г.), и система
openNMS работает. Как же теперь сделать ее более функциональной, а
работу с ней более удобной? Запасаемся временем и терпением, не
забываем подключить к работе голову и руки - и вперед!


Возможности веб-интерфейса

Какую же информацию мы можем получить после начальной настройки OpenNMS
через веб-интерфейс? На главной странице веб-интерфейса, на которую мы
попадаем сразу после авторизации, представлена информация о текущем
состоянии наблюдаемых устройств, и если какое-то устройство, интерфейс
или сервис недоступны, то эта информация выделяется цветом (см. рис. 1).

Рисунок 1. Главная страница веб-интерфейса

В верхней части интерфейса расположено основное навигационное меню, с
помощью которого можно просмотреть список всех проверяемых узлов (меню
"Node List"), либо с помощью поискового интерфейса (меню "Search")
найти конкретное устройство по различным критериям поиска: IP-адресу,
наименованию, предоставляемому сервису и др.

Каждому узлу можно сопоставить дополнительную инвентарную информацию и
затем просматривать ее через меню "Assets" (имущество). Путем
несложной навигации можно узнать подробную статистику о текущих и
исправленных отказах (меню "Outages") устройств и сервисов, об
авариях (меню "Alarms"), а также обо всех событиях (меню "Events"),
зарегистрированных системой.

В меню "Reports" (отчеты) можно просмотреть отчеты о доступности и
графики, полученные при опросах устройств. Это могут быть и основанные
на ICMP-запросах RoundTrip Ping и StrafePing (статистика по потерянным
пакетам), и графики, основанные на данных, собранных с помощью SNMP.
Имеется возможность составлять собственные отчеты (Custom Reports),
основанные на собранных данных.

В меню "Surveillance" (слежение) можно сгруппировать информацию об
узлах сети по определенным признакам в виде таблицы. Можно, например,
категоризировать устройства по территориальной принадлежности и типу
оборудования. По умолчанию ни один узел не принадлежит какой-либо
категории, добавление узла в категорию можно произвести через
администраторский интерфейс (меню "Admin").

В меню "DashBoard" (панель инструментов) на основе категоризации из
меню "Surveillance" собрана дополнительная информация о состоянии
устройств, такая, как текущие аварии, состояние об отказах устройства
за последние 24 часа и статистические графики.

С помощью меню "Admin" существует возможность изменять многие
настройки OpenNMS, но возможностей веб-интерфейса в некоторых случаях
бывает недостаточно, поэтому возникает необходимость прямого
редактирования конфигурационных файлов.


Группировка узлов по определенным признакам с помощью таблиц слежения

Визуальное представление многих данных мониторинга, просматриваемых
через веб-интерфейс, можно изменять в некоторых пределах. Одна из
удобных функций заключается в возможности группировки узлов сети по
различным признакам в виде таблицы слежения. В меню "Surveillance"
(слежение) уже задано разбиение на категории по умолчанию (см. рис. 2),
однако сетевые устройства пока не привязаны к существующим категориям
слежения.

Рисунок 2. Вид меню "Surveillance" после установки системы

Добавить устройство в необходимую категорию по определенным признакам
можно через меню "Admin -> Manage Surveillance Categories" (см. рис.
3).

Рисунок 3. Добавление узлов в категории по определенным признакам

В строках и столбцах таблицы слежения определяются признаки наблюдаемых
устройств, а в местах пересечения конкретной строки и столбца
отображается количество узлов, удовлетворяющих этим признакам. Можно
создать необходимое количество собственных категорий слежения, на
основе которых в дальнейшем построить собственную таблицу (таких таблиц
может быть несколько). Для создания таблицы слежения или модификации
существующей необходимо отредактировать конфигурационный файл
surveillance-views.xml:


<?xml version="1.0" encoding="utf-8"?>
<surveillance-view-configuration
xmlns:this="http://www.opennms.org/xsd/config/surveillance-views"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.opennms.org/xsd/config/surveillance-views
http://www.opennms.org/xsd/config/surveillance-views.xsd"
default-view="by Priority and Office" >
<views >
<view name="default" refresh-seconds="300" >
<rows>
<row-def row="1" label="Main Office" >
<category name="MainOffice"/>
</row-def>
<row-def row="2" label="Filial 1" >
<category name="Filial-1" />
</row-def>
<row-def row="3" label="Filial 2" >
<category name="Filial-2" />
</row-def>
<row-def row="4" label="Filial 3" >
<category name="Filial-3" />
</row-def>
</rows>
<columns>
<column-def col="1" label="Routers" >
<category name="Routers" />
</column-def>
<column-def col="2" label="Servers" >
<category name="Servers" />
</column-def>
<column-def col="3" label="Switches" >
<category name="Switches" />
</column-def>
</columns>
</view>

<view name="by Priority and Office" refresh-seconds="300" >
<rows>
<row-def row="1" label="Main Office" >
<category name="MainOffice"/>
</row-def>
<row-def row="2" label="Filial 1" >
<category name="Filial-1" />
</row-def>
<row-def row="3" label="Filial 2" >
<category name="Filial-2" />
</row-def>
<row-def row="3" label="Filial 3" >
<category name="Filial-3" />
</row-def>
</rows>
<columns>
<column-def col="1" label="High Priority" >
<category name="HighPriority" />
</column-def>
<column-def col="2" label="Mid Priority" >
<category name="MidPriority" />
</column-def>
<column-def col="3" label="Low Priority" >
<category name="LowPriority" />
</column-def>
</columns>
</view>
</views>
</surveillance-view-configuration>




В тег <views> вложен тег <view>, в котором описываются строки и столбцы
таблицы категорий. В параметре name тега <view> задается название
таблицы категорий. В теге <rows> описываются строки таблицы с помощью
вложенных тегов <row-def>, а в теге <columns> с помощью <column-def>
описываются столбцы. В тегах <row-def> и <column-def>, которые являются
строками и столбцами таблицы категорий, описываются категории узлов с
помощью тегов <category>. Данные в тегах <category> должны
соответствовать данным, заполненным через меню "Admin -> Manage
Surveillance Categories" (данные хранятся в таблице categories базы
данных PostgreSQL), иначе при попытке перейти в меню "Surveillance"
мы получим ошибку.

В приведенном выше примере описаны два разных разбиения на категории -
"default" и "by Priority and Office" (см. рис. 4), однако вы можете
создать таблицы слежения по вашим потребностям.

Рисунок 4. Вид меню "Surveillance" после настройки таблицы категорий

В корневом теге <surveillance-view-configuration> в параметре
default-view можно задать отображаемую по умолчанию таблицу слежения (в
приведенном выше конфигурационном файле этому параметру присвоено имя
таблицы "by Priority and Office", которая будет отображаться при
переходе в меню "Surveillance" и "DashBoard" (см. рис. 5).

Рисунок 5. Меню "DashBoard" после настройки таблицы категорий

Настройка уведомлений

В openNMS существует возможность использовать систему уведомлений,
чтобы оповещать пользователей о происходящих событиях. Основным методом
уведомлений является отправка e-mail-сообщений пользователю, но
существует и ряд других методов, например, отправка POST/GET-запросов
на веб-сервер, отправка уведомлений по протоколу XMPP (jabber),
пересылка уведомлений посредством запуска внешней программы (подобным
образом можно отправить SMS-сообщение с помощью GSM-модема) и
уведомления с помощью формирования SNMP traps.

Мы рассмотрим классический способ с отправкой уведомлений на
электронную почту, для чего нам понадобится внести необходимые
настройки в следующие конфигурационные файлы:

* javamail-configuration.properties - в файле содержатся настройки
почтового сервера и учетной записи (почтового ящика);


* destinationPaths.xml - в файле описывается, кто получает
уведомления;


* notifd-configuration.xml - здесь описываются глобальные настройки
службы уведомлений;


* notificationCommands.xml - в файле описываются методы уведомления,
такие, как e-mail-оповещения, XMPP и др.;


* notification.xml - здесь содержится описание уведомлений.


Будем использовать тип доставки javaEmail (уведомления на электронную
почту) для оповещения о происходящих в системе событиях. Для этого
изменим настройки файла javamail-configuration.properties, чтобы
отправлять сообщения через ящик на сервере Google Mail, например
(однако это может быть и ваш корпоративный почтовый сервер):

org.opennms.core.utils.useJMTA=false
org.opennms.core.utils.transport=smtps
org.opennms.core.utils.mailHost=smtp.gmail.com
org.opennms.core.utils.smtpport=465
org.opennms.core.utils.authenticate=true
org.opennms.core.utils.authenticateUser=user@gmail.com
org.opennms.core.utils.authenticatePassword=userpass
org.opennms.core.utils.starttls.enable=true
org.opennms.core.utils.smtpssl.enable=true
org.opennms.core.utils.messageContentType=text/html
org.opennms.core.utils.charset=windows-1251


Google Mail использует SMTP over SSL (TLSv1 и SSLv3), поэтому параметр
org.opennms.core.utils.smtpssl.enable выставлен в true, в качестве
транспорта (org.opennms.core.utils.transport) используется SMTPS, а
порт для подключения (org.opennms.core.utils.smtpport) используется
стандартный для SMTPS - 465. В более простых случаях, когда
используется обычный SMTP-протокол без шифрования, необходимо будет
заменить номер порта на 25, транспорт - на smtp и параметры
smtpssl.enable и starttls.enable=true выставить в false.

В файле destinationPaths.xml содержится информация об адресах доставки
уведомлений:

<?xml version="1.0" encoding="UTF-8"?>
<destinationPaths xmlns=
"http://xmlns.opennms.org/xsd/destinationPaths">
<ns1:header xmlns:ns1="http://xmlns.opennms.org/xsd/types">
<rev xmlns="">1.2</rev>
<created xmlns="">10 Июнь 2008 г. 4:43:30 GMT</created>
<mstation xmlns="">localhost</mstation>
</ns1:header>
<path name="Email-Admin" initial-delay="0s">
<target interval="0s">
<name xmlns="">Admin</name>
<command xmlns="">javaEmail</command>
</target>
</path>
</destinationPaths>


Атрибут name тега <path> определяет имя блока адреса доставки. Значение
данного атрибута также используется в файле notifications.xml в
качестве адреса доставки при описании конкретного вида уведомлений.
Внутри каждого тега <path> можно описать несколько вложенных тегов
<target>, в которых с помощью тега <name> можно описать адресатов,
которым будут посылаться уведомления, а также способ доставки (в нашем
случае javaEmail) с помощью тега <command>. В качестве адресата может
выступать как отдельный пользователь, так и группа или роль. Добавить
учетную запись пользователя, группы и роли можно через веб-интерфейс
(меню "Admin -> Configure Users, Groups and Roles") или через
конфигурационные файлы users.xml (пользователи) и groups.xml (группы и
роли).

Для обеспечения более гибкой отправки уведомлений в файле
destinationPaths.xml можно описать несколько дополнительных тегов
<path>:

<path name="Email-Filial1" initial-delay="0s">
<target interval="0m">
<name xmlns="">Filial1</name>
<autoNotify xmlns="">auto</autoNotify>
<command xmlns="">javaEmail</command>
</target>
</path>


В приведенном выше коде создается путь для отправки уведомлений на
адрес абонента Filial1. Конечно, учетная запись пользователя (или
группы, роли) Filial1 должна быть предварительно создана, в таком
случае уведомления будут отправляться, например, одному или нескольким
сотрудникам филиала No.1. Эти сотрудники будут получать почтовые
сообщения в случае проблем с сетевыми устройствами или сервисами.

Настройки уведомлений задаются в файле notifications.xml. По умолчанию
здесь уже заданы стандартные типы уведомлений, которые отправляются на
адрес доставки Email-Admin (то есть всем пользователям группы Admin).
Теперь добавим собственное уведомление, которое будет отправляться по
адресу доставки Email-Filial1:

<notification name="Filial1-nodeDown" status="on" writeable="yes">
<uei xmlns="">uei.opennms.org/nodes/nodeDown</uei>
<rule xmlns="">IPADDR IPLIKE 10.10.12.*</rule>
<destinationPath xmlns="">Email-Filial1</destinationPath>
<text-message xmlns="">
All services are down on node %nodelabel%.
</text-message>
<subject xmlns="">Node %nodelabel% down.</subject>
<numeric-message xmlns="">111-%noticeid%</numeric-message>
</notification>


Описанное уведомление будет отправлено по адресу Email-Filial1 (см.
файл destinationPaths.xml) при возникновении события nodeDown (<uei
xmlns=""> uei.opennms.org/nodes/nodeDown </uei>), когда недоступны
узлы, принадлежащие сети 10.10.12.0/24 (см. правило <rule
xmlns="">IPADDR IPLIKE 10.10.12.*</rule>).

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

Тюнинг сбора и отображения SNMP-статистики

Настройки сбора информации, получаемой по протоколу SNMP, описываются в
файле data-collection-config.xml. Данные собираются путем посылки
GET-запросов, содержащих определенный OID (Object IDentificator),
устройству, поддерживающему протокол SNMP. В ответ возвращаются
некоторые значения, которые сохраняются затем в RRD-файлах (RoundRobin
Database (RRD) - это проект, выросший из известного проекта MRTG.
Проект оказался довольно удачным и в настоящее время используется не
только в оpenNMS, но и во многих других системах мониторинга).

В файле data-collection-config.xml уже содержится информация по OID
(Object ID) из MIB (Management Information Base) наиболее
распространенных устройств (как аппаратных, например Cisco Pix, так и
программных - Asterisk), поддерживающих протокол SNMP.

OID описываются внутри тега <mibObj>:

<mibObj oid=".1.3.6.1.2.1.2.2.1.8" instance="ifIndex"
alias="ifOperStatus" type="integer" />


В свою очередь, для обеспечения более удобного дальнейшего
использования OID группируются с помощью тега <group>, например:

<group name="my-mib2-interfaces" ifType="all">
<mibObj oid=".1.3.6.1.2.1.2.2.1.8" instance="ifIndex"
alias="ifOperStatus" type="integer" />
</group>


Если параметру ifType тега <group> присвоено значение "all", как в
примере выше, это значит, что данные в группе имеют табличную природу,
и тогда параметр instance тега <mibObj> принимает последовательные
значения (в нашем случае ifIndex, содержащий индексы имеющихся в
системе интерфейсов). Случай с нетабличными данными проще. Параметр
ifType тега <group> принимает значение "ignore", а параметр instance
тега <mibObj> принимает значение "0".

Различные типы SNMP-устройств описываются в тегах <systemDef>. Для
каждого типа устройств определена одна или несколько OID-групп, на
основе которых для устройства и его интерфейсов в rrd-файлы будет
собираться статистика:

<systemDef name="Cisco Routers">
<sysoidMask>.1.3.6.1.4.1.9.1.</sysoidMask>
<collect>
<includeGroup>cisco-memory</includeGroup>
<includeGroup>cisco-router</includeGroup>
<includeGroup>cisco-temperature</includeGroup>
<includeGroup>cisco-voltage</includeGroup>
<includeGroup>cisco-router-interface</includeGroup>
<includeGroup>mib2-interfaces</includeGroup>
<includeGroup>adsl-line</includeGroup>
</collect>
</systemDef>


При обнаружении на устройстве службы SNMP система OpenNMS пытается
определить тип устройства, посылая GET-запрос с OID=1.3.6.1.2.1.1.2.0.
Полученный ответ сравнивается со значением тега <sysoidMask>,
вложенного в тег <systemDef>.

Например, для многочисленного семейства маршрутизаторов фирмы Cisco
этот ответ будет содержать подстроку .1.3.6.1.4.1.9.1. На основании
такого ответа SNMP-сборщик будет собирать информацию, посылая
GET-запросы с OID, описанными в конфигурации для данного типа
оборудования.

В случае наличия специфичного оборудования можно создать дополнительные
группы OID, а также определить с помощью тега <systemDef> новый тип
оборудования, в который и вложить необходимые OID-группы. Обычно с
таким специфичным оборудованием распространяются и дополнительные
MIB-базы. Для ускорения импортирования данных OID из таких MIB-файлов в
состав дистрибутива openNMS включена утилита mib2opennms, с помощью
которой можно преобразовать данные из MIB-файла в набор тегов <mibObj>,
которые используются в файле data-collection-config.xml.

Давайте теперь рассмотрим, как записываются и хранятся в RRD-файлах
собранные по протоколу SNMP данные. Периодичность сбора данных, а также
продолжительность их хранения описывается в теге <rrd>:

<rrd step="60">
<rra>RRA:AVERAGE:0.5:1:263520</rra>
<rra>RRA:AVERAGE:0.5:60:8784</rra>
<rra>RRA:AVERAGE:0.5:1440:366</rra>
<rra>RRA:MAX:0.5:1440:366</rra>
<rra>RRA:MIN:0.5:1440:366</rra>
</rrd>


Параметр step тега <rrd> определяет шаг хранения информации в
rrd-файлах. Вложенный тег <rrа> состоит из следующих атрибутов:

RRA:Cf:xff:steps:rows


где:

* RRA - однозначно определяет строку как конфигурационную команду.


* cf - тип объединения данных, принимает значения AVERAGE, MAX, MIN
или LAST.


* xff - при объединении собранных значений в одно может случиться, что
некоторые значения не определены (например, какое-то время узел был
недоступен). Данный параметр определяет минимальный процент
неопределенных данных, при котором все собранные за период данные
становятся неопределенными. По умолчанию это 50% (0,5).


* steps - означает коэффициент групировки собранных данных, например:


* 1 - данные сохраняются на каждом шаге (то есть ежеминутноо, в случае,
step=60);


* 60 - данные группируются за 60 периодов и затем сохраняются(то есть
интервал сохранения - 1 час).


* rows - определяет количество сохраняемых значений. Цифра 263520
означает, что данные, в случае ежеминутной группировки будут храниться
около полугода (188 дней).


Собранная в RRD-файлах информация может быть представлена в виде
графиков. Настройка графиков на основе собранных по SNMP данных
производится в файле snmp-graph.properties. В качестве значений секции
reports через запятую перечислены все доступные графики. При
первоначальной установке OpenNMS их уже достаточно внушительное
количество. После перечисления всех графиков находится полная
информация по каждому из графиков. Чтобы лучше понять принцип
построения графиков, можно добавить график состояния интерфейса во
времени, принимающий значение "0" в случае "падения" интерфейса и
"1" - в случае его нормального функционирования. Для этого вернемся
снова к файлу data-collection-config.xml, в который необходимо добавить
соответствующий OID =.1.3.6.1.2.1.2.2.1.8, например, в группу
mib2-interfaces:

<group name="mib2-interfaces" ifType="all">
<mibObj oid=".1.3.6.1.2.1.2.2.1.8" instance="ifIndex"
alias="ifOperStatus" type="integer" />
<mibObj oid=".1.3.6.1.2.1.2.2.1.10" instance="ifIndex"
alias="ifInOctets" type="counter" />
<mibObj oid=".1.3.6.1.2.1.2.2.1.16" instance="ifIndex"
alias="ifOutOctets" type="counter" />
.... другие oid
</group>


Теперь для тех SNMP-устройств (точнее, для их интерфейсов, так как это
данные уровня интерфейса, а не узла), в описании которых указана данная
OID-группа, будет собираться статистика по состоянию интерфейса. Однако
в графическом виде информацию о состоянии интерфейсов посмотреть пока
не получится. Для просмотра графиков на основе rrd-данных необходимо
будет внести соответствующие дополнения в конфигурационный файл
snmp-graph.properties. Добавим строку mib2.opstat в секцию reports
файла snmp-graph.properties. Теперь добавим следующие строки ниже
секции report:

report.mib2.opstat.name=Interface Operational Status
report.mib2.opstat.columns=ifOperStatus
report.mib2.opstat.type=interfaceSnmp
report.mib2.opstat.command=--title="Interface Operational Status" \
--lower-limit 0 --upper-limit 2 --rigid \
--vertical-label="Up(1)|Down (0)" \
--width 400 \
--height 100 \
DEF:opst={rrd1}:ifOperStatus:AVERAGE \
CDEF:copst=2,opst,- \
LINE2:copst#00ff00:"OperStatus" \
GPRINT:copst:AVERAGE:"Status (0 - down 1 - up) \\: %2.0lf %s" \


В данных строках мы описали внешний вид графика, на котором будут
отображаться данные о состоянии интерфейса (ноль на графике - интерфейс
"опущен", а единица - интерфейс функционирует нормально)

В строке "report.mib2.opstat.columns=ifOperStatus" описываются
данные, на основе которых строится график.

Значение interfaceSnmp параметра report.mib2.opstat.type означает, что
график создается для интерфейсов узла (возможен тип nodeSNMP - то есть
для всего узла, а не его интерфейсов).

В строке "DEF:opst={rrd1}:ifOperStatus:AVERAGE \" дается определение
opst - переменной, на основе средних значений (AVERAGE) которой будет
строиться график.

В строке "CDEF:copst=2,opst,- \" дано определение производной
переменной copst, значение которой есть функция 2-opst. Функцию ввели
для того, чтобы отображаемый график выглядел более привычно (в
диапазоне значений от 0 до 1), так как возвращаемые значения для
"поднятого" интерфейса - 1, в противном случае - 2. Функция 2 - opst
решает данную проблему.

В строке "LINE2:copst#00ff00:"OperStatus" \" описывается вид графика,
его цвет и название графика.

Строка "GPRINT:copst:AVERAGE:"Status (0 - down 1 - up) \\: %2.0lf %s"
\", как видно из названия, ответственна за рисование графика на основе
переменной copst.

В строках height и width задаются размеры графика.

После внесения данной информации в конфигурацию openNMS мы можем
просматривать на графике историю изменения оперативного состояния
интерфейса (см. рис. 6).

Рисунок 6. График изменения состояния (Up/Down) интерфейса во времени

Конечно, можно усомниться в практической полезности добавленного
графика, но цель примера - показать, что аналогичным образом можно
построить практически любой график на основе rrd-данных.

Заключение

Ну вот и закончено приведение в надлежащий вид установленной системы
openNMS. Надеюсь, что полученных знаний о принципах работы системы, а
также ее конфигурировании будет достаточно для дальнейшего
самостоятельного освоения и использования.

Система оказалась очень гибкой и функциональной, хотя для настройки
некоторых дополнительных функций и пришлось затратить некоторое
количество усилий. В качестве несомненных плюсов также можно назвать и
активность разработчиков проекта, с каждой новой версией добавляющих
новые функции и исправляющих выявленные ошибки. За время, прошедшее
после выхода первой статьи, было выпущено три обновления продукта,
последнее из которых (версия 1.5.93 на момент написания статьи) было
посвящено только работе над ошибками. Также на официальном сайте есть
внятная документация, хотя, возможно, она не совсем оптимально
структурирована. А после выхода статьи появилась возможность почитать о
системе и на русском.

За кадром осталось описание еще многих возможностей, таких как
интеграция с другими системами мониторинга, в том числе и
коммерческими, распределенная установка системы и тонкости повышения
производительности на высоконагруженных системах. Кроме того, данная
система после некоторых настроек может дополняться графической картой
устройств, что является удобной функцией. Но оставлю эти вопросы для
изучения вам, коллеги, чтобы в повседневной работе оставались
исследовательские и творческие моменты, а не только следование готовым
мануалам и пошаговым инструкциям (что во многих случаях также полезно
для повышения производительности труда). Удачи.

Приложение

Проблема с кириллицей

Данная информация, возможно, уже потеряла актуальность в связи с
выходом исправлений в новой версии 1.5.93. Дело в том, что в процессе
работы с веб-интерфейсом в версии 1.5.90 обнаружилась одна неприятная
проблема с отображением кириллицы. Для ее решения пришлось немного
модифицировать некоторые *.jsp-файлы веб-интерфейса (в сервлетах такой
проблемы не наблюдалось). Принцип модификации заключался в добавлении в
JSP-страницу строки java-кода с указанием используемой кодировки UTF8:

<%response.setCharacterEncoding("UTF-8");%>


То есть все данные, передаваемые сервером браузеру, должны отправляться
в кодировке UTF8.

Возможно, существовало более элегантное решение проблемы отображения
кириллицы, но на тот момент я его не нашел, поэтому до исправления
данной ошибки воспользовался описанным выше способом. В последней
версии (на момент написания статьи - 1.5.93) проблема с кириллицей
полностью исправлена, что не может не радовать.





Network Security Toolkit поможет адми...

 







Network Security Toolkit поможет администраторам сети



Network Security Toolkit - это один из многих дистрибутивов Linux типа
Live CD, направленных на анализ безопасности сети. NST дает
администраторам простой доступ к широкому множеству открытых сетевых
приложений, многие из которых включены в сотню лучших средств безопасности, рекомендованных сайтом insecure.org.


Последняя версия NST - 1.8.0 была выпущена в июне. Предыдущие версии
NST были основаны на Fedora Core 5, а эта новая версия - на Fedora 8,
используется ядро Linux 2.6.25.6-27.fc8 с окружением рабочего стола
Fluxbox. Можно скачать NST с авторского сайта - либо как ISO-образ Live CD, либо виртуальную машину VMware.


При загрузке с Live CD вам будет предложено несколько вариантов
загрузки, для различных аппаратных возможностей или требуемых служб.
Вариант по умолчанию - "desktop/laptop", включающий все утилиты NST,
поддержку USB и консоль. Во всех вариантах требуется наличие
работающего DHCP-сервера, иначе придется ввести параметры сети вручную.
Процесс загрузки занимает минуту или две, и по соображениям
безопасности перед первым попаданием в командную строку необходимо
ввести новый пароль root. Здесь пользователь уже может запустить
Fluxbox с помощью простой команды startx.


Можно установить NST и на жесткий диск,
однако этот процесс не так прост. В больших организациях совершенно
необходимо постоянно следить за сетевой активностью и безопасностью,
поэтому установить NST на жесткий диск будет чрезвычайно полезно.

Виртуальная машина NST дает вам удобную возможность попробовать
дистрибутив на мощной машине. Единственным недостатком такого подхода
является ограничения в использовании беспроводных сетевых карт, ведь
VMware считает беспроводной адаптер за обычную Ethernet-карту
виртуальной машины.

Что у него внутри?


Пусть непритязательный внешний вид Fluxbox не сбивает вас с толку.
Хотя интерфейс легкий и простой, но из него доступно множество мощных
сетевых средств. Из средств защиты от сетевых вторжений можно упомянуть
Kismet, Snort, AirSnort, NMAP и Wireshark. Nessus - популярный сканер
уязвимостей, которому не было уделено внимания в последнем
BackTrack-релизе (BT3), на сей раз включен в дистрибутив. Помогут вам
следить за состоянием сети такие программы как Nagios, Argus и Zabbix.
В дополнение к этим административным средствам, дистрибутив включает в
себя еще и пользовательские программы - почтовый клиент (Pooka), клиент
мгновенного обмена сообщениями (Pidgin), веб-браузер (Firefox),
средства обработки текстов и графики (ImageMagick, XPDF, Nedit и
другие), антивирус (ClamAV), терминальные коммуникации (GTKterm,
Minicom), удаленный рабочий стол (VNC, TSClient) и средства
восстановления данных (cfdisk, Partition Image). Я был удивлен,
обнаружив в составе дистрибутива свободную программу для GPS-навигации
GPSDrive. Еще включены СУБД MySQL и PostgreSQL, а если вам нужен
почтовый сервер - к вашим услугам Sendmail.





Меню Fluxbox в NST

Для запуска программ, включенных в NST, можно пользоваться либо
веб-интерфейсом (Web user interface, WUI), основанном на AJAX и JSON,
либо выбирать их из меню Fluxbox. Если вы знаете, чего ищете, просто
нажмите правой кнопкой мышки на рабочем столе - появится меню Fluxbox
со всеми программами, разделенными по категориям. К примеру, все
графические средства проверки уязвимостей системы можно найти в подменю
Security Applications, а общие средства для работы с сетью (такие как Wireshark) расположены в Network Applications.
Можно упрекнуть разработчиков меню NST Fluxbox в том, что некоторые
программы присутствуют одновременно в разных категориях; к примеру,
приложение ATerm находится в подменю NST WUI и Desktop Applications.





Пользовательский интерфейс


Если программа не обладает графическим интерфейсом или требует консоли
для своей настройки, NST упрощает работу с ней посредством помещения ее
в WUI. Можно выбрать как упрощенный WUI, в котором программы
сгруппированы в соответствии с решаемой задачей (сниффинг, мониторинг
или проверка на вторжения); так и из категоризированного списка.

WUI упрощает использование программ. При выборе программы или
задачи вам будет показана страница, на которой нужно выбрать
определенный скрипт - для настройки или выполнения операции. Если нужно
изменить настройки, это можно легко сделать, отредактировав
конфигурационные файлы программы или введя параметры команды. На
странице каждой программы также есть ее описание и краткая
документация.

Попробуем NST


После беглого осмотра всех программ, я установил NST на отдельный
компьютер и ввел его в нашу офисную сеть. Был задействован
неиспользуемый относительно слабый компьютер - сервер Dell PowerEdge
2500 с процессором Pentium III 1GHz, 768 Мб ОЗУ, тремя сетевыми картами
10/100 и двумя жесткими дисками по 18 Гб.

Сначала я указал первоначальные настройки (такие как IP-адрес)
и включил службы SSH, HTTPS и VNC. Одна из основных особенностей
дистрибутива - веб-интерфейс WUI, и я решил попробовать его в действии,
а именно настроил ntop и Zabbix для проверки сетевого трафика и
слежения за состоянием некоторых серверов.


Настроить ntop очень просто. Всего лишь выберите категорию Network в NST WUI. В подкатегории Monitor
будет располагаться ntop. Нажатие на ntop откроет его конфигурационную
страницу. Выберите интересующую вас сетевую карту, введите другие опции
ntop (годятся настройки по умолчанию) и нажмите на кнопку Start,
чтобы включить ntop. В дополнение ко всему WUI показывает команду, с
помощью которой ntop был включен. Вернитесь на предыдущую страницу и
нажмите "Use ntop interface (HTTPS)", чтобы войти на страницу ntop. На
странице ntop вы увидите сетевой трафик, различные его типы (TCP, UDP,
ARP и т.д.), источник трафика и другую информацию. Итак, можно следить
за трафиком за три щелчка мышки.

Настройка Zabbix, проверяющего состояние хостов в сети, требует
большего количества шагов. Хост в сети может быть сервером или сетевым
устройством. Агент, который можно скачать с сайта Zabbix,
должен быть установлен на каждом исследуемом хосте. Из той же
подкатегории что и ntop, выберите Zabbix Server Management для входа на
его конфигурационную страничку. Перед запуском Zabbix необходимо
включить службы mysqld и ntpd, это можно сделать,
нажав на соответствующих кнопках. После этого просто запустите службу
Zabbix, отправляйтесь на страницу Zabbix, ищите и добавляйте хосты и
можно проводить мониторинг сети.

Можно бегло проверить безопасность своей сети с помощью Snort,
расположенного в WUI в меню Security. Выберите нужный сетевой
интерфейс; я выбрал тот, на котором работает файрволл, ведь большинство
атак и вторжений производятся из интернета. Когда я взглянул на отчеты
Acid (интерфейс Snort), там было огромное количество предупреждений;
если бы не наш файрволл, сеть бы давно вышла из строя.

Еще я проверил безопасность серверов и рабочих станций внутри
сети с помощью Nessus. Были найдены явные уязвимости, однако так как
NST не содержит лицензии на Nessus, более подробный отчет представлен
не был.

Безопасность под вашим контролем


NST, обладая сбалансированным набором средств сетевого мониторинга,
анализа и безопасности, может дать явные преимущества сетевому
администратору, ценой одного лишь старого сервера. Через веб-интерфейс
WUI упрощаются все задачи. Работать с ним могут даже неопытные
администраторы, которые не пользовались Linux (и особенно консолью) и
таким образом задействовать всю мощь сетевых средств с открытым
исходным кодом.


ext3undel

ext3undel



Команда rm - мощное средство удаления данных, до тех пор, пока вы не
удалите по ошибке не те файлы или каталоги. К счастью, есть утилита ext3undel,
способная восстановить ошибочно удаленные данные на файловой системе
ext3. Можно восстанавливать файлы по имени, либо можно восстановить все
файлы, отмеченные как удаленные (хотя имена файлов не
восстанавливаются, однако можно понять что это за файл по его
содержимому).

Файлы, хранящиеся в файловой системе ext3, состоят из двух
частей. Во-первых, это метаданные файла - а именно имя файла, его
размер, время создания и доступа. Они хранятся в структуре данных Unix,
имеющей название inode.
Собственно данные хранятся в блоках жесткого диска. Удаление файла
приводит к тому, что теряется связь между метаданными и блоками
файловой системы (его содержимым). При удалении как inode, так и блоки
данных помечаются как свободные, и операционная система может при
необходимости записывать в них новые данные. Однако до тех пор, пока
inode и блоки отмечены свободными и не перезаписаны, пользователь может
восстановить соответствующий файл. Очень важно сохранять
восстанавливаемые файлы на другой раздел: ведь любые изменения на
оперируемой файловой системе приведут к перезаписи данных, и могут
перезаписаться сами восстанавливаемые данные. Восстановление данных
происходит по обратному алгоритму: удаленные структуры помечаются как
занятые, и происходит установление связи между inode и блоками данных.

На самом деле это сложный процесс, и программа ext3undel сама
по себе не реализует эту фунцию, она является лишь оберткой для других
программ, на которые ложится основной груз. Программе ext3undel можно
отдать одну из двух команд: gabi (get all back immediately -
восстановить всё немедленно) и ralf (recover a lost file - восстановить
удаленный файл).


Gabi основана на двух программах для восстановления данных, носящих имена Photorec и Foremost.
Преимущество использования ext3undel перед этими программами
проявляется во времени: автоматизация процесса и отсутствие
конфигурации приводят к увеличению шансов того, что восстанавливаемый
файл не будет перезаписан новыми данными. Команда gabi запрашивает у
пользователя, файлы с какого раздела нужно восстановить и какой раздел
будет использоваться для сохранения восстановленных данных, и какие
именно типы файлов (или все файлы) Photorec должен восстанавливать.
После этого Photorec просканирует свободные блоки диска на наличие
"сигнатур" - следов того, что когда-либо здесь в этих блоках был файл.
Для больших дисков этот процесс может занять долгое время. Данные inode
не могут быть восстановлены, поэтому придется вручную отсортировать
восстановленные файлы и искать среди них тот файл, который нужен.


Команда ralf основана на программе SleuthKit,
призванной восстанавливать конкретный файл. Другими словами, SleuthKit
отыскивает нужный inode. Затем обращается к файловой системе, ищет в
ней блоки, которые когда либо были ассоциированы с этим inode. Наконец,
SleuthKit сохраняет данные в образ, который затем обрабатывается
Photorec (в отличие от всего жесткого диска как в gabi). Кстати, будет
восстановлен не только тот файл, что вы указали. Как и в gabi, придется
отыскивать нужный файл среди общей кучи восстановленных файлов.

Для пробы я установил обертку ext3undel на обновленную версию
Ubuntu 8.04 Server Edition в VMware. Создал три разных текстовых файла
и JPEG-картинку, после чего удалил их командой rm. Все прошло успешно,
мне удалось восстановить все файлы с помощью как gabi, так и ralf. Это
была свежая установка, поэтому мне не пришлось продираться через кучу
файлов (хотя было интересно посмотреть, что именно удалял производитель
виртуальной машины перед ее релизом).


Последнюю версию ext3undel можно скачать с веб-сайта разработчика.
Программа распространяется в виде tar-архива, а также в
прекомпилированных пакетах deb и rpm. Естественно, придется установить
зависимости - Photorec, Sleuthkit и Foremost. Эти программы есть в
репозиториях большинства дистрибутивов.

ext3undel - замечательное средство для эффективного
восстановления данных. Однако не следует слишком на нее рассчитывать;
все равно следует проводить резервное копирование, ведь бывают случаи,
когда невозможно восстановить данные, даже если запускать ext3undel
сразу после удаления. Если удаленный файл фрагментирован, программа
сможет найти лишь первый фрагмент. Также ext3undel не может
восстанавливать данные с испорченных жестких дисков. Однако это
средство наверняка поможет вам в критических ситуациях, и уменьшит
потери от случайных ошибок.



UDEV: Как установить свои правила

UDEV: Как установить свои правила


Содержание:






Введение





Об этой статье


Программа udev нацелена на ядро Linux 2.6, и предназначена для решения
задачи создания динамической директории /dev с постоянным наименованием
элементов. Предшествующая реализация /dev, известная под названием
devfs, теперь подвергается критике, и udev выглядит правопреемником.
Впрочем, на тему udev vs devfs продолжаются чувствительные споры - вам
стоит просмотреть этот документ, прежде чем делать сравнения.


С течением лет область применения правил udev изменялась, так же как и
гибкость самих правил. В современных системах, udev обеспечивает
постоянное наименование для ряда типов устройств (элементов), что
называется "из коробки", исключая тем самым установление правил для
этих устройств (элементов). Однако некоторые пользователи по-прежнему
требуют (желают) дополнительного уровня настройки.

В данной статье подразумевается, что udev у вас установлен, и
нормально работает с настройками по умолчанию. Это обычно и происходит
при установке дистрибутива Linux.

Статья не охватывает каждый нюанс установки правил, но
претендует на описание всех основных концепций. Тонкие детали требуют
изучения манов.


Для иллюстрации идей и концепций в статье приводится множество примеров (многие
из которых полностью выдуманы). Поскольку не весь синтаксис подробно и
недвусмысленно объясняется в сопровождающих текстах, для полного понимания
лучше всего обратиться к примерам.


Общее представление, концепция





Термины: devfs, sysfs, nodes, etc



Это - только базовое введение; местами оно может быть не совсем строго.


В типичной Linux системе, директория /dev используется для хранения элементов, называемых нодами.
Они похожи на файлы и соответствуют определенным устройствам системы.
Каждая нода указывает на часть системы (устройство), которое может
существовать, а может и не существовать. Пользовательские приложения
могут использовать ноды этих устройств для взаимодействия с системным
"железом". Например, X server будет "прислушиваться" к /dev/input/mice,
чтобы иметь возможность соотнести пользовательские движения мыши с
видимыми на экране перемещениями курсора.

Первоначально директории /dev были заполнены попросту всеми
возможными в системе элементами. Из-за этого директории /dev были очень
велики по размеру. devfs
пытался обеспечить более управляемый подход к проблеме (причем заметно
- он заполнял директорию /dev только теми устройствами, которые были
подключены к системе), а также некоторые другие возможности. Но и эта
система оказалась чреватой проблемами, которые было нелегко разрешить.


udev - это "новый" способ управления директорией /dev, созданный
для того, чтобы расчистить некоторые проблемы предыдущих реализаций
/dev и обеспечить надежный путь в будущее. С целью создания и
наименования нод директории /dev, которые соответствовали бы
устройствам реально присутствующим в системе, udev опирается на
соответствующую информацию, поставляемую sysfs, по правилам, которые
устанавливает пользователь. Эта статья ставит своей целью детально
описать процесс составления таких правил. Это единственная работа,
связанная с udev, которую может (при желании) выполнять пользователь.


sysfs является новой файловой системой для ядер 2.6. Она
управляется ядром и выдает основную информацию об устройствах, в данный
момент времени подключенных к системе. udev использует эту информацию
для создания нод устройств, соответствующих вашему аппаратному
обеспечению. Файловая система sysfs монтируется в точку /sys и является
просматриваемой. Можно исследовать файлы, находящиеся в этой
директории, прежде чем начинать дело с udev. В данной статье я буду
обращаться с терминами /sys и sysfs как с синонимами.





Зачем это нужно?



Правила udev являются гибкими и очень мощными. Вот список некоторых задач, решить которые можно с помощью правил:



  • Изменить имя ноды устройства с умолчального на какое-либо другое.
  • Создать альтернативное/постоянное имя ноды устройства, путем создания символической ссылки на ноду по умолчанию.
  • Наименовать ноду устройства на основании вывода (output) некоей программы.
  • Изменить права доступа и права собственности ноды устройства.
  • Запустить скрипт, которым создается (либо удаляется) нода устройства (обычно, когда устройство подключается, или отключается).
  • Переименовать сетевые интерфейсы.


Установлением правил нельзя обойти проблему, когда для
вашего конкретного устройства не существует ноды. Даже если нет никаких
подходящих правил, udev все равно создаст ноду устройства с именем по
умолчанию, обеспеченному ядром.

У постоянных имен нод устройств есть ряд преимуществ.
Предположим, у вас есть два USB накопителя: цифровая камера и USB
флешка. Эти два устройства являются типичными нодами устройств с
назначаемыми именами: /dev/sda и /dev/sdb. Но конкретное назначение
имени устройства зависит от порядка их подключения. Это может сбивать с
толку пользователей, которые, несомненно, были бы рады, если бы каждое
устройство каждый раз называлось одинаково, скажем, /dev/camera и
/dev/flashdisk.





Встроенные постоянные схемы наименования

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

udev обеспечивает постоянное наименование "из коробки" для
накопительных устройств в директории /dev/disk. Чтобы ознакомиться с
постоянными именами, которые созданы для ваших накопителей, можно
воспользоваться командой:


# ls -lR /dev/disk


Команда работает для всех типов накопителей.

В качестве примера: udev создал постоянную символическую ссылку на мой корневой
раздел -

/dev/disk/by-id/scsi-SATA_ST3120827AS_4MS1NDXZ-part3


Когда я подключаю свой USB флеш диск, udev создает ноду-

/dev/disk/by-id/usb-Prolific_Technology_Inc._USB_Mass_Storage_Device-part1,

что также является постоянным именем.



Установление правил





Файлы правил и их семантика (смысл слов и символов)

Решая
вопрос наименования устройства и характер дополнительных действий, udev
считывает ряд файлов правил. Эти файлы находятся в директории
/etc/udev/rules.d , и обязаны иметь суффикс (расширение) ".rules".

Правила udev по умолчанию находятся в
/etc/udev/rules.d/50-udev.rules. Не лишено интереса просмотреть эти
файлы - они содержат несколько примеров, после которых следуют сами
правила, обеспечивающие вид директории /dev в стиле devfs. Вам не
следует устанавливать свои правила прямо в этих файлах.

Файлы в директории /etc/udev/rules.d/ расположены в алфавитном
порядке; в некоторых обстоятельствах этот порядок может быть важен. Вы
ведь хотите, чтобы ваши правила шли впереди правил по умолчанию, так я
предлагаю создать файл в директории /etc/udev/rules.d/10-local.rules и
вписывать все ваши правила в этот файл.

В файлах правил, строки, начинающиеся со знака "#", считаются
комментариями. Любая другая непустая строка является правилом. Правило
не может занимать несколько строк.

Одну устройству может соответствовать больше одного правила.
Это имеет практические преимущества, например можно установить два
правила, относящихся к одному и тому же устройству, и каждое правило
будет обеспечивать устройству собственное альтернативное имя. Оба
альтернативных имени будут созданы, даже если правила прописаны в
разных файлах. Важно понять, что udev не остановится, найдя
соответствующее устройству правило, но будет продолжать поиск и
пытаться выполнить каждое правило, о котором знает.

Синтаксис правил

Каждое правило
представляет собой цепочку пар ключ-значение, и пары эти разделены
запятыми. Ключ соответствия (match key) является условием для
идентификации устройства, к которому относится правило. Когда ВСЕ ключи
соответствия в данном правиле относятся к обрабатываемому устройству,
тогда правило начинает применяться, и активизируются ключи назначения
(assignment key).


Вот пример правила для иллюстрации вышесказанного:


KERNEL=="hdb", NAME="my_spare_disk"

Это правило включает в себя один ключ соответствия (KERNEL) и
один ключ назначения (NAME). Семантика и свойства этих ключей будут
детализированы позже. Важно отметить, что ключ соответствия (match key)
относится к своему значению через оператор равенства (==), тогда как
ключ назначения (assignment key) относится к своему значению через
оператор присвоения (=).

Помните, что udev не поддерживает переноса строк ни в какой
форме. Не допускайте разрыва строк в ваших правилах, так как udev
интерпретирует ваше одно правило как несколько правил, и не будет
работать как ожидалось.

Базовые правила

Для установления
правил, udev обеспечивает несколько различных ключей соответствия
(match key), которые должны точно соответствовать устройствам.
Несколько обычных ключей представлены ниже, с остальными мы
познакомимся позже в этой статье. Полный список доступен на страницах
манов.
  • KERNEL - устанавливает соответствие с именем, данным ядром для устройства
  • SUBSYSTEM - устанавливает соответствие подсистемы устройства
  • DRIVER - устанавливает соответствие имени драйвера, поддерживающего устройство
После того, как вы использовали серию ключей соответствия для
точного указания устройства, udev предоставляет вам хороший контроль
над дальнейшими действиями при помощи ряда ключей назначения
(assignment key). Полный список возможных ключей назначения вы найдете
на странице ман udev. Основные ключи назначения представлены ниже.
Другие будут описаны позже в этой статье.


NAME - имя, которое должно быть присвоено ноде устройства.


SYMLINK - список символических ссылок, выполняющих роль альтернативных имен ноды устройства.

Как уже отмечалось ранее, udev создает только одну настоящую
ноду устройства для одного устройства. Если вы хотите обеспечить этой
ноде устройства альтернативные имена, то пользуйтесь возможностями
символических ссылок. При помощи ключа назначения (assignment key)
SYMLINK, вы фактически создаете список символических ссылок, каждая из
которых нацелена (явно указывает) на реальную ноду устройства. Для
управления этими ссылками мы представляем новый оператор для
присоединения к спискам: +=. Вы можете присоединить множественные симлинки к списку любого правила путем отделения каждого следующего пробелом.


KERNEL=="hdb", NAME="my_spare_disk"


Это правило означает: речь идет об устройстве, которое было поименовано
ядром как hdb; отныне вместо того, чтобы называть это устройство hdb,
называйте ноду этого устройства my_spare_disk. Нода устройства появится
как /dev/my_spare_disk.


KERNEL=="hdb", DRIVER=="ide-disk", SYMLINK+="sparedisk"

А это правило означает: речь идет об устройстве, которое было
поименовано ядром как hdb, и где драйвером является ide-disk.
Наименуйте ноду этого устройства по умолчанию, и создайте к нему
символическую ссылку по имени sparedisk. Обратите внимание, что мы не
указали имя ноды устройства, поэтому udev использовал имя по умолчанию.
Для того чтобы сохранить стандартную компоновку директории /dev, ваши
собственные правила не будут обычно затрагивать ключ назначения NAME,
но будут создавать ключи SYMLINK и (или) производить другие назначения.


KERNEL=="hdc", SYMLINK+="cdrom cdrom0"


Скорее всего, это правило вы будете устанавливать чаще других. Оно
создает две символические ссылки: на устройство /dev/cdrom, и
устройство /dev/cdrom0, которые оба указывают на /dev/hdc. Опять-таки,
ключ назначения NAME не был использован, так что ядро, по умолчанию,
применило имя hdc.



Приведение в соответствие атрибутам sysfs

Ключи
соответствия, описанные до сих пор, обладали весьма небольшими
возможностями установления соответствия. В действительности мы желаем
лучше контролировать соответствия: мы хотим идентифицировать устройство
на основе других свойств, например на основе кодов производителя, на
основе номера продукта, на основе серийного номера, на основе объема
диска, на основе количества разделов, и так далее.

Многие драйверы экспортируют подобную информацию в sysfs, и udev
позволяет нам включать sysfs-соответствия в наши правила. Это делается
при помощи ключа ATTR, имеющего слегка отличающийся синтаксис.

Вот пример правила, устанавливающего единственное соответствие
из sysfs. Позже в этой статье мы подробно опишем детали, помогающие вам
составлять правила, основанные на атрибутах sysfs.


SUBSYSTEM=="block", ATTR{size}=="234441648", SYMLINK+="my_disk"



Иерархия устройств

Ядро Linux
представляет устройства в виде древовидной структуры, это отражается на
строении sysfs и полезно для установления правил. Например, устройство,
представляющее мой жесткий диск, является дочерним по отношению к
устройству SCSI диск; которое, в свою очередь, является дочерним по
отношению к устройству Serial ATA controller (контроллер); которое, в
свою очередь, является дочерним устройству шина (bus) PCI. Весьма
возможно, что вам придется обратиться к информации из родительского
устройства, с вопросом, скажем, о серийном номере жесткого диска. Этого
номера может не быть представлено на уровне устройства (диска), оно
представлено на уровне его прямого родителя - SCSI диска.

Четыре основные ключа соответствия, представленные до сих пор
(KERNEL/SUBSYSTEM/DRIVER/ATTR), соответствуют только значениям самих
устройств, и не устанавливают соответствия со значениями родительских
устройств. Но этот случай udev имеет варианты ключей соответствия,
которые осуществляют поиск вверх по дереву устройств:

KERNELS - устанавливает соответствие с именем, данным ядром для
устройства; или именем, данным ядром любому из родительских устройств.


SUBSYSTEMS - устанавливает соответствие подсистемы устройства; или подсистему любого родительского устройства.

DRIVERS - устанавливает соответствие имени драйвера,
поддерживающего устройство; или имя драйвера, поддерживающего любое
родительское устройство.


ATTRS - устанавливает соответствие с атрибутом sysfs устройства; или атрибутом sysfs любого родительского устройства.

Постоянно имея в виду рассуждения об иерархии устройств,
установление правил становится довольно сложным делом. Хорошо, что есть
инструменты, способные помочь в этом деле: мы представим их немного
позже.


Подстановка, или замена строк

При
установлении правил, потенциально относящихся ко множеству сходных
устройств, очень полезны операторы подстановки строк udev, работающие
сходно с командой printf (или функцией printf в языке си). Вы можете
включить эти операторы в любые назначения в ваших правилах, и udev
вычислит их по мере выполнения.


Наиболее часты операторы %k и %n. %k вычисляет имя,
присваиваемое ядром устройству, например "sda3" для устройства, которое
по умолчанию появится как /dev/sda3. %n вычисляет номер, присваиваемый
ядром устройству (номер раздела для накопителя), например, "3" для
устройства /dev/sda3.

В распоряжении udev есть еще несколько операторов подстановки
для повышенной функциональности. Проконсультируйтесь с udev страницей
ман, после прочтения данной статьи. Существует также альтернативный
синтаксис для этих операторов - $kernel и $number для вышеупомянутых
операторов. По этой причине, если вы хотите написать значок % в
правиле, то должны писать %%, а если хотите изобразить просто значок $,
тогда должны писать $$.


Для иллюстрации концепции подстановки строк вот несколько примеров правил:


KERNEL=="mice", NAME="input/%k"


KERNEL=="loop0", NAME="loop/%n", SYMLINK+="%k"

Первое правило обеспечивает появление ноды устройства мышь
только в директории /dev/input (тогда как по умолчанию, ей следовало
находиться в директории /dev/mice). Второе правило обеспечивает
создание ноды устройства по имени loop0 в директории /dev/loop/0 , но
также, как обычно, создает символическую ссылку на /dev/loop0.

Применение вышеприведенных правил под вопросом, так как их
можно было составить без применения операторов подстановки. Полная сила
операторов подстановки станет ясной из следующего раздела.



Подстановка по шаблонам

Наряду с
подстановкой самих строк, udev поддерживает подстановку по шаблону, как
в оболочке (shell). Существуют 3 поддерживаемых шаблона:
  • * - заменяет любой символ, любое число раз, в том числе ни одного

  • ? - заменяет любой символ, строго один раз

  • [] - заменяет любой один символ, указанный в скобках, разрешается также диапазон или интервал


Вот несколько примеров, включающих перечисленные шаблоны. Обратите внимание на операторы подстановки строк.


KERNEL=="fd[0-9]*", NAME="floppy/%n", SYMLINK+="%k"

Это правило устанавливает соответствие со всеми флоппи
дисководами, обеспечивает размещение нод устройств в директории
/dev/floppy, а также создает символическую ссылку на имя по умолчанию.


KERNEL=="hiddev*", NAME="usb/%k"


Второе правило обеспечивает присутствие устройств hiddev только в директории /dev/usb.




Получение информации из sysfs



Дерево sysfs

Возможность использования
интересной информации из sysfs была мельком упомянута выше. Чтобы
составлять правила, на основе этой информации, сначала нужно знать
названия характеристик (атрибутов, attributes) и их текущие значения.

sysfs имеет весьма простую структуру. Она логически поделена на
директории. Каждая директория содержит определенное число файлов
(характеристик), которые, как правило, имеют одно значение. Некоторое
количество символических ссылок связывают устройства с их родителями.
Иерархическая структура была описана выше.

К некоторым директориям обращаются как к путям устройств
(paths) высшего уровня. Такие директории представляют реальные
устройства, имеющие соответствующие ноды устройств. Пути устройств
высшего уровня, могут быть классифицированы как директории sysfs,
содержащие dev файл; их список можно просмотреть при помощи следующей
команды:


# find /sys -name dev

Для примера, на моей системе, директория /sys/block/sda является
путем устройства моего жесткого диска. При помощи символической ссылки
/sys/block/sda/device он слинкован со своим родителем, устройством SCSI
диск.

Когда вы устанавливаете правила на основе информации от sysfs,
вы просто вставляете значение характеристики некоего файла в одну часть
цепочки. Например, я могу узнать размер моего жесткого диска вот так:


# cat /sys/block/sda/size

234441648

При составлении правила udev, я могу использовать
ATTR{size}=="234441648" для идентификации этого диска. Так как udev
повторяет поиск по всей цепочке устройств, я могу предпочесть, в
качестве альтернативы, вставить атрибут (характеристику) в другую часть
цепочки (например, атрибут /sys/class/block/sda/device/, используя
ATTRS). Правда, существуют некоторые предостережения при работе с
разными частями цепочки, которые будут описаны ниже.

Хотя это и полезное введение в структуру sysfs, и в механизм
подбора значений udev, однако "прочесывание" sysfs вручную занимает
много времени и вовсе необязательно.



udevinfo

Введите команду udevinfo,
самый простой инструмент для составления правил udev. Все, что нужно
знать, это sysfs путь устройства, которое вам нужно. Вот "причесанный"
пример:


# udevinfo -a -p /sys/block/sda


looking at device '/block/sda':
KERNEL=="sda"
SUBSYSTEM=="block"
ATTR{stat}==" 128535 2246 2788977 766188 73998 317300 3132216 5735004 0 516516 6503316"
ATTR{size}=="234441648"
ATTR{removable}=="0"
ATTR{range}=="16"
ATTR{dev}=="8:0"


looking at parent device '/devices/pci0000:00/0000:00:07.0/host0/target0:0:0/0:0:0:0':
KERNELS=="0:0:0:0"
SUBSYSTEMS=="scsi"
DRIVERS=="sd"
ATTRS{ioerr_cnt}=="0x0"
ATTRS{iodone_cnt}=="0x31737"
ATTRS{iorequest_cnt}=="0x31737"
ATTRS{iocounterbits}=="32"
ATTRS{timeout}=="30"
ATTRS{state}=="running"
ATTRS{rev}=="3.42"
ATTRS{model}=="ST3120827AS "
ATTRS{vendor}=="ATA "
ATTRS{scsi_level}=="6"
ATTRS{type}=="0"
ATTRS{queue_type}=="none"
ATTRS{queue_depth}=="1"
ATTRS{device_blocked}=="0"


looking at parent device '/devices/pci0000:00/0000:00:07.0':
KERNELS=="0000:00:07.0"
SUBSYSTEMS=="pci"
DRIVERS=="sata_nv"
ATTRS{vendor}=="0x10de"
ATTRS{device}=="0x037f"



Как легко видеть, udevinfo просто выдает список атрибутов
(характеристик), которые вы можете использовать в качестве готовых
ключей соответствия в ваших правилах udev. Используя вышеприведенный
пример, я могу установить любое из двух следующих правил для одного
устройства:


SUBSYSTEM=="block", ATTR{size}=="234441648", NAME="my_hard_disk"



SUBSYSTEM=="block", SUBSYSTEMS=="scsi", ATTRS{model}=="ST3120827AS", NAME="my_hard_disk"

Вы видите, что некоторые позиции в примере выделены цветом. Это
иллюстрирует тот факт, что, хотя вполне легально комбинировать атрибуты
нужного устройства с таковыми одного из родительских устройств, нельзя
путать и подставлять атрибуты из многих родительских устройств -
подобным образом составленные правила не будут работать. Вот пример
неправильно составленного правила, в котором сделана попытка подставить
атрибуты от двух родительских устройств:


SUBSYSTEM=="block", ATTRS{model}=="ST3120827AS", DRIVERS=="sata_nv", NAME="my_hard_disk"

Вы обычно имеете на выбор множество атрибутов, и должны выбрать
из них несколько, чтобы составить правило. Как правило, вам стоит
выбирать те атрибуты, которые идентифицируют ваше устройство на
постоянной основе и имеют вид, понятный для человека. В вышеприведенных
примерах, я выбирал размер диска и номер его модели. Я не использовал
бессмысленные (для человека) номера, такие как
ATTRS{iodone_cnt}=="0x31737".


Рассмотрите эффекты иерархии в выводе команды udevinfo. Зеленая секция, соответствующая запрошенному устройству использует стандартные ключи соответствия, такие как KERNEL и ATTR. Синяя и коричневая
секции соответствуют родительским устройствам, и используют отслеженные
у родителей варианты вроде SUBSYSTEMS и ATTRS. Вот почему кажущаяся
сложность иерархической структуры на поверку проста для использования,
нужно только уверенно брать конкретные значения из числа предложенных
командой udevinfo.

Также следует отметить, что обычно текстовые атрибуты
появляются в выводе команды udevinfo с лишними пробелами (см. например
ST3120827AS выше). При составлении ваших правил, можете либо сохранять
лишние пробелы, либо убирать их, как сделал я.

Единственная сложность при работе с udevinfo состоит в
необходимости точно знать полные пути устройств (paths) (в приведенном
примере это /sys/block/sda). А эти пути не всегда очевидны. Однако,
учитывая тот факт, что вы обычно устанавливаете правила для нод
устройств, которые уже существуют, вы можете "попросить" udevinfo найти
пути устройства для вас:


# udevinfo -a -p $(udevinfo -q path -n /dev/sda)



Альтернативные методы

Хотя udevinfo
самый очевидный способ просмотра атрибутов для составления правил udev,
некоторые пользователи с успехом пользуются другими инструментами.
Такие утилиты, как usbview, выводят похожий набор информации, большая часть которой пригодна при составлении правил udev.



Более сложные правила



Установка прав доступа и прав собственности


Для контроля над правами доступа и правами собственности на устройства,
udev позволяет использовать дополнительные ключи назначения.

Ключ назначения GROUP позволяет установить, какая Юникс группа
будет владеть нодой устройства. Вот пример правила, устанавливающего,
что группа video владеет устройствами framebuffer'а:


KERNEL=="fb[0-9]*", NAME="fb/%n", SYMLINK+="%k", GROUP="video"

Ключ назначения OWNER, возможно малоупотребительный, позволяет
вам назначить владельца Юникс для ноды устройства. Не вдаваясь в
довольно странную ситуацию, когда вы предаете право собственности на
ваши флоппи устройства некоему john'у, вы можете составить такое
правило:


KERNEL=="fd[0-9]*", OWNER="john"

По умолчанию, udev создает ноды устройств с Юникс правами
доступа 0660 (чтение/запись для владельца и группы). Если потребуется,
вы можете изменить настройки по умолчанию для определенных устройств,
используя в правилах ключ назначения MODE. Следующее правило
устанавливает, что нода inotify будет доступна на чтение и запись для
всех:


KERNEL=="inotify", NAME="misc/%k", SYMLINK+="%k", MODE="0666"



Использование сторонних программ для наименования устройств

При
некоторых обстоятельствах, вам может потребоваться бОльшая гибкость,
чем стандартные правила udev могут предложить. В этом случае, вы можете
попросить udev запустить программу, и использовать стандартный вывод
этой программы для наименования устройств.

Для этого вы просто указываете абсолютный путь (path) к этой
программе (и любые параметры) в ключе назначения PROGRAM, а затем
применяете один из вариантов оператора подстановки строк %c в ключах
NAME/SYMLINK.

Следующие примеры относятся к вымышленной программе
device_namer, находящейся в директории /bin; таким образом, ее
абсолютный путь /bin/device_namer. Программа device_namer берет один
аргумент командной строки, точнее - имя, присвоенное ядром устройству.
Исходя из имени, данного ядром, программа device_namer производит некие
действия, результат которых, разбитый на несколько частей, выдает на
обычный конвейер (stdout pipe). Каждая часть является просто одним
словом, и части отделяются одним пробелом.

В нашем первом примере, мы подразумеваем, что device_namer
выдает несколько частей, каждая из которых служит для создания
символической ссылки (альтернативным именем) для нашего устройства.


KERNEL=="hda", PROGRAM="/bin/device_namer %k", SYMLINK+="%c"

Следующий пример подразумевает, что device_namer выдал две
части, первая - имя устройства, вторая - имя для дополнительной
символической ссылки. Теперь мы вводим оператор подстановки %c{N},
относящийся к части N вывода программы:


KERNEL=="hda", PROGRAM="/bin/device_namer %k", NAME="%c{1}", SYMLINK+="%c{2}"

Третий пример подразумевает, что device_namer выдал одну часть
для имени устройства, а затем несколько частей для создания
символических ссылок. Мы теперь вводим оператор подстановки %c{N+},
который перебирает части N, N+1, N+2, ... и так до конца вывода.


KERNEL=="hda", PROGRAM="/bin/device_namer %k", NAME="%c{1}", SYMLINK+="%c{2+}"

Части вывода могут использоваться в любых ключах назначения, а
не только NAME и SYMLINK. Следующий пример использует фиктивную
программу для назначения Юникс группы, которая будет владеть
устройством:


KERNEL=="hda", PROGRAM="/bin/who_owns_device %k", GROUP="%c"



Запуск сторонних программ по определенным событиям

Еще
одна причин для установления правил udev, это запуск определенных
программ во время подключения или отключения какого-либо устройства.
Например, вы можете запускать скрипт, автоматически загружающий все
снимки с цифровой камеры, как только она подключается.

Не смешивайте этот случай с действием ключа PROGRAM, описанным
выше. PROGRAM применяется для запуска программ, производящих имена
устройств (и они не должны делать ничего, кроме этого). Во время
запуска этих программ, нода устройства еще не создана, то есть никакое
действие с устройством еще не возможно.

Действие, описанное в этой главе, позволяет вам запускать
программу, когда нода устройства уже находится на своем месте. Эта
программа может воздействовать на устройство, однако программа не
должна работать продолжительное время, потому что udev эффективно
останавливается во время работы таких программ. Способом обойти это
ограничение является немедленное самоотключение программы.


Вот пример правила, демонстрирующий применение ключа назначения RUN:


KERNEL=="sdb", RUN+="/usr/bin/my_program"

Во время работы программы /usr/bin/my_program различные части
окружения udev становятся доступны как переменные среды, включая
значения ключей, таких как SUBSYSTEM. Можно также использовать
переменную среды ACTION, чтобы определить, является ли устройство
подключенным или нет - ACTION будет в значении "add" (добавить) или
"remove" (удалить) соответственно.

udev не запускает такие программы на любом активном терминале,
и не запускает их в контексте оболочки (shell). Убедитесь, что ваша
программа является выполняемой (executable); если это скрипт шелла,
убедитесь, что он стартует с соответствующим shebang
http://en.wikipedia.org/wiki/Shebang_(Unix) (например, #!/bin/sh), и не
ожидайте появления на вашем терминале стандартного вывода.



Взаимодействие среды окружения

udev
поддерживает ключ ENV для переменных окружения, который может быть
использован как для установления соответствия, так и для присоединения.


В случае присоединения, вы можете создать переменные окружения, которые вы будете приводить в соответствие позже.

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


KERNEL=="fd0", SYMLINK+="floppy", ENV{some_var}="value"

В плане соответствия, вы можете сделать так, что правило будет
действовать только в зависимости от значения переменной окружения.
Имейте в виду, что окружение, каким его видит udev, вовсе не совпадает
с окружением, которое видит пользователь в консоли. Вымышленный пример
правила, показывающий приведение в соответствие при помощи переменной
окружения, перед вами:


KERNEL=="fd0", ENV{an_env_var}=="yes", SYMLINK+="floppy"


Это правило создает симлинк /dev/floppy, только если переменная $an_env_var имеет значение "yes" в среде окружения udev.



Дополнительные опции



Весьма полезным может оказаться ключ присоединения OPTIONS.
Список этих опций невелик:
  • all_partitions - создает все возможные разделы для блочного устройства, а не только те, что были первоначально зафиксированы

  • ignore_device - полностью игнорировать событие

  • last_rule - делает так, что все последующие по списку правила не будут работать


Примеры



USB принтер

Я подключил принтер,
и ему была назначена нода устройства /dev/lp0. Не удовлетворенный таким
пресным именем, я решил использовать udevinfo помочь мне в составлении
правила, которое обеспечит альтернативное имя:


# udevinfo -a -p $(udevinfo -q path -n /dev/lp0)


looking at device '/class/usb/lp0':
KERNEL=="lp0"
SUBSYSTEM=="usb"
DRIVER==""
ATTR{dev}=="180:0"

looking at parent device '/devices/pci0000:00/0000:
SUBSYSTEMS=="usb"
ATTRS{manufacturer}=="EPSON"
ATTRS{product}=="USB Printer"
ATTRS{serial}=="L7201001107062638


И я составляю вот такое правило:


SUBSYSTEM=="usb", ATTRS{serial}=="L72010011070626380", SYMLINK+="epson_680"



USB камера

Как и большинство
других, моя камера идентифицирует себя как внешний жесткий диск,
подсоединенный по шине USB, используя SCSI соединение. Чтобы получить
доступ к своим фотографиям, я монтирую этот "диск" и копирую файлы
изображений на свой винчестер.

Не все камеры работают подобным образом, некоторые используют
протокол, отличный от протокола накопительных устройств. Таковы камеры,
поддерживаемые gphoto2.
В этом случае вам не придется писать правил для данного устройства, так
как оно целиком контролируется в пространстве пользователя (а не
специальным драйвером ядра).

Обычная сложность с USB камерой состоит в том, что она обычно
идентифицирует себя как диск с единственным разделом, в нашем случае
диск /dev/sdb с разделом /dev/sdb1. Нода sdb для меня бесполезна, но
нода sdb1 интересна - именно ее я хочу примонтировать. Тут кроется
проблема: так как sysfs представляет собой цепочку, то и полезные
атрибуты, выработанные udevinfo для /dev/sdb1 идентичны таковым для
/dev/sdb. Это приведет к тому, что потенциально ваше правило будет
относиться как ко всему диску, так и к разделу, что вас не может
устроить; правило должно быть однозначно.

Чтобы выйти из этого затруднения, нужно подумать: "А какая
разница между sdb и sdb1?" Ответ ошеломительно прост - разница в самом
названии. Так что мы можем использовать обычный шаблон (pattern)
приводящий в соответствие в поле NAME.


# udevinfo -a -p $(udevinfo -q path -n /dev/sdb1)


looking at device '/block/sdb/sdb1':
KERNEL=="sdb1"
SUBSYSTEM=="block"

looking at parent device '/devices/pci0000:00/0000:00:02.1/usb1/1-1/1-1:1.0/host6/target6:0:0/6:0:0:0':
KERNELS=="6:0:0:0"
SUBSYSTEMS=="scsi"
DRIVERS=="sd"
ATTRS{rev}=="1.00"
ATTRS{model}=="X250,D560Z,C350Z"
ATTRS{vendor}=="OLYMPUS "
ATTRS{scsi_level}=="3"
ATTRS{type}=="0"


Вот мое правило:


KERNEL=="sd?1", SUBSYSTEMS=="scsi", ATTRS{model}=="X250,D560Z,C350Z", SYMLINK+="camera"



Жесткий USB диск

Жесткий USB
диск
USB винчестер похож на USB камеру, описанную выше, однако типичное
использование шаблонов отличается. В случае с камерой, я объяснял, что
меня не интересовала нода sdb, единственное назначение которой -
создание разделов (скажем с помощью fdisk), но зачем я стану создавать
разделы в камере!?

Конечно, если у вас 100Гб USB винчестер, вполне понятно желание
разбить его на разделы. В этом случае, мы используем преимущества
подстановки строк:


KERNEL=="sd*", SUBSYSTEMS=="scsi", ATTRS{model}=="USB 2.0 Storage Device", SYMLINK+="usbhd%n"


Это правило создает симлинки:


/dev/usbhd - Нода, к которой можно применять fdisk


/dev/usbhd1 - Первый раздел (монтируемый)


/dev/usbhd2 - Второй раздел (монтируемый)



USB Card Reader (читатель флеш карт)

USB
Card Reader (читатель флеш карт)
USB Card Reader (CompactFlash, SmartMedia, и другие) - это другой тип
USB накопительного устройства, имеющий другие пользовательские
требования.

Обычно эти устройства не информируют компьютер, к которому
подключены, о замене носителя (карты). Так что, если вы подключите
кардридер без карты, а потом вставите карту, компьютер этого "не
поймет" и у вас не будет монтируемой ноды sdb1 для носителя.

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


KERNEL="sd*", SUBSYSTEMS=="scsi", ATTRS{model}=="USB 2.0 CompactFlash Reader", SYMLINK+="cfrdr%n", OPTIONS+="all_partitions"


У вас теперь будут ноды с именами: cfrdr, cfrdr1, cfrdr2, cfrdr3, ..., cfrdr15.


USB Palm Pilot (наладонник)

Это
устройство работает как USB-serial устройства, так что по умолчанию вы
получите только ttyUSB1 ноду устройства. Утилиты palm рассчитаны на
/dev/pilot, так что многие захотят составить правило для обеспечения
этого.

Carsten Clasohm's blog post
http://www.clasohm.com/blog/one-entry?entry%5fid=12096 является
прекрасным источником для этого дела. Правило Carsten'а приведено ниже:


SUBSYSTEMS=="usb", ATTRS{product}=="Palm Handheld", KERNEL=="ttyUSB*", SYMLINK+="pilot"

Заметьте, что атрибут с названием продукта будет другим для
других моделей, так что проверьте (при помощи udevinfo), какой именно
соответствует вашему.


CD/DVD дисководы

У меня два
оптических дисковода в системе: DVD reader (hdc), и DVD rewriter (hdd).
Я не думаю, что ноды этих устройств изменятся, если только я физически
не подключу провода по-другому. Тем не менее, многие захотят иметь ноды
типа /dev/dvd для удобства.


Так как мы знаем имена, присвоенные ядром этим устройствам, составление правил просто. Вот несколько примеров для моей системы:


SUBSYSTEM=="block", KERNEL=="hdc", SYMLINK+="dvd", GROUP="cdrom"


SUBSYSTEM=="block", KERNEL=="hdd", SYMLINK+="dvdrw", GROUP="cdrom"



Сетевые интерфейсы

Даже если
сетевой интерфейс называется по имени, как правило, он не имеет
связанной с ним ноды устройства. Невзирая на это, процесс установления
правил практически идентичен.

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


# udevinfo -a -p /sys/class/net/eth0


looking at class device '/sys/class/net/eth0':
KERNEL=="eth0"
ATTR{address}=="00:52:8b:d5:04:48"


Вот мое правило:


KERNEL=="eth*", ATTR{address}=="00:52:8b:d5:04:48", NAME="lan"

Вам придется перезагрузить сетевой драйвер, чтобы это правило
заработало. Можете либо выгрузить, и снова загрузить модуль, либо
просто перезагрузить систему. Также придется перенастроить систему на
использование "lan" вместо "eth0". Я имел определенные трудности,
добиваясь этого (интерфейс не был переименован), пока я совершенно не
отказался от ссылок на eth0. После этого, вы сможете использовать "lan"
вместо "eth0" во всех вызовах к ifconfig и прочим утилитам.



Тестирование и отладка



Как заставить правила работать

Если у вас
новое ядро с поддержкой inotify, udev автоматически отследит вашу
директорию с правилами и автоматически прочтет все изменения, которые
вы произвели с файлами правил.

Несмотря на это, udev не станет автоматически переделывать все
устройства и пытаться применить новые правила. Например, если вы
составили правило, добавляющее еще одну символическую ссылку для вашей
камеры, в то время, когда камера была подключена, вы не можете
рассчитывать на появление новой символической ссылки прямо сейчас.

Чтобы ссылка появилась, вы можете либо отключить и снова
подключить камеру, либо (в случае неотключаемого устройства) можете
запустить программу udevtrigger.

Если же ваше ядро не поддерживает inotify, то новые правила не
будут обнаружены автоматически. В этой ситуации следует запускать
программу udevcontrol reload_rules после каждого изменения файла
правил, чтобы эти изменения возымели эффект.



udevtest

udevtest
Если вы знаете в sysfs полные пути (path), то можете пользоваться
программой udevtest, чтобы она показала, какие действия предпримет
udev. Это может помочь при отладке правил. Например, вы хотите отладить
правило, которое работает с /sys/class/sound/dsp:


# udevtest /class/sound/dsp


main: looking at device '/class/sound/dsp' from subsystem 'sound'
udev_rules_get_name: add symlink 'dsp'
udev_rules_get_name: rule applied, 'dsp' becomes 'sound/dsp'
udev_device_event: device '/class/sound/dsp' already known, remove possible symlinks
udev_node_add: creating device node '/dev/sound/dsp', major = '14', minor = '3', mode = '0660', uid = '0', gid = '18'
udev_node_add: creating symlink '/dev/dsp' to 'sound/dsp'

Имейте в виду, что /sys prefix был удален из числа аргументов
командной строки udevtest, потому что udevtest оперирует с путями
(path) устройства. Также заметьте, что udevtest является чисто тестовым
и отладочным инструментом, он не создает ноды устройств, невзирая на
предложения вывода этой программы!