Вы находитесь на странице: 1из 98

№12(13) декабрь 2003

подписной индекс 81655


журнал для cистемных администраторов,
вебмастеров и программистов

Практические советы
по восстановлению системы
Крепость для пингвина:
Bastille Linux
Вторая жизнь модемов
Осваиваем Nagios
LTSP
Инвентаризация в сети
Конвертирование
из Excel в HTML
Профсоюз IT-специалистов
№12(13) декабрь 2003
оглавление

КАЛЕНДАРЬ СОБЫТИЙ HARDWARE

SYSM.02 Вторая жизнь модемов


Запланируйте участие: второй Семинар системных Способы использования модемов, внутреннее устрой-
администраторов и инженеров. ство постоянной памяти, программирование микро-
2 схем flash-памяти с помощью модема Acorp, замена
версий в модемах ZyXEL 1496, подключение 3-х моде-
Профсоюз IT-специалистов мов, развод используемых прерываний и настройка в
IT-специалисты России, соединяйтесь! ОС Linux.
В декабре состоится учредительное собрание Межре- Павел Закляков
гионального Профессионального союза специалистов amdk7@mail.ru 62
в области информационных технологий.
3
WEB
ПРОГРАММИРОВАНИЕ
Конвертирование из Excel в HTML:
Практические советы по восстановлению корректно, качественно, просто
системы в боевых условиях Идеи для корректного конвертирования документов из
Возможные причины нестабильной работы и сбоев си- формата xls в формат HTML с учетом форматирова-
стемы и рекомендации по их устранению. ния исходных документов.
Крис Касперски Алексей Мичурин
kk@sendmail.ru 6 alexey@office-a.mtu-net.ru 76

АДМИНИСТРИРОВАНИЕ ОБРАЗОВАНИЕ

Решение задач инвентаризации в сети LTSP – вторая жизнь старых компьютеров


Инвентаризация аппаратного обеспечения рабочих стан- Использование инструмента LTSP (Linux Terminal Server
ций в сети, построенной на основе Windows 2000/XP. Proekt) для решения вопроса загрузки бездисковых
Иван Коробко терминалов.
ikorobko@prosv.ru 26 Сергей Яремчук
grinder@ua.fm 84
Крепость для пингвина
Обзор и установка Bastille Linux – утилиты, позволяю- Содержание журнала за 2003 год 92
щей улучшить и укрепить безопасность Linux-системы.
Сергей Яремчук
grinder@ua.fm 40

Учет работы Dialup-пользователей


в системе FreeBSD
Общие принципы решения задачи.
Сергей Супрунов
amsand@rambler.ru 44

Осваиваем Nagios
Русификация веб-интерфейса, описание процедуры
инсталляции дополнительного программного обеспе-
чения, необходимого для работы с плоской и трехмер-
ной картами сети, создание иконок хостов и сервисов,
настройка иерархии хостов и многое другое.
Андрей Бешков
tigrisha@sysadmins.ru 48

№12(13), декабрь 2003 1


календарь событий

SYSM.02
20 декабря 2003 года, г. Москва
Портал SysAdmins.RU объявляет о проведении второго дотворные дискуссии и обсуждения, обмен опытом и
Семинара системных администраторов и инженеров и идеями будут проходить не только в конференц-зале,
приглашает специалистов принять участие в меропри- но и в кулуарах.
ятии, которое обещает быть плодотворным и информа- С материалами выступлений можно будет ознакомить-
тивным. ся в ближайших номерах журнала и на официальном сайте
Первая часть Семинара будет посвящена обсужде- Семинара: http://SYSM.ru
нию проблем информационной безопасности, вопросам С материалами профсоюза, Уставом, Положениями,
управления информационными системами, планирова- протоколами собраний и программой действий можно
нию карьеры. ознакомиться на официальном сайте профсоюза IT-спе-
Далее состоится учредительное собрание «Профсою- циалистов: http://ITCU.ru
за специалистов в области информационных технологий», Семинар состоится в субботу, 20 декабря 2003 года в
будут проведены выборы Правления профсоюза и выра- очень уютном и удобном месте – Доме ветеранов кино
ботана программа действий профсоюза на 2004 год. (ДВК) по адресу: г. Москва, ул. Нежинская, 5. (От м. Киев-
Опыт проведения первого Семинара показал, что ская на маршрутном такси №7 до остановки «Дом Вете-
данное мероприятие вызывает живейший интерес спе- ранов Кино»).
циалистов IT-индустрии – системных и сетевых адми- Регистрация участников второго Семинара на сайте:
нистраторов, инженеров, IT-аналитиков, IT-директоров http://SYSM.ru
и менеджеров. Можно утверждать, что активные и пло- Стоимость участия 600 рублей.

2
календарь событий

ПРОФСОЮЗ IT-СПЕЦИАЛИСТОВ
Официальный сайт : http://ITCU.ru
Впервые в России появится общественная организация, шение и укрепление авторитета профессии IT-специалис-
которая объединит под своим началом всех IT-специали- та, поддержка высокого уровня образования будущего по-
стов, – Межрегиональный Профессиональный союз спе- коления IT-специалистов, а также будет предоставлять воз-
циалистов в области информационных технологий. Эта можность выбирать наиболее выгодную программу пенси-
идея уже давно обсуждалась в различных интернет-из- онного и медицинского страхования, добиваться различ-
даниях и на профессиональных конференциях. Теперь она ных льгот, в том числе на отдых, мобильную связь и пр.
чётко сформировалась и стала реальностью. Странно, но Учредительное собрание Межрегионального Профес-
в нашей стране до сих пор не было такого сообщества! сионального союза специалистов в области информаци-
Ведь профсоюзы есть у всех – от врачей до журналистов. онных технологий пройдёт 20 декабря 2003 на Семинаре
Профсоюз представляет собой сообщество специалистов, SYSM.02 (http://SYSM.ru).
объединённых общими профессиональными интересами В программе собрания: выборы Правления, обсужде-
и ставит перед собой цель создать организацию, которая ние организационных вопросов, разработка Программы
будет решать проблемы различного характера, такие как профсоюза на 2004 год.
защита прав IT-специалистов, помощь в трудоустройстве, Самое главное – участники Семинара первыми полу-
совершенствование профессиональных навыков, повы- чат возможность стать членами профсоюза.

Резюме Устава Профсоюза


Общие положения
Ïðîôåññèîíàëüíûé ñîþç ñïåöèàëèñòîâ â îáëàñòè èíôîðìàöèîííûõ òåõ- ×ëåíû ïðîôñîþçà èìåþò ïðàâî:
íîëîãèé, èìåíóåìûé â äàëüíåéøåì «Ïðîôñîþç», ÿâëÿåòñÿ äîáðîâîëü-  Ó÷àñòâîâàòü â óïðàâëåíèè ïðîôñîþçîì â ñîîòâåòñòâèè ñ íàñòîÿ-
íûì ñàìîóïðàâëÿåìûì íåêîììåð÷åñêèì ôîðìèðîâàíèåì, îñíîâàííûì íà ùèì Óñòàâîì.
÷ëåíñòâå è ñîçäàííûì ïî èíèöèàòèâå ãðàæäàí, ñâÿçàííûõ îáùèìè  Èçáèðàòü è áûòü èçáðàííûìè â ðóêîâîäÿùèå è êîíòðîëüíî-ðåâèçè-
ïðîèçâîäñòâåííûìè, ïðîôåññèîíàëüíûìè èíòåðåñàìè ïî ðîäó èõ äåÿ- îííûå îðãàíû.
òåëüíîñòè.  Êîíòðîëèðîâàòü äåÿòåëüíîñòü ðóêîâîäÿùèõ îðãàíîâ ïðîôñîþçà.
Ïðîôñîþç îáúåäèíÿåò ëèö, ðàáîòàþùèõ â îáëàñòè èíôîðìàöèîííûõ  Ó÷àñòâîâàòü â ìåðîïðèÿòèÿõ è ïðîãðàììàõ ïðîôñîþçà.
òåõíîëîãèé, à òàêæå ó÷àùèõñÿ è ñòóäåíòîâ ó÷åáíûõ çàâåäåíèé, îáó-  Âíîñèòü íà ðàññìîòðåíèå ðóêîâîäÿùèõ îðãàíîâ ïðåäëîæåíèÿ ïî
÷àþùèõñÿ ïî ñîîòâåòñòâóþùèì ñïåöèàëüíîñòÿì. âîïðîñàì äåÿòåëüíîñòè ïðîôñîþçà.
 Ïîëó÷àòü íåîáõîäèìóþ èíôîðìàöèþ î äåÿòåëüíîñòè ïðîôñîþçà.
Цели и задачи профсоюза  Èñïîëüçîâàòü ìàòåðèàëüíî-òåõíè÷åñêóþ áàçó ïðîôñîþçà.
 Çàùèùàòü ïðàâà è èíòåðåñû ÷ëåíîâ ïðîôñîþçà ïî âîïðîñàì èíäè-  Ñîñòîÿòü ÷ëåíîì êàññû âçàèìîïîìîùè (êðåäèòíî-ïîòðåáèòåëüñêîãî
âèäóàëüíûõ òðóäîâûõ è ñâÿçàííûõ ñ òðóäîì îòíîøåíèé. ñîþçà).
 Âûñòóïàòü ñ ïðåäëîæåíèÿìè î ïðèíÿòèè ñîîòâåòñòâóþùèìè îðãàíà-  Ïîëó÷àòü áåñïëàòíóþ þðèäè÷åñêóþ ïîìîùü, îêàçûâàåìóþ ïðîôñîþçîì.
ìè ãîñóäàðñòâåííîé âëàñòè çàêîíîâ è íîðìàòèâíûõ ïðàâîâûõ àê-
òîâ, êàñàþùèõñÿ ñîöèàëüíî-òðóäîâîé ñôåðû, à òàêæå èíôîðìàöè- ×ëåíû ïðîôñîþçà îáÿçàíû:
îííûõ òåõíîëîãèé.  Ñîáëþäàòü íàñòîÿùèé Óñòàâ.
 Çàùèùàòü ïðàâà ñâîèõ ÷ëåíîâ ñâîáîäíî ðàñïîðÿæàòüñÿ ñâîèìè ñïî-  Âûïîëíÿòü ðåøåíèÿ ñîáðàíèÿ, Ïðàâëåíèÿ è ïðåäñåäàòåëÿ Ïðàâëåíèÿ.
ñîáíîñòÿìè ê òðóäó, à òàêæå ïðàâî íà âîçíàãðàæäåíèå çà òðóä  Ïëàòèòü ÷ëåíñêèå âçíîñû.
áåç êàêîé áû òî íè áûëî äèñêðèìèíàöèè, â òîì ÷èñëå ïî ïîëîâîìó  Àêòèâíî ñîäåéñòâîâàòü ðåøåíèþ ñòîÿùèõ ïåðåä ïðîôñîþçîì çàäà÷
ïðèçíàêó. ñâîèìè òåõíè÷åñêèìè, èíòåëëåêòóàëüíûìè è äðóãèìè ðåñóðñàìè.
 Ñîãëàñîâûâàòü ñèñòåìû îïëàòû òðóäà, ôîðìû ìàòåðèàëüíîãî ïîîù-  Âîçäåðæèâàòüñÿ îò äåéñòâèé, êîòîðûå ìîãóò íàíåñòè óùåðá çà-
ðåíèÿ, ðàçìåðû òàðèôíûõ ñòàâîê, à òàêæå íîðìû òðóäà ñ ðàáîòî- êîííûì èíòåðåñàì ïðîôñîþçà è åãî ÷ëåíîâ.
äàòåëÿìè è óïîëíîìî÷åííûìè ãîñóäàðñòâåííûìè îðãàíàìè è çàê-
ðåïëÿòü ñîîòâåòñòâóþùèå ïîëîæåíèÿ â êîëëåêòèâíûõ äîãîâîðàõ è Структура и управление организацией
èíûõ äîêóìåíòàõ. Ðóêîâîäñòâî ïðîôñîþçîì îñóùåñòâëÿþò: ñîáðàíèå, Ïðàâëåíèå è ïðåä-
 Ó÷àñòâîâàòü â ðàññìîòðåíèè îðãàíàìè ãîñóäàðñòâåííîé âëàñòè, ñåäàòåëü Ïðàâëåíèÿ.
îðãàíàìè ìåñòíîãî ñàìîóïðàâëåíèÿ, ðàáîòîäàòåëÿìè, èõ îáúåäè- Ñîáðàíèå ïðîôñîþçà – âûñøèé îðãàí óïðàâëåíèÿ, ïðàâîìî÷íûé ïðè-
íåíèÿìè ñâîèõ ïðåäëîæåíèé. íèìàòü ðåøåíèÿ ïî âñåì âîïðîñàì äåÿòåëüíîñòè ïðîôñîþçà. Ñîáðàíèå
 Ó÷àñòâîâàòü â óðåãóëèðîâàíèè êîëëåêòèâíûõ òðóäîâûõ ñïîðîâ, ïðîôñîþçà ñîçûâàåòñÿ ïî ìåðå íåîáõîäèìîñòè, íî íå ðåæå îäíîãî
îðãàíèçîâûâàòü è ïðîâîäèòü â ñîîòâåòñòâèè ñ ôåäåðàëüíûì çàêî- ðàçà â 2 ãîäà.
íîì çàáàñòîâêè, ìèòèíãè, äåìîíñòðàöèè è äðóãèå êîëëåêòèâíûå Ïðàâëåíèå – îðãàí, ðóêîâîäÿùèé äåÿòåëüíîñòüþ ïðîôñîþçà â ïåðèîä
äåéñòâèÿ, èñïîëüçóÿ èõ êàê ñðåäñòâî çàùèòû ñîöèàëüíî-òðóäîâûõ ìåæäó ñîáðàíèÿìè. Ïðàâëåíèå èçáèðàåòñÿ ñîáðàíèåì ïðîôñîþçà èç ÷èñëà
ïðàâ è èíòåðåñîâ ðàáîòíèêîâ. ÷ëåíîâ ïðîôñîþçà. Ïðàâëåíèå äåéñòâóåò íà îñíîâàíèè Ïîëîæåíèÿ î Ïðàâ-
 Îñóùåñòâëÿòü ïðîôñîþçíûé êîíòðîëü çà ñîáëþäåíèåì ðàáîòîäàòå- ëåíèè, ïðèíÿòûì íà Îáùåì ñîáðàíèè ïðîôñîþçà. Çàñåäàíèÿ Ïðàâëåíèÿ
ëÿìè, äîëæíîñòíûìè ëèöàìè çàêîíîäàòåëüñòâà î òðóäå è òðåáî- ïðîâîäÿòñÿ ïî ìåðå íåîáõîäèìîñòè, íî íå ðåæå îäíîãî ðàçà â êâàðòàë.
âàòü óñòðàíåíèÿ âûÿâëåííûõ íàðóøåíèé. Ïðåäñåäàòåëü Ïðàâëåíèÿ èçáèðàåòñÿ Ïðàâëåíèåì èç ÷èñëà ÷ëåíîâ
 Îñóùåñòâëÿòü îáó÷åíèå, ïîäãîòîâêó, ïåðåïîäãîòîâêó è ïîâûøåíèå Ïðàâëåíèÿ.
êâàëèôèêàöèè ÷ëåíîâ ïðîôñîþçà. Ïðåäñåäàòåëü Ïðàâëåíèÿ ïîäîò÷åòåí ñîáðàíèþ è Ïðàâëåíèþ, îðãà-
 Îñóùåñòâëÿòü þðèäè÷åñêóþ è èíóþ ïîääåðæêó. íèçóåò âûïîëíåíèå ðåøåíèé ñîáðàíèÿ è Ïðàâëåíèÿ.
Ïåðâè÷íàÿ ïðîôñîþçíàÿ îðãàíèçàöèÿ – îñíîâà ñòðóêòóðû Ïðîôñîþ-
Членство в профсоюзе çà – äîáðîâîëüíîå îáúåäèíåíèå íå ìåíåå 3-õ ÷ëåíîâ ïðîôñîþçà,
×ëåíîì ïðîôñîþçà ìîæåò áûòü ëþáîé ãðàæäàíèí ÐÔ, äîñòèãøèé 14- äåéñòâóþùåå íà îñíîâàíèè Ïîëîæåíèÿ, ïðèíÿòîãî èì â ñîîòâåòñòâèè
ëåòíåãî âîçðàñòà, ïðèçíàþùèé è âûïîëíÿþùèé Óñòàâ ïðîôñîþçà, ñ íàñòîÿùèì Óñòàâîì, èëè íà îñíîâàíèè îáùåãî Ïîëîæåíèÿ î ïåðâè÷-
ðåãóëÿðíî óïëà÷èâàþùèé ÷ëåíñêèå âçíîñû ïðîôñîþçó è ñâÿçàííûé íîé îðãàíèçàöèè ïðîôñîþçà, óòâåðæäåííîãî Ïðàâëåíèåì ïðîôñîþçà.
îáùèìè ïðîèçâîäñòâåííûìè è(èëè) ïðîôåññèîíàëüíûìè èíòåðåñàìè ñ Âûñøèì îðãàíîì ïåðâè÷íîé ïðîôñîþçíîé îðãàíèçàöèè ÿâëÿåòñÿ ñîáðà-
èíôîðìàöèîííûìè òåõíîëîãèÿìè, ðàáîòàþùèé â îáëàñòè èíôîðìàöè- íèå åå ÷ëåíîâ. Ðàáîòíèêè îäíîãî ïðåäïðèÿòèÿ, ó÷ðåæäåíèÿ, îðãà-
îííûõ òåõíîëîãèé, ïåíñèîíåð, à òàêæå ó÷àùèéñÿ èëè ñòóäåíò ó÷åá- íèçàöèè, ó÷àùèåñÿ è ïðåïîäàâàòåëè ó÷åáíûõ çàâåäåíèé îáúåäèíÿþò-
íîãî çàâåäåíèÿ, îáó÷àþùèéñÿ ïî ñîîòâåòñòâóþùåé ñïåöèàëüíîñòè. ñÿ, êàê ïðàâèëî, â îäíó ïåðâè÷íóþ ïðîôñîþçíóþ îðãàíèçàöèþ.

№12(13), декабрь 2003 3


программирование

ПРАКТИЧЕСКИЕ СОВЕТЫ
ПО ВОССТАНОВЛЕНИЮ СИСТЕМЫ
В БОЕВЫХ УСЛОВИЯХ
1. Во время исполнения ошибки имеют наивысший
приоритет. Прервать исполнение ошибки может
только другая, более активная ошибка.
2. Запросы операционной системы к ошибкам
ошибками могут игнорироваться.
3. Запросы ошибок к операционной системе
игнорироваться не могут.
4. При работе с файлами ошибки могут пользоваться
файловой системой базовой ОС и ее ошибками.
5. На ЭВМ с параллельной архитектурой может
выполняться несколько ошибок одновременно.

В. Тихонов «Теория ошибок»

Практически всем администраторам приходилось сталкиваться с теми или иными сбоями ОС и ее


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

КРИС КАСПЕРСКИ

6
программирование
Типичная реакция домашнего пользователя на нестабиль- чия, поскольку с аппаратными ошибками приходится бо-
ность работы своей машины – полная переустановка опе- роться и программными средствами (помните известное:
рационной системы. Иногда это помогает, иногда – нет, «как нематериальная душа возвращается в тело в резуль-
но, как бы там ни было, переустановка операционной си- тате материальных действий врача?»).
стемы на сервере – достаточно грандиозное событие, са-
мое малое на целый день выводящее локальную сеть Оперативная память
фирмы из игры. Квалифицированный администратор от- Оперативная память относится к одному из наименее на-
личается от неквалифицированного в первую очередь тем, дежных компонентов вычислительной системы, и потому
что со всеми проблемами справляется на лету, до мини- львиная доля всех сбоев приходится именно на нее. Прояв-
мума сводя время простоя сети. ления их могут быть самыми разнообразными: от критичес-
Вообще-то хорошо отлаженная система, базирующа- ких ошибок приложений до периодических или непериоди-
яся на ОС типа FreeBSD (или подобной ей), способна без ческих ошибок чтения (записи) на жесткий диск или даже
сбоев работать годами, не требуя к себе совершенно ни- каскадных ошибок приема/передачи TCP/IP-пакетов (что не
какого внимания. Системы, построенные на базе покажется удивительным, если вспомнить о кэширующем
Windows NT, этим, увы, похвастаться не могут, и для дос- приводе всех драйверов, обслуживающих устройства вво-
тижения сколь-нибудь стабильной работы за ними прихо- да/вывода). Любой аппаратный ресурс, требующий для сво-
дится постоянно ухаживать. ей работы некоторого количества оперативной памяти, так
Аппаратное обеспечение, собираемое на коленках в или иначе зависим от работоспособности последней.
ближайшем подвале, также не отличается высокой надеж- Существует мнение, что память «с четностью» полнос-
ностью, а отличить качественную подделку от оригинала тью решает проблему своей надежности и сводит риск раз-
по внешним признакам достаточно трудно. На просторах рушения данных к разумному минимуму. На самом деле это
России свободно продаются отбракованные чипы, левым не так. Память с четностью распознает лишь одиночные
путем добытые у производителей и выдаваемые за насто- ошибки и не гарантирует обнаружение групповых. Память
ящие. Кстати, многие из именитых производителей грешат типа ECC (Error Check & Correction/Error Correction Code –
передачей своих торговых марок третьим фирмам, выпус- Контроль и Исправление Ошибок), способна автоматичес-
кающим довольно посредственное оборудование, но про- ки исправлять любые одиночные ошибки и обнаруживать
дающих его по «брэндовским» ценам. Яркий тому пример – любые двойные. До тех пор, пока оперативная память фун-
пишущий привод TEAC 552E, к которому фирма TEAC во- кционирует более или менее нормально, противостояние
обще не имеет никакого отношения. Про материнские пла- энтропии и помехозащитных кодов решается в пользу пос-
ты и модули памяти вообще говорить не стоит. Их клепают ледних. Однако при полном или частичном выходе одного
все кому не лень, и многие модели вообще не работают, или нескольких модулей памяти из строя корректирующих
кое-как запускаясь на пониженных таймингах и частотах. способностей контролирующих кодов перестает хватать, и
Словом, если сбой старушки БЭСМ-6 был настоящим система начинает работать крайне нестабильно.
ЧП, то зависание современного сервера – вполне обычное Концепция виртуальной памяти, реализованная в опе-
дело, воспринимаемое администраторами как неизбежное рационных системах семейства Windows и UNIX, рассмат-
зло. Эта статья не убережет вас ни от критических ошибок ривает основную оперативную память как своеобразный
приложений, ни от отказа оборудования, но, по крайней кэш. А это значит, что одни и те же логические страницы
мере, научит быстро и безошибочно находить их источник. адресного пространства в разное время могут отображать-
Речь пойдет преимущественно о Windows NT и производ- ся на различные физические адреса. Разрушение одной-
ных от нее системах (Windows 2000, Windows XP), хотя по- единственной физической ячейки памяти затрагивает мно-
клонники UNIX также найдут здесь немало интересного. жество виртуальных ячеек, и потому сбои памяти практи-
чески всегда проявляются «коллективными» критически-
Аппаратная часть ми ошибками приложений, рассредоточенными в широком
Вот два основных аппаратных виновника нестабильной диапазоне адресов. Если же критические ошибки возни-
работы системы – оперативная память и блок питания. кают лишь в некоторых процессах и располагаются по бо-
Рассмотрим их поподробнее, отмечая особенности взаи- лее или менее постоянным адресам – с высокой степенью
модействия с памятью в современных чипсетах, таких как вероятности можно предположить, что это программная, а
Intel 875P и подобных ему. не аппаратная ошибка. Исключение составляет неоткачи-
Тесная связь между программным и аппаратным обес- ваемая область памяти (non-paged pool), занятая ядром
печением затрудняет деление статьи на две равные час- системы и всегда размещающаяся по одним и тем же фи-
ти, поскольку ряд сбоев системы (и пресловутых голубых зическим адресам. Наличие дефективных ячеек в данной
экранов смерти – в том числе) вызван отнюдь не алго- области обычно приводит к синему экрану смерти и/или
ритмическими ошибками, а неисправностью железа. Но полному зависанию системы, хотя в некоторых случаях
на начальном этапе анализа «голубого экрана смерти» ошибки драйверов передаются на прикладной уровень и
(далее по тексту просто голубого экрана) мы не можем роняют один или несколько процессов.
надежно установить его источник и, чтобы не описывать Самое интересное, что при прогоне нестабильно рабо-
одни и те же методики дважды, условимся относить все тающих драйверов/процессом под отладчиком ошибка вол-
критические ошибки системы к программной среде. В дей- шебным образом может исчезать. В действительности ни-
ствительности же это не вызывает никакого противоре- чего загадочного тут нет. За счет многократного снижения

№12(13), декабрь 2003 7


программирование
интенсивности доступа к памяти отладчик позволяет «вытя- Ряд тестовых пакетов, таких, например, как TestMem
нуть» даже дефективные ячейки, затрудняя их локализацию. от SERJ_M, перебирают большое количество разнотип-
Некоторые руководства рекомендуют исследовать дамп, ных шаблонов и довольно лихо выявляют скрытые дефек-
сброшенный системой при возникновении критической ты модулей памяти, в обычной жизни проявляющиеся
ошибки в ядре системы, наивно надеясь на то, что искажен- лишь при стечении множества маловероятных обстоя-
ные ячейки будут выглядеть как бессмысленный мусор, сразу тельств. К сожалению, эволюция чипсетов в конце кон-
бросающийся в глаза даже при минимальных навыках ди- цов привела к тому, что и эти шаблоны перестали рабо-
зассемблирования. При разрушении большого количества тать. При слишком интенсивном обмене с памятью чипсет
ячеек памяти, затрагивающих исполняемый код, это дей- Intel 875P и другие подобные ему чипсеты начинают встав-
ствительно так. Однако искажение областей данных пред- лять холостые циклы, давая памяти время «остыть», пре-
ложенный алгоритм выявить не в состоянии. Только чрез- дотвращая тем самым ее перегрев. С одной стороны, та-
вычайно опытный разработчик драйверов заподозрит, что кое конструкторское решение можно только приветство-
здесь что-то не так. А ведь в некоторых случаях неисправ- вать, поскольку оно значительно повышает надежность
ный модуль содержит всего лишь один-единственный де- системы, но с другой – чрезвычайно затрудняет ее тес-
фективный бит информации, который при визуальном ос- тирования. Для получения сколь-нибудь достоверных ре-
мотре дампа вообще нереально обнаружить. К тому же не зультатов тестирующая программа должна подобрать та-
стоит забывать, что «замусоривание» памяти может быть кую интенсивность прогона памяти, при которой холостые
вызвано не только аппаратными, но и программными ошиб- циклы еще не вставляются, но система работает уже на
ками (например, программист забыл проинициализировать пределе. Насколько известно автору, подобных программ
буфера или направил указатели в «космос», передав управ- еще нет и когда они появятся на рынке – неизвестно. Так
ление по произвольному адресу памяти). что спасение утопающих – забота самих утопающих.
Худший случай – это разрушение буферов ввода/вы- Сама по себе память, может быть, и не виновата. Ис-
вода, зачастую приводящее к полному краху файловой точником ошибок вполне может быть и северный мост
системы без какой-либо надежды на ее восстановление. чипсета, содержащий контроллер памяти. Исследуя чип-
По непонятной причине разработчики дисковых драйверов сет VIA KT133, автор обнаружил несколько критических
отказались от подсчета контрольной суммы пересылаемых ошибок планировщика очередей, приводящих к искаже-
через них блоков данных, что сделало файловую систему нию передаваемых данных и визуально проявляющихся
чрезвычайно уязвимой. Причем NTFS оказывается даже в как типичные дефекты памяти.
худшей ситуации, чем FAT32, поскольку требует значитель-
но меньшего объема буферной памяти для своей поддер- Блок питания
жки и к тому же значительно легче поддается «ручному» Второй по распространенности источник нестабильной
восстановлению. Автор настоящей статьи использует от- работы компьютера – это блок питания. Современные
казоустойчивые буфера, построенные на основе демонст- компьютеры предъявляют к качеству питающего напря-
рационных драйверов, входящих в состав DDK, и допол- жения достаточно жесткие требования, при нарушении
ненные специальными средствами контроля. Главное ноу- которых работа компьютера становится совершенно не-
хау данной технологии состоит в том, что обмен с диском предсказуемой, проявляясь зависаниями, критическими
ведется на «сыром» (RAW MODE) уровне, т.е. помимо об- ошибками и голубыми экранами смерти, выскакивающи-
ласти пользовательских данных в сектор входит конт- ми в самых неожиданных местах. В ряде случаев отмеча-
рольная сумма, по которой драйвер с одной и привод с ется замедление быстродействия приводов, обычно но-
другой стороны контролируют целостность данных. В жиз- сящее характер внезапных провалов производительнос-
ни автора эта технология срабатывала дважды (т.е. выяв- ти (копирование файлов движется как бы рывками).
ляла дефективный модуль памяти, пытавшийся разрушить Практически все уважающие себя производители ма-
жесткий диск), так что усилия, затраченные на разработку теринских плат оснащают свои детища развитой элект-
драйверов, многократно окупили себя сполна! ронной системой контроля основных (опорных) напряже-
Кстати, тестирование оперативной памяти путем про- ний, показания которых отображаются специальными ути-
гона специальных программ (Check It, PC Diagnostic и им литами. Убедитесь, что питающий потенциал соответству-
подобных) – не самый лучший путь для выявления ее ра- ет норме, отклонясь от нее не более чем на 5-10%, и ос-
ботоспособности. В силу физической неоднородности под- тается более или менее постоянным в процессе работы
системы памяти дефективность бракованных модулей за- компьютера. Причем «недобор» напряжения намного бо-
частую проявляется не на любой, а на строго определен- лее опасен, чем «перебор». Увеличение потенциала на
ной последовательности запросов и при определенном 15-20% практически никогда не приводит к моментально-
сочетании содержимого разрушенной и окрестных яче- му выходу электроники из строя, правда, вызывает ее пе-
ек. Тестирующие программы перебирают ограниченное регрев, но при наличии качественной системы охлажде-
количество наиболее типичных шаблонов и потому обна- ния с этим можно и смириться. Но даже незначительное
руживают лишь некоторые, наиболее дефективные де- уменьшение потенциала заметно снижает реакционность
фекты. Ряд серверных чипсетов содержит в себе более переходных процессов полупроводниковых элементов, и
или менее продвинутые средства тестирования памяти, система не успевает поспевать за тактовой частотой, что
работающие в фоновом режиме и работающие достаточ- приводит к зависаниям, критическим ошибкам, перезаг-
но эффективно. рузкам и т. д.

8
программирование
На рисунке 1 приведен плохой блок питания, обнару- Если ошибка будет повторяться, обратитесь к разработ-
живающий значительную просадку на линии 12 вольт и чику». К несчастью, критические ошибки приложения (в
чудовищные пульсации напряжения. Линия 3.3 вольт, об- терминологии Windows 2000 просто «ошибки приложе-
служивающая святую святых – оперативную память, так- ния») имеют устойчивую тенденцию появляться в самые
же слегка пульсирует, хотя стабилизируется отнюдь не ответственные моменты времени, например, накануне
блоком питания, но самой материнской платой, предел сдачи финансового отчета. А разработчики… они в боль-
стабилизации которой, впрочем, тоже небезграничен, и шинстве своем такие сообщения просто игнорируют.
даже качественная материнская плата бессильна выпра- Иногда потому, что просто не знают, как эту информа-
вить кривой от рождения блок питания. цию интерпретировать, иногда потому, что вообще не за-
ботятся о проблемах своих пользователей.
Многие сетуют на тупость Windows и ее неспособность
противостоять критическим ошибкам. Но эти обвинения
совершенно безосновательны. Возникновение критичес-
кой ошибки свидетельствует о том, что программа поеха-
ла крышей и пошла вразнос. Все, что только операцион-
ная система может сделать, – это пристрелить ее, в про-
тивном случае программа возвратит заведомо неверные
данные, чего допускать ни в коем случае нельзя. Так что
операционную систему не ругать следует, а благодарить!
Иногда сообщения о критических ошибках удается пре-
дотвратить установкой нового сервис-пака, а иногда, на-
оборот, – путем удаления нового. Еще можно попробовать
переустановить операционную систему или только само не-
стабильно работающее приложение. Однако никаких га-
Ðèñóíîê 1. Ïðèìåð ïëîõîãî áëîêà ïèòàíèÿ рантий, что после всех этих манипуляций сбой действитель-
К сожалению, точность интегрированных вольтметров но у вас исчезнет, нет. Достаточно вспомнить нашумев-
достаточно невелика, и многие из них явно нуждаются в шую историю с червем MSBLASTER, вызывающим крити-
хорошей калибровке. Поэтому доверять таким показани- ческую ошибку в системном сервисе svchost. Но сколько
ям следует с осторожностью и большой долей скептициз- бы вы ни переустанавливали свою Windows 2000, сколько
ма, при необходимости уточняя их нормальным цифро- бы ни меняли железо, ситуация не улучшалась. Антивиру-
вым мультиметром. сы, правда, сообщали о наличии вируса на компьютере (да
и то не всегда), однако не объясняли, какие меры безопас-
…и все-все-все ности следует принять. К тому же обрушение сервиса
Остальные компоненты компьютера практически никог- svchost происходило отнюдь не вследствие инфицирова-
да не вызывают серьезных проблем. Процессоры (при ния компьютера вирусом, а лишь при неудачной попытке
надлежащей системе охлаждения и не слишком боль- оного. Именно неумение хакеров сорвать стек, не уронив
шой тактовой частоте, конечно) лишь в исключительных при этом всю систему, и демаскировало вирус, попутно
случаях позволяют себе подвесить систему (да и то ос- организовав разрушительную DoS-атаку, до сих пор при-
новная доля вины ложится не на сам процессор, а на носящую весьма ощутимые убытки.
интегрированный кэш). Кстати, характерная болезнь Всякий администратор, считающий себя профессио-
«разогнанных процессоров» – голубой экран с надписью налом, не может позволить себе роскошь действовать
«UNEXPECTED_KERNEL_MODE_TRAP» (подробнее об вслепую. Знание ассемблера и умение быстро и грамот-
этом рассказывается во второй части статьи). но интерпретировать сообщения о критических ошибках,
Жесткие диски, становясь все более и более интеллек- если еще не решит проблему, то, по крайней мере, при-
туальными устройствами, достаточно неприхотливы, прав- даст вам чувство уверенности и поможет локализовать
да, при неправильной установке терминаторов на SCSI-уст- истинного виновника нестабильности системы. Во всяком
ройствах Windows NT может выбрасывать голубой экран случае будет куда ткнуть носом зарвавшегося разработ-
смерти, но хорошие диски термируют себя самостоятельно. чика. Согласитесь, одно дело догадываться об ошибке и
Карты расширения от сторонних производителей, бу- совсем другое – показывать на нее пальцем.
дучи расположенными на разделяемой PCI-шине, способ-
ны вызывать любые мыслимые и немыслимые конфлик-
ты, поэтому не пользуйтесь продукцией тех поставщиков, Приложения,
которым вы не доверяете. недопустимые операции
Программная часть и все-все-все
Катастрофическая небрежность тестирования фирменно- Различные операционные системы по-разному реагиру-
го и кустарного ПО приводит к появлению многочислен- ют на критические ошибки. Так, например, Windows NT
ных критических ошибок при его исполнении: «Програм- резервирует два региона своего адресного пространства
ма выполнила недопустимую операцию и будет закрыта. для выявления некорректных указателей. Один находит-

№12(13), декабрь 2003 9


программирование
ся на самом «дне» карты памяти и предназначен для от- Если никакой из отладчиков в системе не установ-
лавливания нулевых указателей. Другой расположен меж- лен, то окно о критической ошибке имеет всего лишь
ду «кучей» и областью памяти, закрепленной за опера- одну кнопку – кнопку «ОК», нажатие которой приводит
ционной системой. Он контролирует выход за пределы к аварийному закрытию политнекорректного приложе-
пользовательской области памяти и, вопреки расхожему ния. При желании окно критической ошибки можно ос-
мнению, никак не связан в функцией WriteProcessMemory настить кнопкой «Отмена» («Cancel»), запускающей от-
(см. техническую заметку ID: Q92764 в MSDN). Оба ре- ладчик или иную утилиту анализа ситуации. Важно по-
гиона занимают по 64 Кб, и всякая попытка доступа к нять, что «Отмена» отнюдь не отменяет автоматическое
ним расценивается системой как критическая ошибка. закрытие приложения, но при некоторой сноровке вы
В Windows 9x имеется всего лишь один 4 Кб регион, сле- можете устранить «пробоину» вручную, продолжив нор-
дящий за нулевыми указателями, поэтому по своим конт- мальную работу1.
ролирующим способностям она значительно уступает NT.
В Windows NT экран критической ошибки (см. рис. 2) Доктор Ватсон
содержит следующую информацию: «Доктор Ватсон» является штатным обработчиком кри-
 адрес машинной инструкции, возбудившей исключение; тических ошибок, входящим в базовый пакет поставки
 словесное описание категории исключения (или его всех операционных систем семейства Windows. По своей
код, если категория исключения неизвестна); природе он представляет статическое средство сбора
 параметры исключения (адрес недействительной ячей- релевантной информации. Предоставляя исчерпывающий
ки памяти, род операции и т. д.). отчет о причинах сбоя, «Доктор Ватсон» в то же самое
время лишен активных средств воздействия на некоррек-
тно работающие программы. Утихомирить разбушевав-
шееся приложение, заставив его продолжить свою рабо-
ту с помощью одного «Доктора Ватсона», вы не сможете,
и для этого вам придется прибегать к интерактивным от-
Ðèñóíîê 2. Ñîîáùåíèå î êðèòè÷åñêîé îøèáêå, âûäàâàåìîå îïå- ладчикам, одним из которых является Microsoft Visual
ðàöèîííîé ñèñòåìîé Windows 2000 Studio Debugger, входящий в состав одноименной среды
Операционные системы семейства Windows 9x в этом разработки и рассматриваемый в статье далее.
отношении намного более информативны (см. рис. 3) и Считается, что «Доктор Ватсон» предпочтительнее
помимо категории исключения выводят содержимое ре- использовать на рабочих станциях (точнее, на автомати-
гистров ЦП на момент сбоя, состояние стека и байты па- зированных рабочих местах), а интерактивные средства
мяти по адресу CS:EIP (т.е. текущему адресу исполне- отладки – на серверах. Дескать, во всех премудростях
ния). Впрочем, наличие «Доктора Ватсона» (о нем – да- ассемблера пользователи все равно не разбираются, а
лее) стирает различие между двумя системами, и пото- вот на сервере продвинутый отладчик будет как нельзя
му можно говорить лишь об удобстве и эргономике 9x, кстати. Отчасти это действительно так, но не стоит игно-
сразу предоставляющей весь минимум необходимых све- рировать то обстоятельство, что далеко не все источники
дений, в то время как в NT отчет об ошибке создается ошибок обнаруживаются статическими средствами ана-
отдельной утилитой. лиза, к тому же интерактивные инструменты значительно
упрощают процедуру анализа. С другой стороны, «Док-
тор Ватсон» достается нам даром, а все остальные про-
граммные пакеты приходится приобретать за дополни-
тельную плату. Так что предпочтительный обработчик
критических ошибок вы должны выбирать сами.
Для установки «Доктора Ватсона» отладчиком по
умолчанию добавьте в реестр следующую запись или за-
пустите файл Drwtsn32.exe c ключом «–i» (для выполне-
ния обоих действий вы должны иметь права админист-
ратора):

Ëèñòèíã 1. Óñòàíîâêà «Äîêòîðà Âàòñîíà» îòëàä÷èêîì ïî óìîë÷àíèþ


[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\ ↵
CurrentVersion\AeDebug]
"Auto"="1"
"Debugger"="drwtsn32 -p %ld -e %ld -g"
Ðèñóíîê 3. Ñîîáùåíèå î êðèòè÷åñêîé îøèáêå, âûäàâàåìîå îïå- "UserDebuggerHotKey"=dword:00000000
ðàöèîííîé ñèñòåìîé Windows 98

1
Запустите «Редактор Реестра» и перейдите в раздел «HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug».
Если такого раздела нет – создайте его самостоятельно. Строковой параметр «Debugger» задает путь к файлу отладчи-
ка со всеми необходимыми ключами; строковой параметр «Auto» указывает, должен ли отладчик запускаться автомати-
чески (значение «1») или предлагать пользователю свободу выбора («0»). Наконец двойное слово параметра
«UserDebuggerHotKey» специфицирует скэн-код горячей клавиши для принудительного вызова отладчика.

10
программирование
Теперь возникновение критических ошибок програм- eax=00000064 ebx=7ffdf000 ecx=00000000 edx=00000064 ↵
мы станет сопровождаться генерацией отчета, состав- esi=00000000 edi=00000000
eip=00401014 esp=0012ff70 ebp=0012ffc0 iopl=0 ↵
ляемого «Доктором Ватсоном» и содержащим более nv up ei pl nz na pe nc
или менее подробные сведения о характере ее проис- cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 ↵
efl=00000202
хождения. ; Ñîäåðæèìîå ðåãèñòðîâ è ôëàãîâ.

ôóíêöèÿ: <nosymbols>
; Ðàñïå÷àòêà îêðåñòíîé òî÷êè cáîÿ.
00400ffc 0000 add [eax],al ds:00000064=??
; Çàïèñûâàåì â ÿ÷åéêó, íà êîòîðóþ ññûëàåò EAX, çíà÷åíèå AL.
; Çíà÷åíèå àäðåñà ÿ÷åéêè, âû÷èñëåííîé Äîêòîðîì Âàòñîíîì,
; ðàâíî 64h, ÷òî, î÷åâèäíî, íå ñîîòâåòñòâóåò
; äåéñòâèòåëüíîñòè. «Äîêòîð Âàòñîí» ïîäñòàâëÿåò â âûðàæåíèå
; çíà÷åíèå ðåãèñòðà EAX íà ìîìåíò âîçíèêíîâåíèÿ ñáîÿ,
; è ýòî ñîâñåì íå òî çíà÷åíèå, êîòîðîå áûëî â ìîìåíò
; èñïîëíåíèÿ! Ê ñîæàëåíèþ, ÷åìó áûë ðàâåí EAX â ìîìåíò
Ðèñóíîê 4. Ðåàêöèÿ «Äîêòîðà Âàòñîíà» íà êðèòè÷åñêóþ îøèáêó ; èñïîëíåíèÿ íè íàì, íè «Äîêòîðó Âàòñîíó» íå èçâåñòåí.
Образец дампа, созданный «Доктором Ватсоном», при- 00400ffe 0000 add [eax],al ds:00000064=??
веден ниже. Комментарии, добавленные автором, выде- ; Çàïèñûâàåì â ÿ÷åéêó, íà êîòîðóþ ññûëàåò EAX, çíà÷åíèå AL.
; Êàê? Îïÿòü? Âîîáùå-òî òàê êîäèðóåòñÿ ïîñëåäîâàòåëüíîñòü
лены красным цветом: ; 00 00 00 00, ïî âñåé âèäèìîñòè ÿâëÿþùàÿñÿ îñêîëêîì
; íåêîòîðîé ìàøèííîé êîìàíäû, íåïðàâèëüíî
; èíòåðïðåòèðîâàííîé äèçàññåìáëåðíûì äâèæêîì
Ëèñòèíã 2. Îáðàçåö îò÷åòà «Äîêòîðà Âàòñîíà» ; «Äîêòîðà Âàòñîíà».
Èñêëþ÷åíèå â ïðèëîæåíèè: 00401000 8b542408 mov edx,[esp+0x8] ss:00f8d547=????????
Ïðèë.: (pid=612) ; Çàãðóæàåì â EDX àðãóìåíò ôóíêöèè.
; pid ïðîöåññà, â êîòîðîì ïðîèçîøëî èñêëþ÷åíèå. ; Êàêîé èìåííî àðãóìåíò – ñêàçàòü íåâîçìîæíî, ò.ê. ìû íå
; çíàåì àäðåñ ñòåêîâîãî ôðåéìà.
Âðåìÿ: 14.11.2003 @ 22:51:40.674
; Âðåìÿ, êîãäà ïðîèçîøëî èñêëþ÷åíèå. 00401004 33c9 xor ecx,ecx
; Îáíóëÿåì ECX
Íîìåð: c0000005 (íàðóøåíèå ïðàâ äîñòóïà)
; Êîä êàòåãîðèè èñêëþ÷åíèÿ. 00401006 85d2 test edx,edx
; Ðàñøèôðîâêó êîäîâ èñêëþ÷åíèé ìîæíî íàéòè â WINNT.H 00401008 7e18 jle 00409b22
; âõîäÿùèì â ñîñòàâ SDK, ïðèëàãàåìîì ê ëþáîìó ; Åñëè EDX == 0, ïðûãàåì íà àäðåñ 409B22h.
; Windows-êîìïèëÿòîðó. Ïîäðîáíîå îïèñàíèå âñåõ èñêëþ÷åíèé
; ñîäåðæèòñÿ â äîêóìåíòàöèè ïî ïðîöåññîðàì Intel è AMD, 0040100a 8b442408 mov eax,[esp+0x8] ss:00f8d547=????????
; áåñïëàòíî ðàñïðîñòðàíÿåìîé èõ ïðîèçâîäèòåëÿìè (âíèìàíèå: ; Çàãðóæàåì óæå óïîìÿíóòûé àðãóìåíò â ðåãèñòð EAX.
; äëÿ ïåðåâîäà êîäà èñêëþ÷åíèÿ îïåðàöèîííîé ñèñòåìû â
; âåêòîð ïðåðûâàíèÿ ÖÏ, âû äîëæíû îáíóëèòü ñòàðøåå ñëîâî), 0040100e 56 push esi
; â äàííîì ñëó÷àå ýòî 0x5 – ïîïûòêà äîñòóïà ê ïàìÿòè ; Ñîõðàíÿåì ESI â ñòåêå, ïåðåìåùàÿ òåì ñàìûì óêàçàòåëü
; ïî çàïðåùåííîìó àäðåñó. ; âåðøèíû ñòåêà íà 4 áàéòà ââåðõ (â îáëàñòü ìëàäøèõ
; àäðåñîâ).
*----> Ñâåäåíèÿ î ñèñòåìå <----*
Èìÿ êîìïüþòåðà: KPNC 0040100f 8b742408 mov esi, [esp+0x8] ss:00f8d547=????????
Èìÿ ïîëüçîâàòåëÿ: Kris Kaspersky ; Çàãðóæàåì â ESI î÷åðåäíîé àðãóìåíò.
×èñëî ïðîöåññîðîâ: 1 ; Ïîñêîëüêó ESP áûë òîëüêî ÷òî èçìåíåí, ýòî ñîâñåì íå òîò
Òèï ïðîöåññîðà: x86 Family 6 Model 8 Stepping 6 ; àðãóìåíò, ñ êîòîðûì ìû èìåëè äåëî ðàíåå.
Âåðñèÿ Windows 2000: 5.0
Òåêóùàÿ ñáîðêà: 2195 00401013 57 push edi
Ïàêåò îáíîâëåíèÿ: None ; Ñîõðàíÿåì ðåãèñòð EDI â ñòåêå.
Òåêóùèé òèï: Uniprocessor Free
Çàðåãèñòðèðîâàííàÿ îðãàíèçàöèÿ: ÑÁÎÉ -> 00401014 0fbe3c31 movsx edi,byte ptr [ecx+esi] ↵
Çàðåãèñòðèðîâàííûé ïîëüçîâàòåëü: Kris Kaspersky ds:00000000=??
; Êðàòêèå ñâåäåíèÿ î ñèñòåìå. ; Âîò ìû è äîáðàëèñü äî èíñòðóêöèè, âîçáóäèâøåé èñêëþ÷åíèå
; äîñòóïà. Îíà îáðàùàåòñÿ ê ÿ÷åéêå ïàìÿòè, íà êîòîðóþ
*----> Ñïèñîê çàäà÷ <----* ; óêàçûâàåò ñóììà ðåãèñòðîâ ECX è ESI, à ÷åìó ðàâíî èõ
0 Idle.exe ; çíà÷åíèå? Ïðîêðó÷èâàåì ýêðàí íåìíîãî ââåðõ è íàõîäèì, ÷òî
8 System.exe ; ECX è ESI ðàâíû 0, î ÷åì «Äîêòîð Âàòñîí» íàì è ñîîáùàåò:
232 smss.exe ; «ds:000000» îòìåòèì, ÷òî ýòîé èíôîðìàöèè ìîæíî âåðèòü,
… ; ïîñêîëüêó ïîäñòàíîâêà ýôôåêòèâíîãî àäðåñà îñóùåñòâëÿëàñü
1244 os2srv.exe ; íåïîñðåäñòâåííî â ìîìåíò èñïîëíåíèÿ, òåïåðü âñïîìíèì,
1164 os2ss.exe ; ÷òî ESI ñîäåðæèò êîïèþ ïåðåäàííîãî ôóíêöèè àðãóìåíòà
1284 windbg.exe ; è ÷òî ECX áûë îáíóëåí ÿâíî, ñëåäîâàòåëüíî, â âûðàæåíèè
1180 MSDEV.exe ; [ECX+ESI] ðåãèñòð ESI – óêàçàòåëü, à ECX – èíäåêñ. Ðàç ESI
1312 cmd.exe ; ðàâåí íóëþ, òî íàøåé ôóíêöèè ïåðåäàëè óêàçàòåëü
612 test.exe ; íà íåâûäåëåííóþ îáëàñòü ïàìÿòè. Îáû÷íî ýòî ïðîèñõîäèò
1404 drwtsn32.exe ; ëèáî âñëåäñòâèå àëãîðèòìè÷åñêîé îøèáêè â ïðîãðàììå,
0 _Total.exe ; ëèáî âñëåäñòâèå èñ÷åðïàíèÿ âèðòóàëüíîé ïàìÿòè,
; ê ñîæàëåíèþ, «Äîêòîð Âàòñîí» íå îñóùåñòâëÿåò
(00400000 - 00406000) ; äèçàññåìáëèðîâàíèå ìàòåðèíñêîé ôóíêöèè, è êàêîé èç äâóõ
(77F80000 - 77FFA000) ; ïðåäïîëàãàåìûõ âàðèàíòîâ ïðàâèëüíûé – íàì îñòàåòñÿ ëèøü
(77E80000 - 77F37000) ; ãàäàòü… Ïðàâäà, ìîæíî äèçàññåìáëèðîâàòü äàìï ïàìÿòè
; Ïåðå÷åíü çàãðóæåííûõ DLL. ; ïðîöåññà (åñëè, êîíå÷íî, îí áûë ñîõðàíåí), íî ýòî óæå
; Ñîãëàñíî äîêóìåíòàöèè, ñïðàâà îò àäðåñîâ äîëæíû áûòü ; íå òî…
; ïåðå÷èñëåíû èìåíà ñîîòâåòñòâóþùèõ ìîäóëåé, îäíàêî
; ïðàêòè÷åñêè âñå îíè òàê õîðîøî «çàìàñêèðîâàëèñü», ÷òî ñòàëè 00401018 03c7 add eax, edi
; ñîâåðøåííî íå âèäíû. Âûòàùèòü èõ èìåíà èç ôàéëà ïðîòîêîëà ; Ñëîæèòü ñîäåðæèìîå ðåãèñòðà EAX ñ ðåãèñòðîì EDI
; âñå-òàêè ìîæíî, íî ïðèäåòñÿ íåìíîãî «ïîøàìàíèòü» (ñì. íèæå ; è çàïèñàòü ðåçóëüòàò â EAX.
; «òàáëèöó ñèìâîëîâ»).
0040101a 41 inc ecx
Êîïèÿ ïàìÿòè äëÿ ïîòîêà 0x188 ; Óâåëè÷èòü ECX íà åäèíèöó.
; Íèæå èäåò êîïèÿ ïàìÿòè ïîòîêà, âûçûâàâøåãî èñêëþ÷åíèå.

№12(13), декабрь 2003 11


программирование
0040101b 3bca cmp ecx,edx kernel32.dll
0040101d 7cf5 jl 00407014 77E81765 0000003d IsDebuggerPresent
; Äî òåõ ïîð ïîêà ECX < EDX, ïåðåõîäèòü íà àäðåñ 407014 …
; (î÷åâèäíî, ìû èìååì äåëî ñ öèêëîì, óïðàâëÿåìûì ñ÷åò÷èêîì 77EDBF7A 00000000 VerSetConditionMask
; ECX). Ïðè èíòåðàêòèâíîé îòëàäêå ìû ìîãëè áû ïðèíóäèòåëüíî ;
; âûéòè èç ôóíêöèè, âîçâðàòèâ ôëàã îøèáêè, ÷òîáû ìàòåðèíñêàÿ ; Èòàê, âîçâðàùàåìñÿ ê òàáëèöå çàãðóæåííûõ DLL.
; ôóíêöèÿ (à ñ íåé è âñÿ ïðîãðàììà öåëèêîì) ìîãëà ïðîäîëæèòü ; (00400000 - 00406000) - ýòî, î÷åâèäíî, îáëàñòü ïàìÿòè,
; ñâîå âûïîëíåíèå, è â ýòîì ñëó÷àå ïîòåðÿííîé îêàæåòñÿ ëèøü ; çàíÿòàÿ ñàìîé ïðîãðàììîé
; ïîñëåäíÿÿ îïåðàöèÿ, íî âñå îñòàëüíûå äàííûå îêàæóòñÿ ; (77F80000 - 77FFA000) – ýòî KERNEL32.DLL
; íåèñêàæåííûìè. ; (77E80000 - 77F37000) - ýòî NTDDL.DLL

0040101f 5f pop edi


00401020 5e pop esi
00401021 c3 ret
; Âûõîäèì èç ôóíêöèè.
Microsoft Visual Studio Debugger
При установке среды разработки Microsoft Visual Studio
*----> Îáðàòíàÿ òðàññèðîâêà ñòåêà <----* она регистрирует свой отладчик основным отладчиком
; Ñîäåðæèìîå ñòåêà íà ìîìåíò âîçíèêíîâåíèÿ ñáîÿ.
; Ðàñïå÷àòûâàåò àäðåñà è ïàðàìåòðû ïðåäûäóùèõ âûïîëíÿåìûõ ôóíêöèé, критических ошибок по умолчанию. Это простой в исполь-
; ïðè èíòåðàêòèâíîé îòëàäêå ìû ìîãëè áû ïðîñòî ïåðåäàòü óïðàâëåíèå зовании, но функционально ущербный отладчик, не под-
; íà îäíó èç âûøåëåæàùèõ ôóíêöèé, ÷òî ýêâèâàëåíòíî âîçâðàùåíèþ
; â ïðîøëîå, ýòî òîëüêî â ðåàëüíîé æèçíè ðàçáèòóþ ÷àøêó держивающий даже такой банальной операции, как по-
; âîññòàíîâèòü íåëüçÿ, â êîìïüþòåðíîé âñåëåííîé âîçìîæíî âñå! иск hex-последовательности в оперативной памяти. Един-
FramePtr ReturnAd Param#1 Param#2 Param#3 Param#4 ↵
Function Name ственная «вкусность», отличающая его от продвинутого
; FramePtr: Óêàçûâàåò íà çíà÷åíèå ôðåéìà ñòåêà, во всех отношениях Microsoft Kernel Debugger – это воз-
; âûøå (ò.å. â áîëåå ìëàäøèõ àäðåñàõ)
; ñîäåðæàòñÿ àðãóìåíòû ôóíêöèè, íèæå – åå можность трассировки «упавших» процессов, выбросив-
; ëîêàëüíûå ïåðåìåííûå. ших критическое исключение.
;
; ReturnAd: Áåðåæíî õðàíèò àäðåñ âîçâðàòà â ìàòåðèíñêóþ В опытных руках отладчик Microsoft Visual Studio Debugger
; ôóíêöèþ. Åñëè çäåñü ñîäåðæèòñÿ ìóñîð è способен творить настоящие чудеса, и одно из таких чу-
; îáðàòíàÿ òðàññèðîâêà ñòåêà íà÷èíàåò
; õàðàêòåðíî øóìåòü, ñ âûñîêîé ñòåïåíüþ дес – это возобновление работы приложений, совершив-
; âåðîÿòíîñòè ìîæíî ïðåäïîëîæèòü, ÷òî ìû ших недопустимую операцию и при нормальном течении
; èìååì äåëî ñ îøèáêîé «ñðûâà ñòåêà», à
; âîçìîæíî, è ñ ïîïûòêîé àòàêè âàøåãî событий, аварийно завершаемых операционной системой
; êîìïüþòåðà. без сохранения данных. В любом случае интерактивный
;
; Param#: ×åòûðå ïåðâûõ ïàðàìåòðà ôóíêöèè – èìåííî отладчик (коим Microsoft Visual Studio Debugger и являет-
; ñòîëüêî ïàðàìåòðîâ «Äîêòîð Âàòñîí» îòîáðàæàåò ся) предоставляет намного более подробную информа-
; íà ýêðàíå. Ýòî äîñòàòî÷íî æåñòêîå îãðàíè÷åíèå –
; ìíîãèå ôóíêöèè èìåþò äåñÿòêè ïàðàìåòðîâ è цию о сбое и значительно упрощает процесс выявления
; ÷åòûðå ïàðàìåòðà åùå íè î ÷åì íå ãîâîðÿò; источников его возникновения. К сожалению, тесные рам-
; îäíàêî íåäîñòàþùèå ïàðàìåòðû ëåãêî âûòàùèòü
; èç êîïèè íåîáðàáîòàííîãî ñòåêà âðó÷íóþ – ки журнальной статьи не позволяют изложить всю мето-
; äîñòàòî÷íî ëèøü ïåðåéòè ïî óêàçàííîìó â ïîëå дику поиска неисправностей целиком, и приходится ог-
; FramePtr àäðåñó.
; раничиваться лишь узким кругом наиболее интересных
; Func Name: Èìÿ ôóíêöèè (åñëè òîëüêî åãî âîçìîæíî (и наименее известных!) вопросов (см. раздел «Обитате-
; ëåãêî âûòàùèòü è îïðåäåëèòü);
; ðåàëüíî îòîáðàæàåò ëèøü èìåíà ôóíêöèé, ли сумеречной зоны, или из морга в реанимацию»).
; èìïîðòèðóåìûå èç äðóãèõ DLL, ïîñêîëüêó Для ручной установки Microsoft Visual Studio Debugger
; âñòðåòèòü êîììåð÷åñêóþ ïðîãðàììó,
; îòêîìïèëèðîâàííóþ âìåñòå ñ îòëàäî÷íîé основным отладчиком критических ошибок добавьте в
; èíôîðìàöèåé ïðàêòè÷åñêè íåðåàëüíî. реестр следующие данные:
;
0012FFC0 77E87903 00000000 00000000 7FFDF000 C0000005 !<nosymbols>
0012FFF0 00000000 00401040 00000000 000000C8 00000100 ↵ Ëèñòèíã 3. Óñòàíîâêà Microsoft Visual Studio Debugger îñ-
kernel32!SetUnhandledExceptionFilter íîâíûì îòëàä÷èêîì êðèòè÷åñêèõ îøèáîê
; Ôóíêöèè ïåðå÷èñëÿþòñÿ â ïîðÿäêå èõ èñïîëíåíèÿ; ñàìîé ïîñëåäíåé
; èñïîëíÿëàñü kernel32!SetUnhandledExceptionFilter ôóíêöèÿ, [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\ ↵
; îáðàáàòûâàþùàÿ äàííîå èñêëþ÷åíèå. CurrentVersion\AeDebug]
"Auto"="1"
*----> Êîïèÿ íåîáðàáîòàííîãî ñòåêà <----* "Debugger"="\"C:\\Prg Files\\MS VS\\Common\\MSDev98\\Bin\\ ↵
; Êîïèÿ íåîáðàáîòàííîãî ñòåêà ñîäåðæèò ñòåê òàêèì, êàêîé îí åñòü. msdev.exe\" -p %ld -e %ld"
; Î÷åíü ïîìîãàåò ïðè îáíàðóæåíèè buffer overfull àòàê – "UserDebuggerHotKey"=dword:00000000
; âåñü shell-êîä, ïåðåäàííûé çëîóìûøëåííèêîì, áóäåò ðàñïå÷àòàí
; «Äîêòîðîì Âàòñîíîì», è âàì îñòàíåòñÿ âñåãî ëèøü îïîçíàòü åãî Ëèñòèíã 4. Äåìîíñòðàöèîííàÿ ïðîãðàììà, âûçûâàþùàÿ ñîîáùå-
; (ïîäðîáíåå îá ýòîì ðàññêàçûâàåòñÿ â ìîåé êíèãå "Òåõíèêà íèå î êðèòè÷åñêîé îøèáêå
; ñåòåâûõ àòàê")
0012ff70 00 00 00 00 00 00 00 00 - 39 10 40 00 00 00 00 00 ........9.@..... // Ôóíêöèÿ âîçâðàùàåò ñóììó n ñèìâîëîâ òèïà char. Åñëè åé
0012ff80 64 00 00 00 f4 10 40 00 - 01 00 00 00 d0 0e 30 00 d.....@.......0. // ïåðåäàòü null-pointer, îíà «óïàäåò», õîòÿ èñòî÷íèê îøèáêè
… // íå â íåé, à â àðãóìåíòàõ, ïåðåäàííûõ ìàòåðèíñêîé ôóíêöèåé.
00130090 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................ test(char *buf, int n)
001300a0 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 ................ {
int a, sum;
*----> Òàáëèöà ñèìâîëîâ <----* // Çäåñü âîçáóæäàåòñÿ èñêëþ÷åíèå.
; Òàáëèöà ñèìâîëîâ ñîäåðæèò èìåíà âñåõ çàãðóæåííûõ DLL âìåñòå for (a = 0; a < n; a++) sum += buf[a];
; ñ èìåíàìè èìïîðòèðóåìûõ ôóíêöèé. Èñïîëüçóÿ ýòè àäðåñà â return sum;
; êà÷åñòâå îòïðàâíîé òî÷êè, ìû áåç òðóäà ñìîæåì âîññòàíîâèòü }
; «ïåðå÷åíü çàãðóæåííûõ DLL».
main()
ntdll.dll {
77F81106 00000000 ZwAccessCheckByType #define N 100
… // Èíèöèàëèçèðóåì óêàçàòåëü íà áóôåð.
77FCEFB0 00000000 fltused char *buf = 0;

12
программирование
// «Çàáûâàåì» âûäåëèòü ïàìÿòü, çäåñü îøèáêà. Ëèñòèíã 5. Îòëàä÷èê Microsoft Visual Studio Debugger äèçàñ-
/* buf = malloc(100); */ ñåìáëèðîâàë ôóíêöèþ, âîçáóäèâøóþ èñêëþ÷åíèå
// Ïåðåäàåì null-pointer íåêîòîðîé ôóíêöèè.
test(buf, N); 0040135C push esi
} 0040135D mov esi,dword ptr [esp+8]
00401361 push edi
00401362 movsx edi,byte ptr [ecx+esi]
Обитатели сумеречной зоны, 00401366
00401368
add
inc
eax,edi
ecx
или из морга в реанимацию 00401369 cmp ecx,edx
0040136B jl 00401362
Хотите узнать, как заставить приложение продолжить 0040136D pop edi
нормальную работу после появления сообщения о крити- 0040136E pop esi
0040136F ret 8
ческой ошибке? Это действительно очень актуально.
Представьте, что рухнуло приложение, содержащее уни- Проанализировав причину возникновения исключения
кальные и еще не сохраненные данные. По минимуму их (функции передан указатель на невыделенную память), мы
придется набивать заново, по максимуму – они потеряны приходим к выводу, что заставить функцию продолжить свою
для вас навсегда. На рынке имеется некоторое количе- работу невозможно, поскольку структура передаваемых
ство утилит, нацеленных на эту задачу (взять те же Norton данных нам не известна. Приходится прибегать к принуди-
Utilities), но их интеллектуальность оставляет желать луч- тельному возврату в материнскую функцию, не забыв при
шего и в среднем они срабатывают один раз из десяти. В этом установить флаг ошибки, сигнализируя программе, что
то же самое время ручная реанимация программы вос- текущая операция не была выполнена. К сожалению, ника-
крешает ее в 75-90% случаев. ких общепринятых флагов ошибок не существует, и различ-
Строго говоря, гарантированно восстановить работос- ные функции используют различные соглашения. Чтобы
пособность обрушавшейся программы нельзя, равно как выяснить, как обстоят дела в данном конкретном случае,
и невозможно выполнить откат тех действий, что пред- мы должны дизассемблировать материнскую функцию и
шествовали ее обрушению. В лучшем случае вам удаст- определить, какой именно код ошибки она ожидает.
ся сохранить свои данные на диск до того, как программа Переместив курсор в окно дампа, набьем в строке ад-
полностью потеряет нить управления и пойдет вразнос. реса название регистра указателя вершины стека – «ESP»
Но и это неплохо! и нажмем на <Enter>. Содержимое стека тут же предста-
Существует по меньшей мере три различных способа нет перед нашими глазами:
реанимации:
 принудительный выход из функции, возбудившей ис- Ëèñòèíã 6. Ïîèñê àäðåñà âîçâðàòà èç òåêóùåé ôóíêöèè (âûäå-
ëåí êðàñíûì øðèôòîì)
ключение;
 «раскрутка» стека с передачей управления назад; 0012F488
0012F494
0012FA64
00000000
0012FA64
00000064
004012FF
00403458
 передача управления на функцию обработки сообщений. 0012F4A0 FFFFFFFF 0012F4C4 6C291CEA
0012F4AC 00000019 00000000 6C32FAF0
0012F4B8 0012F4C0 0012FA64 01100059
Рассмотрим каждый из этих способов на примере при- 0012F4C4 006403C2 002F5788 00000000
ложения test.exe, копию которого вы можете скачать по 0012F4D0 00640301 77E16383 004C1E20
адресу: www.samag.ru/sourse/test.zip.
Забегая вперед, отметим, что реанимации поддаются Первые два двойных слова соответствуют машинным
лишь те сбои, что вызваны алгоритмическими, а не аппа- командам POP EDI/POP ESI и не представляют для нас
ратными ошибками (т.е. сбоем оборудования). Если ин- совершенно никакого интереса. А вот следующее двой-
формация, хранящаяся в оперативной памяти, оказалась ное слово содержит адрес выхода в материнскую проце-
искажена в результате физического дефекта последней, дуру (в приведенном выше листинге оно выделено крас-
то восстановить работоспособность упавшего приложе- ным шрифтом). Как раз оно-то нам и нужно!
ния скорее всего уже не удастся, хотя если сбой не затро- Нажимаем <Ctrl-D> и затем 0x4012FF, отладчик по-
нул жизненно важные структуры данных, некоторая на- слушно отображает следующий дизассемблерный текст:
дежда на благополучный исход все-таки есть.
Ëèñòèíã 7. Äèçàññåìáëåðíûé ëèñòèíã ìàòåðèíñêîé ôóíêöèè
Принудительный выход из функции 004012FA call 00401350
Запускаем тестовую программу, набиваем в одном или 004012FF cmp eax,0FFh
00401302 je 0040132D
нескольких окнах какой-нибудь текст, затем в меню «Help» 00401304 push eax
выбираем пункт «About TestCEdit» и в появившемся диа- 00401305 lea eax, [esp+8]
00401309 push 405054h
логовом окне щелкаем по кнопке «make error». Програм- 0040130E push eax
ма выбрасывает критическую ошибку и, если мы нажмем 0040130F call dword ptr ds:[4033B4h]
00401315 add esp, 0Ch
на «ОК», все несохраненные данные необратимо погиб- 00401318 lea ecx, [esp+4]
нут, что никак не входит в наши планы. Однако при нали- 0040131C push 0
0040131E push 0
чии предварительно установленного отладчика мы еще 00401320 push ecx
можем кое-что предпринять. Пусть для определенности 00401321 mov ecx, esi
00401323 call 00401BC4
это будет Microsoft Visual Studio Debugger. 00401328 pop esi
Нажимаем «Отмену», и отладчик немедленно дизассем- 00401329 add esp,64h
0040132C ret
блирует функцию, возбудившую исключение (см. листинг 5). 0040132C

№12(13), декабрь 2003 13


программирование
0040132D push 0 ны, чрезмерно глубокий откат ведет к потере всех несох-
0040132D ; ýòà âåòêà ïîëó÷àåò óïðàâëåíèå, åñëè Ôóíêöèÿ раненных данных…
; 401350h âåðíåò FFh
0040132F push 0 Процедура отката состоит из трех шагов:
00401331
00401336
push
mov
405048h
ecx,esi
 построения дерева вызовов;
00401338 call 00401BC4  определения координат стекового фрейма для каждо-
0040133D pop esi го из них;
0040133E add esp,64h
00401341 ret  восстановления регистрового контекста материнской
функции.
Смотрите: если регистр EAX равен FFh, то материнс-
кая функция передает управление на ветку 40132Dh и, спу- Хороший отладчик все это сделает за нас, и нам оста-
стя несколько машинных команд, завершает свою работу, нется лишь записать в регистры EIP и ESP соответствую-
передавая бразды правления функции более высокого щие значения. К сожалению, отладчик Microsoft Visual
уровня. Напротив, если EAX != FFh, то его значение пере- Studio Debugger к хорошим отладчикам не относится. Он
дается функции 4033B4h. Следовательно, мы можем пред- довольно посредственно трассирует стек, пропуская FPO-
положить, что FFh – это флаг ошибки и есть. Возвращаем- функции (Frame Point Omission – функции с оптимизиро-
ся в подопытную функцию, нажав <Ctrl-G> и «EIP», пере- ванным фреймом) и не сообщает координат стекового
ходим в окно «Registers» и меняем значение EAX на FFh. фрейма, «благодаря» чему самую трудоемкую часть ра-
Теперь необходимо найти подходящую точку возвра- боты нам приходится выполнять самостоятельно.
та из функции. Просто перейти к машинной команде Впрочем, даже такой стек вызовов все же лучше, чем
«RET» нельзя, поскольку перед выходом из функции сле- совсем ничего. Раскручивая его вручную, мы будем от-
дует в обязательном порядке сбалансировать стек, или талкиваться от того, что координаты фрейма естествен-
нас выбросит неизвестно куда, и программа обрушится ным образом определяются по адресу возврата. Допус-
окончательно. тим, содержимое окна «Call Stack» выглядит так:
В общем случае число PUSH-команд должно в точно-
сти соответствовать количеству POP (также учитывайте, Ëèñòèíã 8. Ñîäåðæèìîå îêíà Call Stacks îòëàä÷èêà Microsoft
Visual Studio Debugger
что PUSH DWORD X эквивалентен SUB ESP, 4, а POP
DWORD X – ADD ESP, 4). Проанализировав дизассемб- TESTCEDIT! 00401362()
MFC42! 6c2922ae()
лерный листинг функции, мы приходим к выводу, что для MFC42! 6c298fc5()
достижения гармонии добра и зла мы должны стащить с MFC42! 6c292976()
MFC42! 6c291dcc()
вершины стека два двойных слова, соответствующие ма- MFC42! 6c291cea()
шинным командам 40135С:PUSH ESI и 401361:PUSH EDI. MFC42! 6c291c73()
MFC42! 6c291bfb()
Это достигается передачей управления по адресу MFC42! 6c291bba()
40136Dh, где живут два добродушных POP, приводящие
стек в равновесное состояние. Подводим сюда курсор и Попробуем найти в стеке адреса 6C2922AEh и
уверенным щелчком правой клавиши мыши вызываем 6C298FC5h, соответствующие двум последним ступеням
контекстное меню, среди пунктов которого выбираем «Set исполнения. Нажимаем <ATL-6> для перехода в окно дам-
Next Statement». Как вариант можно перейти в окно реги- па и, воспользовавшись горячей комбинацией клавиш
стров и изменить значение EIP с 401362h на 40136Dh. <Ctrl-G> в качестве базового адреса отображения, выби-
Нажатием <F5> мы заставляем процессор продолжить раем «ESP». Прокручивая окно дампа вниз, мы обнару-
выполнение программы и… о чудо! Она действительно живаем оба адреса возврата (в приведенном ниже лис-
продолжает свою работу (незлобное ругательство на тинге они выделены рамкой):
ошибку последней операции – не в счет!). Несохранен-
ные данные спасены! Ëèñòèíã 9. Ñîäåðæèìîå ñòåêà ïîñëå ðàñêðóòêè
0012F488 0012FA64 0012FA64 004012FF ↵
Раскрутка стека <-- 0040136F:ret 8 ïåðâûé àäðåñ âîçâðàòà
0012F494 00000000 00000064 00403458 ↵
Далеко не во всех случаях принудительный выход из фун- <-- 00401328:pop esi
кции оказывается возможным. Ряд критических сбоев 0012F4A0 FFFFFFFF 0012F4C4 6C291CEA
0012F4AC 00000019 00000000 6C32FAF0
затрагивает не одну, а сразу несколько вложенных функ- 0012F4B8 0012F4C0 0012FA64 01100059
ций, и тогда для реанимации программы мы должны со- 0012F4C4 00320774 002F5788 00000000
0012F4D0 00320701 77E16383 004C1E20
вершить глубокий откат назад, продолжив выполнение 0012F4DC 00320774 002F5788 00000000
программы с того места, где бы ее работоспособности 0012F4E8 000003E8 0012FA64 004F8CD8
0012F4F4 0012F4DC 002F5788 0012F560
ничто не угрожало. Точная глубина отката подбирается 0012F500 77E61D49 6C2923D8 00403458 ↵
экспериментально и обычно составляет три-пять ступе- <-- 0040132C:ret;
0012F50C 00000111 0012F540 6C2922AE ↵
ней. Имейте в виду, что если вложенные функции моди- <--6C29237E:pop ebx/pop ebp/ret 1Ch
фицируют глобальные данные (например, данные «кучи»), 0012F518 0012FA64 000003E8 00000000
0012F518 0012FA64 000003E8 00000000
то попытка отката может привести к полному краху отла- 0012F524 004012F0 00000000 0000000C
живаемой программы, поэтому требуемую глубину отка- 0012F530 00000000 00000000 0012FA64
0012F53C 000003E8 0012F564 6C298FC5
та желательно угадать с первого раза, придерживаясь пра- 0012F548 000003E8 00000000 00000000
вила «лучше перебрать, чем недобрать». С другой сторо- 0012F554 00000000 000003E8 0012FA64

14
программирование
Ячейки памяти, лежащие выше адресов возврата, Ëèñòèíã 13. Ñîäåðæèìîå ðåãèñòðîâ, ðàíåå ñîõðàíåííûõ â ñòåêå
представляют собой значения регистров, сохраненные в âìåñòå ñ àäðåñîì âîçâðàòà
стеке при входе в функцию и восстанавливаемые при ее 0012F500 77E61D49 6C2923D8 00403458 <-- 6C29237D:pop esi
завершении. Ячейки памяти, лежащие ниже адресов воз- 0012F50C 00000111 0012F540 6C2922AE <-- 6C29237E:pop ebx ↵
/pop ebp/ret 1Ch
врата, оккупированы аргументами функции (если, конеч-
но, у функции есть аргументы), или же принадлежат ло- Как вариант можно переместить регистр EIP на адрес
кальным переменным материнской функции, если дочер- 6C29237Dh, а регистр ESP на адрес 12F508h, после чего
няя функция не принимает никаких аргументов. нажать на <F5> для продолжения выполнения програм-
Возвращаясь к листингу 5, отметим, что два двойных мы. И этот прием действительно срабатывает! Причем
слова, лежащие на верхушке стека, соответствуют ма- реанимированная программа уже не ругается на ошибку
шинным командам POP EDI и POP ESI, а следующий за последней операции (как это было при восстановлении
ними адрес – 4012FFh – это тот самый адрес, управление путем принудительного выхода из функции), а просто ее
которому передается командой 40136Fh:RET 8. Для про- не выполняет. Красота!
должения раскрутки стека мы должны дизассемблировать
код по этому адресу: Передача управления на функцию
обработки сообщений
Ëèñòèíã 10. Äèçàññåìáëåðíûé ëèñòèíã ïðàìàòåðèíñêîé ôóíêöèè Двум предыдущим способам «реанимации» приложений
(«áàáóøêè»)
присущи серьезные ограничения и недостатки. При тя-
004012FA call 00401350 желых разрушениях стека, вызванных атаками типа
004012FF cmp eax,0FFh
00401302 je 0040132D buffer overfull или же просто алгоритмическими ошибка-
00401304 push eax ми, содержимое важнейших регистров процессора ока-
00401305 lea eax,[esp+8]
00401309 push 405054h жется искажено, и мы уже не сможем ни совершить откат
0040130E push eax (стек утерян), ни выйти из текущей функции (EIP смотрит
0040130F call dword ptr ds:[4033B4h]
00401315 add esp,0Ch в космос). В консольных приложениях в такой ситуации
00401318 lea ecx,[esp+4] действительно очень мало что можно сделать… Вот GUI –
0040131C push 0
0040131E push 0 другое дело! Концепция событийно ориентированной ар-
00401320 push ecx хитектуры наделяет всякое оконное приложение опреде-
00401321 mov ecx,esi
00401323 call 00401BC4 ленными серверными функциями. Даже если текущий
00401328 pop esi контекст выполнения необратимо утерян, мы можем пе-
00401329 add esp,64h
0040132C ret ; SS:[ESP] = 6C2923D8 редать управление на цикл извлечения и диспетчериза-
ции сообщений, заставляя программу продолжить обра-
Прокручивая экран вниз, мы замечаем инструкцию ботку действий пользователя.
ADD ESP, 64, закрывающую текущий кадр стека. Еще Классический цикл обработки сообщений выглядит так:
восемь байт снимает инструкция 40136Fh:RET 8 и четы-
ре байта оттягивает на себя 401328:POP ESI. Таким об- Ëèñòèíã 14. Êëàññè÷åñêèé öèêë îáðàáîòêè ñîîáùåíèé
разом, позиция адреса возврата в стеке равна: while (GetMessage(&msg, NULL, 0, 0))
current_ESP + 64h + 8 + 4 == 70h. Спускаемся на 70h байт {
TranslateMessage(&msg);
ниже и видим: DispatchMessage(&msg);
}
Ëèñòèíã 11. Àäðåñ âîçâðàòà èç ïðàìàòåðèíñêîé ôóíêöèè
0012F500 77E61D49 6C2923D8 00403458 <-- 00401328:POP ESI/ret; Все, что нам нужно, – это передать управление на цикл
while, даже не заботясь о настройке кадра стека, поскольку
Первое двойное слово – это значение регистра ESI, оптимизированные программы (а таковых большинство)
который нам предстоит вручную восстановить; второе – адресуют свои локальные переменные не через EBP, а
адрес возврата из функции. Нажатием <Ctrl-G>, непосредственно через сам ESP. Конечно, при обраще-
«0x6C2923D8» мы продолжаем раскручивать стек: нии к переменной msg, функция угробит содержимое сте-
ка, лежащее ниже его вершины, но это уже не важно.
Ëèñòèíã 12. Äèçàññåìáëåðíûé ëèñòèíã ïðàïðàìàòåðèíñêîé ôóíêöèè Правда, при выходе из приложения оно упадет окон-
6C2923D8 jmp 6C29237B чательно (ведь вместо адреса возврата из функции об-
… работки сообщений машинная команда RET обнаружит
6C29237B mov eax,ebx
6C29237D pop esi на вершине стека неизвестно что), но это произойдет пос-
6C29237E pop ebx ле сохранения всех данных, и потому никакой угрозы не
6C29237F pop ebp
6C292380 ret 1Ch несет. Исключение составляют приложения, «забываю-
щие» закрыть все открытые файлы и перекладывающие
Вот мы и добрались до восстановления регистров! эту работу на плечи функции ExitProcess. Что ж! Можно
Сместившись на одно двойное слово вправо (оно только так подправить адрес возврата, чтобы он указывал на
что было вытолкнуто из стека командой RET), переходим ExitProcess!
в окно «Registers» и восстанавливаем регистры ESI, EBX, Давайте создадим простейшее Windows-приложение
EBP, извлекая сохраненные значения из стека: и поэкспериментируем с ним. Запустив Microsoft Visual

№12(13), декабрь 2003 15


программирование
Studio выберем «New → Project → Win32 Application» и .text:00401077 ; íà÷àëî öèêëà îáðàáîòêè ñîîáùåíèé
там – «Typical Hello, World application». Добавим новый .text:00401077
.text:00401077 mov eax, [esp+2Ch+Msg.hwnd]
пункт меню, а в нем: char *p; *p = 0; и откомпилируем этот .text:0040107B lea edx, [esp+2Ch+Msg]
проект с отладочной информацией. .text:0040107B ; EDX óêàçûâàåò íà îáëàñòü ïàìÿòè,
; èñïîëüçóåìóþ äëÿ ïåðåäà÷è ñîîáùåíèé
Роняем приложение на пол и, запустив отладчик, под- .text:0040107B
гоняем мышь к первой строке цикла обработки сообще- .text:0040107F push edx ; lpMsg
.text:00401080 push esi ; hAccTable
ний и в появившемся контекстном меню находим пункт .text:00401081 push eax ; hWnd
«Set Next Statement». Нажимаем <F5> для возобновления .text:00401082 call ebx ; TranslateAcceleratorA
.text:00401082 ; âûçûâàåì ôóíêöèþ TranslateAcceleratorA
работы программы и… она действительно возобновляет .text:00401082
свою работу! .text:00401084 test eax, eax
.text:00401086 jnz short loc_40109A
А теперь откомпилируем наш проект в чистовом вари- .text:00401086 ; ïðîâåðêà íà íàëè÷èå â î÷åðåäè
анте (т.е. без отладочной информации) и попробуем реа- ; íåîáðàáîòàííûõ ñîîáùåíèé
.text:00401086
нимировать приложение в голом машинном коде. Пользу- .text:00401088 lea ecx, [esp+2Ch+Msg]
ясь тем обстоятельством, что Windows – это действитель- .text:0040108C push ecx ; lpMsg
.text:0040108D call ebp ; TranslateMessage
но многозадачная среда, в которой крушение одного про- .text:0040108D ; âûçûâàåì ôóíêöèþ TranslateMessage, åñëè
цесса не мешает работе всех остальных, запустим свой ; åñòü ÷òî òðàíñëèðîâàòü
.text:0040108D
любимый дизассемблер (например IDA PRO) и проанали- .text:0040108F lea edx, [esp+2Ch+Msg]
зируем таблицу импорта отлаживаемой программы (во- .text:00401093 push edx ; lpMsg
.text:00401094 call ds:DispatchMessageA
обще-то это может сделать и бесплатно распространяе- .text:00401094 ; äèñïåò÷åðèçóåì ñîîáùåíèå
мый dumpbin, но его отчет не так нагляден). .text:0040109A
.text:0040109A loc_40109A: ; CODE XREF: _WinMain@16+86?j
Целью нашего поиска будут функции TranslateMessage/ .text:0040109A push 0 ; wMsgFilterMax
DispatchMessage и перекрестные ссылки, ведущие к цик- .text:0040109C push 0 ; wMsgFilterMin
.text:0040109E lea eax, [esp+34h+Msg]
лу выборки сообщений. .text:004010A2 push 0 ; hWnd
.text:004010A4 push eax ; lpMsg
.text:004010A5 call edi ; GetMessageA
Ëèñòèíã 15. Ïîèñê ôóíêöèé TranslateMessage/DispatchMessage .text:004010A5 ; ÷èòàåì î÷åðåäíîå ñîîáùåíèå èç î÷åðåäè
â òàáëèöå èìïîðòà .text:004010A5
.text:004010A7 test eax, eax
.idata:004040E0 ; BOOL __stdcall ↵ .text:004010A9 jnz short loc_401077
TranslateMessage(const MSG *lpMsg) .text:004010A9 ; âðàùàåì öèêë îáðàáîòêè ñîîáùåíèé
.idata:004040E0 extrn TranslateMessage:dword ; DATA ↵ .text:004010A9
XREF: _WinMain@16+71?r .text:004010AB pop ebp
.idata:004040E0 ; _WinMain@16+8D?r .text:004010AC pop ebx
.idata:004040E4 ; LONG __stdcall ↵ .text:004010AD
DispatchMessageA(const MSG *lpMsg) .text:004010AD loc_4010AD: ; CODE XREF: _WinMain@16+67?j
.idata:004040E4 extrn DispatchMessageA:dword ; DATA ↵ .text:004010AD mov eax, [esp+24h+Msg.wParam]
XREF: _WinMain@16+94?r .text:004010B1 pop edi
.idata:004040E8 .text:004010B2 pop esi
.text:004010B3 add esp, 1Ch
.text:004010B6 retn 10h
С функцией DispatchMessage связана всего лишь одна .text:004010B6 _WinMain@16 endp
перекрестная ссылка, со всей очевидностью ведущая к
искомому циклу обработки сообщений, дизассемблерный Мы видим, что цикл обработки сообщений начинается
код которого выглядит так: с адреса 401050h и именно на этот адрес следует пере-
дать управление, чтобы возобновить работу упавшей про-
Ëèñòèíã 16. Äèçàññåìáëåðíûé ëèñòèíã ôóíêöèè îáðàáîòêè ñîîáùåíèé граммы. Пробуем сделать это и… программа работает!
.text:00401050 mov edi, ds:GetMessageA Разумеется, настоящее приложение оживить намного
.text:00401050 ; ïåðâûé âûçîâ GetMessageA (ýòî åùå сложнее, поскольку цикл обработки сообщений в нем рас-
; íå öèêë, ýòî òîëüêî åãî ïðåääâåðüå)
.text:00401050 средоточен по большому количеству функций, отожде-
.text:00401056 push 0 ; wMsgFilterMax ствить которые при беглом дизассемблировании невоз-
.text:00401058 push 0 ; wMsgFilterMin
.text:0040105A lea ecx, [esp+2Ch+Msg] можно. Тем не менее, приложения, построенные на осно-
.text:0040105A ; ECX óêàçûâàåò íà îáëàñòü ïàìÿòè, ÷åðåç ве общедоступных библиотек (например MFC, OVL) об-
.text:0040105A ; êîòîðóþ GetMessageA ñòàíåò âîçâðàùàòü
.text:0040105A ; ñîîáùåíèå. Òåêóùåå çíà÷åíèå ESP ìîæåò áûòü ладают вполне предсказуемой архитектурой, и реаними-
.text:0040105A ; ëþáûì, ãëàâíîå, ÷òîáû îíî óêàçûâàëî íà ровать их вполне возможно.
.text:0040105A ; äåéñòâèòåëüíóþ îáëàñòü ïàìÿòè (ñì. êàðòó
; ïàìÿòè, åñëè çíà÷åíèå ESP îêàçàëîñü èñêàæåíî Рассмотрим, как устроен цикл обработки сообщений в
; íàñòîëüêî, ÷òî âûâåëî åãî â «êîñìîñ») MFC. Большую часть своего времени исполнения MFC-при-
.text:0040105A
.text:0040105E push 0 ; hWnd ложения проводят внутри функции CWinThread::Run(void),
.text:00401060 push ecx ; lpMsg которая периодически опрашивает очередь на предмет
.text:00401061 mov esi, eax
.text:00401063 call edi ; GetMessageA поступления свежих сообщений и рассылает их соответ-
.text:0040106 ; âûçûâàåì GetMessageA ствующим обработчикам. Если один из обработчиков
.text:00401063
.text:00401065 test eax, eax споткнулся и довел систему до критической ошибки, вы-
.text:00401067 jz short loc_4010AD полнение программы может быть продолжено в функции
.text:00401067 ; ïðîâåðêà íà íàëè÷èå íåîáðàáîòàííûõ
; ñîîáùåíèé â î÷åðåäè Run. В этом-то и заключается ее главная прелесть!
.text:00401067 Функция не имеет явных аргументов, но принимает

.text:00401077 loc_401077: ;CODE XREF: _WinMain@16+A9?j скрытый аргумент this, указывающей на экземпляр клас-

16
программирование
са CWinThread или производный от него класс, без кото- наименее значимый байт располагается по меньшему
рого функция просто не сможет работать. К счастью, таб- адресу, т.е. все числа записываются задом наперед (к
лицы виртуальных методов класса CWinThread содержат сожалению, отладчик Microsoft Visual Studio Debugger не
достаточно количество «родимых пятен», чтобы указатель поддерживает операцию поиска в памяти, и нам прихо-
this можно было воссоздать вручную. дится действовать обходным путем – копировать содер-
Загрузим функцию Run в дизассемблер и отметим все жимое дампа в буфер обмена, вставлять его в текстовой
обращения к таблице виртуальных методов, адресуемой файл и, нажав <F7>, искать адреса уже там).
через регистр ECX. Долго ли, коротко ли, но интересующие нас указатели
обнаруживаются по адресам 403044h/40304Сh (естествен-
Ëèñòèíã 17. Äèçàññåìáëåðíûé ëèñòèíã ôóíêöèè Run (ôðàãìåíò) но, у вас эти адреса могут быть и другими). Причем обра-
.text:6C29919D n2k_Trasnlate_main: тите внимание: расстояние между указателями в точнос-
; CODE XREF: MFC42_5715+1F?j ти равно расстоянию между указателями на [EAX + 64h]
.text:6C29919D ; MFC42_5715+67?j ...
.text:6C29919D mov eax, [esi] и [EAX + 6Ch], а очередность их размещения в памяти
.text:6C29919F mov ecx, esi обратна порядку объявления виртуальных методов. Это
.text:6C2991A1 call dword ptr [eax+64h]
; CWinThread::PumpMessage(void) хороший признак, и мы, скорее всего, находимся на пра-
.text:6C2991A4 test eax, eax вильном пути:
.text:6C2991A6 jz short loc_6C2991DA
.text:6C2991A8 mov eax, [esi]
.text:6C2991AA lea ebp, [esi+34h] Ëèñòèíã 18. Àäðåñà ôóíêöèé IsIdleMessage/PumpMessage, íàé-
.text:6C2991AD push ebp äåííûå â ñåêöèè äàííûõ
.text:6C2991AE mov ecx, esi
.text:6C2991B0 call dword ptr [eax+6Ch] ; IsIdleMessage/PumpMessage
; CWinThread::IsIdleMessage(MSG*) 00403044 6C2911D4 6C292583 6C291194
.text:6C2991B3 test eax, eax 00403050 6C2913D0 6C299144 6C297129
.text:6C2991B5 jz short loc_6C2991BE 0040305C 6C297129 6C297129 6C291A47
.text:6C2991B7 push 1
.text:6C2991B9 mov [esp+14h], ebx
.text:6C2991BD pop edi Указатели, указывающие на адреса 403048h/40304Ch,
.text:6C2991BE
.text:6C2991BE loc_6C2991BE: очевидно, и будут кандидатами в члены искомой табли-
; CODE XREF: MFC42_5715+51?j цы виртуальных методов класса CWinThread. Расширив
.text:6C2991BE push ebx ; wRemoveMsg
.text:6C2991BF push ebx ; wMsgFilterMax сферу поиска всем адресным пространством отлаживае-
.text:6C2991C0 push ebx ; wMsgFilterMin мого процесса, мы обнаруживаем два следующих пере-
.text:6C2991C1 push ebx ; hWnd
.text:6C2991C2 push ebp ; lpMsg ходника:
.text:6C2991C3 call ds:PeekMessageA
.text:6C2991C9 test eax, eax
.text:6C2991CB jnz short n2k_Trasnlate_main Ëèñòèíã 19. Ïåðåõîäíèêè ê ôóíêöèÿì IsIdleMessage/PumpMessage,
.text:6C2991CD íàéäåííûå òàì æå
00401A20 jmp dword ptr ds:[403044h] ; IsIdleMessage
00401A26 jmp dword ptr ds:[403048h] ;
Таким образом, функция Run ожидает получить ука- 00401A2C jmp dword ptr ds:[40304Ch] ; PumpMessage
затель на двойное слово, указывающее на таблицу вир-
туальных методов, 0x19 и 0x1B элементы которой пред- Ага, уже теплее! Мы нашли не сами виртуальные фун-
ставляют собой функции PumpMessage и IsIdleMessage кции, но переходники к ним. Раскручивая этот запутан-
соответственно (или переходники к ним). Адреса импор- ный клубок, попробуем отыскать ссылки на 401A26h/
тируемых функций, если только динамическая библиоте- 401A2Ch, которые передают управление на приведенный
ка не была перемещена, можно узнать в том же дизас- выше код:
семблере; в противном случае, следует отталкиваться от
базового адреса модуля, отображаемого отладчиком по Ëèñòèíã 20. Âèðòóàëüíàÿ òàáëèöà êëàññà CWinThread
команде «Modules». При условии, что эти две функции не 00403490 00401A9E 00401040 004015F0
были перекрыты программистом, поиск нужной нам вир- <-- 0x0, 0x1, 0x2 ýëåìåíòû
0040349C 00401390 004015F0 00401A98
туальной таблицы не составит никакого труда. <-- 0x3, 0x4, 0x5 ýëåìåíòû
По непонятным причинам библиотека MFC42.DLL не 004034A8 00401A92 00401A8C 00401A86
<-- 0x6, 0x7, 0x8 ýëåìåíòû
экспортирует символьных имен функций, и эту информа- 004034B4 00401A80 00401A7A 00401A74
цию нам приходится добывать самостоятельно. Обрабо- <-- 0x9, 0xA, 0xB ýëåìåíòû
004034C0 00401010 00401A6E 00401A68
тав библиотеку MFC42.LIB утилитой dumpbin, запущен- <-- 0xC, 0xD, 0xE ýëåìåíòû
ной с ключом «/ARCH», мы определим ординалы обеих 004034CC 00401A62 00401A5C 00401A56
<-- 0xF, 0x10, 0x11 ýëåìåíòû
функций (ординал PumpMessage – 5307, а IsIdleMessage – 004034D8 00401A50 00401A4A 00401A44
4079). Остается найти эти значения в экспорте библиоте- <-- 0x12, 0x13, 0x14 ýëåìåíòû
004034E4 00401A3E 004010B0 00401A38
ки MFC42.DLL (dumpbin /EXPORTS mfc42.dll > mfc42.txt), <-- 0x15, 0x16, 0x17 ýëåìåíòû
из чего мы узнаем что адрес функции PumpMessage: 004034F0 00401A32 00401A2C 00401A26
<-- 0x18, 0x19, 0x1A ýëåìåíòû (PumpMessage)
6C291194h, а IsIdleMessage – 6С292583h. 004034FC 00401A20 00401A1A 00401A14
Теперь мы должны найти указатели на функции <-- 0x1B, 0x1C, 0x1D ýëåìåíòû (IsIdleMessage)
PumpMessage/IsIdleMessage в памяти, а точнее – в сек-
ции данных, базовый адрес которой содержится в заго- Даже неопытный исследователь программ распозна-
ловке PE-файла, только помните, что в x86-процессорах ет в этой структуре данных таблицу виртуальных функций.

№12(13), декабрь 2003 17


программирование
Указатели на переходники к PumpMessage/IsIdleMessage лиза, увы, не добавляет им уверенности в тех ситуациях,
разделяются ровно одним элементом, как того и требуют когда неумолимая энтропия оставляет их со своими про-
условия задачи. Предположим, что это виртуальная таб- блемами один на один. Но довольно лирики. Переходим к
лица, которая нам и нужна. Для проверки этого предпо- делу, расписывая каждое действие по шагам.
ложения отсчитаем 0x19 элементов верх от 4034F4h и Первым делом необходимо войти в конфигурацию
попытаемся найти указатель, ссылающийся на ее нача- системы («Панель управления» → «Система»/«Control
ло. Если повезет и он окажется экземпляром класса Panel» → «System») и убедиться, что настройки дампа
CwinThread, тогда программа сможет корректно продол- соответствуют предъявляемым к ним требованиям
жить свою работу: («Дополнительно» → «Загрузка и восстановление» →
«Отказ системы»/«Startup/Shutdown» → «Recovery» в
Ëèñòèíã 21. Ýêçåìïëÿð êëàññà CWinThread, âðó÷íóþ íàéäåííûé Windows 2000 RUS и Windows NT 4.0 ENG соответствен-
íàìè â ïàìÿòè
но). Операционная система Windows 2000 поддержива-
004050B8 00403490 00000001 00000000 ет три разновидности дампов памяти: малый дамп па-
004050C4 00000000 00000000 00000001
мяти (small memory dump), дамп памяти ядра (kernel
Действительно, в памяти обнаруживается нечто похо- memory dump) и полный дамп памяти (complete dump
жее. Записываем в регистр ECX значение 4050B8h, нахо- memory). Для изменения настроек дампа вы должны
дим в памяти функцию Run (как уже говорилось, если иметь права администратора.
только она не была перекрыта, ее адрес – 6C299164h – Малый дамп памяти занимает всего лишь 64 Кб (а
известен). Нажимаем <Ctrl-G>, затем «0x6C299164», и в отнюдь не 2 Мб, как утверждает контекстная помощь) и
контекстном меню, вызванном правой клавишей мыши, включает в себя:
выбираем «Set Next Statement». Программа, отделавшись  копию голубого экрана смерти;
легким испугом, продолжает свое исполнение, ну а мы на  перечень загруженных драйверов;
радостях идем пить пиво (кофе, квас, чай – по вкусу).  контекст обрушившегося процесса со всеми его пото-
Аналогичным путем можно вернуть к жизни и завис- ками;
шие приложения, потерявшие нить управления и не реа-  первые 16 Кб содержимого ядерного стека обрушив-
гирующие ни на мышь, ни на клавиатуру. шегося потока.

Разочаровывающие малоинформативные сведения!


Как подключить дамп памяти Непосредственный анализ дампа дает нам лишь адрес
…в отделе программ весь пол был усеян дырочками от перфокарт возникновения ошибки и имя драйвера, к которому этот
и какие-то мужики ползали по раскатанной по полу 20-метровой
распечатке аварийного дампа памяти с целью обнаружения ошибки адрес принадлежит. При условии, что конфигурация сис-
в распределителе памяти ОС-360. К президенту подошел начальник темы не была изменена после возникновения сбоя, мы
отдела и сообщил, что есть надежда сделать это еще к обеду.
Ю.Антонов «Юность Гейтса» можем загрузить отладчик и дизассемблировать подозре-
Дамп памяти (memory dump, также называемый корой [от ваемый драйвер, но это мало что даст. Ведь содержимое
английского core – сердцевина], crash- или аварийным сегмента данных на момент возникновения сбоя нам не-
дампом), сброшенный системой при возникновении кри- известно, более того, мы не можем утверждать, что ви-
тической ошибки – не самое убедительное средство для дим те же самые машинные команды, что вызвали сбой.
выявления причин катастрофы, но ничего другого в ру- Поэтому малый дамп памяти полезен лишь тем админис-
ках администратора зачастую просто не бывает. После- траторам, которым достаточно одного лишь имени неста-
дний вздох операционной системы, похожий на дурно пах- бильного драйвера. Как показывает практика, в подавля-
нущую навозную кучу, из которой высовывается чей-то ющем большинстве случаев этой информации оказыва-
наполовину разложившийся труп, мгновенным снимком ется вполне достаточно. Разработчикам драйвера отсы-
запечатленный в момент неустранимого сбоя, – вот что лается гневный бан-рапорт (вместе с дампом!), а сам драй-
такое дамп памяти! Копание в нем вряд ли доставит вам вер тем временем заменяется другим – более новым и
удовольствие. Не исключено, что истинного виновника надежным. По умолчанию малый дамп памяти записыва-
краха системы вообще не удастся найти. Допустим, не- ется в директорию %SystemRoot%\Minidump, где ему при-
кий некорректно работающий драйвер вторгся в область сваивается имя «Mini», дата записи дампа и порядковый
памяти, принадлежащую другому драйверу, и наглым об- номер сбоя на данный день. Например «Mini110701-
разом затер критические структуры данных, сделав из 69.dmp» – 69 дамп системы от 07 ноября 2001 года (не
чисел винегрет. К тому моменту, когда драйвер-жертва пугайтесь! это просто я отлаживал драйвера).
пойдет вразнос, драйвер-хищник может быть вообще Дамп памяти ядра содержит намного более полную
выгружен из системы, и определить его причастность к информацию о сбое и включает в себя всю память, выде-
крушению системы по одному лишь дампу практически ленную ядром и его компонентами (драйверами, уровнем
нереально. абстракции от оборудования и т. д.), а также копию экра-
Тем не менее, полностью игнорировать факт существо- на смерти. Размер дампа памяти ядра зависит от количе-
вания дампа, право же, не стоит. В конце концов, до воз- ства установленных драйверов и варьируется от систе-
никновения интерактивных отладчиков ошибки в програм- мы к системе. Контекстная помощь утверждает, что эта
мах приходилось искать именно так. Избалованность со- величина составляет от 50 до 800 Мб. Ну, на счет 800 Мб
временных программистов визуальными средствами ана- авторы явно загнули, и объем в 50-100 Мб выглядит бо-

18
программирование
лее вероятным (техническая документация на систему со-  Одна или несколько книжек, описывающих архитекту-
общает, что ориентировочный размер дампа ядра состав- ру ядра системы. Очень хороша в этом смысле «Внут-
ляет треть объема физической оперативной памяти, ус- реннее устройство Windows 2000» Марка Руссинови-
тановленной на системе). Это наилучший компромисс ча и Дэвида Соломона, интересная как системным про-
между накладными расходами на дисковое пространство, граммистам, так и администраторам.
скоростью сброса дампа и информативностью последне-
го. Весь джентльменский минимум информации в вашем Итак, установив DDK на свой компьютер и завершив
распоряжении. Практически все типовые ошибки драйве- все приложения, запускаем драйвер-убийцу и… под скри-
ров и прочих ядерных компонентов могут быть локализо- пящий звук записывающегося дампа, система немедлен-
ваны с точностью до байта, включая и те, что вызваны фи- но выбрасывает голубой экран смерти, кратко информи-
зическим сбоем аппаратуры (правда, для этого вы должны рующий нас о причинах сбоя (см. рис. 5).
иметь некоторый патологоанатомический опыт исследова-
ния трупных дампов системы). По умолчанию дамп памяти
ядра записывается в файл %SystemRoot%\Memory.dmp, за-
тирая или не затирая (в зависимости от текущих настро-
ек «Системы») предыдущий дамп.
Ðèñóíîê 5. Ãîëóáîé ýêðàí ñìåðòè (BSOD – Blue Screen Of Death),
Полный дамп памяти включает в себя все содержи- ñâèäåòåëüñòâóþùèé î âîçíèêíîâåíèè íåóñòðàíèìîãî ñáîÿ ñèñòåìû
мое физической памяти компьютера, занятое как приклад- ñ êðàòêîé èíôîðìàöèåé î íåì
ными, так и ядерными компонентами. Полный дамп памя- Для большинства администраторов голубой экран
ти оказывается особенно полезным при отладке ASPI/SPTI смерти означает лишь одно – системе поплохело настоль-
приложений, которые в силу своей специфики могут уро- ко, что она предпочла смерть позору неустойчивого фун-
нить ядро даже с прикладного уровня. Несмотря на доволь- кционирования. Что же до таинственных письмен – они
но большой размер, равный размеру оперативной памяти, остаются сплошной загадкой. Но только не для настоя-
полный дамп остается наиболее любимым дампом всех щих профессионалов!
системных программистов (системные же администрато- Мы начнем с левого верхнего угла экрана и, зигзага-
ры в своей массе предпочитают малый дамп). Это не пока- ми спускаясь вниз, трассируем все надписи по порядку.
жется удивительным, если вспомнить, что объемы жест-  «*** STOP:» буквально означает «останов [системы]» и
ких дисков давно перевалили за отметку 100 Гб, а оплата не несет в себе никакой дополнительной информации;
труда системных программистов за последние несколько  «0x0000001E» представляет собой Bug Check-код, со-
лет даже несколько возросла. Лучше иметь невостребо- держащий категорию сбоя. Расшифровку Bug Check-
ванный полный дамп под рукой, чем кусать локти при его кодов можно найти в DDK. В данном случае это 0x1E –
отсутствии. По умолчанию полный дамп памяти записыва- KMODE_EXEPTION_NOT_HALTED, о чем и свидетель-
ется в файл %SystemRoot%\Memory.dmp, затирая или не ствует символьное имя, расположенное строкой ниже.
затирая (в зависимости от текущих настроек «Системы») Краткое объяснение некоторых, наиболее популярных
предыдущий дамп. Bug Check-кодов приведено в таблице 1. Полноту фир-
Выбрав предпочтительный тип дампа, давайте совер- менной документации она, разумеется, не заменяет,
шим учебный урон системы, отрабатывая методику его но некоторое представление о целесообразности ска-
анализа в полевых условиях. Для этого нам понадобится: чивания 70 Мб DDK все-таки дает;
 Комплект разработчика драйверов (Driver Development  арабская вязь в круглых скобках – это четыре Bug
Kit или сокращенно DDK), бесплатно распространяе- Check-параметра, физический смысл которых зави-
мый фирмой Microsoft и содержащий в себе подроб- сит от конкретного Bug Check-кода и вне его кон-
ную техническую документацию по ядру системы; не- текста теряет всякий смысл; применительно к
сколько компиляторов Си/Си++ и ассемблера, а так- KMODE_EXEPTION_NOT_HALTED – первый Bug Check-
же достаточно продвинутые средства анализа дампа параметр содержит номер возбужденного исключения.
памяти. Судя по таблице 1, это – STATUS_ACCESS_VIOLATION –
 Драйвер W2K_KILL.SYS или любой другой драйвер- доступ к запрещенному адресу памяти – и четвертый
убийца операционной системы, например BDOS.EXE от Bug Check-параметр указывает, какой именно. В дан-
Марка Русиновича, позволяющий получить дамп в лю- ном случае он равен нулю, следовательно, некоторая
бое удобное для нас время, не дожидаясь возникнове- машинная инструкция попыталась совершить обраще-
ния критической ошибки (бесплатную копию програм- ние по null-pointer соответствующему инициализиро-
мы можно скачать с адреса http://www.sysinternals.com). ванному указателю, ссылающемуся на невыделенный
 Файлы символьных идентификаторов (symbol files), не- регион памяти. Ее адрес содержится во втором Bug
обходимые отладчикам ядра для его нормального функ- Check-параметре. Третий Bug Check-параметр в дан-
ционирования и делающие дизассемблерный код более ном конкретном случае не определен;
наглядным. Файлы символьных идентификаторов входят  «*** Address 0xBE80B00» – это и есть тот адрес, по ко-
в состав «зеленого» набора MSDN, но, в принципе, без торому произошел сбой. В данном случае он иденти-
них можно и обойтись, однако переменная окружения чен второму Bug Check-параметру, однако так бывает
_NT_SYMBOL_PATH по любому должна быть определе- далеко не всегда (Bug Check-коды собственно и не под-
на, иначе отладчик i386kd.exe работать не будет. ряжались хранить чьи-либо адреса);

№12(13), декабрь 2003 19


программирование
 «base at 0xBE80A00» – содержит базовый адрес заг-
рузки модуля нарушителя системного порядка, по ко-
торому легко установить паспортные данные самого это-
го модуля (внимание: далеко не во всех случаях пра-
вильное определение базового адреса вообще возмож-
но). Воспользовавшись любым подходящим отладчиком
(например, soft-ice от Нумега или i386kd от Microsoft),
введем команду, распечатывающую перечень загружен-
ных драйверов с их краткими характеристиками (в
i386kd это осуществляется командой «!drivers»). Как
одним из вариантов можно воспользоваться утилитой
drivers.exe, входящей в NTDDK. Но какой бы вы путь ни
избрали, результат будет приблизительно следующим:

Обратите внимание на выделенную жирным цветом


строку с именем «w2k_kill.sys», найденную по ее базо-
вому адресу 0xBE80A00. Это и есть тот самый драй-
вер, который нам нужен! А впрочем, этого можно и не
делать, поскольку имя «неправильного» драйвера и
без того присутствует на голубом экране;
 две нижние строки отражают прогресс сброса дампа
на диск, развлекая администратора чередой быстро
меняющихся циферок на это время.
Òàáëèöà 1.

Восстановление системы
после критического сбоя
Неестественное, почти половое влечение к кнопке F8 появилось
в Кролике совершенно не внезапно.
Щербаков Андрей
«14400 бод и 19200 юзеров, и те же самые все-все-все...»
Операционные системы семейства NT достаточно безбо-
лезненно переносят критические сбои, даже если те про-
изошли в самый неудобный момент времени (например,
в период дефрагментации диска). Отказоустойчивый
драйвер файловой системы все сделает сам (хотя запус-
тить ChkDsk все же не помешает).
Если был выбран «полный дамп памяти» или «дамп
памяти ядра», то при следующей успешной загрузке сис-
темы жесткий диск будет долго молотить головкой, даже
если к нему и не происходит никаких обращений. Не пу-
гайтесь! Просто Windows перемещает дамп из виртуаль-
ной памяти на место его постоянного проживания. Запус-
тив «Диспетчер Задач», вы увидите новый процесс в спис-
ке – SaveDump.exe, – вот он этим и занимается. Необхо-

20
программирование
димость в подобной двухтактной схеме сброса дампа Судя по символьным идентификаторам PspUnhandled
объясняется тем, что в момент возникновения критичес- ExceptionInSystemThread и KeBugCheckEx, мы находимся
кой ошибки работоспособность драйверов файловой си- глубоко в ядре, а точнее – в окрестностях того кода, что
стемы уже не гарантируется, и операционная система не выводит BSOD на экран:
может позволить себе их использовать, ограничиваясь
временным размещением дампа в виртуальной памяти. Ëèñòèíã 22. Ðåçóëüòàò äèçàññåìáëèðîâàíèÿ ïîäêëþ÷åííîãî äàìïà
ïàìÿòè ñ òåêóùåãî àäðåñà
Кстати, если имеющегося объема виртуальной памяти
окажется недостаточно (Дополнительно → Параметры 8045249c 6a01 push 0x1
kd>u
быстродействия → Виртуальная память), сброс дампа _PspUnhandledExceptionInSystemThread@4:
окажется невозможным. 80452484 8B442404 mov eax, dword ptr [esp+4]
80452488 8B00 mov eax, dword ptr [eax]
Если же система от загрузки отказывается, упорно 8045248A FF7018 push dword ptr [eax+18h]
забрасывая вас голубыми экранами смерти, вспомните 8045248D FF7014 push dword ptr [eax+14h]
80452490 FF700C push dword ptr [eax+0Ch]
о существовании клавиши <F8> и выберите пункт «Заг- 80452493 FF30 push dword ptr [eax]
рузка последней удачной конфигурации («Last Known 80452495 6A1E push 1Eh
80452497 E8789AFDFF call _KeBugCheckEx@20
Good Configuration»). Более радикальной мерой являет- 8045249C 6A01 push 1
ся запуск системы в безопасном (safe) режиме с мини- 8045249E 58 pop eax
8045249F C20400 ret 4
мумом загружаемых служб и драйверов. Переустанов-
ка системы – это крайняя мера и без особой нужды к В стеке ничего интересного также не содержится, су-
ней лучше не прибегать. Лучше войдите в «консоль вос- дите сами (просмотр содержимого стека осуществляется
становления» и перетащите файл дампа на другую ма- командной «kb»):
шину для его исследования.
Ëèñòèíã 23. Ñîäåðæèìîå ñòåêà íå äàåò íèêàêèõ íàìåêîâ
íà ïðèðîäó èñòèííîãî âèíîâíèêà
Подключение дампа памяти
Для подключения дампа памяти к отладчику Windows kd> kb
ChildEBP RetAddr Args to Child
Debugger (windbg.exe) в меню «File» выберите пункт f403f71c 8045251c f403f744 8045cc77 f403f74c ↵
«Crash Dump» или воспользуйтесь горячей комбинацией ntoskrnl!PspUnhandledExceptionInSystemThread+0x18
f403fddc 80465b62 80418ada 00000001 00000000 ↵
<Ctrl-D>. В отладчике i386kd.exe для той же цели служит ntoskrnl!PspSystemThreadStartup+0x5e
ключ «–z» командной строки, за которым следует полный 00000000 00000000 00000000 00000000 00000000 ↵
ntoskrnl!KiThreadStartup+0x16
путь к файлу дампа, отделенный от ключа одним или не-
сколькими пробелами, при этом переменная окружения Такой поворот событий ставит нас в тупик. Сколько
_NT_SYMBOL_PATH должна быть определена и содер- бы мы ни дизассемблировали ядро, это ни на йоту не
жать полный путь к файлам символьных идентификато- приблизит нас к источнику критической ошибки. Что ж,
ров, в противном случае отладчик аварийно завершит все вполне логично. Текущий адрес (8045249Сh) лежит
свою работу. Как один из вариантов можно указать к далеко за пределами драйвера-убийцы (0BE80A00h).
командой строке ключ «–y», и тогда экран консоли бу- Хорошо, давайте развернемся и пойдем другим путем.
дет выглядеть так: «i386kd –z C:\WINNT\memory.dmp -y Помните тот адрес, что высвечивал голубой экран смер-
C:\WINNT\Symbols», причем отладчик следует вызывать ти? Не помните – не беда! Если это только не запреще-
из Checked Build Environment/Free Build Environment кон- но настройками, копии всех голубых экранов сохраня-
соли, находящейся в папке Windows 2000 DDK, иначе у ются в Журнале системы. Откроем его («Панель уп-
вас ничего не получится. равления» → »Администрирование» → »Просмотр со-
Хорошая идея – ассоциировать dmp-файлы с отлад- бытий»):
чиком i386kd, запуская их одним ударом «Enter» из FAR.
Впрочем, выбор средства анализа – дело вкуса. Кому- Ëèñòèíã 24. Êîïèÿ ãîëóáîãî ýêðàíà ñìåðòè, ñîõðàíåííàÿ â ñè-
ñòåìíîì æóðíàëå
то нравится KAnalyze, а кому-то достаточно и простень-
кого DumpChk. Выбор аналитических инструментов Êîìïüþòåð áûë ïåðåçàãðóæåí ïîñëå êðèòè÷åñêîé îøèáêè:
0x0000001e (0xc0000005, 0xbe80b000, 0x00000000, 0x00000000).
чрезвычайно велик (один лишь DDK содержит четыре Microsoft Windows 2000 [v15.2195]
из них!), и чтобы хоть как-то определиться с выбором, Êîïèÿ ïàìÿòè ñîõðàíåíà: C:\WINNT\MEMORY.DMP.
мы остановимся на i386kd.exe, также называемом
Kernel Debugger. Отталкиваясь от категории критической ошибки (0x1E),
Как только консоль отладчика появится на экране (а мы без труда сможем определить адрес инструкции-убий-
Kernel Debugger – это консольное приложение, горячо цы – 0xBE80B000 (в приведенном выше листинге он вы-
любимое всеми, кто провел свою молодость за текстовы- делен красным шрифтом). Даем команду «u BE80B000»
ми терминалами), курсор наскоро дизассемблирует теку- для просмотра его содержимого и видим:
щую машинную инструкцию и своим тревожным мерца-
нием затягивает нас в пучину машинного кода. «Ну что, Ëèñòèíã 25. Ðåçóëüòàò äèçàññåìáëèðîâàíèÿ äàìïà ïàìÿòè
ïî àäðåñó, ñîîáùåííîìó ãîëóáûì ýêðàíîì ñìåðòè
глазки строить будем или все-таки дизассемблиро-
вать?» – незлобно ворчим мы, выбивая на клавиатуре kd>u 0xBE80B000
be80b000 a100000000 mov eax,[00000000]
команду «u», заставляющую отладчик продолжить дизас- be80b005 c20800 ret 0x8
семблирование. be80b008 90 nop

№12(13), декабрь 2003 21


программирование
be80b009 90 nop есть адрес машинной команды, породившей это исклю-
be80b00a 90 nop чение. В комбинации же 0F 00 00 00 93 08 легко узнает-
be80b00b 90 nop
be80b00c 90 nop ся номер билда системы, стоит только записать его в
be80b00d 90 nop десятичной нотации.
Ага! Вот это уже больше похоже на истину! Инструк- Для просмотра Bug Check-параметров в более удобо-
ция, на которую указывает курсор (в тексте она выделе- читаемом виде можно воспользоваться следующей коман-
на красным цветом), обращается к ячейке с нулевым ад- дой отладчика: «dd KiBugCheckData»:
ресом, возбуждая тем самым губительное для системы
исключение. Теперь мы точно знаем, какая ветка програм- Ëèñòèíã 27. Bug Check ïàðàìåòðû, îòîáðàæàåìûå â óäîáî÷èòà-
åìîì âèäå
мы вызвала сбой.
Хорошо, а как быть, если копии экрана смерти в на- kd> dd KiBugCheckData
dd KiBugCheckData
шем распоряжении нет? На самом деле, синий экран все- 8047e6c0 0000001e c0000005 be80b000 00000000
гда с нами, надо только знать, где искать! Попробуйте от- 8047e6d0 00000000 00000000 00000001 00000000
8047e6e0 00000000 00000000 00000000 00000000
крыть файл дампа в любом hex-редакторе, и вы обнару- 8047e6f0 00000000 00000000 00000000 00000000
жите следующие строки: 8047e700 00000000 00000000 00000000 00000000
8047e710 00000000 00000000 00000000 00000000
8047e720 00000000 00000000 00000000 00000000
Ëèñòèíã 26. Êîïèÿ ãîëóáîãî ýêðàíà â çàãîëîâêå äàìïà ïðîãðàììû 8047e730 00000000 e0ffffff edffffff 00020000

Другие полезные команды: «!drivers» – выводящая


список драйверов, загруженных на момент сбоя,
С первого же взгляда удается опознать все основ- «!arbiter» – показывающая всех арбитров вместе с диа-
ные Bug Check-параметры: 1E 00 00 00 – это код кате- пазонами арбитража, «!filecache» – отображающая инфор-
гории сбоя 0x1E (на x86 процессорах наименее значи- мацию о кэше файловой системы и PT, «!vm» – отчиты-
мый байт располагается по меньшему адресу, то есть вающаяся об использовании виртуальной памяти и т. д. –
все числа записываются задом наперед); 05 00 00 C0 – всех не перечислишь! (полный перечень команд вы най-
код исключения ACCESS VIOLATION; а 00 B0 80 BE – и дете в руководстве по своему любимому отладчику).

22
программирование
Конечно, в реальной жизни определить истинного ви- зассемблирование в силу своей статической природы,
новника краха системы намного сложнее, поскольку вся- не гарантирует, что управление не перекинулось отку-
кий нормальный драйвер состоит из множества сложно да-то еще, но по крайней мере сужает круг поиска. Во-
взаимодействующих функций, образующих запутанные обще же, о дизассемблировании написано множество
иерархические комплексы, местами пересеченные тунне- хороших книг (и «Фундаментальные основы хакерства»
лями глобальных переменных, превращающих драйвер в Криса Касперски в том числе), поэтому не будем оста-
самый настоящий лабиринт. Приведем только один при- навливаться на этом вопросе, а просто пожелаем всем
мер. Конструкция вида «mov eax, [ebx]», где ebx == 0, ра- читателям удачи.
ботает вполне нормально, послушно возбуждая исклю-
чение, и пытаться поговорить с ней по-мужски – бессмыс-
ленно! Нужно найти тот код, который записывает в EBX
нулевое значение, и сделать это непросто. Можно, конеч-
но, просто прокрутить экран вверх, надеясь, что на дан-
ном участке программный код выполнялся линейно, но
никаких гарантий, что это действительно так, у нас нет,
равно как нет и возможности обратной трассировки
(back trace). Грубо говоря, адрес предшествующей машин-
ной инструкции нам неизвестен, и закладываться на про-
крутку экрана нельзя!
Загрузив подопытный драйвер в любой интеллекту-
Ðèñóíîê 6. Îòëàä÷èê i386kd çà ðàáîòîé. Íåñìîòðÿ íà ñâîþ
альный дизассемблер, автоматически восстанавлива- îòòàëêèâàþùóþ âíåøíîñòü, ýòî ÷ðåçâû÷àéíî ìîùíûé è óäîáíûé â
ющий перекрестные ссылки (например IDA PRO), мы ðàáîòå èíñòðóìåíò, ïîçâîëÿþùèé ïðîâîðà÷èâàòü óìîïîìðà÷è-
òåëüíûå ïàññàæè íàæàòèåì âñåãî ïàðû-òðîéêè êëàâèø (îäíà èç
получим более или менее полное представление о то- êîòîðûõ âûçûâàåò âàø ñîáñòâåííûé ñêðèïò)
пологии управляющих ветвей программы. Конечно, ди-

Ðèñóíîê 7. windbg c çàãðóæåííûì äàìïîì ïàìÿòè. Îáðàòèòå âíèìàíèå: îòëàä÷èê ñàìîñòîÿòåëüíî âûñâå÷èâàåò Bug Check-êîäû, íå
îæèäàÿ, ïîêà ìû îá ýòîì åãî ïîïðîñèì, à ïðè ïîïûòêå äèçàññåìáëèðîâàíèÿ èíñòðóêöèè, âîçáóäèâøåé èñêëþ÷åíèå, íà ýêðàíå âûñêàêè-
âàåò «Module Load: W2K_KILL.SYS», ñîîáùàþùàÿ íàì èìÿ äðàéâåðà-óáèéöû. Âðîäå áû ìåëî÷ü, à êàê ïðèÿòíî!

№12(13), декабрь 2003 23


УНИКАЛЬНЫЕ СОБЫТИЯ
НА КОМПЬЮТЕРНОМ РЫНКЕ
Впервые организованная в 1989 году, выставка Неделя 4. Software Expo – специализированная выставка, ори-
Информационных Технологий «IT Week Russia», изве- ентированная на программные продукты для систем
стная в прошлом как Comtek, за пятнадцать лет своего бухгалтерского и складского учета, комплексного ПО
существования пережила и взлеты и падения. В преды- управления предприятием, систем управления доку-
дущие годы в Неделю Информационных Технологий вхо- ментооборотом, систем распознавания документов,
дила выставка Сomtek, которая состояла из нескольких разработку ПО, защиту информации. В рамках этой
направлений, и конференция E-Business. Развитие выс- выставки будет подготовлен цикл тематических семи-
тавки в течение последних лет привело к необходимос- наров, посвященных актуальным вопросам в области
ти выделить отдельные разделы в самостоятельные вы- разработки экономических программ и систем управ-
ставки. С этого года в Неделю Информационных Техно- ления бизнесом.
логий будут входить пять самостоятельных выставок и 5. Специализированная выставка CAD/CAM/CAE пред-
две конференции. Этот шаг позволил расширить масш- ставляет системы автоматизированного проектиро-
таб выставки, объединяющей все аспекты компьютер- вания. Для большинства российских производителей
ного бизнеса, что, в свою очередь, дает возможность необходимость использования САПР для оптимиза-
привлечь к участию в выставке большее число компа- ции работы предприятия стала очевидной. Особенно
ний, занятых во всех сферах индустрии информацион- ярко это проявляется в таких отраслях, как авиастро-
ных технологий. ение, автомобилестроение, тяжелое машинострое-
Давид Патеишвили, директор выставки, сказал: «В ние, архитектура, строительство, нефтегазовая про-
этом году мы расширили темы, представленные на экс- мышленность.
позиции, которые теперь охватывают все области компь- 6. eLearn Expo – специализированная выставка, на ко-
ютерной индустрии. Это дает превосходную возможность торой будут демонстрироваться новейшие продукты
и участникам, и посетителям выставки принять участие и и технологии в сфере электронного обучения, пред-
ознакомиться сразу с пятью выставками и двумя конфе- назначенные для коллективного и индивидуального
ренциями, проходящими в одно время и в одном месте. пользования. Дистанционное обучение через сети
Это также позволит нам улучшить маркетинговую и рек- Internet и Intranet, получившее широкое распростра-
ламную кампании для каждой из выставок и конферен- нение в развитых странах, становится все более ак-
ций, проходящих в рамках Недели Информационных Тех- туальным и для России.
нологий, с учетом целевой аудитории, специфичной для 7. eBusiness Russia (Электронный бизнес в России) –
каждой из них. Хочется добавить, что некоторые выстав- международная конференция, посвященная вопросам
ки, которые будут проходить в рамках Недели Информа- автоматизации бизнес-процессов, развития электрон-
ционных технологий, не имеют аналогов в России, явля- ной коммерции, подбора ИТ-персонала.
ясь тем самым уникальными».
В рамках Недели Информационных Технологий прой- Выставка IT-week остается ведущей международной
дут следующие выставки и конференции: выставкой информационных технологий в России и стра-
1. Personal Computing Expo – общая, неспециализиро- нах СНГ. Это уникальное место для проведения перего-
ванная выставка, ориентированная на конечных воров с первыми лицами сразу нескольких крупных фирм-
пользователей. В ней представлены производители и поставщиков оборудования и решений. Практически все
дистрибьюторы персональных компьютеров и перифе- крупные западные вендоры присутствуют на выставке не-
рии, компьютерных игр, дистрибьюторы сотовой тех- посредственно или при посредстве своих российских парт-
ники и портативных компьютеров, интернет- и контент- неров.
провайдеры и многие другие. В соответствии с растущими потребностями рынка и
2. Hardware & Peripherals Expo – специализированная увеличением числа участников экспозиция расширила
выставка, на которой представлены: компьютеры, мо- площадь, которая в этом году составит 8000 кв. м. В вы-
ниторы, периферийные устройства, комплектующие, ставках, которые пройдут в течение 4 дней, примут уча-
накопители, коммуникационное оборудование и услу- стие 250 ведущих компаний отрасли из 25 стран мира.
ги, т.е. весь спектр hardware, ориентированного на ве- Ожидается, что число посетителей выставки превысит
дение бизнеса. 75 000 человек, включая руководителей верхнего и сред-
3. Международная конференция eLearning Russia (Ин- него звена, технических специалистов и IT-администра-
формационные технологии в образовании), на которой торов, из более 500 городов России и СНГ.
будут освещены последние достижения образователь- «IT Week 2004», 15-ая Международная Выставка Ин-
ных технологий в школах, вузах, а также рассмотрены формационных Технологий пройдет в «Экспоцентре» на
вопросы дистанционного и бизнес-образования. Красной Пресне в Москве с 26 по 29 апреля 2004 года.

24
администрирование

РЕШЕНИЕ ЗАДАЧ
ИНВЕНТАРИЗАЦИИ В СЕТИ

ИВАН КОРОБКО

26
администрирование
Опытный системный администратор сети, построенной на Òàáëèöà 1
основе Microsoft Windows 2000 и Windows XP, использует
сценарии загрузки для решения различных задач. Одной
из таких задач является инвентаризация аппаратного
обеспечения рабочих станций. Решение данной задачи
актуально в компаниях с большим количеством рабочих
станций.
Решение задачи инвентаризации состоит из двух час-
тей: первая часть – сбор информации с помощью сцена-
рия загрузки, написанном на VBScript и сохранение полу-
ченных данных в файл отчета на сервер в формате XML.
Вторая часть – анализ полученных данных. В качестве
инструмента для анализа данных предлагается создать
сайт на ASP, который позволит объединить в единое це-
лое данные о конфигурации всех рабочих станций, осу-
ществить поиск по заданному критерию; создать файл от-
чета о проделанном поиске.  На третьем этапе, после окончания обработки запро-
Обе части реализованы с помощью стандартных са, поставщик пересылает результаты исходному сце-
средств Microsoft Windows, что делает их надежными в нарию или приложению.
работе, легко внедряемыми.
Способы доступа к объектам WMI
WMI. Основные понятия На практике для получения доступа к объектам WMI
Решение задачи накопления и сохранения информации об пользуются одним из следующих шаблонов:
аппаратной конфигурации рабочей станции обеспечивает-
ся стандартными средствами Microsoft Windows. Одним из Øàáëîí 1. Ïîëó÷åíèå äîñòóïà ê WMI-îáúåêòàì
Âàðèàíò1
таких средств является Microsoft Windows Management
Instrument (WMI). strComputer=””
strNameSpace=””
WMI, разработанный в 1998 году, предоставляет раз- strClass=””
работчикам программного обеспечения и администрато- Set objElements = GetObject( "winmgmts:{ImpersonationLevel= ↵
Impersonate}!//" & strComputer & ”/ ” ↵
рам сети стандартизированные способы наблюдения и & strNameSpace & ”: ” & strClass)
управления как локальными, так и удаленными ресурса- For each Element in objElements
Temp=Element.Value
ми сети. Next
Âàðèàíò2
Теоретические сведения
о внутреннем устройстве WMI strComputer=””
strNameSpace=””
Исполняемым файлом, обеспечивающим функционирова- strClass=””
ние WMI, является файл winmgmt.exe, находящийся в Set objWMIService = GetObject( "winmgmts:{ImpersonationLevel= ↵
Impersonate}!//" & strComputer & ”/ ” ↵
Microsoft Windows 200x каталоге c:\WINNT\system32\wbem\. & strNameSpace)
Механизм работы WMI следующий: Set colItems = objWMIService.InstancesOf(strClass )
For Each objItem in colItems
 На первом этапе происходит подключение к службе Temp=Element.Value
WMI локального или удаленного компьютера: при об- Next
ращении приложения к WMI запросы приложения пе- Âàðèàíò3
ресылаются диспетчеру объектов CIM (Common
strComputer=””
Information Model (CIM) Object Manager). CIMOM обес- strNameSpace=””
печивает первоначальное создание объектов и од- strClass=””
Set objWMIService = GetObject("winmgmts:{ImpersonationLevel= ↵
нообразный способ доступа к управляемым объек- Impersonate }!// " & strComputer & ”/ ” ↵
там. Наиболее простым способом подключения к & strNameSpace)
Set colItems = objWMIService.ExecQuery(“SELECT ïîëå_1, ↵
удаленному компьютеру является вызов функции ïîëå_2, …, ïîëå_n FROM” & strClass )
языка VBScript GetObject(). Подключение к удален- For Each objItem in colItems
Temp=Element.Value
ному компьютеру происходит с помощью протокола Next
winmgmts.
 На втором этапе происходит проверка хранилища В приведенных примерах переменная strComputer со-
объектов. Затем запрос передается поставщику объек- держит имя удаленного компьютера. Если компьютер ло-
та. Поставщик (provider) – это интерфейс между уп- кальный, то вместо имени указывается символ «.»:
равляемым устройством и диспетчером CIMOM. По- strComputer=”.”; Переменная strNameSpace содержит про-
ставщик собирает информацию об устройствах и де- странство имен (см. таблицу 1). strClass – переменная, со-
лает их доступными для диспетчера. держащая название класса. Например, для Win32 Provider,
одним из классов является Win32_BIOS, соответственно,
В состав WMI входит несколько поставщиков: переменная strNameSpace принимает значение Root\Cimv2.

№12(13), декабрь 2003 27


администрирование
Инстркуция {ImpersonationLevel=Impersonate}! заставляет SELECT * FROM strClass
выполнить сценарий с привилегиями пользователя, вызы-
вающего сценарий, а не с привилегиями пользователя, В зависимости от способа доступа к хранилищу раз-
который в настоящий момент работает на рабочей стан- мер пересылаемых данных разный (см. таблицу 2).
ции. Таким образом, осуществляется подстановка, кото- Òàáëèöà 2
рая полезна при выполнении сценариев удаленного досту-
па на таких ОС, как Microsoft Windows 200x. Инструкция
{ImpersonationLevel=Impersonate}! в Microsoft Windows 200x
является выражением подстановки по умолчанию, поэто- Вывод: видно, что выгодно пользоваться шаблоном 3.
му для семейства Windows 200x ее можно опустить. Несмотря на то, что код получится несколько громоздким,
Варианты 1 и 2 шаблона 1 родственны и отличаются уменьшится межсетевой трафик, сократится время рабо-
лишь формой записи. В варианте 3 обращение к классу ты сценария.
строится с помощью SQL-запроса, что позволяет эконо-
мить трафик. Практика использования WMI
В общем случае запрос SQL выглядит следующим об- Данная статья посвящена решению задачи инвентаризации.
разом: Как видно из таблицы 1, для решения этой задачи необхо-
димо использовать Win32 Provider, которому соответствует
SELECT ïîëå_1, ïîëå_2, …, ïîëå_n FROM strClass пространство имен Root\Cimv2. Win32 Provider соответству-
ет массив, состоящий из двух частей: идентификатора и на-
В поле SELECT указываются поля, по которым идет звания ресурса, которые разделены знаком подчеркивания.
выборка. Поля перечисляются через запятую, «пробелы» Идентификатором всегда является «WIN32». С объектной
после запятой обязательны. Если выборка должна идти моделью WMI можно ознакомиться с помощью утилиты WMI
по всем полям, то вместо названий полей указывается Object Browser (см. рис. 1), входящей в пакет WMI Tools. Набор
символ «*». В поле FROM указывается один из ранее пе- утилит WMI Tools можно найти на сайте компании Microsoft:
речисленных поставщиков: http://msdn.microsoft.com/developer/sdk/wmisdk/default.asp.

Ðèñóíîê 1. Îáúåêòíàÿ ìîäåëü WMI

28
администрирование
Таким образом, вариант 3 шаблона 1 примет следую- или обработаны любым другим приложением, предназ-
щий вид: наченным для этой цели. Об одном из таких альтерна-
тивных приложений и пойдет речь во второй части. Сто-
Øàáëîí 1. Îáîáùåííûé âàðèàíò 3 ит лишь добавить, что оно также будет создано с помо-
strComputer=”” щью стандартных средств, предоставляемых компани-
strNameSpace=” Root\Cimv2” ей Microsoft – ASP и HTML.
strClass=”Win32_Value”
Set objWMIService = GetObject( " winmgmts: // " & ↵ Запись файла отчета на диск сервера является зак-
strComputer & ”/ ” & strNameSpace) лючительным этапом, однако формирование файла от-
Set colItems = objWMIService.ExecQuery(“SELECT ïîëå_1, ↵
ïîëå_2, …, ïîëå_n FROM” & strClass ) чета идет на протяжении всего времени выполнения сце-
For Each objItem in colItems нария загрузки. Поэтому начать описание работы сцена-
Temp=Element.Value
Next рия загрузки необходимо с процесса формирования фай-
ла отчета.
Приведем пример получения информации о материн-
ской плате на основе обобщенного варианта 3 рабочей Формирование файла отчета
станции ComputerName (VBScript). Массив данных, в ко- Файл отчета представляет собой текстовый файл в коди-
тором содержится информация о материнской плате, на- ровке Unicode с данными, записанными в формате XML.
зывается WIN32_BIOS: Extensible Markup Language (XML) – это язык разметки до-
кументов, созданный Microsoft, структурированного хра-
Ïðèìåð 1. Ïîëó÷åíèå èíôîðìàöèè î ìàòåðèíñêîé ïëàòå ðàáî÷åé нения информации. Полную спецификацию XML см. на
ñòàíöèè
сайте: http://www.w3c.org/xml
strComputer="." Файл отчета формируется в течение всего времени
strNameSpace="Root\Cimv2"
strClass="Win32_BIOS" выполнения сценария загрузки методом накопления. Оп-
Set objWMIService = GetObject("winmgmts://"&strComputer&"/ ↵ ределяя требуемые для отчета параметры по ходу выпол-
"& strNameSpace)
Set colItems = objWMIService.ExecQuery("SELECT ↵ нения сценария загрузки, происходит пополнение пере-
SMBIOSBIOSVersion FROM " & strClass ) менной. Для этого используют выражение вида:
For Each objItem in colItems
MsgBox objItem.SMBIOSBIOSVersion temp=temp+data, где выражение data строится по шабло-
Next ну <раздел> значение </раздел>. Названия разделов чув-
ствительны к регистру. В подтверждение приведем при-
Необходимо отметить, что переменная objItem.SMBIOS- мер, в котором в раздел «Date» XML-файла помещают
BIOSVersion строковая (см. рис. 1). Если переменная яв- текущую дату и точное время запуска сценария загрузки:
ляется числом, то ее необходимо преобразовать в стро-
ковую переменную с помощью функции Сstr(). Если пе- temp = temp + ”<Date>” + Date() + ”; ” + Time() + ”</Date>”
ременная представляет собой массив, то необходимо про-
читать элементы массива и преобразовать их в строки, В конце сценария загрузки открывается текстовый
если элементы массива не являются строковыми пере- файл, в него записывается содержимое переменной temp:
менными.
Результатом выполнения данной программы будет со- Ïðèìåð 2. Ôîðìèðîâàíèå ôàéëà îò÷åòà
общение вида: Set fso = CreateObject("Scripting.FileSystemObject")
Set f = fso.OpenTextFile(FileName, 2, True)
f.Write "temp"
f.Close

Переменная FileName, фигурирующая в данном при-


Ðèñóíîê 2. Èíôîðìàöèÿ î ìîäåëè ìàòåðèíñêîé ïëàòû мере, состоит из двух частей – пути к папке на сервере, в
которой будут храниться файлы отчетов со всех рабочих
Порядок работы сценария загрузки станций; имени файла. Имя файла должно совпадать с
Сценарий загрузки, написанный на VBScript, работает именем рабочей станции. В папку, предназначенную для
в соответствии со следующим алгоритмом. На первой хранения файлов отчетов, пользователи группы Everyone
стадии работы, для идентификации рабочей станции си- должны иметь возможность записи. Второе требование к
стемным администратором, сценарием загрузки опре- этой папке – ее скрытость от всех пользователей. Исходя
деляются следующие параметры: имя рабочей станции; из ранее сказанного, отметим, что переменная FileName
домен, к которому принадлежит рабочая станция; вер- имеет следующий вид: \\server\folder$\PC_name.xml.
сия операционной системы, установленной на рабочей
станции, учетная запись пользователя; текущая дата. Определение параметров рабочей станции
На втором этапе определяются аппаратные характери- Определяя те или иные параметры рабочей станции, мно-
стики рабочей станции с помощью WMI. На третьем гократно повторяется один и тот же программный код, пре-
этапе формируется файл отчета в формате XML. Дан- терпевающий небольшие изменения. Для сокращения
ные, хранящиеся в XML, могут быть экспортированы для программного кода рекомендуется названия WMI-классов,
последующей обработки в одно из следующих прило- к которым происходит обращение, объединить в массив.
жений: Microsoft Excel, Microsoft Access, Microsoft SQL Шаблон будет выглядеть следующим образом:

№12(13), декабрь 2003 29


администрирование
Øàáëîí 2. Îáåñïå÷åíèå óíèâåðñàëüíîãî äîñòóïà ê íåñêîëüêèì Set colItems = objWMIService.InstancesOf(strClass(a))
êëàññàì WMI For Each objItem in colItems
select case a
dim strClass
strClass=Array(”Win32_Value1”, ”Win32_Value2”,… ↵ case 0
”Win32_Value?”) FileName="\\server\folder\" & cstr(objItem.Name) & ".xml"
Set objWMIService = GetObject( " winmgmts: //./ ↵ temp=temp + "<Computer><PCName>" + objItem.Name + ↵
Root\Cimv2 ") "</PCName>" + chr(10)
for a=0 to ? temp=temp + " <Domain> " + objItem.Domain + ↵
Set colItems = objWMIService.ExecQuery(“SELECT * ↵ " </Domain>" + chr(10)
FROM” & strClass(a) ) temp=temp + "<User> " + objItem.Username + ↵
For Each objItem in colItems " </User>" + chr(10)
Select case a temp = temp + "<Date>" + cstr(Date()) + "; ↵
Case 0 " + cstr(Time()) + "</Date> </Computer>" + chr(10)
b=b+1
temp=temp+"<Parametr1" + cstr(b) +">" case 1
temp=temp+"<Parametr2" + cstr(objItem.Value1) +">" temp=temp + "<MB> <Version> " + objItem.Version + ↵
temp=temp+"<Parametr3" + cstr(objItem.Value2) +">" " </Version>" + chr(10)
…………………………………………………… temp=temp + "<Mbinfo> " + objItem.SMBIOSBIOSVersion + ↵
temp=temp+"<Parametrµ" + cstr(objItem.Valueµ) +">" " </Mbinfo></MB>" + chr(10)
temp=temp+"</Parametr1" + cstr(b) +">" case 2
b=b+1
Case1 temp=temp + "<CD-ROM" + cstr(b) +"> <Model>" + ↵
c=c+1 objItem.Caption + " </Model>" + chr(10)
temp=temp+"<Parametr1" + cstr(c) +">" temp=temp + "<Description>" + objItem.Description + ↵
temp=temp+"<Parametr2" + cstr(objItem.Value1) +">" " </Description>" + chr(10)
temp=temp+"<Parametr3" + cstr(objItem.Value2) +">" temp=temp + "<Letter>" + objItem.Drive + ↵
…………………………………………………… " </Letter> </CD-ROM" + cstr(b) +">" + chr(10)
temp=temp+"<Parametr?" + cstr(objItem.Value?) +">" end select
temp=temp+"</Parametr1" + cstr(c) +">" Next
……………………………………………………………………… Next
Case ? Set fso = CreateObject("Scripting.FileSystemObject")
y=y+1 Set f = fso.OpenTextFile(FileName, 2, True)
temp=temp+"<Parametr1" + cstr(y) +">" f.Write "<inf>" & temp & "</inf>"
temp=temp+"<Parametr2" + cstr(objItem.Value1) +">" f.Close
temp=temp+"<Parametr3" + cstr(objItem.Value2) +">"
…………………………………………………… Результатом данного сценария является файл в фор-
temp=temp+"<Parametr?" + cstr(objItem.Value?) +">" мате XML. Формат файла совпадает с названием рабо-
temp=temp+"</Parametr1" + cstr(y) +">"
чей станции (см. рис. 3).
End Select
Next
Next
Set FileName=”\\server\folder”
Set fso = CreateObject("Scripting.FileSystemObject")
Set f = fso.OpenTextFile(FileName, 2, True)
f.Write temp
f.Close

Поскольку поля в разных классах разные, то использова-


ние варианта 3 шаблона 1 становится невозможным – необ-
ходимо использовать вариант 1 или 2. В шаблоне 2 строка:

Set colItems = objWMIService.ExecQuery(“SELECT * FROM” ↵


& strClass(a))

заменяется на строку:

Set colItems = objWMIService.InstancesOf(strClass(a))

Приведем конкретный пример, в котором определим


некоторые данные о рабочей станции. Названия парамет-
ров и соответствующие им названия WMI-классов приве-
дены таблице:
Òàáëèöà 3

Ðèñóíîê 3. Ïðèìåð XML-ôàéëà


Полная версия сценария загрузки приведена в Прило-
жении 1.

Обработка полученных данных


Ïðèìåð 3 Ñîçäàíèå XML-ôàéëà Инструмент, позволяющий обработать данные о рабочих
dim strClass станциях, собранные в XML-файлы, представляет собой
strClass=Array("Win32_ComputerSystem", "Win32_BIOS", ↵ сайт, построенный на основе ASP. Выбор ASP обусловлен
"Win32_CDROMDrive")
Set objWMIService = GetObject("winmgmts://./Root\Cimv2") его способностью работать с OLE-объектами. Инструмент
for a=0 to 2 представляет сайт, точкой входа в который является стра-

30
администрирование
ница на языке HTML. Сайт создан на основе окон (Frameset): Set oFiles=oFolder.Files
файл default.htm делит окно браузера на два столбца. Текст For each oFile in oFiles
temp=temp+oFile.Name & chr(10)
файла default.htm (HTML) см. в Приложении 2. next
Остальные страницы написаны на ASP и взаимосвя- MsgBox temp
заны друг с другом. Для их создания выбран VBScript.
VBScript выбран потому, что является языком, поставля- Шаг 2. Чтение полей и занесение их в массивы
емым с Microsoft Windows; обладает необходимыми воз- Чтение полей XML-файла осуществляется с помощью объек-
можностями для реализации данного проекта, имеет про- та Microsoft.XMLDOM. XML-файл представляет собой струк-
стой синтаксис. турированную базу данных. Для чтения полей XML-файла
С помощью файла xml_list.asp осуществляется чтение необходимо четко представлять принцип построения кар-
XML-файлов в заданном каталоге, составляется список ты XML-файла. Рассмотрим карту, представленную на ри-
рабочих станций или пользователей в домене. Выбор сунке 3: она имеет 4 раздела – Computer, MB, CD-ROM1 и
списка осуществляется в HTML-файле. Вторая задача, ре- CD-ROM2. Видно, что в ширину XML-файл имеет четыре
шаемая этим файлом, – осуществление поиска по ука- ячейки. Количество ячеек можно определить с помощью
занному значению. Поиск является сквозным, т.е. поиск функции .childNodes.Lenght-1. Каждая из ячеек имеет глу-
происходит по всем полям всех файлов. Результатом по- бину – второе измерение (см. рис. 3). Глубина одной ячейки
иска является таблица, левый столбец которой содержит может быть отлична от другой. В приведенном примере глу-
в себе название рабочей станции, правый – значение па- бина каждой из ячеек различна. Например, глубина ячейки
раметра в контексте (см. рис. 5). Computer равна четырем – PCName, Domain, User, Data. Глу-
Второй ASP-файл – analyse.asp, предназначен для ото- бина ячейки определяется функцией функции .childNodes(i).
бражения информации по интересующей системного ад- childNodes.Lenght-1, где i – номер ячейки. Название ячейки
министратора рабочей станции. осуществляется с помощью функции .childNodes(i).child-
Nodes(j).NodeName, где i – номер ячейки, j – ее глубина.
Принцип работы файла Вызывая функция .childNodes(2).childNodes(0).NodeName для
рис. 3, в результате получим «Model». Необходимо отметить,
xml_list.asp что нумерация и ширины поля XML и глубина ячеек начина-
ются с нуля. Чтение значения параметра осуществляется с
Чтение данных из XML-файла помощью функции .childNodes(i).childNodes(j).Text, где i и j
Процесс чтения значений параметров XML-файла, как и имеют ту же смысловую нагрузку, что и ранее.
других структурированных файлов, состоит из несколь- Необходимо отметить одну особенность: при чтении зна-
ких этапов: чения уровня, ниже которого есть уровень, который также
 получение списка файлов, которые необходимо обра- содержит значения, происходит логическое сложение дан-
ботать; ных нижнего уровня и присовокупление их к верхнему. Рас-
 чтение полей и занесение их в массивы; смотрим этот процесс на примере карты на рис. 3. Резуль-
 упорядочивание массивов по одному из полей; татом чтения .childNodes(3).Text будет выражение «SONY
 отображение полученной информации. DVD-ROM DDU1211 CD-ROM Drive F:». Именно эта способ-
ность сквозного просмотра ячейки до дна будет использо-
Рассмотрим каждый из этих этапов подробнее. вана при поиске по заданному значению. Приведем при-
мер, который иллюстрирует эту особенность:
Шаг 1. Получение списка файлов
в указанном каталоге Ïðèìåð 5. Ñêâîçíîå ÷òåíèå ÿ÷åéêè XML-ôàéëà
Получение списка файлов осуществляется с помощью <%@ Language=VBScript%>
Windows Hosting Script (WSH). WSH был предложен в 1998 <% path="xml\10000PC.xml"
set xmlVisitor=server.CreateObject("Microsoft.XMLDOM")
году Microsoft в качестве инструмента разработки и вы- XMLFile=xmlVisitor.load(server.MapPath(path))
полнения сценариев для операционной системы Microsoft With xmlVisitor.documentElement
response.write .childNodes(3).text
Windows. Бесспорным достоинством WSH является тот End With
факт, что он входит в комплект поставки Microsoft Windows set xmlVisitor=Nothing %>
и поддерживает два встроенных в Microsoft Windows язы-
ка программирования – Microsoft Visual Basic Script Edition Зная основные принципы чтения XML-файла, приведем
(VBScript) и Miscrosoft Java Script Edition(Jscript). пример, в котором сначала происходит чтение списка из
В приведенном ниже примере (VBScript), осуществля- названий файлов, находящихся в каталоге; затем чтение
ется чтение имен всех файлов, находящихся в каталоге, двух полей в каждом файле – название рабочей станции и
указанном в переменной Path, и вывод этой информации имени пользователя с последующим занесением в массив
на экран: каждого из параметров. Необходимо отметить, что в при-
веденном примере переопределяется размер массивов, в
Ïðèìåð 4. ×òåíèå íàçâàíèé ôàéëîâ, ñîäåðæàùèõñÿ â êàòàëîãå которые в конце примера будут заноситься названия рабо-
Path="\\Server\Folder" чих станций и имен пользователей. Переопределение раз-
Set a=Wscript.CreateObject("Wscript.Shell") меров массивов осуществляется с помощью функции redim
Set fso=CreateObject("Scripting.FileSystemObject")
Set oFolder=fso.GetFolder(a.ExpandEnvironmentStrings(Path)) preserve array_name(count), где array_name – название мас-

№12(13), декабрь 2003 31


администрирование
сива, а count – новый размер массива. Полный листинг Шаг 4. Отображение полученной информации
файла xml_list.asp см. в Приложении 2. После упорядочивания массивов обработанная информа-
ция готова к отображению в браузере. В зависимости от
Ïðèìåð 6. Ôîðìèðîâàíèå ìàññèâîâ èç íàçâàíèé ðàáî÷èõ ñòàíöèé значения параметра sort в HTML-файле, выводится либо
è ó÷åòíûõ çàïèñåé ïîëüçîâàòåëåé
список пользователей, либо список рабочих станций до-
<%@ Language=VBScript%> мена. Оба списка упорядочены по алфавиту. Рассмотрим
<% path="\\server\folder"
Set a=CreateObject("Wscript.Shell") механизм передачи данных из одной страницы в другую.
Set fso=CreateObject("Scripting.FileSystemObject") Данные могут передаваться двумя способами: прямым и
Set oFolder=fso.GetFolder(a.ExpandEnvironmentStrings(path))
Set oFiles=oFolder.Files косвенным.
set xmlVisitor=server.CreateObject("Microsoft.XMLDOM")
dim array_pcname() Прямой метод:
dim array_username() В исходной странице создается форма, которая содержит
redim preserve array_pcname(oFiles.count)
redim preserve array_username(oFiles.count) поля для ввода информации и кнопку для отправки инфор-
i=0 мации и загрузки страницы, принимающей данные (HTML):
For each oFile in oFiles
XMLFile=xmlVisitor.load(server.MapPath(path ↵
& oFile.Name)) Ïðèìåð 8. Ïðÿìîé ìåòîä ôîðìèðîâàíèÿ çàïðîñîâ
With xmlVisitor.documentElement <FORM ACTION="printer_adsi.asp" TARGET="main" METHOD="get">
UN=.childNodes(0).childNodes(2).text <INPUT TYPE="submit" VALUE="Ïîèñê"></INPUT>
array_filename(i)=oFile.Name <INPUT NAME="Search_Text"></INPUT>
array_pcname(i)=.childNodes(0). ↵ </FORM>
childNodes(0).text
array_username(i)=right(UN, ↵
len(UN)-instr(UN,"\")) В разделе FORM присутствуют следующие парамет-
i=i+1 ры: ACTION, TARGET, METHOD. В параметре ACTION ука-
End With
Next зывается файл, в который будут передаваться данные
set xmlVisitor=Nothing %> после нажатия на кнопку.
Подразделом, который обязательно присутствует в раз-
деле FORM, является INPUT. INPUT имеет следующие па-
Шаг 3. Упорядочивание массивов раметры: TYPE, NAME, VALUE. Параметр TYPE определя-
по одному из полей ет вид приемника информации: кнопка (TYPE=«submit» или
Упорядочивание массива является классической задачей, «reset»); окно для ввода текста (TYPE=«text»), значение по
поэтому нет необходимости углубляться в то, как это де- умолчанию; кнопка выбора одного параметра из группы
лается. В данном случае применен пузырьковый метод (TYPE=«radio»). VALUE – название поля, отображаемое в
упорядочивания массивов. Следует отметить, что, читая объекте. NAME – имя, которое участвует в формировании
XML-файлы, формируются два массива. Задача состоит запроса.
в том, чтобы упорядочить один из массивов, при этом не Запрос, который формируется с помощью метода GET,
нарушить соответствия элементов второго массива пер- в общем виде выглядит следующим образом:
вому массив. Для достижения этой цели используется
третий массив – array_sort(i), элементам которого присва- http://èìÿ_ñòðàíèöà.asp(htm)?Ï1=Ç1&Ï2=Ç2&...Ïn=Çn
иваются в зависимости от поставленного условия элемен-
ты первого или второго массивов. В приведенной строке присутствуют следующие обо-
значения: П – параметр, З – значение.
Ïðèìåð 7. Óïîðÿäî÷èâàíèå âçàèìîñâÿçàííûõ ìàññèâîâ В используемом примере данная строка будет выгля-
<%@ Language=VBScript%> деть следующим образом:
<% path="\\server\folder"
…………………………………
'Âåðõíÿÿ ãðàíèöà ìàññèâîâ îïðåäåëÿåòñÿ ñ ïîìîùüþ ôóíêöèè http://printer_adsi.asp?Search_Text=value1
'Ubound(). Óñëîâèå ñîðòèðîâêè ìàññèâà îñóùåñòâëÿåòñÿ ñ
'ïîìîùüþ StrComp().
dim array_sort () если в строке было введено «value1».
redim preserve array_sort(oFiles.count) Рассмотрим «страницу-приемник»: для получения пе-
size_array=ubound(array_sort)
………………………………… реданных принимающей странице данных, необходимо
on error resume next прочитать запрос и присвоить переданные значения пе-
for j=0 to size_array
for i=0 to size_array ременным. Данная операция, опираясь на приведенный
if strcomp(array_sort(i),array_sort(i+1),0)=1 then пример, осуществляется следующим образом:
temp=array_sort(i)
array_sort(i)=array_sort(i+1)
array_sort(i+1)=temp Set search_value= Request.QueryString(«Search_Text»)
temp=array_pcname(i)
array_pcname(i)=array_pcname(i+1)
array_pcname(i+1)=temp таким образом, параметр search_value=«value1».
temp=array_pcname(i)
array_pcname(i)=array_pcname(i+1)
array_pcname(i+1)=temp Косвенный метод:
end if
next Косвенный метод используется для передачи данных из
next %> одной ASP-страницы в другую. Он основан на том, что

32
администрирование
при нажатии пользователем на картинку или текст, явля- target=""analyse"" title=""Ðàáî÷àÿ ñòàíöèÿ - " & ↵
ющийся ссылкой, сразу формируется запрос, который пе- array_pcname(i) &""" a>" & array_username(i) &"</a><BR>"
end select
редает данные. next
Поскольку очередью принтера невозможно управлять, …………………………………%>
если рассматривать принтер как сетевое устройство, то
использование протокола LDAP становится невозможным. Поиск данных в XML-файле
Для доступа к очереди принтера, как ранее отмечалось, Вторая задача, решаемая файлом xml_list.asp – осуще-
используется протокол WINNT. Для использования про- ствление поиска по указанному значению. Поиск проис-
токола необходимо передавать 2 параметра: сетевое имя ходит по всем полям всех файлов. Результатом поиска
принтера (Share Name) и название окна (Frame), в кото- является таблица, левый столбец которой содержит в себе
ром необходимо вывести данную страницу. Опираясь на название рабочей станции, правый – значение парамет-
приведенные ранее примеры, данные будут передавать- ра в контексте. Рекурсивная передача данных в файле
ся на страницу View_Printer.asp, запрос будет иметь сле- xml_list.asp осуществляется с помощью прямого метода,
дующий вид (ASP): который был рассмотрен в предыдущем разделе (см. при-
мер 8). Методика поиска основана на использовании осо-
Ïðèìåð 9. Êîñâåííûé ìåòîä ôîðìèðîâàíèÿ çàïðîñîâ бенности XML-файла – сквозного просмотра ячейки до
<% <A HREF=""View_Printer.asp?Printer_to=" & printer_name ↵ дна. Более подробную информацию и наглядный пример
& "" "target=""var"" > <IMG SRC =images\pr1.jpg ↵ использования этой особенности можно найти в преды-
BORDER=0> </A> %>
дущем разделе (см. пример 5). Приведем пример, демон-
В данном проекте прямой метод используется для осу- стрирующий реализацию процесса поиска. Параметр
ществления поиска в файлах, косвенный – для определе- search_var содержит в себе искомое словосочетание:
ния вида вывода информации (по названиям рабочих
станций или именам пользователей). Ïðèìåð 11. Ïðîöåäóðà ïîèñêà â XML-ôàéëàõ
<%@ Language=VBScript%>
В приведенном примере определяется значение пара- <%…………………………………
метра sort. Если параметр sort=1, то перед сортировкой XMLFile=xmlVisitor.load(server.MapPath(fname ↵
& oFile.Name))
массива происходит присвоение элементов массива For each oFile in oFiles
array_pcname(i) массиву array_sort(i). В том случае, если With xmlVisitor.documentElement
For i=0 to .childNodes.length-1
sort=2, происходит присвоение элементов массива if instr(Lcase(.childNodes(i).text),LCase(search_var)) then
array_username(i). Response.Write " <TR> <TD width=100><H6><a ↵
href=analyse.asp?FN=" & fname & ofile.name & " ↵
Вывод информации осуществляется с помощью кон- target=""analyse"">" & ↵
струкции Response.Write «Value». Информация является left(oFile.Name,len(oFile.Name)-4)& " </a> </TD><H6> ↵
<TD><H6>" & .childNodes(i).text & "</TD><H6></TR>"
гиперссылкой на второй фрейм. Название фрейма, в ко- end if
тором будет загружаться HTML-страница, указывается в Next
End With
параметре target. Название фрейма задается в HTML- Next
странице, которая является родительским объектом для Response.Write "</Table>"
…………………………………%>
обоих ASP-страниц (см. Приложение 2, файл default.htm).
В гиперссылке также формируется запрос, содержащий
параметр, значением которого является UNC-путь, вклю-
чающий имя XML-файла, который необходимо прочитать.

Ïðèìåð 10. Ôîðìèðîâàíèå çàïðîñîâ â çàâèñèìîñòè îò çíà÷åíèÿ


ïàðàìåòðà sort

<%@ Language=VBScript%>
<% path="\\server\folder"
…………………………………
set sort_var = Request.QueryString("sort")
select case sort_var
case 1
for i=0 to size_array
array_sort(i) = array_pcname(i)
next
case 2
for i=0 to size_array
array_sort(i) = array_username(i)
next
end select
…………………………………
for i=0 to size_array-1
select case sort_var
case 1
response.write "<a href=analyse.asp?FN=" & fname & ↵
array_filename(i+1) & "&Sort=" & sort_var & " ↵
target=""analyse"" title=""Èìÿ ïîëüçîâàòåëÿ - " & ↵
array_username(i) &""" a>" & array_pcname(i) &"</a><BR>"
case 2
response.write "<a href=analyse.asp?FN=" & fname & ↵
array_filename(i+1) & "&Sort=" & sort_var & " ↵
Ðèñóíîê 4. Ðåçóëüòàò ïîèñêà

№12(13), декабрь 2003 33


администрирование
Принцип работы файла analyse.asp  чтение переданного параметра из файла xml_list.asp,
содержащего UNC-путь и название XML-файла;
Стилизация оформления страниц  чтение параметров из XML-файла и формирование от-
Обе ASP-страницы используют таблицу стилей и работа- чета; вывод результата на экран. Чтение параметра осу-
ют в кодировке WIN-1251. Стили описываются в подклю- ществляется с помощью функции Request.QueryString(),
чаемом файле style.css (см. Приложение 2) .Файл стилей которая была ранее многократно описана. Затем ука-
указывается в разделе LINK, необходимая кодировка – в занный в запросе XML-файл открывается для чтения.
разделе META (HTML): Чтение файла осуществляется по описанной ранее ме-
тодике.
Ïðèìåð 12. Óñòàíîâêà êîäèðîâêè è ÷òåíèå òàáëèöû ñòèëåé
<HEAD> Внедрение продукта
<LINK HREF="style.css" TYPE=text/css REL=stylesheet> Готовый продукт, как отмечалось в самом начале статьи,
<META HTTP-EQUIV ="Content-Type" CONTENT="text/html;
CHARSET=windows-1251"> состоит из двух частей – сценария загрузки, который обес-
</HEAD> печивает сбор информации, и сайта на ASP, с помощью
которого осуществляется анализ собранной информации
Параметр CHARSET отвечает за выбор кодировки, в ко- о рабочих станциях домена.
торой будет отображаться документ. После задания таблицы
стилей и подключения этой таблицы в ASP или HTML-файле, Внедрение сценария загрузки
можно приступить к использованию данной таблицы. Опи- Внедрение сценария загрузки состоит из нескольких этапов:
раясь на приведенный пример таблицы стилей, в ASP- или  В свойствах каждого пользователя необходимо про-
HTML-файле открывается и закрывается соответствующий писать в разделе Logon Script сценарий загрузки (см.
раздел – тэг, например: <H4> «Hellow» </H4>. В приведенном рис. 6). Поскольку сценарий должен быть гибким, то
примере начертание слова Hellow будет выдержано в стиле рекомендуется создать файл Script.bat и в нем пропи-
<H4>, т.е. будет написано шрифтом Arial 11-го размера. сывать скрипты. Предлагаемое модульное решение в
случае сбоя позволит быстро справиться с возникшей
Формирование страницы отчета проблемой, при этом лишив пользователя минималь-
Процесс формирования страницы отчета состоит из двух ного количества сервисов, которые предлагаются на-
этапов: бором сценариев загрузки.

Ðèñóíîê 5. Ñòàòèñòèêà ïî ðàáî÷åé ñòàíöèè

34
администрирование

Ðèñóíîê 7. Ãðóïïîâûå ïîëèòèêè

Установка сайта и особенности


конфигурирования IIS
Для работы ASP-страницы, созданный сайт необходимо
опубликовать с помощью IIS на любом компьютере доме-
на. Желательно, чтобы этим компьютером был компью-
Ðèñóíîê 6. Ñöåíàðèé çàãðóçêè тер, который функционирует круглосуточно. Таким ком-
Естественно, что прописывать сценарий загрузки для пьютером является сервер. Теоретически просматривать
каждого пользователя вручную – занятие неблагодарное, результаты могут все пользователи сети, однако это не-
поэтому предлагается скрипт, который позволит автомати- рационально. Необходимо назначить следующие права
зировать данную задачу. Скрипт будет прописан всем доступа на папку, в которой опубликован сайт: группе
пользователям домена, кроме тех, которые входят в группу. «Domain Admins» необходимо предоставить уровень дос-
Название файла присваивается Logon Script (см. рис. 6). тупа «Full Control» на папку с сайтом; остальные группы и
Приведенный скрипт перебирает учетные записи всех пользователи должны быть удалены (см. рис. 8). В на-
пользователей домена и проверяет членство пользователя стройке IIS для данного сайта в его свойствах необходи-
в группе. Если пользователь не входит в группу, то в свой- мо, как показано на рис. 9, войти во вкладку «Authentication
ствах этого пользователя прописывается сценарий загруз- Methods», нажав на кнопку «Edit». Затем выключить ано-
ки. Необходимо отметить, что сценарий загрузки самостоя- нимный доступ (Anonnymos access), убрав галку напро-
тельно определяет название домена, в котором находится тив соответствующей записи. В разделе «Authenticated
пользователь, запускающий скрипт; скрипт должен быть access» необходимо установить галку только напротив
запущен с правами администратора, т.к. изменения в Active «Basic authentication».
Directory могут быть внесены только системным админист- Желательно включить «Integrated Windows authentication»
ратором; для увеличения скорости отработки скрипта реко- для того, чтобы системному администратору, который во-
мендуется запускать сценарий на контроллере домена; груп- шел в сеть под своей учетной записью, не предлагалось
па, созданная для пользователей, которым сценарий заг- вводить пароль. Однако этот механизм доступа к сайту
рузки не нужен, может быть создана в любом месте Active невозможен по неизвестным причинам. Рекомендуется не
Directory; группа должна быть глобальной; название группы ставить эту галку.
и скрипта, который прописывается в свойствах пользовате-
ля, могут быть изменены в ходе выполнения скрипта. Текст
скрипта см. в Приложении 1 – файл auto_script.vsb.
 Файл Script.bat (пример файла см. в Приложении 1) и
VBS-файл должны находиться в каталоге Netlogon кон-
троллера домена. Физически эта папка находится в ка-
талоге с установленной операционной системой в под-
каталоге SYSVOL\Domain\Script\.
 При загрузке рабочей станции выполняется сценарий
загрузки. На время выполнения сценария загрузки не-
обходимо скрыть CMD-панель, в которой выполняется
скрипт, и приостановить загрузку рабочего стола до
окончания работы всего скрипта. Необходимы резуль-
тат достигается использованием групповых политик.

В разделе групповой политики «User Configuration» вам


необходимо, соответственно, включить «Run legacy logon script
synhronously» (Запускать сценарий загрузки синхронно) и
«Run legasy script hidden» (Запускать сценарий скрыто). Ðèñóíîê 8

№12(13), декабрь 2003 35


администрирование
temp=temp + "<MB> <Version> " + objItem.Version + ↵
" </Version>" + chr(10)
temp=temp + "<Mbinfo> " + objItem.SMBIOSBIOSVersion + ↵
" </Mbinfo></MB>" + chr(10)
+
case 2
temp=temp + "<CPU> <Name> " + objItem.name + ↵
" </Name>" + chr(10) ' CPU name
temp=temp + "<Description> " + objItem.Description + ↵
" </Description>" + chr(10) ' Description
temp=temp + "<Socket> " + objItem.SocketDesignation + ↵
" </Socket></CPU>" + chr(10) ' Socket type

case 3
if b=0 then
temp=temp +"<Memory>"
end if
b=b+1
temp=temp+"<Device" + cstr(b) +">"
temp=temp+" <Slot> " + objItem.DeviceLocator + " </Slot> "
temp=temp+" <Capacity> " + objItem.Capacity + "</Capacity> "
temp=temp+"</Device" + cstr(b) +">"
case 4
if c=0 then
temp=temp +"</Memory>" & chr(10) &"<Audio>"
end if
c=c+1
temp=temp+"<Device" + cstr(c) + "> "
Ðèñóíîê 9 temp=temp+"<Manufacturer> " + objItem.Manufacturer + ↵
" </Manufacturer> "
temp=temp+"<Name> " + objItem.Name + " </Name> "
Замечание temp=temp+"</Device" + cstr(c) + "> "
Компания Microsoft утверждает, что корректно работать case 5
с WMI можно только пользователю с административными if d=0 then
temp=temp +"</Audio>" & chr(10) &"<Video>"
привилегиями. Практика показывает, что более 90% па- end if
раметров корректно определяются при работе с WMI без d=d+1
наличия административных привилегий и привилегий temp=temp+"<Device" + cstr(d) + "><Type> " + ↵
опытного пользователя. Замечено, что для пользовате- objItem.AdapterType+ " </Type> "
temp=temp+"<Memory> " + cstr(objItem.AdapterRAM) + ↵
ля, не обладающего привилегиями, возникают проблемы "</Memory> "
при определении биоса материнской платы и характери- temp=temp+ "<Resolution>"+ ↵
cstr(objItem.HorizontalResolution)+ ↵
стик жесткого диска. Возникшие проблемы решаются чте- "x"+cstr(objItem.VerticalResolution)+ ↵
нием соответствующих ветвей реестра с помощью "x"+cstr(objItem.BitsPerPixel)+"@"+ ↵
cstr(objItem.RefreshRate)+"Hz</Resolution>"
VBScript или WSH. Пользователи, имеющие привилегии temp=temp+"</Device" + cstr(d) + "> "
опытного пользователя на локальной машине, не испы- case 6
тывают никаких неудобств. if e=0 then
temp=temp +"</Video>" & chr(10) &"<NetCard>"
end if
Приложение 1 e=e+1
if objItem.MacAddress<>"" then
q=q+1
Sysinfo.VBS temp=temp+"<Device" + cstr(q) + "> ↵
<Manufacturer>"+objItem.Manufacturer+"</Manufacturer>"
temp=temp+"<Name>"+objItem.Name+"</Name>"
dim strClass temp=temp+"<MAC>"+objItem.MacAddress+"</MAC> ↵
strClass=Array("Win32_ComputerSystem", "Win32_BIOS", ↵ </Device" + cstr(q) + "> "
"Win32_Processor", "Win32_PhysicalMemory", ↵ end if
"Win32_SoundDevice", "Win32_VideoConfiguration", ↵
"Win32_NetworkAdapter", "Win32_USBController", ↵ case 7
"Win32_CDROMDrive", "Win32_DiskDrive", ↵ if g=0 then
"Win32_LogicalDisk", "Win32_DiskPartition") temp=temp +"</NetCard>" & chr(10) & "<USB>"
Set objWMIService = GetObject("winmgmts://./Root\Cimv2") end if
for a=0 to 11
Set colItems = objWMIService.InstancesOf(strClass(a)) if objItem.Name<>"" then
For Each objItem in colItems g=g+1
select case a temp=temp + "<NameUSB" + cstr(g) +">" + objItem.Name + ↵
"</NameUSB" + cstr(g) +"> " + chr(10) ' USB Controller
case 0 end if
FileName=objItem.Name & "_Ïðèëîæåíèå1.xml"
temp=temp + "<Computer><PCName>" + objItem.Name + ↵ case 8
"</PCName>" + chr(10) if h=0 then
temp=temp + " <Domain> " + objItem.Domain + " ↵ temp=temp +"</USB>" & chr(10) & "<CD-ROM>"
</Domain>" + chr(10) end if
temp=temp + "<User> " + objItem.Username + ↵
" </User>" + chr(10) if objItem.Caption<>"" then
temp = temp + "<Date>" + cstr(Date()) + "; ↵ h=h+1
" + cstr(Time()) + "</Date> </Computer>" + chr(10) temp=temp + "<Device" + cstr(h) +"> <Model>" + ↵
objItem.Caption + " </Model>" + chr(10) ' Model
case 1 temp=temp + "<Description>" + objItem.Description + ↵

36
администрирование
" </Description>" + chr(10) ' Description AutoScript.VBS
temp=temp + "<Letter>" + objItem.Drive + " </Letter> ì
</Device" + cstr(h) +"> " + chr(10) ' Letter
Set objNameSpace = GetObject("WinNT:")
end if For Each Domain in objNameSpace
strDomain Domain.Name
case 9 Next
if i=0 then Set Users_Domain = getobject("WinNT://" & strDomain)
temp=temp + "</CD-ROM>" & chr(10) & " <HDD>" Users_Domain.Filter = Array("user")
end if strGroup="Skip"
strGroup = InputBox("Group:", "Skip users", "Skip")
i=i+1 strScript="Script.bat"
temp=temp + "<Device" +cstr(i) +"> <Model>" + ↵ strScript=InputBox("Script:","Script Name", ↵
objItem.Caption + " </Model>" + chr(10) ' Model " Script.bat ")
temp=temp + "<Description>" + objItem.Description + ↵
" </Description>" + chr(10) ' Description For each user in users_domain
temp=temp + "<Size>" + cstr(objItem.Size) + ↵ i=0
" </Size>" + chr(10) ' Size of HDD a=user.name
temp=temp + "<Number>" + cstr(objItem.Index) + ↵ Set user_group = GetObject("WinNT://" & ↵
" </Number>" + chr(10) ' Number of HDD strDomain & "/" & strGroup)
temp=temp + "<Partitions>" + cstr(objItem.Partitions) + ↵ For each user_group in ↵
" </Partitions> </Device" + cstr(i) +">" + ↵ user_group.Members
chr(10)' Number of partitions b=user_group.name
if b=a then
i=1
case 10 end if
if k=0 then next
temp=temp + "</HDD>" & chr(10) & " <Media>" if i=0 then
end if User.LoginScript=strScript
User.setinfo
End if
k=k+1 Next
temp=temp +"<Device" +cstr(k) +"> <Letter>" + ↵
objItem.Name + " </Letter>" + chr(10) ' Letter
temp=temp + "<Description>" + cstr(objItem.Description) + ↵
" </Description>" + chr(10) ' Description Приложение 2
if objItem.FileSystem<>"" then
temp=temp + "<FullSize>" + objItem.Size + ↵
" </FullSize>" + chr(10) ' File System Default.HTM
temp=temp + "<FreeSize>" + objItem.FreeSpace + ↵
" </FreeSize>" + chr(10) ' File System <HTML>
end if <HEAD>
temp=temp +"</Device" + cstr(k) +"> " <!-- Ëåâûé ñòîëáåö ñîñòàâëÿåò 30% îò øèðèíû âñåãî îêíà.
Ëåâîå îêíî èìååò èäåíòèôèêàòîð «main», âòîðîå «var». -->
<TITLE>Ñïèñîê äîñòóïíûõ ñåòåâûõ ïðèíòåðîâ </TITLE>
case 11 <META HTTP-EQUIV ="Content-Type" CONTENT="text/html; ↵
if l=0 then CHARSET=windows-1251">
temp=temp + "</Media> " & chr(10) & "<Partition>" </HEAD>
end if <!-- Åñëè ïàðàìåòð sort=1, îñóùåñòâëÿåòñÿ ñîðòèðîâêà ïî
íàçâàíèþ ðàáî÷èõ ñòàíöèé, åñëè sort=2 – ñîðòèðîâêà èäåò
l=l+1 ïî èìåíè ïîëüçîâàòåëÿ». -->
temp=temp + "<Device" + cstr(l) +"> <Name>" + ↵ <FRAMESET cols="30%,*" FRAMEBORDER="5" BORDER="yes" ↵
objItem.Name + " </Name>" + chr(10) ' Model FRAMESPACING="5" >
temp=temp + "<Size>" + cstr(objItem.Size) + " </Size> ↵ <FRAME SRC="xml_list.asp?sort=1&Search_Text=""" ↵
</Device" + cstr(l) +">" + chr(10) ' Number of partitions NAME="xml" SCROLLING="yes" ÌÀRGINHEIGHT=1 >
<FRAME SRC ="about:blank" NAME="var">
end select </FRAMESET >
Next </HTML>
Next

temp=temp + "</Partition>"
Set fso = CreateObject("Scripting.FileSystemObject") Stylet.CSS
Set f = fso.OpenTextFile(FileName, 2, True)
f.Write "<inf>" & temp & "</inf>" H4 {font-size:11; font-family:Arial;}
f.Close H5 {font-size:10; font-family:Arial;}
H6 {font-size:9; font-family:Arial;}
msgbox "end"

Script.BAT Xml_List.ASP
@ECHO OFF <%@ Language=VBScript CODEPAGE=1251%>
<HEAD>
if c:\%os%==c:\ goto win9x <LINK href="style.css" type=text/css rel=stylesheet>
if not c:\%os%==c:\ goto winnt <meta http-equiv="Content-Type" content="text/html" ↵
:winnt charset=windows-1251>
@echo Ïîäîæäèòå! Âûïîëíÿåòñÿ íàñòîéêà Âàøåãî êîìïüþòåðà. <meta http-equiv="refresh" content=10 >
start /wait sysinfo.vbs </HEAD>
goto end <BODY>
:win9x
@echo windows 9x <H4><b><center>"Èíôîðìàöèÿ î ðàáî÷èõ ↵
%0\..\Script. sysinfo.vbs ñòàíöèÿõ"</center></H4> <br> <h6>
goto end <FORM ACTION="xml_list.asp" target="xml" METHOD="get">
<INPUT TYPE="submit" VALUE="Ïîèñê"></INPUT>
:end <INPUT NAME="Search_Text"></INPUT>
@echo End Of Batch File </FORM> </h6>

№12(13), декабрь 2003 37


администрирование
<%set search_var = Request.QueryString("Search_Text") else
set sort_var = Request.QueryString("sort")
Response.Write "<table width=""100%"", Cellpacing=""0"">"
path="\\server\folder" Response.Write "<TR><TD width=150><H4> Ðåçóëüòàòû ïîèñêà ↵
Set a=CreateObject("Wscript.Shell") ïî </H4></TD><TD> <H6>" & search_var & "</H6></TD></TR>"
Set fso=CreateObject("Scripting.FileSystemObject") Response.Write "<table width=""100%"", Cellpacing=""0"">"
Set oFolder=fso.GetFolder(a.ExpandEnvironmentStrings(path)) For each oFile in oFiles
Set oFiles=oFolder.Files XMLFile=xmlVisitor.load(server.MapPath(path ↵
& oFile.Name))
set xmlVisitor=server.CreateObject("Microsoft.XMLDOM") With xmlVisitor.documentElement
for i=0 to .childNodes.length-1
dim array_pcname() if instr(Lcase(.childNodes(i).text),LCase(search_var)) then
dim array_username() Response.Write " <TR> <TD width=50><H6><a ↵
dim array_sort() href=analyse.asp?FN=" & fname & ↵
dim array_filename() ofile.name & " target=""analyse"">" & ↵
redim preserve array_pcname(oFiles.count) left(oFile.Name,len(oFile.Name)-4)& " ↵
redim preserve array_username(oFiles.count) </a> </TD><H6> <TD><H6>" & ↵
redim preserve array_sort(oFiles.count) .childNodes(i).text & "</TD><H6></TR>"
redim preserve array_filename(oFiles.count) end if
size_array=ubound(array_sort) next
i=0 End With
next
For each oFile in oFiles Response.Write "</Table>"
XMLFile=xmlVisitor.load(server.MapPath(path ↵ end if
& oFile.Name)) set xmlVisitor=Nothing %>

With xmlVisitor.documentElement
UN=.childNodes(0).childNodes(2).text
array_filename(i)=oFile.Name Analyse.ASP
array_pcname(i)=.childNodes(0).childNodes(0).text
array_username(i)=right(UN, len(UN)-instr(UN,"\"))
i=i+1 <%@ Language=VBScript CODEPAGE=1251%>
End With <HEAD>
next <LINK href="style.css" type=text/css rel=stylesheet>
<meta http-equiv="Content-Type" content="text/html" ↵
if search_var="" then charset=windows-1251>
select case sort_var
case 1 </HEAD>
for i=0 to size_array <%set path=Request.QueryString("fn")
array_sort(i) = array_pcname(i) set xmlVisitor=server.CreateObject("Microsoft.XMLDOM")
next XMLFile=xmlVisitor.load(server.MapPath(path))
case 2
for i=0 to size_array With xmlVisitor.documentElement
array_sort(i) = array_username(i)
next Response.Write "<H4> Ðàáî÷àÿ ñòàíöèÿ</H4> ↵
end select <table width=""100%"", Cellpacing=""0"">"
Response.Write " <TR> <TD width=300><H6> Ðàáî÷àÿ ñòàíöèÿ ↵
</TD><H6> <TD width=300><H6>" & ↵
.childNodes(0).childNodes(0).text & "</TD><H6></TR>"
on error resume next Response.Write " <TR> <TD width=300><H6> Ïîëüçîâàòåëü ↵
for j=0 to size_array </TD><H6> <TD width=300><H6>" & ↵
for i=0 to size_array .childNodes(0).childNodes(2).text & "</TD><H6></TR>"
if strcomp(array_sort(i),array_sort(i+1),0)=1 then Response.Write " <TR> <TD width=300><H6> Äîìåí </TD><H6> ↵
temp=array_sort(i) <TD width=300><H6>" & ↵
array_sort(i)=array_sort(i+1) .childNodes(0).childNodes(1).text & "</TD><H6></TR>"
array_sort(i+1)=temp Response.Write " <TR> <TD width=300><H6> Äàòà ðåãèñòðàöèè ↵
temp=array_pcname(i) â ñåòè</TD><H6> <TD width=300><H6>" & ì
array_pcname(i)=array_pcname(i+1) .childNodes(0).childNodes(3).text & "</TD><H6></TR>"
array_pcname(i+1)=temp Response.Write "</Table>"
temp=array_pcname(i)
array_pcname(i)=array_pcname(i+1) Response.Write "<H4> Ìàòåðèíñêàÿ ïëàòà, ïðîöåññîð, ↵
array_pcname(i+1)=temp ïàìÿòü</H4> <table width=""100%"", Cellpacing=""0"">"
temp=array_filename(i) Response.Write " <TR> <TD width=300><H6> Ìàòåðèíñêàÿ ïëàòà ↵
</TD><H6> <TD width=300><H6>" & ↵
array_filename(i)=array_filename(i+1) .childNodes(1).childNodes(1).text & "</TD><H6></TR>"
array_filename(i+1)=temp Response.Write " <TR> <TD width=300><H6> Ìîäåëü BIOS ↵
end if </TD><H6> <TD width=300><H6>" & ↵
next .childNodes(1).childNodes(0).text & "</TD><H6></TR>"
next Response.Write " <TR> <TD width=300><H6> Ïðîöåññîð ↵
</TD><H6> <TD width=300><H6>" & ↵
for i=0 to size_array-1 .childNodes(2).childNodes(0).text & "</TD><H6></TR>"
select case sort_var Response.Write " <TR> <TD width=300><H6> Ïîêîëåíèå ↵
case 1 </TD><H6> <TD width=300><H6>" & ↵
response.write "<a href=analyse.asp?FN=" & ↵ .childNodes(2).childNodes(1).text & "</TD><H6></TR>"
fname & array_filename(i+1) & "&Sort=" & ↵ Response.Write " <TR> <TD width=300><H6> Ðàçúåì ïðîöåññîðà ↵
sort_var & " target=""analyse"" ↵ </TD><H6> <TD width=300><H6>" & ↵
title=""Èìÿ ïîëüçîâàòåëÿ - " & ↵ .childNodes(2).childNodes(2).text & "</TD><H6></TR>"
array_username(i) &""" a>" & ↵
array_pcname(i) &"</a><BR>" Response.Write " <TR> <TD width=300><H6> Ñëîò è òèï RAM ↵
case 2 </TD><H6> <TD width=300><H6>" & ↵
response.write "<a href=analyse.asp?FN=" & ↵ .childNodes(3).childNodes(0).childNodes(0).text & ↵
fname & array_filename(i+1) & "&Sort=" & ↵ "</TD><H6></TR>"
sort_var & " target=""analyse"" ↵ Response.Write " <TR> <TD width=300><H6> Ðàçìåð, Ìá ↵
title=""Ðàáî÷àÿ ñòàíöèÿ - " & ↵ </TD><H6> <TD width=300><H6>" & ↵
array_pcname(i) &""" a>" & ↵ .childNodes(3).childNodes(0).childNodes(1).text/(1000*1000) ↵
array_username(i) &"</a><BR>" & "</TD><H6></TR>"
end select Response.Write "</Table>"
next

38
администрирование
Response.Write "<H4> Æåñòêèå äèñêè</H4> ↵ for i=0 to .childNodes(q).childNodes.length-1
<table width=""100%"", Cellpacing=""0"">" Response.Write " <TR> <TD width=300><H6><i> Àäàïòåð ↵
</i>" & i+1 & "</TD><H6> <TD width=300><H6></TD><H6></TR>"
q=9 Response.Write " <TR> <TD width=300><H6> Ìîäåëü ↵
for i=0 to .childNodes(q).childNodes.length-1 </TD><H6> <TD width=300><H6>" & ↵
Response.Write " <TR> <TD width=300><H6> <i>" & ↵ .childNodes(q).childNodes(i).childNodes(0).text & ↵
.childNodes(q).childNodes(i).childNodes(1).text & ↵ "</TD><H6></TR>"
i+1 & "</i></TD><H6><TD width=300><H6>" & ↵ Response.Write " <TR> <TD width=300><H6> Ïàìÿòü, Ìá ↵
.childNodes(q).childNodes(i).childNodes(0).text & ↵ </TD><H6> <TD width=300><H6>" & ↵
"</TD><H6></TR>" .childNodes(q).childNodes(i).childNodes(1). ↵
Response.Write " <TR> <TD width=300><H6> Ðàçìåð, Ãá ↵ text/(1000*1000) & "</TD><H6></TR>"
</TD><H6> <TD width=300><H6>" & ↵ Response.Write " <TR> <TD width=300><H6> ↵
round(.childNodes(q).childNodes(i).childNodes(2). ↵ Õàðàêòåðèñòèêè ýêðàíà </TD><H6> <TD width=300><H6>" & ↵
text/(1000*1000*1000),1) & "</TD><H6></TR>" .childNodes(q).childNodes(i).childNodes(2).text & ↵
Response.Write " <TR> <TD width=300><H6> ↵ "</TD><H6></TR>"
Ëîãè÷åñêèõ ðàçäåëîâ</TD><H6> <TD width=300><H6>" & ↵ next
.childNodes(q).childNodes(i).childNodes(4).text & ↵ Response.Write "</Table>"
"</TD><H6></TR>"
next
Response.Write "</Table>" Response.Write "<H4> Ñåòåâîé àäàïòåð</H4> ↵
<table width=""100%"", Cellpacing=""0"">"
Response.Write "<H4> CD-ROM</H4> <table width=""100%"", ↵ q=6
Cellpacing=""0"">" for i=0 to .childNodes(q).childNodes.length-1
q=8 Response.Write " <TR> <TD width=300><H6> <i> Àäàïòåð ↵
for i=0 to .childNodes(q).childNodes.length-1 </i>" & i+1 & "</TD><H6> <TD width=300><H6></TD><H6></TR>"
Response.Write " <TR> <TD width=300><H6>" & ↵ Response.Write " <TR> <TD width=300><H6> Ïðîèçâîäèòåëü ↵
.childNodes(q).childNodes(i).childNodes(1).text & ↵ </TD><H6> <TD width=300><H6>" & ↵
i+1 & "</TD><H6><TD width=300><H6>" & ↵ .childNodes(q).childNodes(i).childNodes(0).text & ↵
.childNodes(q).childNodes(i).childNodes(0).text & ↵ "</TD><H6></TR>"
"</TD><H6></TR>" Response.Write " <TR> <TD width=300><H6> Ìîäåëü ↵
next </TD><H6> <TD width=300><H6>" & v
Response.Write "</Table>" .childNodes(q).childNodes(i).childNodes(1).text & ↵
"</TD><H6></TR>"
Response.Write "<H4> Çâóêîâàÿ ïëàòà</H4> ↵ Response.Write " <TR> <TD width=300><H6> ÌÀÑ-àäðåñ ↵
<table width=""100%"", Cellpacing=""0"">" </TD><H6> <TD width=300><H6>" & ↵
q=4 .childNodes(q).childNodes(i).childNodes(2).text & ↵
for i=0 to .childNodes(q).childNodes.length-1 "</TD><H6></TR>"
Response.Write " <TR> <TD width=300><H6> <i> Àäàïòåð" & ↵ next
i+1 & "</i> </TD><H6> <TD width=300><H6></TD><H6></TR>" Response.Write "</Table>"
Response.Write " <TR> <TD width=300><H6> Ïðîèçâîäèòåëü ↵
</TD><H6> <TD width=300><H6>" & ↵ Response.Write "<H4> USB </H4> <table width=""100%"", ↵
.childNodes(q).childNodes(i).childNodes(0).text & ì Cellpacing=""0"">"
"</TD><H6></TR>" q=7
Response.Write " <TR> <TD width=300><H6> Ìîäåëü ↵ for i=0 to .childNodes(q).childNodes.length-1
</TD><H6> <TD width=300><H6>" & ↵ Response.Write " <TR> <TD width=300><H6> Ïîðò " & i+1 & ↵
.childNodes(q).childNodes(i).childNodes(1).text & ↵ " </TD><H6> <TD width=300><H6>" & ↵
"</TD><H6></TR>" .childNodes(q).childNodes(i).childNodes(0).text & ↵
next "</TD><H6></TR>"
Response.Write "</Table>" next
Response.Write "</Table>"
Response.Write "<H4> Ãðàôè÷åñêèé àäàïòåð</H4> ↵
<table width=""100%"", Cellpacing=""0"">" End With
q=5 set xmlVisitor=Nothing%>

№12(13), декабрь 2003 39


администрирование

КРЕПОСТЬ ДЛЯ ПИНГВИНА

СЕРГЕЙ ЯРЕМЧУК
40
администрирование
Сегодня, как никогда, особое внимание уделяется защите Установка
серверов и персональных компьютеров от вторжения из- При закачке необходимо по ссылке выбрать пакет для
вне. Описание различных методов атак можно найти прак- используемого дитсрибутива или исходные тексты для
тически везде, у нападающего способов пробраться в чу- предпочитающих устанавливать из исходников. Кроме
жой компьютер немало, да и с желающими также проблем этого потребуется интерпретатор Perl версии не ниже 5.6.1
обычно не бывает. Но сисадмину или обычному пользова- и для интерактивного режима потребуются на выбор: для
телю от этого не легче, все больше и больше приходится ease-of-use X-Window Perl/Tk версии не ниже 800.23 (вер-
уделять времени чтению документации, настройке систе- сия для RedHat: ftp://ftp.redhat.com/pub/redhat/linux/7.1/en/
мы, но время, как правило, не на стороне обороняющего- DMA/CPAN/RPMS/perl-Tk-800.022-11.i386.rpm) и для тек-
ся, да и опыт приходит вместе с ошибками. Ситуация усу- стового режима (recommended for high security) Perl/Curses
губляется тем, что производители в последнее время вы- версии 1.06 и выше (ftp://ftp.redhat.com/pub/redhat/linux/7.1/
пускают дистрибутивы по типу «два в одном», которые en/DMA/CPAN/RPMS/perl-Curses-1.05-10.i386.rpm).
могут быть с одинаковым успехом установлены как на сер- Для установки при помощи rpm-пакетов необходимо
вер, так и на персональный компьютер, причем, по моему ввести все те же rpm -iv, а при установке из исходников
мнению, все равно, для того чтобы привлечь большее ко- после распаковки архива заходим внутрь образовавше-
личество народа, упор делается все-таки на последний. гося каталога и вводим ./Instal.sh. После чего программа
А пользователю главное – удобство, естественно, оно дос- скопирует все файлы на свои места и установит необхо-
тигается и путем уменьшения требований к защите. Что димые для работы модули Perl. Теперь можно запускать.
делать в таком случае? Не ждать же в самом деле, пока Как уже говорил, программа может использоваться дву-
сисадмин будет готов к выходу в Интернет. Можно, конеч- мя способами: в интерактивном режиме и в неинтерактив-
но, пойти на курсы, может, и научат, но фактор времени ном. В интерактивном режиме интерфейс пользователя по-
остается. Существует множество различных утилит, так или зволяет объяснить системному администратору проблемы в
иначе предназначенных для улучшения защиты Linux-сис- защите и попутно позволяет их решить. Этот подход удобен
темы, в данной статье хочу обратить внимание на проект тем, что, с одной стороны, защищает систему, а с другой –
Bastille Linux, домашняя страница которого находится по обучает на конкретных примерах. Неинтерактивный режим
адресу: http://www.bastille-linux.org/. позволяет использовать уже готовые файлы конфигурации,
Помимо главной задачи – укрепление установленной изготовленные в интерактивном режиме для изменения па-
системы – разработчики Bastille Linux преследовали и дру- раметров на других системах, что позволяет избегать повтор-
гие не менее важные цели: ного прохождения всех этапов, т.к. для того, чтобы спокойно
 всесторонность – все, что описано в открытых источ- и обдуманно ответить на все вопросы, потребуется отвести
никах по поводу усиления защиты Linux, нашло свою приличное время. При этом программа должна быть запуще-
реализацию Bastille Linux. В основу легли разработки на каждый раз после установки нового ПО или установки пат-
Джея Била (Jay Beale) по укреплению Solaris и Linux, ча (для RedHat http://www.redhat.com/apps/support/errata/), ко-
нашедших свое отражение в книге института SANS торые могли повлиять на ослабление защиты. Также могут
(SysAdmin, Audit, Network, Security) «Securing Linux Step быть случаи, когда применение Bastille может вызвать побоч-
by Step», руководство Курта Сеифриеда (Kurt Seifried) ный эффект, когда блокируются ни в чем не повинные про-
Linux Administrator’s Security Guide Linux (http:// граммы, поэтому все-таки перед применением на рабочем
www.seifried.org/lasg/) и другие источники; компьютере поэкспериментируйте на тестовом.
 поучительность – Bastille Linux был разработан также Запустить программу конфигурации в интерактивном
с целью обучить администратора проблемам в защи- режиме можно двумя способами. Первый состоит в запус-
те, включенным в каждую из задач сценария. Каждый ке perl-скрипта InteractiveBastile, по умолчанию или с ука-
необязательный шаг содержит описание включенных занием дополнительного аргумента -х, используется Tk-
проблем безопасности; интерфейс, требующий запуска Х-Window, что проверяет-
 сообщество – после того как были сделаны началь- ся установленным значением переменной $DISPLAY. При
ные разработки, было создано сообщество разработ- этом всегда можно вернуться к предыдущему пункту, что
чиков, которое совместными усилиями вносило изме- позволяет использовать выборочную конфигурацию, для
нение в Bastille. удобства обладающую статус-баром, позволяющим оце-
нить «пройденное расстояние». Если же система исполь-
При помощи программы настройки Bastille Linux с целью зуется, например, на роутере и не имеет установленной
улучшения общей безопасности настраиваются демоны, из- системы Х-Window, то с заданием ключа -с, bastille будет
меняются некоторые системные параметры и firewall. Допол- запущен с текстовым интерфейсом Perl/Curses.
нительно (при необходимости) отключаются ненужные сер- Но этим способом, описанным в инструкции, не всегда уда-
висы вроде печати, rcp и rlogin. С ее помощью можно со- ется запустить программу. Поэтому в таком случае можно вос-
здать среду «chroot jails», при помощи которой можно умень- пользоваться вторым вариантом, вызов bastille напрямую.
шить уязвимость некоторых интернет-сервисов вроде Web
и DNS. В настоящее время поддерживаются следующие ди- # /usr/sbin/bastille
стрибутивы и системы RedHat, Debian, Mandrake, SuSE и
TurboLinux, а также HP-UX и Mac OS X (поддержка после- Ключи для выбора интерфейса в этом случае анало-
дней добавилась совсем недавно). гичны предыдущим.

№12(13), декабрь 2003 41


администрирование
Иногда программа не может узнать, в каком дистри- Для неинтерактивного режима первоначально проделы-
бутиве она установлена, и начинает ругаться, приводя ваем все вышеописаное, для того чтобы содать необходи-
длинный список «совместимых». мые файлы конфигурации, все ответы на вопросы находят-
ся в /etc/Bastille/config. После этого устанавливаем Bastille
Could not determine operating system version! на каждую машину с такой же самой операционной систе-
Bastille does not work on this OS: unknown
Currently, Bastille works on the following: мой, как и та, в которой он был сделан. И вводим на каждой:
DB2.2 DB3.0 RH6.0 RH6.1 RH6.2 RH7.0 RH7.1 RH7.2 RH7.3 RH8.0
RH9 MN6.0 MN6.1 MN7.0 MN7.1 MN7.2 MN8.0 MN8.1 HP-UX11.00
HP-UX11.11 HP-UX11.22 HP-UX11.23 SE7.2 SE7.3 SE8.0 TB7.0 # /usr/sbin/bastille -b
OSX10.2.0 OSX10.2.1 OSX10.2.2 OSX10.2.3 OSX10.2.4
При этом могут возникнуть и ошибки. Чтобы просмот-
Для того чтобы все-таки уговорить ее работать, зада- реть информацию об изменяемых параметрах для всех
ем при помощи ключа –os название дистрибутива, выб- систем разом, введите:
рав сокращенное название из приведенного выше спис-
ка (только при первом запуске). # tail -f /var/log/Bastille/action-log

# /usr/sbin/bastille –os RH8.0 или вывод ошибок:

И в результате появится окно, представленное на рисун- # tail -f /var/log/Bastille/error-log


ках. Выбрав интересуемую категорию, начинаем отвечать на
вопросы, в большинстве пунктов ответом будет выбор из двух Дополнительно в файл /var/log/Bastille/TODO система
вариантов – Yes или No, но, например, при вводе диапазонов заносит оставшиеся действия, которые система не мо-
портов дополнительно активируется внизу экрана полоса жет выполнить автоматически и их пользователь должен
«Answer», куда и следует вводить данные. При ответе на воп- выполнить вручную (например, перезагрузка сервисов).
росы можно использовать кнопку «Explain More/Explain Less» Возврат к предыдущему (до Bastill) состоянию можно
для более или менее подробного объяснения, правда, для не- осуществить при помощи опции -r (revert) или запуском
которых пунктов доступен только один из вариантов подска- отдельного скрипта RevertBastille.
зок. К сожалению, русификацией Bastille Linux еще никто не
занимался, поэтому, чтобы разобраться в вопросах, необхо- # /usr/sbin/bastille -r
димо знание английского (оптом вопросы можно просмотреть,
ознакомившись с файлом Questions.txt). После ответа на все При этом удаление самой программы Bastille без выпол-
вопросы в последнем пункте сохраняем конфигурацию. нения этого действия не приведет к автоматическому откату.

42
администрирование

Пользователю придется ответить не на один десяток воп-


росов, чтобы иметь представление об основных разделах
программы. При этом разделы, которые касаются только
одной из систем, помечены как HP-UX only или Linux only.
Пару слов о PSAD. Эта программа, написанная на Perl
(http://www.cipherdyne.com), использует программы firewall
для анализа сканирования портов и методы обнаружения
сигнатур, используемые в Snort Intrusion Detection System
(http://www.snort.org). При этом обнаруживается большин-
ство различных методов сканирования. Все интересные
события регистрируются при помощи syslog.
Как видите, Bastille Linux представляет собой легкий в
использовании, удобный и интуитивно понятный инстру-
мент, позволяющий существенно поднять защищенность
компьютера, будь то сервер или десктоп. И дополнитель-
но является неплохим пособием по изучению защиты
Linux-систем. Удачи.

№12(13), декабрь 2003 43


администрирование

УЧЕТ РАБОТЫ DIALUP-ПОЛЬЗОВАТЕЛЕЙ


В СИСТЕМЕ FreeBSD

СЕРГЕЙ СУПРУНОВ

44
администрирование
Если вы вознамерились стать провайдером услуг Ин- Итак, для начала рассмотрим способы, которыми мож-
тернета, имея сервер под управлением FreeBSD и несколь- но определить момент входа пользователя в систему. В
ко модемов на входе, то одной из первых задач, которая простейшем случае, когда информация о работе пользо-
встанет перед вами, будет проблема учета времени ра- вателей нужна нам «задним числом», вполне достаточно
боты ваших пользователей. будет анализа данных, возвращаемых командой last. На-
Безусловно, существует целый ряд готовых программ- пример, в конце месяца мы можем просто просуммиро-
ных продуктов, в той или иной степени решающих задачу вать продолжительность соединений для каждого пользо-
учета (и тарификации) работы пользователей, выходящих вателя, и выставить счета на основе этой информации
в Интернет через модемный пул сервера. Однако для «ча- (простейший скрипт lastreader.pl, выполняющий данную
стного» использования вряд ли целесообразно «прикру- функцию, представлен на вкладке).
чивать» к вашей системе RADIUS или что-то подобное. В
данной статье мы попытаемся рассмотреть общие прин- lastreader.pl:
#!/usr/bin/perl –w
ципы решения задачи учета работы «дайлапников», ска-
жем так, подручными средствами. Конкретную реализа- # îòêðûâàåì last íà ÷òåíèå
open(LAST, ‘last -s|’) || die ‘Error’;
цию оставим за рамками данной статьи. while(<LAST>) {
Итак, для того чтобы посчитать время работы пользо- chomp;
if($_) {
вателя, мы должны решить три задачи: определение мо- # âûäåëÿåì èìÿ ïîëüçîâàòåëÿ è óñòðîéñòâî
мента входа пользователя в систему, определение момен- ($user, $tty) = split(/\s/);
# Äàëåå îáðàáàòûâàåì òîëüêî ìîäåìíûå ñîåäèíåíèÿ ttydX
та выхода из системы и сохранение информации о дан- if($tty =~ /ttyd/) {
ном соединении для последующего использования. Если # âûäåëÿåì çíà÷åíèå â ñêîáêàõ – ïðîäîëæèòåëüíîñòü
# ñîåäèíåíèÿ â ñåêóíäàõ
мы изберем авансовую систему оплаты доступа (когда $_ =~ s/\(\s*(\d+)\)/$1/g;
«утром деньги – вечером стулья»), то потребуется также if(($user)&&($1) {
# ñóììèðóåì ïðîäîëæèòåëüíîñòè ïî ïîëüçîâàòåëÿì
контролировать состояние счета абонента в процессе его $totals{$user} += $1;
работы, и отключать его, если аванс на его счету будет }
}
исчерпан. Также может потребоваться и учет потреблен- }
ного трафика. }
close(LAST);
Поскольку мы не ставим своей задачей разработку
серьезной и универсальной системы, то будем стремить- # ñîðòèðóåì ïî àëôàâèòó ïîëüçîâàòåëåé
@res = sort keys %totals;
ся максимально использовать то, что у нас уже есть. Так- foreach $item (@res) {
же мы не будем связываться с программированием, что- # âûâîäèì ðåçóëüòàò íà ýêðàí
print “$item - $totals{$item}\n”;
бы основная идея не затерялась в дебрях алгоритмиза- }
ции, а ограничимся скромными скриптами на Shell и Perl. exit(1);
Посмотрим, какие «встроенные» средства учета нам до-
ступны. Или обрабатывать эту информацию ежедневно, сохра-
Прежде всего это wtmp – файл, в котором хранится няя результаты в свои файлы. Однако такой способ учета
информация о последних соединениях. Просмотреть со- не позволяет контролировать текущее состояние счета
держащуюся в нем информацию можно командой last. Как абонента с тем, чтобы не допустить превышения установ-
видно, используя эту команду, можно получить подроб- ленного лимита (или округляет такой контроль до суток,
ную информацию о моментах входа-выхода пользовате- например). Также если нам нужно блокировать работу
ля в систему и о продолжительности соединения (last с определенных пользователей без изменения информации
ключом -s (last -s) отображает продолжительность соеди- в системных файлах, то определять вход пользователя
нения в секундах) за период с момента последней рота- нужно в режиме реального времени.
ции (перезаписи) файла wtmp. Период ротации выбира- Одним из самых очевидных способов является про-
ется в зависимости от нагрузки на систему и задается с смотр списка находящихся в данный момент в системе
таким расчетом, чтобы его размер не достигал катастро- пользователей. Например, если запускать команду who
фических значений. Учитывая, что мы рассматриваем не- каждые пять секунд, то мы сможем определить появле-
большую систему, обновлять файл wtmp достаточно еже- ние в системе пользователя с точностью до этого значе-
месячно (cкрипт, производящий обновление, в этом слу- ния. Присутствие в системе пользователя можно опреде-
чае скорее всего будет располагаться в /etc/periodic/ лить и по команде last – подключенные в данный момент
monthly). абоненты отмечены как «still logged in».
Второй важный инструмент, который нам понадобит- Однако рассмотренный выше способ чреват нерацио-
ся – команда who, которая выводит информацию о нальным расходом ресурсов (постоянные вызовы «левых»
пользователях, подключенных к системе в данный мо- программ даром не проходят) и точностью, ограниченной
мент. Любители языка Си могут воспользоваться фай- периодом вызова вспомогательных команд. Чтобы опре-
лом utmp, из которого информация о текущих подклю- делить более элегантный способ, рассмотрим процесс
чениях и черпается. входа в систему с модемного пула.
С остальными вспомогательными средствами позна- В данной статье остановимся на рассмотрении двух
комимся в процессе рассмотрения конкретных методов способов входа в систему – pap- и login-аутентификации.
учета. В первом случае последовательность такова:

№12(13), декабрь 2003 45


администрирование
 после того, как модемы установят соединение, конк- Поскольку аутентификация уже выполнена, то сред-
ретное ttyd-устройство сопоставляется с интерфейсом ствами pppd она не осуществляется, и потому скрипт auth-
pppX; up не отрабатывается. Таким образом, если мы попыта-
 запускается демон pppd, обслуживающий данное со- емся использовать для регистрации входа пользователя
единение; в систему именно его, то при login-аутентификации пользо-
 выполняется pap-аутентификация пользователя; ватель зарегистрирован не будет. Поэтому, если мы хо-
 отрабатывается скрипт auth-up (если есть), как прави- тим оставить пользователю возможность устанавливать
ло, располагающийся в /etc/ppp; соединение и через стандартный скрипт (с помощью login-
 отрабатывается скрипт ip-up (если есть), располагаю- аутентификации), то для определения его входа в систе-
щийся там же, где и auth-up. му нам остается только скрипт ip-up, который отрабаты-
вается в любом случае. Однако теперь мы знаем только
Скрипт ip-up вызывается со следующими параметрами: устройство, через которое пользователь подключен, и нам
придется сопоставить устройство с конкретным пользо-
ip-up interface-name tty-device speed local-IP remote-IP ipparam вателем самим. Для этого нам как раз и пригодится ко-
манда who (например, имя пользователя возвратит сле-
где: дующая команда:
 interface-name – имя интерфейса pppX,
 tty-device – устройство tty, через которое осуществля- who | grep “ttydX” | awk ‘{print $1;}’
ется соединение,
 speed – скорость на порту (на tty-устройстве), где «Х» – номер нужного нам ttyd-устройства).
 local-IP, remote-IP – соответственно локальный и уда- Вторая задача – определение момента, когда пользо-
ленный IP-адреса, ватель покидает систему, – решается аналогично. Это
 ipparam – дополнительные параметры. может быть либо проверка подключенных пользователей
периодическим вызовом who, либо использование скрип-
Для нас интерес представляют первые два парамет- тов ip-down и auth-down. Первый отрабатывается при вы-
ра, передаваемые в скрипт. К сожалению, имя пользова- ходе из системы пользователя, вошедшего через pap-
теля в ip-up не передается, и мы можем узнать только о аутентификацию (для которого отрабатывался скрипт
том, что какой-то пользователь выполнил подключение. auth-up), второй – при завершении сеанса связи. Однако
Параметры вызова скрипта auth-up следующие: нужно иметь в виду, что в некоторых случаях «down-скрип-
ты» могут не отрабатываться, например, при аварийной
auth-up interface-name peer-name user-name tty-device speed перезагрузке системы.
Особо нужно отметить, что вышеописанные ppp-скрип-
где: ты исполняются с правами суперпользователя (root). С
 interface-name – имя интерфейса pppX, одной стороны, это хорошо, поскольку позволяет нам со-
 peer-name – имя пользователя, установившего соеди- вершать любые действия, но с другой – требует особой
нение, осторожности и аккуратности. Также не забывайте под-
 user-name – пользователь, с чьими правами запущен держивать права доступа к данным файлам как r-x------
pppd (как правило, root), (на стадии отладки можно поставить rwx------, но потом
 tty-device – устройство tty, через которое осуществле- возможность записи необходимо снять).
но соединение, Сохранение статистической информации проблем
 speed – скорость на порту (на tty-устройстве). вызвать не должно. Если мы знаем, когда пользователь
вошел в систему и когда ее покинул, то достаточно про-
В данном случае, как видно, в скрипт передается еще сто сохранить эту информацию в файл или базу данных.
один полезный параметр – имя авторизованного пользо- Выбор конкретного формата (база MySQL, единый тек-
вателя. Таким образом, мы можем сразу установить факт стовый файл, индивидуальные файлы для хранения ста-
входа в систему конкретного абонента. тистики по каждому пользователю) оставим на совести
Небольшая неприятность появляется в случае login- администратора.
аутентификации (например, при входе в систему через Теперь несколько слов о том, как можно определить
стандартный скрипт). Если в качестве стандартной обо- обнуление счета абонента в процессе работы и соответ-
лочки пользователю задать pppd, то процесс входа в сис- ственно дальнейшую работу оного пресечь самым жес-
тему будет следующим: токим образом. Основных способов здесь тоже два – по-
 после того, как модемы установят соединение, конк- стоянный (периодический) контроль остатка, и предвари-
ретное ttyd-устройство сопоставляется с интерфейсом тельное вычисление остатка. В первом случае специаль-
pppX; ный скрипт должен время от времени определять остаток
 проводится login-аутентификация; на счете пользователя (который можно хранить в БД или
 запускается программа, указанная в /etc/passwd как текстовом файле), вычитать из него стоимость наработ-
стандартная оболочка (в нашем случае это демон pppd); ки на текущий момент и в случае отрицательной разно-
 отрабатывается скрипт ip-up (если есть), как правило, сти давать команду на отключение пользователя. Суть
располагающийся в /etc/ppp. второго способа заключается в следующем: при входе

46
администрирование
пользователя в систему определяется остаток на его счете Затем, когда пользователь отключается, считываем
и вычисляется время, которое абоненту хватит с данной его наработку (ipfw show 10000) и удаляем правило (ipfw
суммой при действующем тарифе. Затем дается задание delete 10000). А наработку, соответственно пишем в фай-
планировщику (это может быть как специально разрабо- лик для последующего предъявления.
танный скромный скрипт, так и системная команда at) от- Обобщая сказанное, можно сделать вывод, что встро-
ключить данного пользователя через данное время. Ес- енных средств FreeBSD вполне достаточно, чтобы за ночь
тественно, нужно предусмотреть ситуацию, когда пользо- «на коленке» написать биллинговую систему для обслу-
ватель отключится добровольно: в этом случае нужно живания нескольких десятков пользователей.
давать отмену планировщику, как только будет обнару- Если нам нужны только сведения о том, сколько
жено отсутствие пользователя в системе, а также про- пользователь провел времени в Сети за месяц, оптималь-
грамма-киллер (которая будет заниматься черным делом ным будет обработка результата, выдаваемого по last –s.
отключения пользователя) должна уметь определять, нуж- Если мы предоставляем доступ в Интернет только с
даются ли еще в ее услугах. Первое нужно, чтобы избе- использованием ppp-аутентификации (например, pap), то
жать накапливания сотен заданий на отключение пользо- для определения входа пользователя в систему вполне
вателя через дни и месяцы, в то время как он уже давно может служить скрипт auth-up. Если наш сервер будет
пьет пиво вдали от родного Интернета, второе – для ис- поддерживать и login-аутентификацию, то придется ис-
ключения банальных ошибок. пользовать скрипт ip-up. В этом случае имя пользователя
Для принудительного завершения работы пользовате- придется определять вручную, основываясь на сведени-
ля рекомендуется использовать утилиту killpppd (для ях, предоставляемых командой who. Эту же команду, ви-
FreeBSD ее можно найти в коллекции портов). Принимая димо, придется использовать и для определения момен-
в качестве параметров peer-name и tty-device, утилита та отключения пользователя, поскольку метод, связанный
осуществляет корректное завершение работы всех про- со скриптами ip-down и auth-down, слишком ненадежен.
цессов, связанных с данным устройством. Хотя в целях экономии ресурсов можно использовать ком-
Если нам нужно еще и учитывать трафик, потребляе- бинацию этих методов: отключение производить по ко-
мый пользователем, то самый простой вариант – исполь- манде соответствующего скрипта, но выполнять контроль
зовать для этих целей ipfw (брандмауэр, входящий в со- по команде who через относительно большой промежу-
став FreeBSD). При входе пользователя в систему запус- ток времени (например, раз в 5 минут).
каем подсчет трафика на конкретном устройстве (если Конечно, для построения эффективной, точной и надеж-
точнее, то подсчет трафика запускается на IP-адрес, од- ной системы учета придется прибегнуть к программирова-
нако определить адрес, присвоенный устройству, как пра- нию на С, однако в большинстве случаев концепция оста-
вило, проблемой не является): ется прежней – контроль файлов wtmp (last) и utmp (who).

ipfw add 10000 count ip from any to 100.100.100.5 out Дополнительные материалы:
1. man last(1) – команда last;
Приведенная выше строка заставит брандмауэр счи- 2. man who(1) – команда who;
тать входящий интернет-трафик («out» говорит о том, 3. man grep(1), man awk(1) – команды обработки тексто-
что будет учитываться трафик, исходящий из FreeBSD вых строк;
по направлению к клиенту, для клиента этот трафик 4. man at(1) – отложенное выполнение команды;
будет соответственно входящим), приходящий на ад- 5. man pppd(8) – информация по auth-up, ip-up, auth-down,
рес 100.100.100.5 с любого источника. 10000 – номер ip-down;
правила, которое назначается для данной операции. Ес- 6. man ipfw(8) – информация по ipfw, в том числе по под-
тественно, для каждого соединения нужно будет назна- счету трафика;
чать свободный в данный момент номер правила (пра- 7. man periodic(8) – дополнительные сведения по рота-
вила с одинаковым номером также будут корректно ции wtmp;
работать, но при удалении одного из них возникнут про- 8. man utmp(5) – обработка utmp на С;
блемы). 9. man wtmp(5) – обработка wtmp на С.

№12(13), декабрь 2003 47


администрирование

АНДРЕЙ БЕШКОВ

48
администрирование
Как обычно, в начале статьи хотелось бы упомянуть то об- # cp –R /tmp/nagios_rus_1_1/* /tmp/nagios-1.1/
стоятельство, что описываемые действия выполнялись на # cd nagios-1.1
# ./configure --prefix=/usr/local/nagios ↵
хосте, работающем под управлением FreeBSD 4.8. Пере- --with-cgi-url=/nagios/cgi-bin --with-html-url=/nagios/ ↵
живать по этому поводу не стоит, так как все обсуждае- --with-nagios-user=nagios --with-nagios-grp=nagios ↵
--with-gd-lib=/usr/local/lib ↵
мые приемы будут отлично работать с любым дистрибу- --with-gd-inc=/usr/local/include/gd
тивом Unix-подобных операционных систем, для которых
существует версия Nagios. Единственным щекотливым Я думаю, объяснять назначение ключей команды configure
моментом может быть различие в именах директорий, где смысла нет. Поэтому сразу же переходим к компиляции.
расположились Nagios и остальное вспомогательное про-
граммное обеспечение, необходимое для нашей работы. /usr/local/etc/nagios.sh stop
Первым делом хотелось бы научить Nagios «говорить»
на чистом русском языке. Примерно девять месяцев назад После того как этот процесс завершится успешно, оста-
я завершил работы по локализации Nagios версии 1.06 beta. навливаем демона Nagios. Все-таки резать по живому не
Затем, по мере выхода новых версий продукта, та же судь- очень хорошо, и подобные действия могут вызвать разно-
ба постигла официальные релизы 1.0 и 1.1. Методика ру- образные сбои в функционировании системы мониторинга.
сификации для всех версий одинакова, поэтому я буду опи-
сывать ее на примере версии 1.1 как наиболее свежей и, # make install
надеюсь, наиболее распространенной. Итак, что же нам
нужно сделать? Первым делом скачиваем дистрибутив вер- Вот теперь можно спокойно выполнять инсталляцию.
сии Nagios, которая установлена у вас с официального сай-
та http://www.nagios.org. Здесь берем соответствующие # make all
файлы локализации: htpp://onix.opennet.ru/files/.
Распаковываем дистрибутив и пакет локализации в В результате файлы из директории дистрибутива дол-
любое удобное место, например в директорию /tmp. жны заменить те файлы, которые Nagios использовал
до сегодняшнего дня. Таким образом, файлы из /tmp/
# tar zxvf nagios-1.1.tar.gz nagios-1.1/html должны попасть в /usr/local/nagios/share/,
# tar zxvf nagios_rus_1_1.tar.gz
а скомпилированные файлы из /tmp/nagios-1.1/cgi в /usr/
Копируем все необходимые файлы из пакета локализа- local/nagios/sbin/.
ции в распакованный дистрибутив и затем, как обычно, про- Снова запустив Nagios и обратившись к веб-интерфей-
водим конфигурирование. су, должны увидеть что-то вроде такой картинки:

№12(13), декабрь 2003 49


администрирование
Судя по всему, русификация прошла без сучка без за- NOTE: After you install the necessary libraries on your system:
1. Make sure /etc/ld.so.conf has an entry for the directory
доринки. Следующая проблема, нуждающаяся в исправ- in which the GD, PNG, and JPEG libraries are installed.
лении, – неработающая карта сети. 2. Run 'ldconfig' to update the run-time linker options.
3. Run 'make clean' in the Nagios distribution to clean
При попытке воспользоваться пунктами «Карта сети» out any old references to your previous compile.
(statusmap.cgi) и «3D карта сети» (statuswrl.cgi) на экране 4. Rerun the configure script.
вместо карты обычно появляется такое меню: NOTE: If you can't get the configure script to recognize the
GD libs on your system, get over it and move on to other
things. The CGIs that use the GD libs are just a small
part of the entire Nagios package. Get everything else
working first and then revisit the problem. Make sure
to check the nagios-users mailing list archives for
possible solutions to GD library problems when you resume
your troubleshooting.
********************************************************************

Ну а в случае, если вам повезло и вы нашли в указан-


ном выше файле вот такое:

checking for gdImagePng in -lgd (order 1)... yes


GD library was found!

Причин этому может быть две. Первая – не работает биб- значит с GD у вас все в порядке, и вы можете спокойно
лиотека GD, которую мы установили вместе с Nagios. И вто- пойти попить кофе, пока я расскажу остальным, как из-
рая – в используемом нами браузере отсутствует или непра- бавиться от проблем с этой неуловимой библиотекой.
вильно работает подключаемый модуль для отображения vrml. По традиции начинаем с FreeBSD. Посмотреть, уста-
Итак, начнем с первой проблемы. Если вы помните, навливалась ли библиотека GD в эту систему стандарт-
перед компилированием Nagios мы использовали команду ными средствами, то есть с помощью пакетов или пор-
configure. Следует обратить особое внимание на парамет- тов, можно командой:
ры --with-gd-lib и --with-gd-inc, которые указывают на дирек-
тории, где в нашей системе находятся заголовочные и биб- # pkg_info | grep gd
gd-1.8.4_6 A graphics library for fast image creation
лиотечные файлы пакета GD. Команда configure пытается
автоматически подключить нужные файлы к проекту, но Теперь мы знаем полное название пакета. Смотрим,
ей не всегда это удается. Обычно в процессе конфигури- куда установились его файлы.
рования на экран выводятся соответствующие сообщения,
но вся проблема в том, что туда же сыпется довольно мно- # pkg_-L gd-1.8.4_6
го прочих диагностических сообщений, и поэтому найти и Information for gd-1.8.4_6:
понять то, что нам нужно в этом винегрете, довольно слож-
Files:
но. Для более точного диагностирования проблемы очис- /usr/local/bin/bdftogd
тим дистрибутив от файлов конфигурации, созданных во /usr/local/bin/gd2copypal
/usr/local/bin/gd2topng
время предыдущей компиляции командой: /usr/local/bin/gdparttopng
/usr/local/bin/gdtopng
/usr/local/bin/pngtogd
# make clean /usr/local/bin/pngtogd2
/usr/local/bin/webpng
/usr/local/include/gd/gd.h
Затем перенаправим все сообщения команды configure /usr/local/include/gd/gd_io.h
в файл make.log c помощью следующей конструкции: /usr/local/include/gd/gdcache.h
/usr/local/include/gd/gdfontg.h
/usr/local/include/gd/gdfontl.h
# ./configure --prefix=/usr/local/nagios ↵ /usr/local/include/gd/gdfontmb.h
--with-cgi-url=/nagios/cgi-bin --with-html-url=/nagios/ ↵ /usr/local/include/gd/gdfonts.h
--with-nagios-user=nagios --with-nagios-grp=nagios ↵ /usr/local/include/gd/gdfontt.h
--with-gd-lib=/usr/local/lib ↵ /usr/local/lib/libgd.a
--with-gd-inc=/usr/local/include/gd > make.log /usr/local/lib/libgd.so
/usr/local/lib/libgd.so.2
Если во время компоновки gd не найден, то внутри фай- /usr/local/share/doc/gd/index.html
ла make.log среди всего прочего будут вот такие надписи:
Итак, судя по выводу, параметры команды configure,
checking for gdImagePng in -lgd (order 1)... no относящиеся к библиотке GD, должны выглядеть так:
checking for gdImagePng in -lgd (order 2)... no
checking for gdImagePng in -lgd (order 3)... no
--with-gd-lib=/usr/local/lib ↵
*** GD, PNG, and/or JPEG libraries could not be located... **** --with-gd-inc=/usr/local/include/gd
Boutell's GD library is required to compile the statusmap, Давайте посмотрим, как можно добиться подобного
trends and histogram CGIs. Get it from http://www.boutell.com/gd/,
compile it, and use the --with-gd-lib and --with-gd-inc arguments эффекта для Linux-систем, основанных на rpm. В каче-
to specify the locations of the GD library and include files. стве примера возьмем ALT Linux.
NOTE: In addition to the gd-devel library, you'll also need
to make sure you have the png-devel and jpeg-devel
libraries installed on your system. # rpm -qa | grep gd

50
администрирование
libgd2-devel-2.0.4-alt2 Теперь все те, кто ушли пить кофе, могут возвращать-
gdm-2.4.4.5-alt1 ся. Сейчас мы начнем починку 3D-карты. Не работает она
gdk-pixbuf-loaders-0.22.0-alt2
gdk-pixbuf-0.22.0-alt2 по причине того, что ваш браузер не знает, что делать с
libgd2-2.0.4-alt2 vrml-файлом, который возвращается в ответ на запросы
libgda2-1.0.0-alt1
gnome2-utils-gdict-applet-2.4.0-alt2 к скрипту statuswrl.cgi. Для того чтобы все заработало как
libgda2-devel-1.0.0-alt1
положено, нужно установить в используемый браузер
В отличие от FreeBSD, в Linux-системах библиотека модуль для работы с vrml или отдельную программу, пред-
GD обычно разделена на два отдельных пакета. Судя по назначенную для тех же целей.
всему, нас интересуют rpm-файлы libgd2 и libgd2-devel. Программного обеспечения, подходящего для этого,
Первый содержит динамически загружаемые библиоте- написано воз и маленькая тележка. Как обычно, пальма
ки, ну а второй, соответственно, заголовочные файлы. первенства по количеству экземпляров принадлежит
Windows. Затем идет MAC OS и, наконец, бронзовое тре-
# rpm -ql libgd2 тье место занимает Linux.
/usr/lib/libgd.so.2
/usr/lib/libgd.so.2.0.4 Итак, начнем с фаворита. При необходимости рабо-
тать под управлением Windows и MAC-систем я предпо-
# rpm -ql libgd2-devel
/usr/include/gd.h читаю использовать Cortona VRML Client по той простой
/usr/include/gd_io.h причине, что он совместим с большинством наиболее рас-
/usr/include/gdcache.h
/usr/include/gdfontg.h пространенных браузеров, к числу которых несомненно
/usr/include/gdfontl.h относятся Internet Explorer, Netscape Navigator, Mozilla,
/usr/include/gdfontmb.h
/usr/include/gdfonts.h iCab. Интересным фактом является то обстоятельство, что
/usr/include/gdfontt.h этот подключаемый модуль можно использовать даже из
/usr/lib/libgd.so
/usr/share/doc/gd-2.0.4 офисных приложений Microsoft PowerPoint, Microsoft Word.
/usr/share/doc/gd-2.0.4/index.html К сожалению, разработчики Cortona почему-то решили
полностью проигнорировать Linux. Скачать дистрибутив
Ну и наконец, универсальный способ, подходящий для можно с сайта http://www.parallelgraphics.com/products/
любой Unix-подобной операционной системы. Им можно cortona/download/. Что делать после совершения этого
воспользоваться в случае, если все предыдущие попыт- сакраментального действа, мы обсудим немного позднее.
ки не дали никаких результатов. Нужно самостоятельно Следующая достойная нашего внимания программа,
отыскать, где находятся файлы libgd.* и gd.h называемая Cosmo player, живет по адресу: http://ca.com/
cosmo/html/. Работает в виде отдельного приложения и,
#find / -name libgd.* конечно же, только под Windows и MAC.
/usr/lib/libgd.so.1.2
/usr/lib/libgd.so.1 ExpressVR – конкурент Cortona для всем известной яб-
/usr/lib/libgd.so лочной платформы. Под другими операционными система-
#find / -name gd.h ми не живет, попыток экспансии не предпринимает и, судя
/usr/include/gd.h по последним тенденциям, скорее всего через некоторое
время будет окончательно вытеснен своим многофункцио-
Теперь вы можете уверенно сказать, чему должны быть нальным противником. Предназначен только для Netscape
равны параметры --with-gd-lib и --with-gd-inc команды Navigator и Internet Explorer. Скачать дистрибутив можно от-
configure. Выполняем ее со всеми необходимыми настрой- сюда: http://members.aol.com/maxmac/vrml/download.html.
ками и, как описано выше, проверяем, найдена ли биб- FreeWRL – отдельное приложение, работающее в ка-
лиотека GD. И наконец, проводим компиляцию и инстал- честве самостоятельного vrml-браузера. Функционирует
ляцию, не забыв остановить демона Nagios. После этого на платформах Linix и MAC и располагается по этому ад-
карта сети (statusmap.cgi) должна приобрести вид, при- ресу: http://www.crc.ca/FreeWRL/.
мерно похожий на этот: Следующий экземпляр в нашем списке называется
VRwave и проживает тут: http://www.iicm.edu/vrwave. Пред-
назначен для Linux и Windows. Замыкает стройные ряды vrml-
клиентов OpenVrml, обитающий сугубо под Linux: http://
sourceforge.net/project/showfiles.php?group_id=7151
&release_id=192066. Кстати, стоит сделать маленькую ре-
марку по ходу изложения. Практически все программы, ко-
торые мы назвали предназначенными под Linux, теорети-
чески должны работать и под другими Unix-подобными си-
стемами, в состав которых входит графический сервер X11.
На самом деле программ, подходящих для наших це-
лей, гораздо больше, чем вы могли бы подумать. Я поста-
рался упомянуть лишь наиболее известные из них. Если
же вы хотите непременно огласить весь список, то вам нуж-
но провести поиск по слову vrml на следующих серверах, в
народе ласково называемых софтомогильниками:

№12(13), декабрь 2003 51


администрирование
 http://sourceforge.net
 http://freshmeat.net
 http://tucows.com
 http://filesearch.ru

А здесь: http://www.chuvsu.ru/download/vrml/browsers/
можно найти очень неплохую подборку vrml-клиентов для
Windows.
Надеюсь, что среди подобного разнообразия вы сможе-
те самостоятельно подобрать себе инструмент по вкусу.
Теперь сделаем перерыв в изучении теории и попрак-
тикуемся в том, как правильно провести инсталляцию и По окончании инсталляции текущая страница в брау-
использование Cortona VRML Client в связке с браузером зере должна обновиться. И в центре нее появится враща-
Microsoft Internet Explorer. Сделать это можно двумя спо- ющийся куб.
собами. Начнем с самого простого.
С помощью браузера идем по адресу: ht tp://
www.parallelgraphics.com/products/cortona/download/ и,
выбрав нужный тип браузера, пользуемся кнопкой
«online install».

На этом первый способ инсталляции можно считать


оконченным. Если в процессе выполнения этих инструк-
ций что-то пошло не так, как должно было, и установка
завершилась неудачно, то огорчаться не стоит. Можно
выполнить все требуемые действия вручную.
Обратите внимание на пустой прямоугольник в цент- Итак, переходим ко второму способу инсталляции.
ре страницы. Его появление означает, что в вашем брау- Скачиваем дистрибутив, подходящий для нашего брау-
зере нет vrml-модуля. Нажимаем на кнопку «Install Now». зера. После запуска принимаем лицензионное соглаше-
После того как процесс скачивания закончится, перед ние и несколько раз жмем кнопку «Next». После распа-
нами появится следующее окно: ковки файлов на экране должно появиться что-то вроде
такой картинки:

Система может задуматься на минуту-другую, а затем


снова очнется и начнет задавать вопросы.

Жмем «Yes» в знак того, что мы доверяем цифровой


подписи ParallelGraphics LTD. Подобный механизм циф-
ровых подписей для всех скачиваемых программ помога-
ет избежать подмены или порчи дистрибутива во время
его путешествия через сеть. Требуется уточнить, каким образом мы будем отрисо-
На следующем экране выставляем во всех окошках вывать vrml-сцены. Выбирайте один из пунктов в зависи-
галочки. Таким образом, мы назначаем vrml-клиента мости от программного обеспечения, установленного в
программой по умолчанию для обработки файлов wrl, вашей системе. Если вы ошибетесь, и у вас нет выбран-
wrml и wrz. ного компонента, то ничего страшного не произойдет. Си-

52
администрирование
стема самостоятельно переключит отрисовку в программ-
ный режим.

В открывшемся меню выберем пункт «Preferences». А


затем, воспользовавшись вкладкой «Render», выбираем
альтернативный механизм рендеринга.
Лично я – человек ленивый, и не люблю читать readme-
файлы без нужды, поэтому на следующем экране отклю-
чаю такую возможность. А вот во втором окошке галочку
лучше оставить нетронутой, потому что это позволит нам
проверить, правильно ли работает vrml.
Вслед за нажатием кнопки «Next» на экране появит-
ся 3D-сцена, изображающая постепенно расцветающую
розу.

Думаю, вы сможете легко самостоятельно разобрать-


ся с настройками и изучить способы перемещения в трех-
мерном виртуальном пространстве. Теперь можно посмот-
реть на 3D-карту Nagios.

Если нам не удалось правильно угадать нужный ре-


жим отрисовки, то рядом откроется окно консоли с соот-
ветствующим сообщением.

Выглядит она пока не так уж и красиво, но дайте вре-


мя, и все еще изменится к лучшему.
А теперь вновь одним прыжком вернемся к плоской
карте сети statusmap.cgi.
Для того чтобы избавиться от этой надоедливой по- Для наглядности давайте представим, что наша сис-
мехи, закрываем окно консоли и щелкаем правой клави- тема мониторинга наблюдает за сетью, изображенной на
шей мыши в середине окна с 3D-сценой. следующем рисунке:

№12(13), декабрь 2003 53


администрирование
У нас есть две отдельные подсети, созданные на ос- check_command check-host-alive
max_check_attempts 10
нове управляемых коммутаторов 3com. Каждому из них notification_interval 120
выдан собственный IP-адрес. Таким образом, мы имеем notification_period 24x7
notification_options d,u,r
возможность проверять их работоспособность с помощью }
подключаемого модуля check_ping. Внутренняя сеть вклю-
define host{
чает в себя следующие компьютеры: use generic-host
 Nagios – система мониторинга; host_name 3com_Dmz
 Linux – рабочая станция на основе Linux; alias 3COM dmz switch
address 3com-dmz
 Win_2000 – рабочая станция на основе Windows 2000 parents Inner_Firewall
check_command check-host-alive
Professional. max_check_attempts 10
notification_interval 120
notification_period 24x7
Вторая сеть у нас используется как демилитаризован- notification_options d,u,r
ная зона. В нее включены серверы c именами WWW и }
Mail. Думаю, названия говорят сами за себя, и поэтому define host{
неудивительно, что на них запущены сервисы IMAP, POP3, use generic-host
host_name Mail
SMTP и HTTP. Между собой сети соединены с помощью alias Mail Server
машины, фигурирующей под именем Inner_Firewall. Вы- address mailer
parents 3com_Dmz
ход в Интернет защищает аппаратный межсетевой экран, check_command check-host-alive
называемый Outer_Firewall. В файле hosts.cfg содержат- max_check_attempts 10
notification_interval 120
ся следующие данные, полностью описывающие нашу notification_period 24x7
сеть и ее хосты: notification_options d,u,r
}
define host{ define host{
name generic-host use generic-host
notifications_enabled 1 host_name WWW
event_handler_enabled 1 alias WWW Server
flap_detection_enabled 1 address web
process_perf_data 1 parents 3com_Dmz
retain_status_information 1 check_command check-host-alive
retain_nonstatus_information 1 max_check_attempts 10
register 0 notification_interval 120
} notification_period 24x7
notification_options d,u,r
define host{ }
use generic-host
host_name Win_2000 define host{
alias Standard Windows Server use generic-host
address bianca host_name Outer_Firewall
parents 3com_Lan alias Hardware Firewall
check_command check-host-alive address outer-firewall
max_check_attempts 10 parents 3com_Dmz
notification_interval 120 check_command check-host-alive
notification_period 24x7 max_check_attempts 10
notification_options d,u,r notification_interval 120
} notification_period 24x7
notification_options d,u,r
define host{ }
use generic-host
host_name Linux
alias Linux Server Я думаю, что цитировать файл services.cfg с описани-
address lira
parents 3com_Lan ем сервисов нужды нет, потому что в нем нет ничего ин-
check_command check-host-alive тересного, да и для повествования он некритичен, кроме
max_check_attempts 10
notification_interval 120 того, каждый из вас может заполнить его нужными све-
notification_period 24x7 дениями за пять минут. Если же у кого-то из читателей
notification_options d,u,r
} это действо вызывает затруднение, то тогда им прямая
дорога в первую статью о Nagios. Прочитать ее можно в [1]
define host{
use generic-host либо на моем сайте: http://www.onix.opennet.ru.
host_name 3com_Lan К сожалению, Nagios пока не умеет строить карту
alias 3COM inner Lan switch
address 3com-lan сети, более или менее приближенную к реальному рас-
check_command check-host-alive положению наблюдаемых объектов внутри нее. Несмот-
max_check_attempts 10
notification_interval 120 ря на то что у нас есть две подсети на карте, все маши-
notification_period 24x7 ны отображаются так, как будто они находятся в одном
notification_options d,u,r
} и том же сетевом облаке, то есть все свалено в одну
кучу. С одной стороны, это упрощает процедуру рисова-
define host{
use generic-host ния карты, но с другой – усложняет жизнь администра-
host_name Inner_Firewall тора. Представьте себе ситуацию, когда из строя выхо-
alias Firewall PC
parents 3com_Lan дит машина Inner_Firewall. При следующем цикле выпол-
address inner-firewall нения проверок нас засыпет лавина уведомлений о кри-

54
администрирование
тическом состоянии хостов Inner_Firewall, WWW, Mail, ный факт, что фирменная документация в разделе
3com_Dmz и Outer_Firewall. Хотя на самом деле не рабо- «Determining Status and Reachability of Network Hosts» этот
тает только первый из всех вышеперечисленных компью- тег почему-то называет parent_hosts. Хотя если покопаться
теров. Получается, что администратор должен самостоя- в исходных текстах Nagios, то понимаем, что на самом
тельно догадаться, что привело к таким массовым сбоям. деле должен быть просто parents. Если в описании хос-
Для того чтобы впредь избежать подобных неприятнос- тов неукоснительно придерживаться указания использо-
тей, нам необходимо объяснить Nagios, как построена вать тег parent_host, то при попытке сделать nagios reload
наша сеть и каким образом добираться до ее самых уда- для того, чтобы применить изменения в конфигурации,
ленных уголков. Делается это с помощью создания отно- получим вот такие ошибки:
шений «родитель» – «потомок» между всеми нашими хо-
стами. После таких изменений критические уведомления Running configuration check...
Nagios 1.1
будут приходить только для компьютера Inner_Firewall, все Copyright (c) 1999-2003 Ethan Galstad (nagios@nagios.org)
остальные машины, задействованные в данной пробле- Last Modified: 06-02-2003
License: GPL
ме, получат статус «недоступно». Согласитесь, это все-
таки более соответствует действительному положению Reading configuration data...
вещей в контролируемых сетях. Error: Could not add object property in file
Прародителем всех компьютеров считается машина, '/usr/local/nagios/etc/hosts.cfg' on line 74.
на которой работает процесс системы мониторинга. И уже ***> One or more problems was encountered while processing
от него строится цепочка. the config files...
Check your configuration file(s) to ensure that they contain
valid directives and data defintions. If you are upgrading
from a previous version of Nagios, you should be aware that
some variables/definitions may have been removed or modified
in this version. Make sure to read the HTML documentation on
the main and host config files, as well as the 'Whats New'
section to find out what has changed.

failed - aborting reload.

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


ется тег parent_host. Думаю, других доказательств не нужно.
Машины, считающиеся локальными по отношению к
Nagios, находятся на одну ступеньку ниже в иерархии, и по-
этому не должны использовать тег parents в своем описа-
нии. Все остальные машины, относящиеся к группе удален-
ных, в вышеуказанном теге пишут имя ближайшего родите-
ля. Таким образом, для хостов Inner_Firewall, Linux и Win_2000
родителем является 3com_Lan. В свою очередь, Inner_Firewall
указан родителем для 3com_Dmz. А 3com_Dmz выполняет
ту же роль для хостов WWW, Outer_Firewall, Mail.
Итак, разобравшись с понятием иерархии, посмотрим,
как оно влияет на отображение наших сетей на карте.

Для правильной диагностики неполадок иерархия дол-


жна выглядеть так, как изображено на предыдущей схе-
ме. С точки зрения Nagios бывают два вида хостов – «ло-
кальные» и «удаленные». Локальными считаются те, кто
находится в том же сетевом сегменте, что и система мо-
ниторинга. Между ними не должно быть ни маршрутиза-
торов, ни межсетевых экранов. Если бы у нас были неуп-
равляемые коммутаторы, не поддающиеся мониторингу,
то локальными хостами считались бы Linux и Win_2000.
Но в связи с тем, что между ними есть промежуточное
звено в виде коммутатора 3com_Lan, который можно под-
вергнуть мониторингу, они переходят в разряд удаленных.
А единственным локальным становится 3com_Lan.
Добиться этого можно применением тега parents в оп-
ределении хостов. Стоит обратить внимание на тот стран-

№12(13), декабрь 2003 55


администрирование
ших сетей. Тут нам на помощь приходят два новых фай-
ла. Первый из них, hostextinfo.cfg, отвечает за добавоч-
ные атрибуты хостов, а второй, serviceextinfo.cfg, выпол-
няет ту же функцию для сервисов.
Кстати, не забудьте скачать отсюда: http://nagios.org/
download/extras.html файлы с коллекциями иконок, обыч-
но называемые image packs.
Итак, начнем с файла hostextinfo.cfg.

define hostextinfo{
# Òåã, ñ êîòîðîãî äîëæíî íà÷èíàòüñÿ îïèñàíèå õîñòà
host_name 3com_Lan
# Èìÿ õîñòà, ê êîòîðîìó îòíîñèòñÿ îïèñàíèå
icon_image 3Com.png
# Èìÿ ôàéëà èêîíêè, êîòîðàÿ áóäåò îòîáðàæàòüñÿ ðÿäîì ñ èìåíåì
# õîñòà. Èêîíêà ìîæåò áûòü â ôîðìàòå GIF, PNG èëè JPG. Ìîæåò
# ñîäåðæàòü âíóòðè ñåáÿ ïðîçðà÷íûå îáëàñòè. Æåëàòåëüíî,
# ÷òîáû èêîíêè áûëè ðàçìåðîì 40x40 ïèêñåëåé. Ðàñïîëàãàòüñÿ
# îíè äîëæíû â äèðåêòîðèè logos. Îáû÷íî ýòà äèðåêòîðèÿ
# íàõîäèòñÿ â /usr/local/nagios/share/images/logos

icon_image_alt 3Com LAN Switch


# Íàäïèñü, îòîáðàæàåìàÿ, åñëè âåá-ñåðâåðó íå óäàåòñÿ
# çàãðóçèòü èêîíêó

vrml_image 3Com.png
# Èìÿ ôàéëà, êîòîðûé áóäåò èñïîëüçîâàòüñÿ êàê òåêñòóðà äëÿ êóáà,
# èçîáðàæàþùåãî õîñò íà òðåõìåðíîé êàðòå. Ìîæåò áûòü â ôîðìàòå
# PNG, JPG, GIF. Êàðòèíêà íå äîëæíà ñîäåðæàòü ïðîçðà÷íûõ
# îáëàñòåé, èíà÷å ýòî áóäåò âûãëÿäåòü î÷åíü ñòðàííî. Äîëæíà
# õðàíèòüñÿ â òîé æå äèðåêòîðèè, ÷òî è èêîíêà, îïèñàííàÿ
# òåãîì icon_image
statusmap_image 3Com.gd2
# Èìÿ ôàéëà, ãäå õðàíèòñÿ èçîáðàæåíèå, êîòîðîå áóäåò
# èñïîëüçîâàòüñÿ êàê èêîíêà õîñòà íà ïëîñêîé ñåòåâîé êàðòå.
# Ìîæåò áûòü â ôîðìàòå PNG, JPG, GIF, íî âñå-òàêè ëó÷øå,
# åñëè äëÿ ýòîãî ôàéëà áóäåò èñïîëüçîâàòüñÿ ôîðìàò GD2, ïîòîìó
# ÷òî äëÿ êàæäîãî öèêëà ðèñîâàíèÿ êàðòû èêîíêà áóäåò ñíîâà
# è ñíîâà ïðèâîäèòüñÿ ê âèäó, óäîáíîìó äëÿ áèáëèîòåêè GD.
# À ýòî çíà÷èò, ÷òî ìû áóäåì çðÿ âûïîëíÿòü îäíè è òå æå
# áåñïîëåçíûå âû÷èñëåíèÿ. Ìîæåò ñîäåðæàòü âíóòðè ñåáÿ
# ïðîçðà÷íûå îáëàñòè. Æåëàòåëüíî ÷òîáû èêîíêè áûëè ðàçìåðîì
# 40x40 ïèêñåëåé. Ðàñïîëàãàòüñÿ îíè äîëæíû â äèðåêòîðèè logos.
# Îáû÷íî ýòà äèðåêòîðèÿ íàõîäèòñÿ â /usr/local/nagios/share/
# images/logos

2d_coords 160,99
# Äâóìåðíûå êîîðäèíàòû òî÷êè, â êîòîðîé áóäåò íàõîäèòüñÿ öåíòð
# èêîíêè õîñòà íà ïëîñêîé êàðòå. Ìîãóò áûòü òîëüêî
# ïîëîæèòåëüíûìè ÷èñëàìè. Ðèñîâàíèå êàðòû íà÷èíàåòñÿ èç òî÷êè
# 0,0 êîòîðàÿ ÿâëÿåòñÿ âåðõíèì ëåâûì óãëîì êàðòû. Êîîðäèíàòû
# ïåðå÷èñëÿþòñÿ â ñëåäóþùåì ïîðÿäêå x, y
3d_coords 20.0,32.0,6.0
# Êîîðäèíàòû öåíòðà êóáà, ñèìâîëèçèðóþùåãî õîñò â ïðîñòðàíñòâå
# òðåõìåðíîé êàðòû. Ìîãóò áûòü êàê ïîëîæèòåëüíûìè, òàê è
Думаю, выглядит довольно впечатляюще. Какой из # îòðèöàòåëüíûìè ÷èñëàìè. Ðàçìåð îäíîé ñòîðîíû êóáà 0.5 åäèíèö.
способов отображения карты будет использоваться по # Îòðèñîâêà êàðòû íà÷èíàåòñÿ öåíòðà òðåõìåðíîé êàðòû, êîòîðûé
# íàõîäèòñÿ â òî÷êå ñ êîîðäèíàòàìè 0.0, 0.0, 0.0.
умолчанию, указывает параметр default_statusmap_layout. # Êîîðäèíàòû ïåðå÷èñëÿþòñÿ â ñëåäóþùåì ïîðÿäêå x, y, z
Для трехмерной карты такой параметр называется соот- notes_url http://192.168.80.2/nagios/notes/3com_lan.txt
# Ññûëêà íà àäðåñ, ïî êîòîðîìó ëåæèò ôàéë c äîïîëíèòåëüíûìè
ветственно default_statuswrl_layout. Оба этих параметра # ñâåäåíèÿìè î õîñòå. Ïðè ùåë÷êå íà ñïåöèàëüíûé çíà÷îê
скрываются внутри файла cgi.cfg. Кроме заметного с пер- # â áðàóçåðå áóäåò îòêðûò ýòîò ôàéë. Ýòî ïîëåçíî äëÿ çàïèñè
# ðàçëè÷íûõ ñâåäåíèé, êîòîðûå íå âîøëè â ñòàíäàðòíûé øàáëîí
вого взгляда лоска, мы к тому же приобрели более точ- # îïèñàíèÿ õîñòà Nagios. Íàïðèìåð, òàì ìîæíî íàïèñàòü äàííûå,
ное диагностирование сетевых неполадок. # îòâå÷àþùèå íà âîïðîñ, êòî èç àäìèíèñòðàòîðîâ îòâå÷àåò
# çà óïðàâëåíèå ýòèì ñåðâåðîì, ê êîìó îáðàùàòüñÿ â ñëó÷àå ïðîáëåì.
Все это, конечно, хорошо, но душа требует чего-то # Îáðàòèòå âíèìàíèå íà URL, èñïîëüçóåìûé äëÿ óêàçàíèÿ ïóòü
более красивого. Также хотелось бы уметь самостоятель- # ê ôàéëó. Äëÿ òîãî ÷òîáû ôàéëû ñ çàïèñêàìè ìîæíî áûëî õðàíèòü
# íà òîì æå õîñòå, ÷òî è Nagios, ÿ ñîçäàë äèðåêòîðèþ
но указывать расположение тех или иных объектов на # /usr/local/nagios/share/notes, è ïîýòîìó ìû òåïåðü ìîæåì
картах. Такая задача нам по плечу, и сейчас вы научи- # ïîëó÷èòü ê íåé äîñòóï èìåííî ïî òàêîìó URL.
}
тесь управлять важнейшими параметрами отрисовки се-
тевых карт. Для начала мы раздадим каждому хосту и define hostextinfo{
host_name Win_2000
сервису по красивой иконке, а затем расположим их так, notes_url http://listios.lan.domain.ru/Win_2000.html
чтобы они максимально совпадали с нашим рисунком, # Êñòàòè, ñòîèò îòìåòèòü, ÷òî äîáàâî÷íûå çàïèñêè î õîñòàõ ìîãóò
# õðàíèòü íå òîëüêî íà òîì æå õîñòå, ãäå ðàáîòàåò Nagios, íî è íà
основываясь на котором мы описывали содержимое на- # ëþáîì äðóãîì. Ãëàâíîå, ÷òîáû òàì ðàáîòàë âåá-ñåðâåð è URL

56
администрирование
# áûë ïðàâèëüíî ïðîïèñàí host_name WWW
icon_image win40.png # Èìÿ õîñòà, íà êîòîðîì ðàáîòàåò ñåðâèñ
icon_image_alt Windows workstation service_description HTTP
vrml_image win40.png # Èìÿ ñåðâèñà èç ôàéëà services.cfg
statusmap_image win40.gd2 notes_url http://192.168.80.2/nagios/notes/service_www.html
2d_coords 163,195 # Óæå ìíîãîêðàòíî âèäåííûé íàìè URL äëÿ äîïîëíèòåëüíûõ çàïèñîê
3d_coords 15.0,38.0,6.0 icon_image apache.png
} # Èìÿ ôàéëà èêîíêè, êîòîðàÿ áóäåò îòîáðàæàòüñÿ ðÿäîì ñ èìåíåì
# ñåðâèñà. Èêîíêà ìîæåò áûòü â ôîðìàòå GIF, PNG èëè JPG. Ìîæåò
define hostextinfo{ # ñîäåðæàòü âíóòðè ñåáÿ ïðîçðà÷íûå îáëàñòè. Æåëàòåëüíî, ÷òîáû
host_name Linux # èêîíêè áûëè ðàçìåðîì 40x40 ïèêñåëåé. Ðàñïîëàãàòüñÿ îíè äîëæíû
notes_url http://10.10.5.7/hostinfo.pl?host=Linux1 # â äèðåêòîðèè logos. Îáû÷íî ýòà äèðåêòîðèÿ íàõîäèòñÿ â
#  êà÷åñòâå URL äëÿ õðàíåíèÿ äîáàâî÷íûõ çàïèñîê ìîæíî èñïîëüçîâàòü # /usr/local/nagios/share/images/logos
# äàæå CGI. Â çàâèñèìîñòè îò äàííûõ, ïåðåäàííûõ â çàïðîñå, âû áóäåòå icon_image_alt Web Service
# ïîëó÷àòü ñâåäåíèÿ î òîì èëè èíîì õîñòå. # Íàäïèñü, îòîáðàæàåìàÿ, åñëè âåá-ñåðâåðó íå óäàåòñÿ çàãðóçèòü
icon_image_alt Linux Workstation # èêîíêó, ïðèâÿçàííóþ ê ñåðâèñó
vrml_image mandrake.gd2 }
statusmap_image mandrake.gd2
2d_coords 60,198 define serviceextinfo{
3d_coords 30.0,38.0,6.0 host_name WWW
} service_description SMTP
notes_url http://192.168.80.2/nagios/notes/service_www.html
define hostextinfo{ icon_image apache.png
host_name Mail icon_image_alt Web Service
notes_url http://192.168.80.2/nagios/notes/mail.html }
icon_image MailServer.png
icon_image_alt Mail Server define serviceextinfo{
vrml_image MailServer.png host_name Mail
statusmap_image MailServer.gd2 service_description SMTP
2d_coords 520,183 notes_url http://192.168.80.2/nagios/notes/service_smtp.html
3d_coords 20.0,44.0,6.0 icon_image smtp.png
} icon_image_alt Web Service
}
define hostextinfo{
host_name WWW define serviceextinfo{
notes_url http://192.168.80.2/nagios/notes/www_notes.html host_name Mail
icon_image openbsd.png service_description POP3
icon_image_alt WWW Server notes_url http://192.168.80.2/nagios/notes/service_pop3.html
vrml_image openbsd.gd2 icon_image pop3_imap.png
statusmap_image openbsd.gd2 icon_image_alt Web Service
2d_coords 439,186 }
3d_coords 20.0,54.0,6.0
} define serviceextinfo{
host_name Mail
define hostextinfo{ service_description IMAP
host_name Inner_Firewall notes_url http://192.168.80.2/nagios/notes/service_imap.html
notes_url http://192.168.80.2/nagios/notes/ icon_image pop3_imap.png
inner_fw_notes.html icon_image_alt Web Service
icon_image freebsd40.png }
icon_image_alt Inner Firewall
vrml_image freebsd40.png
statusmap_image freebsd40.gd2 Для того чтобы Nagios увидел созданные нами файлы
2d_coords 326,96 hostextinfo.cfg, serviceextinfo.cfg, нужно внести в файл cgi.cfg
3d_coords 17.0,55.0,6.0
следующие директивы.
}

define hostextinfo{ xedtemplate_config_file=/usr/local/nagios/etc/hostextinfo.cfg


host_name Outer_Firewall xedtemplate_config_file=/usr/local/nagios/etc/serviceextinfo.cfg
notes_url http://192.168.80.2/nagios/notes/
outer_fw_notes.html Я думаю, вы сможете самостоятельно положить фай-
icon_image firebox_small.png лы иконок в директорию /usr/local/nagios/share/images/
icon_image_alt Outer Firewall
vrml_image firebox_small.png logos/. Кстати, стоит обязательно убедиться, что все фай-
statusmap_image firebox_small.gd2 лы, создаваемые вами, принадлежат пользователю, от
2d_coords 620,80
3d_coords 16.0,42.0,6.0 имени которого работает Nagios, иначе вы будете очень
} долго недоумевать, почему никаких изменений в картах
не видно, хотя все сделано так, как в этой статье. К таким
define hostextinfo{ файлам относятся hostextinfo.cfg serviceextinfo.cfg иконки,
host_name 3com_Dmz
notes_url http://192.168.80.2/nagios/notes/3com_dmz.html записки и прочая мелкая живность.
icon_image 3Com.png Кстати, создавать самостоятельно файлы иконок в фор-
icon_image_alt 3Com DMZ LAN Switch
vrml_image 3Com.png мате библиотеки GD довольно просто. Мы говорили об этих
statusmap_image 3Com.gd2 файлах во время обсуждения тега statusmap_image фай-
2d_coords 480,73
3d_coords 14.0,56.0,6.0 ла hostextinfo.cfg. Для этого нужно взять файлы иконки в
} формате png и преобразовать его в формат GD с помо-
Теперь пришло самое время обсудить содержимое щью утилиты pngtogd2, поставлявшейся вместе с библио-
файла serviceextinfo.cfg. Принципы построения обоих фай- текой GD. Желательно, чтобы создаваемый файл был
лов довольно схожи. сохранен без компрессии изображения. Это позволит уве-
личить скорость работы функций библиотеки GD, отве-
define serviceextinfo{ чающих за загрузку в память и рисование иконок внутри

№12(13), декабрь 2003 57


администрирование
интерфейса Nagios. Если данные внутри файла не сжа- с ними довольно хорошо. Полюбоваться на результат мож-
ты, значит, не нужно тратить время на их распаковку. Учи- но на следующей картинке.
тывая малый размер наших картинок, сжатие не прине-
сет никакой выгоды.
Например, для конвертации файла www.png в www.gd2
нужно подать следующую команду:

$ /usr/local/bin/png2gd2 www.png www.gd2 4000 1


Теперь у каждого хоста и сервиса есть не только лич-
Я думаю, с первыми двумя параметрами все ясно. ная иконка, но и на страничке с подробной информацией
Третий указывает размер порции кодирования, и четвер- о каждом из них возникло вот такое изображение.
тый – наличие компрессии.
После некоторого количества наблюдений замечено,
что в качестве размера порции кодирования можно пи-
сать какое угодно число. Для исходных файлов малого
размера, к которым относятся и наши иконки, этот пара-
метр смысла не имеет. Если нажать на него, то можно почитать дополнитель-
И не забудьте подать процессу nagios команду «reload», ные сведения из файла, который мы описали тегом notes_url.
которая заставит его обновить конфигурацию. Во FreeBSD Координаты точек, в которых должны рисоваться икон-
это обычно делается так: /usr/local/etc/rc.d/nagios.sh reload. ки и объекты наших хостов на плоской и трехмерной кар-
Если есть желание, можно нарисовать свои собствен- тах сети, не будут использоваться Nagios до тех пор, пока
ные иконки и использовать их вместо стандартных. Я имен- мы не выставим вот таким образом значения тегов
но так поступил с сервисами HTTP, SMTP, POP3 и IMAP. default_statusmap_layout и default_statuswrl_layout в фай-
Для HTTP использовалось перо, потерянное индейцем ле cgi.cfg.
Apache, а для всех остальных изображение открытого и
закрытого почтового конверта. И хотя картинки получились default_statusmap_layout=0
размером чуть более, чем 40x40 пикселей, Nagios работал default_statuswrl_layout=0

58
администрирование
Если вы все сделали правильно, то плоская карта сети Давайте посмотрим, что нужно сделать для того, что-
будет выглядеть вот так: бы это работало на примере файла status.cgi. В директо-
рии /usr/local/nagios/share/ssi нужно создать следующие
файлы:
 common-footer.ssi – файл глобального заголовка
 common-header.ssi – файл глобальной вставки
 status-footer.ssi – файл локального заголовка
 status-header.ssi – файл локальной вставки

Я думаю, все уже сообразили, что имя для файлов


локального заголовка и локальной вставки образуется с
Впечатляет, не правда ли? помощью сращивания имени подопытного файла cgi с
надписями -footer.ssi и -header.ssi. Нужно помнить, что
содержимое всех вышеперечисленных файлов перед до-
бавлением в целевой файл никак не обрабатывается, то
есть создать динамические заголовки и вставки без бе-
зумных ухищрений не получится, потому что нет возмож-
ности использовать в качестве генератора данных cgi или
что-либо другое. Получается, что включаемые файлы
должны содержать в себе только чистый html.
Давайте рассмотрим содержимое всех файлов, при-
менявшихся в этом примере:

Ôàéë common-footer.ssi
<p>
<center>
Трехмерная карта выглядит тоже довольно хорошо. И <h2> Ïî âîïðîñàì òåõïîääåðæêè îáðàùàòüñÿ íà tigrisha@sysadmins.ru
èëè
самое приятное в этом то, что в трехмерное простран- <a href="http://onix.opennet.ru">http://onix.opennet.ru</a> </h2>
ство можно добавить, например, подробный макет зда- </center>
</p>
ния, в котором эта сеть находится, и поставить сервера в
нужных помещениях. Но об этом мы поговорим в другой Ôàéë common-header.ssi
<p>
статье. Ну а если вместо вожделенной карты на экране <center>
появилась следующая надпись: <img src="../images/onix.png" border="0" alt="Nagios">
</center>
</p>
You have not supplied any host drawing coordinates, so you
cannot use this layout method. Read the FAQs for more information Ôàéë status-footer.ssi
on specifying drawing coordinates or select a different layout <p>
method. <center>
<h2> Ðàçäåëèòåëü ñòðàíèöû status.cgi</h2>
</center>
Значит, вы что-то напутали с тегами координат отрисовки. </p>
Еще одной из полезных возможностей, которую мы Ôàéë status-header.ssi
сегодня изучим, будет умение добавлять в страницы, со- <p>
<center>
здаваемые Nagios, свои вставки и заголовки. Каждая стра- <h2>Òåñòîâûé çàãîëîâîê status.cgi</h2>
ница может иметь два заголовка и две вставки. Обычно </center>
</p>
таким образом в текст страницы можно вставлять корпо-
ративную символику, справочные телефоны и прочие све- Как вы могли убедиться, все это работает довольно
дения, относящиеся к выбранной странице. просто. Еще одной вкусностью, которой я с вами поде-
Все заголовки страниц и вставки делятся на глобаль- люсь, будет способность привязывать проигрывание зву-
ные и локальные. Глобальные действуют на все страни- ковых файлов к определенным событиям. Например, моя
цы cgi, а локальные только на те, для которых они были система мониторинга при умирании какого-либо сервиса
определены. Тексты, записанные в файлах заголовков и начинает изображать жалобно мычащую корову. Такая
разрывов страниц, вставляются в начало и конец тега возможность очень полезна для администраторов, кото-
<BODY> </BODY>страницы, создаваемой cgi. рые не хотят постоянно смотреть на веб-интерфейс Nagios
Обычно текст страницы после обработки выглядит так: или ежеминутно проверять свой почтовый ящик на пред-
мет уведомлений о проблемах. Нужно всего лишь открыть
<BODY> в браузере или прикрепить на Active Desktop одну из этих
ãëîáàëüíûé çàãîëîâîê
ëîêàëüíûé çàãîëîâîê страниц tac.cgi, status.cgi. После этого можно минимизи-
ровать браузер и заниматься своими делами. Как только
ïåðâîíà÷àëüíûé òåêñò
случится какое-либо интересующее нас событие, Nagios
ãëîáàëüíàÿ âñòàâêà начнет воспроизводить звук, связанный с ним. Для осу-
ëîêàëüíàÿ âñòàâêà
</BODY> ществления наших желаний есть следующие теги:

№12(13), декабрь 2003 59


администрирование
 host_unreachable_sound – хост недоступен; легко: нужно просто войти в режим управления сервисом
 host_down_sound – хост не работает; или хостом и подать команду подтверждения проблемы.
 service_critical_sound – сервис в критическом состоя-
нии;
 service_warning_sound – сервис в состоянии предупреж-
дения;
 service_unknown_sound – состояние сервиса неизвес-
тно;
 normal_sound – все работает отлично, нет никаких про-
блем.

Опцию normal_sound практически никто не использу-


ет. Но на всякий случай я решил ее упомянуть.
Для того чтобы звуковое оповещение заработало, нуж-
но поместить файлы звуков в формате wav внутрь дирек-
тории /usr/local/nagios/share/media/, как всегда, не забыть
о правах пользователя и принадлежности файлов. А за-
тем добавить следующие записи в файл cgi.cfg.
После подобной обработки записи в таблице серви-
host_unreachable_sound=hostunreachable.wav сов или хостов примут вот такой вид:
host_down_sound=host down.wav
service_critical_sound=servicecritical.wav
service_warning_sound=servicewarning.wav
service_unknown_sound=service unknown.wav
normal_sound=noproblem.wav

В случае если в процессе мониторинга будет обнару-


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

Литература:
1. Бешков А. Установка Nagios. – //Журнал «Системный администратор» №2(3), февраль 2003 г. – 6-14 с.
2. Бешков А. Мониторинг Windows-серверов с помощью Nagios. Часть 1. – //Журнал «Системный администратор»
№7(8), июль 2003 г. – 12-19 с.
3. Бешков А. Мониторинг Windows-серверов с помощью Nagios. Часть 2. – //Журнал «Системный администратор»
№8(9), август 2003 г. – 12-23 с.

60
hardware

ВТОРАЯ ЖИЗНЬ МОДЕМОВ

ПАВЕЛ ЗАКЛЯКОВ
62
hardware
Лирическое отступление старыми техническими решениями, то за них это дела-
Если на обычном, пользовательском компьютере у вас ют пользователи. В конкретном примере выше это «от-
стоит два модема, то это, наверное, уже много, а вот если ставание» было в вопросах организации резервной сети
говорить о серверах, то модемов много не бывает. Про- связи, выделения более широкого канала доступа к Ин-
стой пример: распределённая сеть узлов, единый центр. тернету и организации безопасного удалённого досту-
Узлы связываются с центром и/или центр с узлами. На па. Нередко администраторы вообще не знают о том, что
центральный узел осуществляется DDoS-атака. Как в этом определённые виды трафика разумнее делать более при-
случае связываться и передавать данные? Хорошо, если оритетными по сравнению с другими. (Например, с по-
это происходит в Москве или другом крупном городе, где мощью битов поля TOS в заголовках IP-пакетов.)
пальцем ткни, попадёшь в какого-нибудь провайдера. Не- Чтобы такого не происходило и администратор был
сколько тысяч долларов, и у вас будет несколько резерв- всегда «на высоте», рассмотрим несколько вопросов, свя-
ных каналов связи на такой случай. Усугубим проблему, занных с использованием модемов.
а если узлы находятся в других городах? Вот и получает-
ся, что самое оптимальное и по цене, и по реализации Какие задачи можно решать
решение, если нет необходимости в создании видеокон- с помощью модемов?
ференций, – создание резервной модемной сети связи. 1. Можно организовать резервную сеть связи. Если у
По моему мнению, даже в простой маленькой сетке дол- организации несколько филиалов в разных городах,
жен быть на сервере модем, например, на случай пере- то это вполне здравое решение. Оплатить межгород
дачи срочной почты, если упадёт основной канал подклю- может оказаться дешевле, чем заказать иные виды ре-
чения к Интернету. зервной связи. Следует отметить, что если и имеется
Замечание: в недавние времена в столице, когда под- тенденция к замене АТС на более современные циф-
ключиться по выделенной линии было дорого, многие со- ровые, то темпы замен заметно отстают от последних
здавали домашние локальные сети, скидывались на один модемных решений. Это означает, что для связи с ка-
общий телефон и безлимитный dial-up-интернет. Получа- ким-нибудь сельским районом совсем не нужен самый
лось медленно, но всё же лучше, чем ничего, для почты и последний протокол v.92. Что и говорить, если посто-
ICQ вполне хватало на несколько человек. янно появляются небольшие заметки, как эти v.92 или
Во многих корпоративных сетях, если пропускная спо- v.90 отключить. Даже v.34 (28800) в условиях исполь-
собность подключения к Интернету мала и не предвидит- зования нескольких ретрансляторов междугородней
ся её увеличения, многие пользователи на своих рабо- связи может оказаться завышенным требованием.
чих местах имеют модемы, предпочитая соединяться по 2. Можно организовать резервную сигнальную сеть. Если
dial-up, когда общий интернет-доступ совсем не работа- денег нет на мобильные терминалы [6], нет денег на
ет [5, стр. 208-209]. Если в организации имеется центра- Интернет, либо деньги на Интернет есть, но ищется
лизованная политика безопасности, контролируются все более надёжное решение (с меньшим числом исполь-
подключения к Интернету, то такого быть не должно. Зло- зуемых элементов), то возможна организация отправ-
умышленники и так постоянно пытаются обойти средства ки пейджинговых сообщений с помощью тонального
защиты, а тут появляется удобная лазейка для них. За- набора.
чем пытаться взломать МЭ снаружи, когда можно с боль- 3. Можно использовать функцию «факс». Не секрет, что
шой лёгкостью взломать внутреннего модемного пользо- мы далеки от цивилизованной рекламы. Один раз раз-
вателя, установить у него cниффер и получить пароли для местив свой факсовый номер где-то в открытом ис-
доступа к МЭ. Конечно, есть пользователи, которые мо- точнике, справочнике или засветив его на какой-ни-
гут настроить свой персональный МЭ для модема не хуже будь выставке, вы обрекаете его на постоянные фак-
общего, но согласитесь, что это скорее исключение. совые рассылки отнюдь не по направлению вашей де-
Случаев неконтролируемого применения модемов до- ятельности. Вопрос имеет глубокие юридические кор-
вольно много, многие из них описаны в литературе, в ча- ни, однако, если бороться со следствием, то можно ус-
стности А.Лукацкий [5] пишет: «В процессе проведения тановить факс-модем и, настроив mgetty (или vgetty),
аудита безопасности в одном из московских банков было научить его принимать факсы.
обнаружено несколько компьютеров, к которым были под- 4. Можно использовать функцию «автоответчика» и со-
ключены модемы. В процессе разбирательств выясни- путствующие ей. Голосовая почта и автоответчик мо-
лось, что только на одном из компьютеров применение гут зарегистрировать нужные звонки, проинформи-
модема было «узаконено» (для доступа к обновлениям ровать клиентов о часах работы вашей организации,
баз данных юридической консультационной системы). рассказать о наличии ресурсов в сети Интернет. Даже
Другие модемы были установлены сотрудниками, которые при небольшом умении может прайс-лист по запросу
использовали их для доступа в Интернет в обход МЭ ло- зачитываться по телефону. Если во времена 286-х
кальной сети банка. В одном случае на компьютере с под- были отечественные программки вроде spp.exe
ключённым модемом была найдена программа pcAnywhere, (www.samag.ru/sourse/spp.zip) порядка 44 Kб, которые
которая позволяла сотруднику работать с конфиденциаль- могли на PC Speaker читать понятно, без особой ин-
ными данными из собственного дома». тонации, при этом различая обычную интонацию и
Всё это говорит о том, что если системный админис- вопросительную, то сейчас, я думаю, вообще не про-
тратор или администраторы не успевают за новыми и блема научить компьютер читать текстовые файлы.

№12(13), декабрь 2003 63


hardware
* From : Anton Loginov, 2:5024/11.30@fidonet
=============================================================================

Áûëà òàêàÿ ïðîãðàììà – spp.exe, êîòîðàÿ çàñòàâëÿëà êîìïüþ-


òåð ïðîèçíåñòè ñïèêåðîì ôðàçó, çàäàííóþ â êîìàíäíîé ñòðîêå.
Ïðè ýòîì îíà ðàçëè÷àëà îáû÷íóþ èíòîíàöèþ è âîïðîñèòåëüíóþ.
Ïðîãðàììà áûëà ðóññêàÿ. Ñðåäè ïðî÷èõ áóêâ îíà çíàëà è ðàçíûå
ñèìâîëû, íàïðèìåð íà $ ãîâîðèëà «äîëëàðû».
Èòàê – íî÷ü, ëóíà, çà êîìïüþòåðîì ñèäèò óñòàëûé ñèñòåìíûé
îïåðàòîð, è ðàçáèðàåò User's UpLoad íà ñâîåé BBS. Âèäèò –
ïðîãðàììà spp.exe áåç êîììåíòàðèÿ. Õîòåë îí å¸ óæå F8, íî
ëþáîïûòíî ñòàëî – ÷òî îíà äåëàåò?
Ñîñòîÿëñÿ ñëåäóþùèé äèàëîã:
Ñèñòåìíûé îïåðàòîð: spp.exe
Êîìïüþòåð: "ïøø-ñññ..." – ëåãêîå øèïåíèå ñïèêåðà, òèïà õî-
òåë ãîâîðèòü, à íå÷åãî!
Ñèñòåìíûé îïåðàòîð: spp.exe /?
Êîìïüþòåð, ãîëîñîì ðîáîòà ñ ë¸ãêèì ãðóçèíñêèì àêöåíòîì:
KÎÑÀß ÑKÎÁKÀ ?
Ñèñòåìíîãî îïåðàòîðà ÷óòü óäàð íå õâàòèë – äóìàë ãëþêè ó
íåãî íà÷àëèñü... Âîò êàê áûâàåò.

5. Можно сделать BBS (Bulletin Board System). Хотя пос-


ледний раз я коннектился к BBS и провёл несколько
ночных часов уже как лет 7 назад, не меньше, так что
не знаю, актуальны они ещё или нет.
6. Можно сделать почтовый (UUCP) сервер. До сих пор есть
провайдеры, которые помимо обычного набора протоко-
лов для организации доступа и работы с почтой tcp/ip/ppp
+ pop3/imap/smtp позволяют почту забирать по UUCP. А в
школе, где я учился, и по сегодняшний день висит UUCP-
почта для внутреннего обмена сообщениями, поднятая
моим бывшим одноклассником на базе Red Hat Linux v.5.2.
Uptime-системы уже исчисляется тысячами дней.

Замечание: имеется неплохой клиент для приёма и ре-


дактирования сообщений для DOS. Так что, имея загру-
зочную дискету, 286, хоть с монохромным CGA-монитором,
и модем можно быть равноправным участником почтового
обмена и по сей день!
7. Можно сделать ФИДО-шный почтовый сервер (node).
Для этого, правда, если не изменились порядки, для
начала придётся побыть обычным пользователем ФИДО
(point) порядка полгода. Ðèñóíîê 1. Âíåøíèé âèä ìîäåìîâ:
a) U-1496B+
8. Можно поднять dial-in-сервер, скажем, для доступа в á) U-1496E+
Интернет. â) U-1496S+(U-1496+)
9. Можно сделать шлюз IP-телефонии при наличии дос- Именно доступность на рынке (цены порядка $7-20),
таточных функций у модема, хотя, честно признаюсь, высокое качество и широкий набор услуг обусловили мой
ни у кого такого не видел, и скорее эта возможность выбор. Конечно, можно было взять и другие модели. Но
теоретическая. тут критерий выбора был таков: если модемы ZyXEL, в
10. Можно объединить частично или полностью вышеупо- частности U-1496S+ и USR Courier используются в банко-
мянутые возможности. матах, то на них и стоит ставить свой выбор по надёжно-
сти. Касаемо хорошо работающих Courier, так они доро-
Какой модем купить? ги, и я встречал глючные Courier, купленные дороже чем
По поводу подключения нескольких модемов и модемных $150, может, это было исключение, но реализация того
пулов мы поговорим ниже. А пока заметим, что не все пун- же ZyXEL под шину ISA (с определителем и голосовыми
кты реализуемы всеми модемами, поэтому для решения функциями) обойдётся куда дешевле ($7-10). Конечно,
той или иной задачи лучше остановить выбор на лучших шина ISA сейчас не везде есть, но зато те, у кого она есть,
моделях. Каждый волен выбирать, что ему больше нравится могут в полной мере получить от неё пользу. За $100 мож-
и больше подходит по цене. Я свой выбор остановил на но собрать неплохо работающий сервер с не одним моде-
старых профессиональных модемах фирмы ZyXEL серии мом на базе какого-нибудь Pentium.
1496. Что ни говори, а стоечные версии и модемные пулы Перед тем как разобрать модемы и начать их улуч-
дороги, посему лучше выбирать профессиональные моде- шать, хотелось бы сделать небольшой ликбез в области
ли ближе к пользовательскому классу. На мой взгляд, та- постоянной памяти, так как мы столкнёмся непосредствен-
ковыми являются три модели: ZyXEL U-1496B+, U-1496E+, но с ней. Те, кто знакомы с устройством и видами посто-
U-1496S+, либо без «+». янной памяти, могут смело пропустить этот раздел.

64
hardware
Организация постоянной памяти Использовать 1024 вывода для выбора нужной ячейки
также неразумно. На практике для выбора нужной ячейки
ПЗУ используется несложный декодер, встроенный в то же ПЗУ,
ПЗУ – постоянное запоминающее устройство, оно же ROM, преобразующий двоичный параллельный сигнал в выбор
Read Only Memory. Рассмотрим на пальцах работу данной нужной линии (ячейки) ПЗУ. Дорисовав последовательно с
схемы. В первом приближении для организации такой па- каждым диодом плавкие предохранители, целые, если диод
мяти ничего сложного не надо – простые перемычки, и ус- есть, и сгоревшие предохранители вместе с диодами, если
тройство готово. их в схеме нет, мы получим схему, более-менее приближаю-
щуюся к реальности и встречающуюся в литературе.
На практике организация записи в ПЗУ организуется
по-разному. Если тираж очень большой, то дешевле полу-
чается штамповать уже зашитые ПЗУ, как обычные алю-
миниевые CD. Если тираж меньше и заранее неизвестно,
что будет прошито, то дешевле обходится производить
матрицы с диодами и предохранителями, после чего про-
жигать предохранители у ненужных ячеек либо на заводе-
изготовителе, либо продавать непрошитые микросхемы. В
данные микросхемы возможно осуществить одноразовую
запись. Что-то вроде обычного CD-R получается, правда,
Ðèñóíîê 2. Âíóòðåííåå óñòðîéñòâî îäíîé ÿ÷åéêè ïàìÿòè íà 8 áèò. аналога мультисессионности тут пока не придумали. По
Çàïèñàííîå ÷èñëî (01101011) аналогии с пишущими приводами для записи CD существу-
При подаче напряжения на вход, например, логичес- ют программаторы, осуществляющие запись.
кой «1», на выходах, соединённых с входом, появится тоже Если на диоды, используемые при выборе какой-то ячей-
«1». На неподключенных выходах (болтающихся в возду- ки памяти, посмотреть внимательно, то можно заметить,
хе) будет «0». Если надо запомнить два байта, берём два что у всех у них используется общий анод (или катод, если
таких устройства, если нужно запомнить n2 байт, берём модифицировать схему). То же самое можно сказать про
n2 таких устройств. Легко заметить, что подобная линей- любую ячейку, у диодов, ответственных за её выбор, име-
ная организация неудобна и избыточна, поэтому на прак- ются общие выводы. Если взять половину транзистора, не
тике используется двухмерная реализация, когда для сня- обращая внимания на всё остальное, то это по сути тот же
тия данных используются одни и те же выводы. Потеря самый p-n переход. На практике, при реализации схемы в
пропускной способности (нельзя параллельно считывать интегральном исполнении, оказывается более выгодным
все ячейки) компенсируется значительным упрощением вместо отдельных групп диодов создавать n-p-n транзис-
схемы. Для того чтобы сигналы с разных ячеек не меша- торы с несколькими эмиттерами. Поэтому нередко ту же
ли друг другу, используются диоды. самую электрическую схему организации ПЗУ можно уви-
деть с транзисторами в следующем виде.

Ðèñóíîê 3. Âíóòðåííåå óñòðîéñòâî 2-õ ÿ÷ååê ïàìÿòè (4 + 4 áèòà),


çàïèñàíî: 1101 è 0101 Ðèñóíîê 4. Ñõåìà ÏÏÇÓ ïîñòðîåííàÿ:
à) íåóäîáíûé ñïîñîá èçîáðàæåíèÿ a) íà äèîäàõ
á) óäîáíûé ñïîñîá èçîáðàæåíèÿ á) íà ìíîãîýìèòòåðíûõ òðàíçèñòîðàõ

№12(13), декабрь 2003 65


hardware
При занесении информации через диоды или эмитте- этот затвор не будет помещён заряд. Для этого между исто-
ры шин с информационными нулями пропускаются боль- ком и стоком прикладывается напряжение около 30 В, при
шие токи, выжигающие плавкие перемычки. При подаче этом происходит лавинный пробой, на затворе образуется
адресного импульса сигналы появляются только на тех остаточный заряд достаточный для образования канала под
выводах, где перемычки сохранены. Так как прошивка затвором. Положительный заряд на затворе притягивает сво-
данного вида ПЗУ возможна один раз в жизни, то в зару- бодные электроны из подложки, а притянутые электроны
бежной литературе данный вид ПЗУ помимо ROM имеет создают канал, способный проводить электрический ток.
ещё одно название OTP ROM (One-Time Programmable Транзистор становится проводящей цепью. Если заряды на
ROM), иногда One-Time опускают и получается ещё одно плавающем затворе не накоплены, то данный транзистор
более общее название PROM (Programmable ROM). ток не проводит. Таким образом можно различать логичес-
В случае, если необходимо иметь возможность редкой кие «1» и «0». Для стирания данных с ПЗУ необходимо уда-
перепрошивки записанных данных, следует использовать лить накопленный на плавающем затворе заряд. Для этого
ППЗУ. Замечание: современные ПЗУ могут иметь немного используют ультрафиолетовое излучение. Микросхемы дан-
отличную и своеобразную организацию, будучи построен- ного вида памяти имеют прозрачные окошечки, выполнен-
ными на полевых транзисторах либо смешанным образом. ные из кварцевого стекла. Обычно они заклеены чем-то не-
В этом случае единичный элемент может выглядеть и так. прозрачным. (Данные микросхемы мы встретим далее в мо-
демах ZyXEL.) Ультрафиолетовое излучение за счёт попа-
дания на кристалл и его ионизации позволяет постепенно
растечься накопленному заряду. В зависимости от интен-
сивности УФ-излучения процесс стирания может колебать-
ся от 10 минут и выше. Несмотря на то что для стирания
рекомендуется использовать освещённость порядка 100 Вт/
м2 при времени экспозиции 1 час, редко кто оказывается в
состоянии ждать такое количество времени.
Срок хранения информации в ПЛМОП ППЗУ практи-
чески бесконечен – постоянная времени утечки заряда со-
Ðèñóíîê 5. Îäèí èç âàðèàíòîâ îðãàíèçàöèè ýëåìåíòà ïàìÿòè ставляет десятки лет. У данной технологии также есть и
ñ ïîìîùüþ ïîëåâîãî òðàíçèñòîðà
минусы: малое число возможных циклов перепрограмми-
ППЗУ рования, примерно порядка 10, плюс для стирания необхо-
ППЗУ – перепрограммируемое ПЗУ, ППЗУ с УФ-стирани- димо наличие источника УФ-излучения и другие связан-
ем, EPROM (Erasable, Programmable, Read-Only Memory), ные с этим неудобства. Так как у ПЛМОП-транзисторов нет
UV-EPROM (UltraViolet EPROM). Несколько более доро- затвора, то для выбора одного элемента памяти, как один
гая технология, чем одноразовые ПЗУ, имеющая некото- из вариантов, последовательно с ними включаются обыч-
рые преимущества. В случае выполнения определённых ные полевые транзисторы, что, несомненно, усложняет схе-
действий позволяющая стирать старые и записывать но- му. Следующая технология лишена этих недостатков.
вые данные. По внутреннему устройству данная память
отличается от обычных ПЗУ. Вместо диодов и многоэмит- ЭС ППЗУ
терных транзисторов используются специальные полевые Электрически стираемые ППЗУ, EEPROM, E2PROM
МДП (металл-диэлектрик-проводник)-транзисторы, в ча- (Electrically Erasable PROM), как легко предположить из на-
стности МОП (металл-оксид кремния(окисел)-проводник) звания, вместо ультрафиолетового излучения для стира-
c плавающим затвором. ния используется электрический ток. В районе 1967 года
для решения вышеописанных неудобств с УФ ППЗУ, в ча-
стности, невозможности электрического стирания, были
придуманы новые решения. В качестве ячейки памяти было
предложено использовать транзисторы, выполненные по
новой на то время МНОП (металл – нитрид кремния – оксид
кремния(окисел) – полупроводник) или МАОП (металл –
алунд – оксид кремния – полупроводник)-технологии.

Ðèñóíîê 6. Ïîëåâîé òðàíçèñòîð ñ ïëàâàþùèì çàòâîðîì (ÏËÌÎÏ)


Из рисунка легко понять, почему затвор, состоящий из
поликристаллического кремния, называется плавающим. Он
со всех сторон окружён двуокисью кремния, не имеет выво-
дов и соединений с остальной схемой. Такой транзистор
представляет собой разомкнутую цепь до тех пор, пока на Ðèñóíîê 7. Òðàíçèñòîð, âûïîëíåííûé ïî ÌÍÎÏ-òåõíîëîãèè

66
hardware
Транзистор, выполненный по МНОП-технологии, пред- составляет 128 Кб, то это означает, что следует выпол-
ставляет из себя обычный МДП-транзистор, в котором ди- нить порядка одного миллиона стираний. Следует отме-
электрик состоит из двух слоёв. Поверх обычного диок- тить, что это не самый большой размер встречающейся
сида кремния, используемого в МОП-транзисторах, нане- на сегодня памяти. Для упрощения процесса стирания,
сён ещё слой нитрида кремния. Нитрид кремния облада- чтобы это можно было сделать одной или несколькими
ет очень высоким сопротивлением, значительно большим, командами, схема ЭС ППЗУ была немного внутренне ус-
чем диоксид кремния. Эффект памяти в МНОП-транзис- ложнена и появилась на свет так называемая flash-
торах основан на изменении порогового напряжения тран- EEPROM-память или flash-память. В технологии непосред-
зистора при наличии захваченного в подзатворном диэ- ственного хранения и записи информации во flash-памя-
лектрике положительного или отрицательного заряда, ти ничего нового не появилось. Сейчас это наиболее хо-
который хранится на глубоких (1.3-1.5 эВ) ловушках, в довая и удобная память, используемая в компьютерной и
нитриде кремния вблизи границы SiO2-Si3N4 [11]. (В тран- бытовой технике. Технология выпуска flash-памяти не-
зисторах памяти фирмы Hitachi толщина слоя окисла со- сколько дороже всех предыдущих, но получаемые преиму-
ставляет порядка 20 ангстремов, а нитрида кремния – щества с лихвой окупают повышение затрат.
порядка 300-500 ангстремов [12].) Если на затвор подать Замечание 1: в некоторой литературе flash-EEPROM пе-
напряжение порядка 30 В относительно подложки, то в реводится как мигающий-EEPROM, моё мнение, что это не
течение 5 мс между тонким слоем окиси кремния и слоем совсем правильно, если дословно перевести слово flash, то
нитрида кремния под затвором за счёт туннельного эф- получится вспышка. Скорее всего, этот смысл и закладыва-
фекта появятся неподвижные заряды. На образование то- ли разработчики данной технологии, насколько быстра
копроводящего канала между истоком и стоком будет вспышка, настолько быстро и осуществляется стирание дан-
влиять суперпозиция двух полей, от затвора и от накоп- ных из памяти. Помимо этого, если посмотреть на техноло-
ленных в ловушках зарядах. Этим и объясняется следую- гию стирания УФ ППЗУ, о которой написано чуть выше, то
щая ВАХ МНОП-транзистора. именно вспышка как раз лучше всего подходит по смыслу.
Замечание 2: в иностранной литературе наблюдается
некоторая путаница, так, у них имеется ещё одно сокра-
щение для обозначения ЭС ППЗУ, а именно EAROM
(Electrically Alterable ROM). По сути ничего нового не при-
думано, однако имеются два различных способа обозна-
чений, частично противоречащих друг другу: часто схе-
мы запоминающих устройств с более высокой ёмкостью
обозначают как EEPROM, а с меньшей как EAPROM. Так-
же через EEPROM иногда обозначают схемы запоминаю-
Ðèñóíîê 8. ÂÀÕ (âîëüò-àìïåðíàÿ õàðàêòåðèñòèêà) ÌÍÎÏ-òðàíçèñòîðà щих устройств, которые стираются целиком или поблоч-
Разность пороговых напряжений транзистора в ВАХ и но, как flash-память, а под EAPROM понимают запомина-
фиксирует запись логических «0» или «1» в ЭС ППЗУ. емые устройства, стираемые только по битам, либо по
Для того чтобы снять накопленные заряды (стереть запи- байтам. В плане внесения путаницы в обозначения мы
санную информацию), необходимо на затвор подать на- также не стоим на последнем месте, иногда под ПЗУ у
пряжение порядка 30 В обратной полярности. В МНОП нас понимается любое ПЗУ из вышеописанных, в том чис-
количество циклов перезаписи очень велико, однако об- ле и flash-память.
ращения для чтения после записи постепенно уменьша- Все описанные выше типы памяти имеют одинаковое
ют заряды, поэтому длительность сигналов чтения лими- обозначение на электрических схемах, за исключением
тирована. Как правило, ЭС ППЗУ допускает 1011-1012 об- случаев, если используется функция записи. Выпуск па-
ращений, пока заряд начинает заметно снижаться. мяти как отечественными, так и импортными производи-
В некоторых ЭС ППЗУ этого типа вместо нитрида телями, производится в вариантах, сопрягаемых с ТТЛ, n-
кремния используется аналогичный по свойствам оксид МОП и КМПОП-схемами. Это означает, что в пределах од-
алюминия (алунд), при этом технология называется ной логики микросхемы памяти взаимозаменяемы. Сдела-
МАОП и получаются не p-канальные, а n-канальные при- но это целенамеренно с целью удешевления производства
боры, причём нормально открытые. При записи их поро- на этапах перехода к более массовому выпуску. Факт, что
говое напряжение не снижается, а повышается. Боль- микросхемы памяти можно менять, нам пригодится при пе-
шим преимуществом МАОП и МНОП ЭС ППЗУ является репрошивке модемов ZyXEL в следующем разделе.
наличие у запоминающих транзисторов внешнего управ-
ляющего затвора, с помощью которого и производится Перепрошивка модемов,
выборка ячейки. использующих ПЗУ
Итак, после того как у меня появились вышеописанные
Flash-память модемы ZyXEL и возникла идея подключить их к Linux-
То, что у каждой ячейки ЭС ППЗУ имеется возможность серверу, я подумал, что неплохо было бы поменять в них
записи и удаления одного бита за одну операцию, это хо- прошивку на более современную перед установкой, бла-
рошо, но реально на практике это порождает много про- го, что такое ПЗУ я себе представлял довольно чётко. Для
блем и замедляет процесс перезаписи. Если ёмкость ПЗУ этого два внешних модема пришлось разобрать.

№12(13), декабрь 2003 67


hardware

Ðèñóíîê 10. Âíóòðåííèé âèä ìîäåìîâ, ÷àñòü, ãäå íàõîäèòñÿ ÏÇÓ.


a) U-1496B+
á) U-1496E+
â) U-1496S+
Именно заменой их мы и займёмся сейчас.
Счастлив тот, у кого есть программатор, кварцевая лам-
па и два настроенных устройства /dev/hands и /dev/head.
Менее часа, и проблема смены версии более не существу-
ет. К сожалению, первого устройства у меня под руками не
оказалось, да и взять ненадолго не у кого тоже было, посе-
му я пошёл по пути, описанному ниже.
Преамбула: несколько лет назад один из моих знако-
мых, перепрошивая модем Acorp-56EMS на своём компь-
ютере, имел возможность на практике подтвердить один
Ðèñóíîê 9. Ðàçáîð ìîäåìîâ. Âèä ñíèçó:
a) U-1496B+ из законов Мерфи: «Если какая-то неприятность может
á) U-1496S+ случиться, то она случается». Как назло во время пере-
Во всех трёх встретились две микросхемы ПЗУ с вер- прошивки на время пропало электричество. Модем умер,
сиями. Это были ППЗУ с УФ-стиранием. он отказывался вообще себя как-либо идентифицировать,
мигать лампочками и подавать какие-либо признаки жиз-
ни. После был куплен новый модем, а сломанный долго
валялся у знакомого в ящике, после чего был подарен мне
как «радиогубителю со стажем» в надежде, что мне он при-
несёт большую пользу, чем если бы он продолжал пылить-
ся. Расчёт оказался как никогда точен. Модем переехал ко
мне. Где-то через пару месяцев, в очередной раз, когда у
меня появился блеск в глазах и желание чего-то покрутить,
я взял отвёртку и разобрал модем. См. рисунок 11.

Ðèñóíîê 11. Ðàçîáðàííûé ìîäåì Acorp-56EMS

68
hardware
Схема модема оказалась самой обычной, ПЗУ (flash), Далее, я зашёл на сайт фирмы ZyXEL и скачал оттуда
как полагается, стояла на панельке. последние версии прошивок для модемов. Для сокращения
Преамбула к преамбуле: незадолго до этого я на сво- статьи я буду писать лишь про прошивку только одного мо-
ём Pentium-100 на Asus P/I-P55TP4N как раз занимался тем, дема ZyXEL U-1496+ (он же U-1496S+), так как прошивка
что перепрошивал себе BIOS с целью: замены логотипа на двух других ничем не отличается, разве что версии программ
более приятный моему глазу и отвоёвывания у жадного для каждого типа модема свои. Воспользовавшись инфор-
компьютера разницы между 9.1 Гб и 8.4 Гб, так как мой мацией из [13], я вставил в модем чистую микросхему flash-
новый винт не хотел видеться в полном объёме. Мой школь- памяти, включил модем и набрал команду AT. Модем выдал
ный друг, зашедший ко мне тогда в гости, вдохновился тем, «ok». Если у вас модем не включается, то, возможно, вам
какие неизведанные возможности может сулить обновле- придётся вставлять микросхему памяти при включённом
ние версии BIOS (перед этим я с полгода жил, не исполь- питании, но об этом и возможных проблемах далее.
зуя свой диск в полном объёме по причине обычной не- (Набор программ по прошивке можно скачать тут: [16].)
хватки времени) и решил повторить у себя операцию с об- Для записи новой прошивки необходим специальный заг-
новлением и перепрошивкой BIOS. Пытаясь залить более рузчик (flash loader). Так как передавать напрямую двоич-
совершенный BIOS от Pentium-II объёмом 256 Кб в ПЗУ ные файлы, особенно с помощью стандартных термина-
объёмом 128 Кб на материнской плате первого Pentium, лов, невозможно (часть символов будут считаться служеб-
знакомый не знал тогда, что его ждёт неудача и поход ко ными командами), были придуманы несколько альтерна-
мне с ПЗУ и винтом, так как на последний, а не на диске- тивных, в том числе и текстовых, форматов. (Например,
ту была сохранена старая прошивка перед записью но- существует формат sb7. Этот формат прошивок, предназ-
вой. Что делать, не пропадать же другу? Была выполнена наченных для заливки во flash ПЗУ модемов Diamond
известная операция перепрошивки «на лету», из работа- Supra.) Наибольшее распространение получил текстовый
ющего компьютера я вытащил свою ПЗУ, вставил его и формат S37, понимаемый модемами Acorp. Соответствен-
зашил обратно ему его версию. Всё прошло на ура. но, имеются утилиты конвертации s37 ↔ bin, которые без
Припоминая свой недавний успех, я, недолго думая, проблем можно найти в Интернете. Программа загрузчи-
решил вытащить flash из модема с целью её изучения и ка, загрузившись на модем, может позволить вам загру-
возможной прошивки в материнской плате. Но как выяс- жать прошивки по более удобному протоколу X-modem.
нилось позже, это и не понадобилось, включив ради инте- Хотя, если у вас есть конвертор (bin → s37), то эта возмож-
реса модем без микросхемы памяти, оказалось, что он жив! ность может вам и не понадобиться.
Загорелись лампочки и на команду «AT» модем бодро от- Если вы встретите файл формата s37, то его содер-
вечал «ok», правда, ничего более, кроме как «AT», он не жимое будет примерно следующее:
понимал. На включённом модеме я воткнул ПЗУ обратно,
модем продолжил жить своей жизнью. После этого я под- S308000080004C0380A8
S3150000800378B2D533B20090C900F00287908AD05374
ключился к Интернету (хорошо, когда есть несколько мо- S3150000801398D050B79027907A68C900F011C901F03B
демов в компьютере) и нашёл там много информации по ....
S31500008CC2C947D0ED6820D383600000000000000091
перепрошивке модемов Acorp и саму прошивку. Нам пона- S70500000000FA
добится только одна ссылка – [13]. В процессе перепро-
шивки модему безразлично, что вы на нём прошиваете, то Создавать свой загрузчик, может, и интересно, но зачем
ли его родную прошивку, то ли что-то другое, главное, что- изобретать велосипед, берём готовый файл hsloader.s37 на
бы прошиваемая микросхема поддерживалась модемом, сайте журнала: www.samag.ru/sourse/hsloader.37.zip (это до-
проверки содержимого прошиваемой программы нет. работанный загрузчик от Sergey.Korolew@p2.f4.n5053.z2.
Соответственно, я решил компенсировать отсутствие fidonet.org). Вместо hsloader.s37 можно взять uploader.s37
программатора тем, что у меня есть «волшебный» модем. из [16]. Далее выполняем следующие действия по загруз-
Основываясь на теоретических знаниях и предположени- ке, краткая инструкция (модем у нас к этому моменту вклю-
ях о совместимости различных типов микросхем памяти, чён, ПЗУ вставлена и на команду AT он выдаёт «ok»):
я решил купить две микросхемы flash-памяти, с целью их 1. Даём модему команду AT**.
прошивания и установки в модемы. 2. Загружаем hsloader.s37 по протоколу ASCII, либо
вставляем из буфера чтобы не набирать руками.
3. Загружаем прошивку в формате s37, также по прото-
колу ASCII.

В некоторых случаях загрузчик не грузится без род-


ной ПЗУ модема, поэтому смену ПЗУ на flash следует
производить на лету после пункта 2. После замены сле-
дует нажать «G» (большое!) и перейти к пункту 3.
Замечание: описанные выше инструкции я выполнил у
себя с небольшим исключением, вместо AT**, я набирал
AT**2, разницы между этими командами я для себя не уяс-
нил, похоже, что можно прошивать разные микросхемы, не
Ðèñóíîê 12. Äâå ìèêðîñõåìû flash-ïàìÿòè AM29F010B только flash, если кто знает – поделитесь, пожалуйста, ин-

№12(13), декабрь 2003 69


hardware
формацией. Вместо hsloader.s37 я использовал uploader.s37. На данном этапе задача номер 1 по обновлению про-
Скачанный с ZyXEL файл: http://www.zyxel.ru/public/u-series/ граммного обеспечения модемов была успешно нами
1496/firmware/6.22/rm622sp1.zip с нужной версией прошив- выполнена.
ки я успешно разархивировал и два файла rm622sp1.u24 и Замечание 1: при попытке прошить на модели с плю-
rm622sp1.u25 сконвертировал и прошил в две миросхемы сом версию от модели без плюса всё прекрасно проши-
flash памяти. После успешной прошивки я увидел надпись валось. При попытке вставить в модем не его версию он
«Upload successfully completed». ругался, выдавая надпись на экранчике о несоответствии
версии.
Замечание 2: после перепрошивки у меня модем U-
1496S+ отказался общаться с терминальной програм-
мой, хотя на индикаторе показывал успешно пройден-
ные тесты и функционировал при управлении им через
клавиши меню. Как выяснилось, произошло это пото-
му, что почему-то в ячейке Character Length вместо зна-
чения 10 байт, обычно используемых по умолчанию,
оказалось записано значение 8. Я перепроверил все ос-
тальные настройки и сохранил профиль. После этого
даже после ATZ и выключения питания модем оставал-
ся в здравом смысле.
Замечание 3: не знаю уж, насколько у меня плохая
связь, но попытки установить связь с каким-либо из мос-
ковских интернет-провайдеров не дали успеха, модем ни
Ðèñóíîê 13. Âèä òåðìèíàëüíîé ïðîãðàììû ïîñëå óñïåøíîé в какую не хотел соединяться. Понимая, что такого быть
ïåðåïðîøèâêè в принципе не может и проблема, видимо, в настройках,
Аналогичным образом можно прошить любые другие я покопался в инструкции [7], так как я далёк от всяких
версии программ для других устройств. треллис-кодирований и полного досконального понима-
Далее две прошитые микросхемы с новой версией я ния происходящих явлений при установке соединений,
собрался установить в модем. При старой версии про- я методом перебора выяснил что оптимальными настрой-
граммы: ками для соединения по моей линии (декадно-шаговая
АТС) оказались команды:
ATI1  AT&N19 – выбор протокола v.32bis 7200/4800 для ус-
тановления связи;
модем выдавал:  AT&K4 – выбор протокола сжатия v.42bis и коррекции
ошибок v.42;
61694
U1496S V 6.12 P
 AT*E1 – устанавливать связь только с использовани-
OK ем протокола коррекции ошибок; ATX7 – выбор более
информативной строки CONNECT при установке со-
После замены старых микросхем памяти на новые единения.
модем гордо показывал свою обновлённую версию как:
После них модем, как танк, соединялся на 7200. Воз-
60837 можно, поэкспериментировав, вы найдёте для себя опти-
U1496S V 6.22 P
мальными другие настройки.
Для работы определителя номера советую дать коман-
ду AT&I4 – включить АОН, информация об определившем-
ся номере будет выдаваться как до установки соедине-
ния, так и в строке CONNECT. Это очень удобно: знать
номер звонящего при использовании модема для входя-
щей связи.
Замечание 4: скорость работы COM-порта следует
выбирать 57600, ZyXEL серии 1496 не поддерживает ра-
боту на 115200. (Если хочется больше, можно попробо-
вать 76800.)
Замечание 5: дополнительная информация c [13] для
желающих поэкспериментировать со своим модемом в
вопросах перепрошивки:
Во время перепрошивки не забудьте о необходимос-
ти сигнала WE на 31 выводе Flash. Во время замены ПЗУ,
надо вытаскивать её аккуратно, если у вас нет соответ-
Ðèñóíîê 14. Íàäïèñü íà èíäèêàòîðå ïåðåïðîøèòîãî ìîäåìà
«U1496S V 6.22 P» ствующего прибора, то, используя отвёртку, старайтесь

70
hardware
вытаскивать ПЗУ равномерно. Имеется опасность пе- А в чём собственно проблема? Поняв суть проблемы,
рекоса ПЗУ в последний момент, когда она уже выни- может, мы сможем решить или обойти её. Изучив по это-
мается легко, и отгибания вбок крайних ног. Несмотря му вопросу литературу, можно хорошую инструкцию от
на то, что при перекосах возможны проблемы по опыту какого-нибудь модема или [17], мы можем выяснить, что
Dmitry. Yalin@p12.f638.n5020.z2.fidonet.org вставлять для работы COM-порта, к которому подключаются моде-
flash надо начиная с 16-17 ног таким образом, чтобы мы, либо которые встроены в сам модем, если он внут-
питание, т.е. 32 и 1 ноги попадали последними. В об- ренний, необходимо иметь адрес, по которому будут про-
щем, вставлять её под небольшим наклоном. Вытаски- изводиться операции чтения и записи и прерывание, че-
вать ПЗУ соответственно наоборот, если же вставлять рез которое будет регулироваться этот процесс. Надеюсь,
flash по-другому, то наблюдается в лучшем случае за- что все понимают, что с точки зрения повышения произ-
висание терминальной программы, в худшем помогает водительности асинхронная запись оказывается более
только кнопочка reset. (Лично у меня, даже при нали- выгодной, чем синхронная. В своей основе это и порож-
чии желания что-то повесить, такого не происходило, дает необходимость в существовании прерываний и вы-
возможно, мне повезло.) текающие из этого проблемы.
Переставляя микросхемы подобным образом, вы може- В наследство от MS-DOS стандартная настройка COM-
те испортить модем или Flash, так что вся ответственность портов оказывается следующей:
за те или иные эксперименты лежит только на вас. Для того
чтобы свести риск к минимуму, нужно либо установить ZIF- /dev/ttys0 (COM1), port 0x3f8, irq 4
/dev/ttys1 (COM2), port 0x2f8, irq 3
socket вместо вашей панельки под ПЗУ, либо соорудить кон- /dev/ttys2 (COM3), port 0x3e8, irq 4
струкцию, подобную той, что описывает Dmitry Gzhibovsky /dev/ttys3 (COM4), port 0x2e8, irq 3
(Dmitry.Gzhibovsky@p5.f52.n5080.z2.fidonet.org).
Берётся любая микросхема с «работающей» прошив- Замечание: для меня, кстати, до сих пор является сек-
кой (хоть родное одноразовое ПЗУ), на неё сверху напа- ретом, почему в моей любимой терминальной программе
ивается панель для flash. 22-ые ноги верхней панели и Telemate под DOS имеется возможность выбора COM1-
ПЗУ отгибаются и через резисторы сопротивлением по- COM8. Мне интересно понять, как разработчикам виде-
рядка 10 КОм подключаются к +5 В. Далее, с 22-ой ноги лось использование, скажем, COM7 или COM8.
панели, которая стоит в модеме, сигнал подается на Если вы уже заметили, то прерывания у COM1 и COM3,
переключатель. С переключателя сигнал идёт на те же COM2 и COM4 совпадают. В этом как раз и состоит ос-
22-ые ноги ПЗУ и верхней панели, то есть переключа- новная проблема. Из-за существующих ограничений в
тель подает сигнал с модемной панели или на ПЗУ, или силу особенностей реализации ранее придуманной AT/ISA
на верхнюю панель, куда собственно flash-память и ста- архитектуры одно прерывание нормально не может ис-
вится. Далее вся эта конструкция втыкается в модем, пользоваться одновременно двумя или несколькими COM-
переключатель в режим «ПЗУ», включаем питание, at**, портами. Если же подключить несколько СОМ-портов на
заливаем специально доработанный для этих целей одно прерывание и попытаться работать с ними всеми од-
uploader, переключатель в положение «flash», нажима- новременно, возникнут сбои, ошибки и зависания. Дан-
ем на клавиатуре «G», uploader просит залить прошив- ные ограничения можно обойти путём использования спе-
ку, что с радостью и делаем. циальных многопортовых карт, о которых я упомянул
После того как все модемы оказались перепрошиты выше. Эти карты умеют делить одно прерывание между
на новые версии, передо мной встала задача номер 2, а несколькими портами. Кстати, большинство из них под-
именно как подключить 3 или 4 модема к компьютеру и держивается Linux/FreeBSD. Соответственно правильным
заставить их вместе работать под ОС Linux. решением, по которому мы пойдём, является поиск сво-
бодных прерываний и развод модемов, чтобы используе-
Несколько модемов мые ими прерывания не пересекались.
Купить модемный пул на 8/16/32 и более модемов или со- Обычно старые внутренние модемы имеют разъём
ответствующую многопортовую плату от фирм Digiboard, ISA 8-bit (именуемый также PC). Выбор прерывания на
Eqiunox, Granato, Cyclades, Moxa могут позволить себе не такой шине значительно ограничен по сравнению с пол-
все, да и как-то бессмысленно покупать столь хитрые и ной ISA (16-bit). А с учётом, что не все прерывания могут
дорогие устройства, если вам надо подключить всего быть использованы, модемы очень редко предоставля-
лишь 3 модема, а не 16 или 32. Можно обойтись покупкой ют возможность выбора большего, чем 4 числа преры-
одного или нескольких переходников USB-COM. Хотя по ваний. При этом используются прерывания по умолча-
цене не скажу, что выйдет дешевле. Также можно поис- нию, закреплённые за параллельными и последователь-
кать старые дешёвые мультикарты, позволяющие гибко ными портами:
настраивать параметры встроенных в неё COM-портов,
но это будет то же самое решение, что мы рассмотрим IRQ 3: COM2
IRQ 4: COM1
ниже. Физически нам ничего не мешает воткнуть в ком- IRQ 5: LPT2
пьютер один или два внутренних модема и к двум вне- IRQ 7: LPT1
шним портам подключить ещё два внешних модема. Но
работать вместе без особой настройки данный квартет У ZyXEL 1496E+ с помощью перемычек (jumpers) мож-
или трио не будут. но выбрать следующие параметры:

№12(13), декабрь 2003 71


hardware
друг другу, если не сказать честно, что это одно и то же
прерывание, а поэтому использовать их вместе никак
не получится. Прерывания 3 и 4 у нас уже заняты двумя
внешними COM-портами, к которым мы уже подключи-
ли два модема. IRQ 5 – редко кто у себя на компьютере
использует его по прямому назначению, а именно для
организации второго параллельного порта. Хотя, несом-
ненно, это удобно – развести устройства в случае, если
у вас на одном параллельном порту висят одновремен-
Ðèñóíîê 15. Ñõåìà âûáîðà àäðåñà COM-ïîðòà è ïðåðûâàíèÿ но: ФАКС (комбайн), принтер, card reader и сканер. По-
ñ ïîìîùüþ ïåðåìû÷åê íà ìîäåìàõ ZyXEL U1496B+ явление USB частично решило эту проблему, однако
Если же вам повезло и у вас модем более продвину- никто же не будет бесплатно менять все используемые
тый, а ещё и 16-битный, то вам станут доступны все пре- устройства на их USB-аналоги, а также переписывать
рывания, в том числе верхние 10-15. Не все прерывания коды предыдущих версий ОС, в которых нет поддержки
можно выбрать и использовать, поэтому, скорее всего, USB. Иногда на это прерывание вешают звуковую кар-
для вас окажется более полезной следующая информа- ту. Если у вас нет ничего из вышеописанного, то это пре-
ция по выбору прерываний. рывание для вас открыто. IRQ 6 используется дисково-
Стандартное использование прерываний следующее: дом. Не секрет, что многие, покупая новые компьютеры,
 IRQ 0 – Таймер, канал 0. не ставят туда дисковод не потому, что им жалко лиш-
 IRQ 1 – Клавиатура. ние 180 рублей, а потому, что он им не нужен. На серве-
 IRQ 2 – Cascade for controller 2. рах можно также обойтись без дисковода. Посему, если
 IRQ 3 – Последовательный порт 2 (COM2). отключить соответствующий контроллер в BIOS, дан-
 IRQ 4 – Последовательный порт 1 (COM1). ным прерыванием можно смело пользоваться. IRQ 7 –
 IRQ 5 – Параллельный порт 2 (LPT2). это скорее принтерное прерывание, лишь потому, что
 IRQ 6 – Накопитель на гибких дисках. чаще всего на первый параллельный порт, использующий
 IRQ 7 – Параллельный порт 1 (LPT1). это прерывание, устанавливают принтер. Соображения
 IRQ 8 – Часы реального времени. тут аналогичны LPT2. Если у вас порт не используется, то
 IRQ 9 – Перенаправлено на IRQ2. прерывание можно смело использовать. IRQ 8 – часы ре-
 IRQ 10 – Не назначено. ального времени, использовать это прерывание вряд
 IRQ 11 – Не назначено. ли получится. IRQ 9 – см. IRQ 2. IRQ 10-12 если не ис-
 IRQ 12 – Не назначено. пользуются, то мы можем забрать их под свои нужды.
 IRQ 13 – Математический сопроцессор. IRQ 13 отвечает за математический сопроцессор. Если
 IRQ 14 – Первый контроллер жёстких дисков. ваш процессор более чем 486 DX2, то есть имеет встро-
 IRQ 15 – Второй контроллер жёстких дисков. енный сопроцессор, то вряд ли вы сможете использо-
вать это прерывание, однако если у вас стоит какая-
Использовать можно любое неиспользуемое преры- нибудь 386 или 486 без сопроцессора, то это прерыва-
вание, однако следует понимать, что есть прерывания, ние для вас открыто. IRQ 14 – вряд ли вы обойдётесь
которые всегда заняты и соответственно без конфлик- без жёсткого диска, поэтому данное прерывание ско-
тов в системе при их использовании обойтись нельзя. рее всего будет для вас занято. Хотя, если пользовать-
Данный факт значительно сужает диапазон нашего вы- ся только дисководом (дискетные версии Linux или дру-
бора, но кто же несколько лет назад знал, что прерыва- гих ОС), либо сетевой картой (полная загрузка по сети)
ний будет катастрофически не хватать, как не хватает или отдельным SCSI-котроллером, то при особых уси-
сейчас пропускной способности московской подземки и лиях можно это прерывание задействовать для своих
автомобильных дорог. нужд. IRQ 15 – если у вас не используется и отключён
Давайте рассмотрим, чем мы можем смело пользо- второй контроллер IDE (CD-ROM и винчестер висят на
ваться, а от чего придётся воздержаться. Без сомнения, одном шлейфе), то без проблем можно использовать и
прерывание 0 использовать не получится. Прерывание 1 это прерывание.
при особых усилиях можно попытаться использовать. За- В общем, не пусто, но и не густо. В целом, если не
чем на сервере клавиатура, ибо можно подключить её вдаваться в описанную выше экзотику, то с большой ве-
по USB, либо вообще управлять компьютером по сети. роятностью вы не сможете использовать IRQ 0, 1, 6, 8, 13
Однако столь радикальные меры можно позволить на или 14. Они будут использоваться вашей материнской пла-
давно отлаженных системах, где клавиатура точно не той. Используя их необдуманно и не по назначению, вы
нужна. Посему для большинства это прерывание также можете заработать множество неприятностей. Когда вы
окажется закрытым для использования. Прерывание закончите ваши эксперименты, посмотрите в /proc/
номер 2 зарезервировано за неким хитрым устройством, interrupts (если в ядре есть поддержка /proc) и удостоверь-
которого, как и людей, его использующих, я никогда не тесь, что конфликтов нет. Выбрав для себя, что для тре-
видел. Так что вполне можно использовать это преры- тьего модема следует использовать IRQ 5, я установил
вание для своих нужд. Следует учесть, что 2-е и 9-е пре- перемычки на модеме ZyXEL в следующее положение и
рывание в силу особенностей реализации идентичны вставил модем в компьютер.

72
hardware
Соответственно, помимо установки файлов, отвеча-
ющих за сообщение ядру нужных параметров во время
загрузки. Операцию по указанию этих самых нужных па-
раметров следует хотя бы один раз выполнить вручную.
В моём случае это была команда:
Ðèñóíîê 16. Âûáîð êîíôèãóðàöèè àäðåñ=3E8, IRQ 5 ñ ïîìîùüþ
ïåðåìû÷åê # setserial /dev/ttyS2 irq 5
В BIOS внешние COM1 и COM2 я назначил стандарт-
но. В результате у меня получилась следующая «желез- Сменяющая стандартно ассоциированное IRQ 4 для COM3
ная» конфигурация: на выбранное мной IRQ 5. Следующие команды проверя-
ют правильность установки (выводят настройки на экран,
COM1 - Port: 0x03f8, IRQ: 4 (/dev/ttyS0) чтобы вы могли их проверить сами) и сохраняют имею-
COM2 - Port: 0x02f8, IRQ: 3 (/dev/ttyS1)
COM3 - Port: 0x03e8, IRQ: 5 (/dev/ttyS2) щуюся конфигурацию, как это было описано выше:

Соответственно, если первые два порта Linux опреде- # setserial /dev/ttyS0


# setserial /dev/ttyS1
лит сам, так как они стандартны, то что же касаемо COM3, # setserial /dev/ttyS2
то ядру Linux надо будет дать пояснение, чтобы оно зна- # /etc/rc.d/init.d/serial stop
ло, где именно искать наш COM3. В качестве программы,
объясняющей ядру, что и где из COM-портов находится, в У меня получилась следующая конфигурация:
Linux используется setserial. Следует заметить, что эта
программа ничего не устанавливает сама, она просто COM1 /dev/ttyS0, UART: 16550A, Port: 0x03f8, IRQ: 4
COM2 /dev/ttyS1, UART: 16550A, Port: 0x02f8, IRQ: 3
сообщает ядру о тех настройках, о которых вы её попроси- COM3 /dev/ttyS2, UART: 16550A, Port: 0x03e8, IRQ: 5
те. Файл конфигурации последовательных портов в неко-
торых версиях Linux по умолчанию находится в директо- Замечание 1: пока я в BIOS не проассоциировал рука-
рии /etc и называется serial.conf. Для описанной выше кон- ми прерывание номер 5 с шиной ISA, в которую был уста-
фигурации у меня он получился следующего содержания: новлен модем, модем не виделся.

/dev/ttyS0 uart 16550A port 0x03f8 irq 4 baud_base ↵


115200 spd_normal skip_test
/dev/ttyS1 uart 16550A port 0x02f8 irq 3 baud_base ↵
115200 spd_normal skip_test
/dev/ttyS2 uart 16550A port 0x03e8 irq 5 baud_base ↵
115200 spd_normal skip_test

Заглянув в директорию с документацией от Red Hat


Linux v.7.3 /usr/share/doc/setserial-2.17q, можно увидеть там
два файла: README и rc.serial, вот поистине правда: RTFM
и станете умнее.
Естественно, что в случае нестандартной конфигура-
ции запускать setserial во время начальной загрузки вам
придётся постоянно. Запускать его руками не есть хоро-
шее решение, прописывать файл в /etc/rc.d/rc.local тоже
не стоит, поэтому наиболее элегантным решением будет Ðèñóíîê 17. Çàêðåïëåíèå ïðåðûâàíèÿ íîìåð 5 çà óñòðîéñòâàìè
использование уровней загрузки и rc?.d директорий. В øèíû ISA
README написано, что файл rc.serial следует поместить Замечание 2: запуск программы kudzu, осуществляю-
в /etc/rc.d/init.d (переименовав просто в serial) и сделать щей поиск нового оборудования, следует производить пос-
на него ссылки из rc?.d либо руками, либо командой: ле установки параметров последовательных портов, то
есть после serial, чего при установке по умолчанию не на-
# chkconfig --add serial блюдается. Если вы хотите, чтобы kudzu обнаружил мо-
дем, запущенный у вас нестандартно на COM3 и после
У второго способа есть особенности. При запуске /etc/ не терял его, сообщая вам, что устройство удалено из ком-
rc.d/init.d/serial с параметром stop или save осуществляется пьютера, то вам придётся поменять номер запуска kudzu
запись существующей конфигурации в /etc/serial.conf, при- на более высокий, например, с 05 на 51. Сделать это мож-
чём туда попадают и все лишние устройства. Мне это пока- но просто, удалив старые ссылки, запустив для этого:
залось не очень удобным, поэтому я удалил файлы /etc/rc.d/
rc?.d/K??serial, осуществляющие ненужное мне сохранение, # chkconfig --del kudzu
и удалил лишние сохранённые строчки из /etc/serial.conf.
Конечно, сделав так, через годик-другой можно забыть про Затем подправив 05 на 51 в /etc/rc.d/init.d/kudzu и создав
эту особенность, но будьте начеку и тренируйте память. новые ссылки:
Очень плохо, когда всегда и все настройки идут по шабло-
ну, даже там, где это особо не нужно. # chkconfig --add kudzu

№12(13), декабрь 2003 73


hardware
Если данное решение неудобно, то можно просто ру- манды. (Например, ATI или ATI1.) Выход из терминала
ками переименовать все файлы S05kudzu в директори- «CTRL-A, Q».
ях /etc/rc.d/rc?.d на S51kudzu. Скорее всего, изменение Повторив вышеописанные операции по отношению ко
уровня запуска kudzu ни на что другое не повлияет. Убе- всем остальным модемам, можно также убедиться, что
диться в том, что все модемы установлены и доступны они работают. Если это так, то значит подключение 3 мо-
для дальнейшей настройки использующих их приложе- демов прошло у вас успешно и далее вы можете настра-
ний, можно с помощью стандартной терминальной про- ивать другие программы, прописывая в них модемы про-
граммы minicom. Если модем будет правильно реагиро- сто как устройства /dev/ttyS0, /dev/ttyS1, /dev/ttyS2.
вать на передаваемые ему команды, скорее всего, он
работает. Для большей надёжности в правильной рабо- Литература, ссылки:
те всех модемов, несомненно, следует проверять рабо- 1. Хоровиц П., Хилл У. Искусство схемотехники: Пер. с
ту всех модемов одновременно, но из-за сложности по- англ. – Изд. 6-е – М.: Мир, 2003.
добной реализации мы опустим этот тест, ограничив- 2. Гальперин М.В. Электронная техника: Учебник. – М.:
шись проверкой на жизнеспособность каждого модема ФОРУМ: ИНФРА-М, 2003.
по отдельности. 3. Фрике К. Вводный курс цифровой электроники – М.:
Если у вас не установлена терминальная программа Техносфера, 2003.
minicom, установите её (или используйте свою). В RedHat 4. Жеребцов И.П. Основы электроники – 5-е изд., пере-
Linux v.7.3 она находится на 2-м диске (RHL v.9 – на 1-м). раб. и доп. – Л.:Энергоатомиздат. Ленинградское от-
Запустите: деление, 1989. – 122-123 с.
5. Лукацкий А.В. Обнаружение атак. – СПб: БХВ-Петер-
# minicom -s бург, 2001. – 624 с.
6. Закляков П. Плохое электропитание, или «Грабли» с
в появившемся меню: UPS. //журнал «Системный администратор», №8(9),
2003 г. – 52-61 с.
7. Руководство для пользователей. Универсальный мо-
дем серии U-1496. Документ № 83011501, Версия
2.21 ZyXEL Communications Corporation и АО МКЦ
«Вариант»
8. Доска объявлений по купле/продаже/обмену: http://
www.komok.com
9. Доска объявлений по продаже.(интернет-аукцион):
Ðèñóíîê 18. Îêíî êîíôèãóðàöèè ïîñëå çàïóñêà "minicom -s" http://www.molotok.ru
Выберите Serial port setup, у вас выскочит новое окно: 10. Каталог продукции фирмы ZyXEL: http://www.zyxel.ru/
techsup/zyx_fil.asp
11. Учебник по теме «Микропроцессоры». Постоянные за-
поминающие устройства. http://docs.lab127.karelia.ru/
hardware/microcpu/pam1.htm
12. Информация о некоторых видах памяти. http://
digital5.ece.tntech.edu/Public/611/Clements%20CDROM/
DATA/HITACHI/A_RAM.PDF
13. Как менять прошивку на модемах Acorp: http://
pirogoff.chat.ru/rockwell/firm.htm
Ðèñóíîê 19. Íàñòðîéêà ïàðàìåòðîâ COM-ïîðòà 14. Официальный сайт Митинского городского радиорынка
Нажав «A», исправьте используемый вами порт на нуж- (г. Москва): http://www.tkmitino.ru/
ный и установите скорость на 57600. Нажмите «Enter» для 15. Сайт сети магазинов «Чип и Дип» по продаже элект-
выхода из подменю. В случае необходимости сохраните ронных компонентов, цены, наличие, справочная ин-
конфигурацию – пункт «Save setup as dfl» и, нажав «ESC», формация. http://www.chip-dip.ru
запустите терминал. На некоторое время у вас выскочит 16. Набор программ для прошивки flash-памяти в Acorp
надпись Initializing Modem. После чего у вас должна по- модемах: http://pirogoff.chat.ru/files/firmware.zip
явиться строка, где, как обычно, можно набирать AT-ко- 17. man setserial

74
web

АЛЕКСЕЙ МИЧУРИН

76
web
Постановка задачи. Или в чем проблема? му, что этот язык знает достаточно много программистов,
Многие веб-мастера часто сталкиваются с задачей конвер- связанных с веб-разработками (если вы не относитесь к их
тирования файлов Microsoft Excel в другие форматы. Не- числу и планируете заниматься web, то искренне рекомен-
редко это сопряжено с трудностями, так как формат xls, дую обратить внимание на Perl). Потому, что этот язык бес-
как все прекрасно знают, не документирован. платен и доступен любому пользователю на любой платфор-
В некоторых случаях возможно сохранение данных Excel ме. И потому, что мой код на Perl можно будет потом легко
в документированных форматах и последующая их обра- модифицировать, заставив его, допустим, помещать каж-
ботка. Но часто этот способ работает неудовлетворитель- дый раздел price-list в отдельный файл, различным образом
но. Простые форматы, удобные для обработки, не способ- сортировать позиции прайса, отслеживать обновления и
ны сохранить всю информацию о форматировании доку- динамику цен, снабжать каждую позицию полями HTML-
мента, а реализация обработчика сложных форматов нео- форм для on-line заказа в веб-магазине... В конце концов,
правданно трудоёмка. мой скрипт легко превратить в CGI-приложение для адми-
За примером далеко ходить не надо. Множество фирм, нистрирования веб-сервера.
которые имеют свои веб-страницы и периодически их об- Такое решение представляется мне максимально гиб-
новляют, ведут свои дела с использованием Excel. Перед ким, функциональным и компактным, потому что каждая
веб-мастером при каждом обновлении информации на сер- часть задачи решается тем средством, которое наиболее
вере возникает задача конвертирования. Причём задача приспособлено для её решения.
может осложняться следующими аспектами: Давайте оттолкнёмся от конкретного примера. В каче-
Во-первых, это изменение дизайна. Price-list, подготов- стве «подопытного кролика» предлагаю следующий прайс:
ленный в Excel, обычно рассчитан на распечатку на чёрно-
белом принтере. Price-list на веб-сайте – нет. Хотя бы по-
этому простое «Сохранить как веб-страницу» не подходит
(я уж молчу о том, какого качества получается HTML-код
при таком сохранении).
Во-вторых, при конвертировании необходимо учесть спе-
цифику Excel. Например, очень многие люди, редактирую-
щие price-list, широко применяют команду «Формат/строка/
скрыть». При этом высота строки становится нулевой, и стро-
ка как бы исчезает с экрана и на печати. Понятно, что и на
веб-сайт такие строки попасть не должны. Однако они пре-
восходно сохраняются в других форматах и ничем не отли-
чаются от обычных, не скрытых, строк. Это приводит к тому,
что доктрина «Сохранить как текст с разделителями и обра-
ботать» не даёт удовлетворительных результатов. Как видите, он сочетает в себе все неприятные элемен-
В-третьих, в price-list часто используется форматирова- ты, упомянутые выше: и форматирование (фон, перечёр-
ние, сохранение которого критично. Например, наименова- кивания, жирный шрифт), и скрытые строки (если пригля-
ния некоторых товаров могут быть зачёркнуты или выделе- деться, то можно заметить, что после девятой сразу идёт
ны цветом в знак того, что эти товары были и обязательно двенадцатая строка). Давайте им займёмся.
будут, но сейчас их нет. Некоторые позиции могут быть вы-
делены курсивом и так далее. Вся эта информация бесслед- Экспорт данных из Excel
но исчезает, если пересохранить price-list в простом форма- Приступим к решению первой задачи. Для экспорта дан-
те, скажем, как текст с разделителями табуляции. ных из Excel я предлагаю несложный макрос на Visual Basic
Итак, наша задача состоит в том, чтобы корректно кон- (номера строк приведены только для удобства комменти-
вертировать документ из формата xls в формат HTML с рования):
учётом форматирования исходного документа и при этом
обойтись «малой кровью». 1: Sub table2table()
2: '
Я предлагаю разбить эту задачу на две. Первая – со- 3: ' ìàêðîñ, ñîõðàíÿþùèé âûäåëåííûé ôðàãìåíò òàáëèöû
хранение данных в простом формате, который тем не ме- 4: ' â òåêñòîâîì ôîðìàòå ñ îòìåòêàìè î ôîðìàòèðîâàíèè
5: '
нее будет нести в себе всю необходимую нам информа- 6: With ActiveWindow.RangeSelection
цию о разметке документа. Вторая – обработка этого фор- 7: c1 = .Columns.Column
8: c2 = .Columns.Count - 1 + c1
мата и создание HTML-страницы. 9: r1 = .Rows.Row
Первую задачу (экспорт) я предлагаю решить средства- 10: r2 = .Rows.Count - 1 + r1
11: End With
ми Excel. Тут у нас фактически нет выбора, формат xls 12: If (r1 - r2 = 0 And c1 - c2 = 0) Then
может обработать только то единственное на свете при- 13: MsgBox _
14: "÷òî-òî ìàëî âûäåëåíî (äëÿ ñîõðàíåíèÿ) ,-)", _
ложение, которое его понимает. Это диалектика. 15: vbCritical, "ñîîáùåíèå ìàêðîñà"
Вторую задачу я предлагаю решить средствами языка 16: End If
17: fileSaveName = Application.GetSaveAsFilename( _
Perl. Почему? Потому, что этот язык ориентирован на рабо- 18: InitialFileName:="file", _
ту со строками и на решение задач, подобных нашей (Perl – 19: fileFilter:="Text Files (*.txt), *.txt", _
20: Title:="ñîõðàíåíèå ñòðàíèöû â íàøåì ôîðìàòå")
Practical Extraction and Report Language – то, что надо). Пото- 21: If fileSaveName = False Then

№12(13), декабрь 2003 77


web
22: MsgBox _
23: "ôàéë-òî íå âûáðàí. íèêàêèõ äåéñòâèé íå ïðåäïðèíÿòî.", _
24: vbCritical, "ñîîáùåíèå ìàêðîñà"
25: Else
26: sep = Chr(9) ' ðàçäåëèòåëü
27: subsep = Chr(8) ' ïîä-ðàçäåëèòåëü
28: Open fileSaveName For Output As #1
29: For r = r1 To r2
30: l = CStr(Rows(r).RowHeight)
31: For c = c1 To c2
32: With Cells(r, c)
33: l = l + sep + CStr(.Text) + _
34: subsep + CStr(.MergeCells) + _
35: subsep + CStr(.Font.Bold) + _
36: subsep + CStr(.Font.Strikethrough)
37: End With
38: Next
39: Print #1, l
40: Next
41: Close #1
42: End If
43: End Sub

Этот макрос сохраняет выделенную часть прайса в за- Опять же вы можете просто задать фиксированное
данный файл. Макрос можно добавить к рабочей версии имя, но мне кажется, что это неудобно даже в том случае,
прайса и сделать для его вызова кнопку (вне области пе- если вы сами эксплуатируете этот макрос.
чати), а можно хранить в отдельном файле. Поместить В строках с 21 по 42 следует конструкция if-then-else с
его в документ очень просто: вызовите редактор Visual проверкой, было ли указано имя файла для сохранения
Basic (меню: сервис → макрос → редактор Visual Basic; или пользователь нажал кнопку «Отмена» диалога «Со-
или Alt-F11), создайте новый модуль (меню: вставить → хранить как...».
модуль) и введите приведённый здесь текст (без номе- Если пользователь отказался от сохранения, то выда-
ров строк). Теперь можно нарисовать кнопку (инструмент ётся соответствующее сообщение (строки с 22 по 24), если
на панели «Формы») и назначить ей макрос. имя файла указано, то начинается самое интересное –
Давайте вкратце рассмотрим, как работает этот код. сохранение данных.
Первая строка – объявление макроса. Как видите, я Но прежде чем обсудить процедуру сохранения (стро-
назвал его незамысловато table2table, вы можете наречь ки с 26 по 41), давайте скажем пару слов о том, в каком
его более звучно. же именно формате мы намерены сохранять данные.
В строках с 6 по 11 мы определяем границы выделен- Предлагаю самый простой для обработки формат: ASCII-
ной части документа (ведь мы будем сохранять только текст. Каждая строка соответствует строке сохраняемой
выделенную часть). Теперь c1 и c2 – номера первого и таблицы. Поля разделены односимвольными разделите-
последнего столбца, а r1 и r2 – первой и последней стро- лями. Первое поле – высота строки (эта информация не-
ки выделенной области. обходима, чтобы отфильтровать «скрытые» строки). Все
Далее, в строках с 12 по 16 проверяем, а была ли выде- последующие поля – содержимое ячеек, но каждое из этих
лена область или нашему макросу предстоит работать толь- полей содержит несколько под-полей, разделённых свои-
ко с одной ячейкой. Этого, конечно, можно и не делать, но ми разделителями. Под-поля несут различную информа-
ведь, скорее всего, запускать этот макрос будете не вы, а цию о ячейке: содержание, параметры форматирования.
менеджеры, редактирующие прайс, на их аккуратность не У нас разделители полей и под-полей задаются ASCII-ко-
всегда можно рассчитывать. Итак, если ничего не было вы- дами в строках 26 и 27 соответственно. Вы можете выбрать
делено, то наш макрос выдаст предупреждение: более удобные разделители. Например, если вы уверены, что
в ваших данных никогда не встречается символ «:», то можно
взять его в качестве разделителя или под-разделителя.
Далее (строка 28) открываем файл.
Организуем цикл по строкам (строка 29).
Для каждой строки вычисляем высоту. Заодно начина-
ем готовить строку для сохранения в файл в переменной l
(строка 30 листинга).
В цикле (строка листинга 31) по ячейкам сохраняемой
строки таблицы добавляем к строке l всю интересующую
нас информацию о ячейках, снабжая её разделителями.
Какие свойства ячейки мы сохраняем?
Первым делом – текст ячейки. Обратите внимание, что
мы используем именно свойство .Text, а не свойство .Value.
Это не случайно. Свойство .Value возвращает истинное со-
В строках с 17 по 20 мы вызываем диалог Application. держимое ячейки, свойство .Text возвращает тот текст, ко-
GetSaveAsFilename, чтобы пользователь мог выбрать имя торый отображается на мониторе и выводится на печать.
файла: Эти две величины могут не совпадать (и обычно не совпа-

78
web
дают), потому что на экран значения выводятся согласно Как я и говорил, предлагаю скрипт на Perl:
заданному формату ячейки (например, числа выводятся с
заданным количеством знаков после запятой). 1: #!/usr/bin/perl -w
2:
Свойство .MergeCells говорит о том, является ли ячей- 3: #use strict;
ка частью группы объединённых ячеек. 4:
5: # my ($TRUE, $FALSE)=('Èñòèíà', 'Ëîæü');
Свойство .Font.Bold отражает жирность текста в ячейке. 6: my ($TRUE, $FALSE)=('True', 'False');
Свойство .Font.Strikethrough говорит о том, был ли 7:
8: sub qtnum {
текст оформлен как зачёркнутый. 9: my $t=shift;
Для нашего примера нам, пожалуй, больше ничего не 10: $t=~s|,(\d+)|,<small>$1</small>|;
11: return $t;
потребуется. Однако не могу не отметить ряд полезных 12: }
свойств, которые могут вам пригодиться. Имена этих свойств 13:
14: sub qtstring {
достаточно красноречивы, и я не буду их комментировать, 15: my $t=shift;
ограничусь перечислением: 16: $t=~s/\&/\&amp;/g;
17: $t=~s/\"/\&quot;/g;
 .Font.Name 18: $t=~s/\>/\&gt;/g;
 .Font.FontStyle 19:
20:
$t=~s/\</\&lt;/g;
return $t;
 .Font.Size 21: }
 .Font.Underline 22:
23: print <<'TEXT';
 .Font.ColorIndex 24: <html>
 .Font.Italic 25: <head>
26: <title>ïðàéñ íåêîé ôèðìû</title>
 .HorizontalAlignment 27: <style type="text/css">
 .VerticalAlignment 28: <!--
29: .al {background-color: #FFFFFF}
 .ColorIndex 30: -->
 .Pattern 31: </style>
32: </head>
33: <body bgcolor="#E8E8E8">
Обратите внимание, все свойства явно приводятся к 34: <table cellspacing="0" cellpadding="1" border="0">
35: <tr><td colspan="3" height="1" bgcolor="#8F0000" ↵
строчному типу функцией CStr (строки с 33 по 36). Это весь- nowrap></td></tr>
ма полезная процедура, навсегда избавляющая вас от го- 36: <tr>
37: <th colspan="3" bgcolor="#FFFFFF"><big>ïðàéñ íåêîé ↵
ловной боли о преобразованиях типов. ôèðìû</big></th>
Здесь следует сделать важную оговорку. Дело в том, 38: </tr>
39: <tr><td colspan="3" height="1" bgcolor="#8F0000" ↵
что функция CStr не в состоянии обработать неопределён- nowrap></td></tr>
ные значения. Если таковые будут встречаться в ваших 40: <tr>
41: <th rowspan="3">íàèìåíîâàíèå òîâàðà</th>
документах, то вместо CStr вы можете использовать соб- 42: <th colspan="2"><small>öåíà</small></th>
ственную функцию преобразования величин в текстовый 43: </tr>
44: <tr><td colspan="2" height="1" bgcolor="#8F0000" ↵
формат. Например, safeCStr: nowrap></td></tr>
45: <tr>
46: <th><small>ó.å.</small></th>
1: Function safeCStr(p As Variant) As String 47: <th><small>ðóá.</small></th>
2: If IsNull(p) Then safeCStr = "" Else safeCStr = CStr(p) 48: </tr>
3: End Function 49: <tr><td colspan="3" height="1" bgcolor="#8F0000" ↵
nowrap></td></tr>
(Должен отметить, что сам я никогда не сталкивался с 50: TEXT
51:
такими ситуациями, но научно-технический консультант жур- 52: while (<>) {
нала без труда нашёл в Интернете прайс-лист, в некоторых 53: s/[\x0A\x0D]+$//;
54: my @f=split /\x09/;
ячейках которого свойство .Font.Bold было не определено. 55: my $lh=shift @f;
Я полагаю, что такие документы могут возникать в резуль- 56: my ($name, $usd, $rub)=map {[split /\x08/]} @f;
57: if ($lh) {
тате экспорта данных из других приложений. Например, про- 58: if ($name->[1] eq $TRUE) { # îáðàáîòêà çàãîëîâêà ðàçäåëà
дукты 1C допускают экспорт данных в Excel. Одним словом, 59: print '<tr><th colspan="3" bgcolor="#FFFF00">' .
60: $name->[0] .
такая ситуация возможна. – Примечание автора.) 61: "</th>\n";
Вот почти и всё. Осталось сохранить готовую строку l в 62: } else { # îáðàáîòêà îáû÷íîé ñòðîêè
63: print <<'TEXT' .
файл (строка 39 листинга) и закрыть файл по завершении 64: <tr
всего цикла по строкам (строка 41). 65: onMouseOver="this.className='al';"
66: onMouseOut="this.className = '';"><td>
Итак, вы выделяете сохраняемую область (в нашем при- 67: TEXT
мере это первые три столбца таблицы, строки с 4 по 21), 68: ($name->[3] eq $TRUE?'<font ↵
color="#888888"><strike>':'') .
нажимаете созданную вами кнопку, выбираете имя фай- 69: qtstring($name->[0]) .
ла, и файл сохранён. Что с ним делать дальше? 70: ($name->[3] eq $TRUE?'</strike></font>':'') .
71: qq|</td>\n<td align="right">| .
72: ($usd->[2] eq ↵
Создание HTML-страницы 73:
$TRUE?'<font color="#880000"><b>':'') .
qtnum($usd->[0]) .
по экспортированным данным 74: ($usd->[2] eq $TRUE?'</b></font>':'') .
С этим файлом можно сделать всё что угодно, потому что 75: qq|</td>\n<td align="right">| .
76: ($rub->[2] eq ↵
его формат нам полностью известен (приятно это осоз- $TRUE?'<font color="#880000"><b>':'') .
навать). Я приведу пример генерации HTML-страницы. 77: qtnum($rub->[0]) .

№12(13), декабрь 2003 79


web
78: ($rub->[2] eq $TRUE?'</b></font>':'') . используется тот же разделитель, что и в макросе на Visual
79: "</td>\n"; Basic (строка макроса 26).
80: }
81: print <<'TEXT'; Первое поле – высота строки – сохраняется в перемен-
82: </tr> ной $lh (строка 55). Все остальные поля разделяются на под-
83: <tr><td colspan="3" height="1" bgcolor="#8F0000" ↵
nowrap></td></tr> поля. В результате переменным $name, $usd, $rub присваи-
84: TEXT ваются указатели на массивы, содержащие всю необходи-
85: } else {
86: warn 'hidden line: '.$name->[0]."\n"; мую информацию о содержимом и форматировании соот-
87: } ветствующей ячейки. $name – ячейка с наименованием то-
88: }
89: вара, $usd – ячейка с ценой в долларах, $rub – ячейка с це-
90: print <<'TEXT'; ной в рублях. Делается это одной-единственной строкой 56.
91: </table>
92: </body> Если высота строки не равна нулю, то выполняем блок
93: </html> с 58 по 84 строки. В противном случае выдаём предупреж-
94: TEXT
дение в стандартный поток ошибок stderr о том, что обна-
Скрипт принимает входные данные из файла, указан- ружена и проигнорирована скрытая строка (строка 86).
ного как параметр командной строки, или со стандартно- Обработка строк таблицы только на первый взгляд
го ввода и выдаёт HTML-код на стандартный выход. То может показаться сложной.
есть запускать его можно так: Прежде всего мы выясняем, с чем мы имеем дело: в
строке 58 проверяем истинность свойства .MergeCells ячей-
perl file2html.pl file.txt >file.html ки с наименованием товара. Если эта ячейка объединена,
то это заголовок раздела, тогда выполняется код генери-
или, например, так: рующий заголовок (строки с 59 по 61).
Если оказывается, что мы имеем дело с обычной стро-
cat file.txt | perl file2html.pl >file.html кой, то выполняется блок else (строки с 63 по 79). Здесь
формируется строка HTML-таблицы, в которую вставля-
Разберёмся, как работает этот скрипт (я буду предпо- ются дополнительные элементы форматирования (для тех
лагать, что читатель немного знаком с Perl). строк таблицы, где это необходимо).
Первая строка – стандартная магическая строка любого Обратите внимание, что мы встроили в наш документ
UNIX-сценария. Пользователи Windows могут её проигно- элементарный DHTML-приём. В таблице всегда подсве-
рировать. В третьей строке – закомментированная инструк- чивается строка, на которой находится указатель мыши.
ция use strict. Она будет полезна вам только при отладке. Это упрощает чтение таблицы. Согласитесь, что добить-
В строках 5 и 6 мы определим переменные $TRUE и ся такого эффекта средствами Excel (путём сохранения
$FALSE, которые будут содержать значения истины и лжи, документа как веб-страницы) затруднительно.
выдаваемые Excel. Дело в том, что русский Excel использу- В строках 90–94 выводим завершающие теги докумен-
ет русские слова, европейский – английские. Откомменти- та. Обратите внимание, что в конце файла с программой
руйте подходящую вам строку и закомментируйте лишнюю. обязательно должна быть пустая строка. Иначе последнее
Процедура qtnum (с 8 по 12 строки) добавляет к запи- слово («TEXT») (строка 94) не будет правильно обрабо-
си числа теги, превращая «3,14» в «3,<small>14</small>». тано интерпретатором Perl.
То есть центы и копейки будут отображаться меньшим То что получается на выходе, смотрите на рисунке
шрифтом. Это чисто косметическая мера. (стр. 82).
Процедура qtstring (строки с 13 по 21) квотирует «небе- Согласитесь, было за что биться!
зопасные» символы: & (and), “ (двойная кавычка), < (боль-
ше), > (меньше). Это, как вы понимаете, обязательная мера. BUGS. Что ещё можно добавить?
В строках с 23 по 50 печатается «шапка» HTML-доку- Я не сомневаюсь, что хотя мои примеры полностью рабо-
мента. тоспособны, мало кто будет использовать их без малей-
В цикле while (строки с 52 по 88) мы считываем пост- ших модификаций. Хочу подбросить пару мыслей о том,
рочно входной файл, преобразуем его в HTML-документ что можно улучшить в этих скриптах, чтобы при их моди-
и выдаём в стандартный поток вывода stdout. фикации вы не делали лишней работы, а убивали сразу
В строке 53 от очередной считанной строки отрезается как можно больше зайцев.
символ(ы) конца строки. Я не использую стандартные фун-
кции Perl chop и chomp, потому что обрабатываемый файл По сценарию на Visual Basic
создаётся под Windows, а обработчик (наш сценарий на Здесь вам скорее всего придётся изменить набор сохра-
Perl) может работать и под UNIX. Файл же может переда- няемых параметров ячейки. Список наиболее полезных я
ваться весьма экзотическими путями. Например, наверня- привожу в обсуждении этого сценария. Если вам понадо-
ка многие захотят чуть доработать мой код и превратить бится какая-нибудь экзотика, обращайтесь к документа-
его в CGI-приложение для администрирования их родного ции Microsoft, свойства объекта Range.
сервера. Поэтому я не полагаюсь на стандартные функ- Наверное, многие сочтут недоработкой то, что макрос
ции, а прописываю явно, что мне необходимо удалить все безусловно заменяет существующие файлы (если вы ука-
символы \x0A и \x0D в конце строки. жите для сохранения существующий файл). Это, как вы
Далее строка разделяется на поля (строка 54). Здесь понимаете, легко исправить.

80
web

Наверное, для реальных документов будет несложно Скорее всего вам придётся «научить» этот сценарий
сформулировать условия, по которым макрос будет сам разбивать большие документы на разделы и сохранять
определять область прайса (или другого документа), под- эти разделы в разных файлах, потому что прайс-лист весь-
лежащую сохранению. Тогда этот процесс можно автома- ма средней фирмы в формате HTML может потянуть на
тизировать. Моё решение (сохранение выделенной облас- сотни килобайт. Не всякий веб-странник дождётся конца
ти) скорее универсально, чем удобно. загрузки такого документа. Возможно, вы захотите доба-
Наконец, читатель может справедливо спросить, зачем вить сортировку (если позиции в печатном прайс-листе и
макрос для Excel сохраняет скрытые строки, ведь их можно в веб-прайсе должны следовать в разном порядке).
отсеять уже на стадии экспорта? Снимаю шляпу перед вни- Несомненно, будет полезна функция сравнения теку-
мательностью читателя (втайне надеясь на ответный жест в щего прайса с предыдущим, которая будет добавлять ин-
адрес моей проницательности). Сохранять скрытые строки формацию об обновлениях и динамике цен.
действительно совсем не обязательно, просто я привык со- Я бы советовал организовать подобные процедуры (не
хранять всё. Причины? Возможно, скрытые строки всё-таки относящиеся непосредственно к HTML-вёрстке) в виде от-
понадобятся. Или вы захотите точно знать, какие строки были дельных программ или модулей. Кстати, часть работы по
проигнорированы (мой Perl-сценарий, как вы помните, со- HTML-вёрстке можно доверить механизму SSI, а скрипт
общает о каждой скрытой строке). Кроме того, информация пусть собирает SHTML-документ. Набор простых инстру-
о высоте строк может быть критерием для идентификации ментов всегда удобнее, гибче и управляемее, чем один
заголовков... Хотя, конечно, вы можете слегка модифици- универсальный. Держитесь подальше от грабель, по ко-
ровать VB-код и не сохранять скрытые строки. торым гуляют создатели телефона-микроволновки и те-
левизора-зубной щётки.
По скрипту на Perl Список советов и предложений можно продолжать бес-
Конечно, весь HTML-код (а это большая часть скрипта) конечно, но я думаю, что уже разбудил вашу фантазию, и
вы скорее всего значительно измените. Конечно, вам при- дальше вы справитесь и без меня. Адаптация приведённо-
дётся изменить количество столбцов, шапку, многие уда- го здесь примера к вашим конкретным условиям, возмож-
лят из HTML-кода мои пустые строчки-разделители, на- но, потребует несколько часов работы. Зато потом вы бу-
крутят вложенных таблиц, изменят DHTML-функции, до- дете щедро вознаграждены, ведь все последующие обнов-
бавят CSS-таблицы... Но это не самое главное и не прин- ления информации на вашем веб-сервере вы будете де-
ципиальное изменение. лать буквально в несколько касаний клавиатуры и мыши!

82
образование

СЕРГЕЙ ЯРЕМЧУК

84
образование
Сейчас во многих школах, институтах и других учеб- Оказывается, можно. Открытость Linux-систем поро-
ных заведениях можно встретить компьютеры старого дила вокруг себя довольно много полезных проектов, и
парка, уже отслужившие свое как морально, так и фи- часто для решения какой-нибудь проблемы необходимо
зически. На таких компьютерах можно изучать разве просто найти подходящий. Решением вопроса загрузки
что Dos, что далеко от реалий сегодняшнего дня. К тому бездисковых терминалов занимается LTSP (Linux Terminal
же у большинства, как правило, жесткий диск уже в не- Server Project).
рабочем состоянии. Но и выбросить жалко, а новых В чем же преимущество компьютера без диска:
никто не дает. Различные спонсоры, меценаты, быва-  Подвижность пользователя, ведь как уже отмечалось,
ет, подарят компьютер (один) и радуются, как дети. Спа- пользователь не связан с конкретным компьютером.
сибо, конечно, большое, но проблемы, как вы понима-  Снижение стоимости и упрощение операции обновле-
ете, этот компьютер в общем не решает, даже наобо- ния программного обеспечения, так как это произво-
рот, усугубляет, работать на старых уже как-то не хо- дится только на одном компьютере.
чется, теперь просто есть с чем сравнивать. Но выход  Резервирование, восстановление данных будет про-
из такой ситуации есть. И мне кажется, что даже почти исходить также только на одном компьютере.
идеальный, но сначала суть.  Физическая защита данных лучше, так как единствен-
Все ОС Unix и подобные операционные системы из- ное, что необходимо защищать – сервер, а его можно
начально отлично подготовлены для полноценной рабо- поставить в специальном хорошо охраняемом поме-
ты в среде клиент-сервер. Даже X-Window не удалось щении (которое, кстати, можно оборудовать фильтра-
избежать данной участи. Это сетевой продукт, одна часть ми от проникновения пыли и аппаратурой для поддер-
которого (сервер) взаимодействует непосредственно с жания постоянной температуры, что существенно про-
пользователем с помощью клавиатуры, мыши и мони- длит срок работы сервера).
тора, она обрабатывает команды пользователя и фор-  UPS можно предоставить только серверу.
мирует соответствующие запросы на их выполнение. Ре-  Также будет существенно ниже общая цена – эконо-
зультаты работы программ передаются также непосред- мия = (стоимость жесткого диска + стоимость CD-ROM
ственно ему. А другая (клиент) уже обрабатывает резуль- + стоимость флоппи-дисковода) ∗ количество компь-
таты запросов и запускает запрошенные программы, а теров.
затем передает результат выполнения обратно серверу.  Защищать от вирусов необходимо только сервер, так
Основой взаимодействия графических приложений с как другие компьютеры не имеют жесткого диска.
сервером является протокол Х, который реализован так,  Уровень шума на рабочем месте ниже, так как в ком-
что ему абсолютно не важно, где находится клиент и пьютере нет частей, которые движутся – практически
сервер. В самом общем случае они работают на одном нет необходимости в администрировании и обслужи-
компьютере, но ничто, повторяю, ничто не мешает раз- вании в клиентских компьютерах.
местить их на разных компьютерах, ну разве что отсут-  Большая долговечность клиентских машин как мораль-
ствие какой-либо связи между ними. ная, так и физическая.
Такая организация позволяет эффективно использо-  Возможность работы в запыленных помещениях (здесь
вать компьютерный парк организации: все ресурсоемкие желателен «холодный» процессор типа VIA C3, ЖК мо-
операции выполняются на специально выделенном мощ- нитор).
ном компьютере. То есть имеется несколько более сла-
бых компьютеров, за которыми работают пользователи. Как видите, подобное решение может быть исполь-
Такие компьютеры используют Unix с установленным сер- зовано и в офисах и прочих местах, где нет необходимо-
вером X-Window. Операционная система обрабатывает сти держать мощные компьютеры. Вот мы подошли, на-
запросы, создаваемые пользователем, и передает его конец, к практическому решению поставленной в нача-
серверу, который в свою очередь возвращает результат. ле статьи задачи. Чтобы разобраться в дальнейших дей-
Эти компьютеры принято называть Х-терминалами. А ком- ствиях, необходимо немного понимать общую картину.
пьютер, выполняющий основную наиболее трудоемкую ра- Поэтому сначала давайте проследим, как же все это про-
боту, называют сервером графических приложений. Ко- исходит. Загрузка бездисковых станций происходит сле-
нечно же, к ресурсам такого компьютера предьявляются дующим образом.
особые требования, особенно это относится к объему опе- После включения питания управление передается, как
ративной памяти, которой должно теперь хватать на всех, обычно BIOS, который в свою очередь выполняет инициа-
и к скорости дисковых операций. А вот к рабочим стан- лизацию, проверку POST (Power-On-Self-Test) и анали-
циям пользователя требования уже гораздо ниже. С воз- зирует порты на наличие дополнительных устройств. В
лагаемой на них задачей спокойно могут справиться и ходе последней обнаруживается установленная сете-
«четверки». вая карта, в энергонезависимой памяти которой обна-
Но и это еще не все. При подключении к серверу жес- руживается код, начинающий выполняться после завер-
ткий диск становится не у дел. Все необходимые для об- шения теста.
работки данные находятся на сервере. Терминал в таком Дальнейшую работу условно можно разделить на три
случае использует локальный жесткий диск фактически этапа: получение IP-адреса, получение образа операци-
лишь для загрузки системы. Неужели в таком случае онной системы и собственно работа с данными. Чтобы
нельзя обойтись как-нибудь без него? получить IP-адреса, программа загрузки инициализиру-

№12(13), декабрь 2003 85


образование
ет широковещательный запрос (для нашего примера  DOS Executable ROM Image (.com) – DOS-загрузчик
192.168.0.255, по умолчанию используется порт 68, про- тоже подходит, только уберите загрузку himem.sys и
токол UDP), в котором указывается свой уникальный для emm386.exe, а то работать, скорее всего, не будет, и
каждой сетевой карты МАС-адрес. Для динамического добавьте соответствующие строки в файл config.sys
распределения IP-адреса между компьютерами в сети для загрузки.
используется служба DHCP. DHCP-сервер, приняв зап-  PXE loadable ROM Image (.lzpxe) – то же, что и второй
рос, находит конфигурацию, соответствующую данному пункт, но разработки Intel.
МАС-адресу, и возвращает cледующие данные:
 IP-адрес рабочей станции. Выбираем вариант Floppy Bootable ROM Image, при
 Маску сети. нажатии на кнопку «Get ROM» вы получаете нужный об-
 Путь к загружаемому ядру ОС. раз. Чтобы перезаписать его на дискету, воспользуйтесь
 Путь к каталогу, который монтируется в качестве кор- программой rewrite под Windows, которая входит в состав
невого. практически каждого дистрибутива Linux, а в Linux дайте
следующую команду:
Переговоры между клиентом и сервером можно вос-
произвести примерно так. #cat your_image.lzdsk > /dev/fd0
Клиент: «Привет, мой аппаратный адрес 00-02-44-07-
FC-C4, дай мне мой IP-адрес». или
Сервер: «(Ищет адрес в базе данных.) Ваше имя –
aldebaran, ваш IP-адрес – 192.168.0.100, ваш сервер – #dd if=/path/to/rom-image of=/dev/fd0 bs=1024
192.168.0.1, файл, от которого вы загружаетесь, нахо-
дится в /tftpboot/ltsp/vmlinuz-2.4.21-ltsp-1 и остальная ин- как кому привычнее. Программа первоначальной загруз-
формация). ки готова. Первоначально я советую попробовать загру-
Естественно, в сети должен находиться один такой сер- жаться с дискеты и настроить схему один сервер – один
вер, иначе они передерутся между собой, и, конечно же, клиент, а после успешного преодоления всех подводных
необязательно он должен быть нашим сервером графи- камней уже нарастить количество клиентов и заняться
ческих приложений. После получения адреса клиент дол- прошивкой кода в ПЗУ. Приступаем к наиболее весело-
жен загрузить ядро операционной системы. Для этого ис- му занятию – настройке сервера.
пользуется протокол TFTP (тривиальный протокол пере- Отправная точка в Интернете для поиска необходимой
дачи файлов). Это просто облегченная версия протокола информации и программ – официальный сайт проекта
FTP, которая не требует идентификации и использует http://www.ltsp.org.
UDP-протокол вместо TCP. Ну а чтобы пользоваться фай- Конфигурация сервера Athlon 1.3 Гц, 256 Мб, 10 Mбит
ловой системой, на другом компьютере на сервере долж- сетевая карта. Пять клиентов Pentium-100, 16 Мб, Video
на быть настроена служба NFS. После загрузки ядра оно, S3 Trio 3D 4 Мб. Все это настраивалось под операцион-
уже как и положено, берет бразды правления в свои руки. ными системами Linux Mandrake 8.0 и Red Hat 7.3. Для
Вот вкратце и все. того чтобы это все работало на данных системах, были
Теперь займемся практической реализацией. Для установлены следующие сервисы: dhcp, nfs, portmap, tftp
того чтобы было возможным загружаться описанным (клиент и сервер), если понадобится telnet-сессия, то и
выше способом, необходимо записать образ загрузчи- telnet-сервер и запущена служба xinetd. На установке
ка, поддерживающего определенную сетевую карту в выше перечисленных сервисов я останавливаться не
EPROM (Erasable Programmable Read-Only Memory – пе- буду, хотя бы потому, что большинство их входит в со-
резаписываемая память). Для этого заходим на сайт став соответствующих дистрибутивов, и если нет в стан-
http://rom-o-matic.net/ и в выпадающем списке «Choose дартной поставке, то их всегда можно найти на соответ-
NIC/ROM type» выбираем марку чипа на сетевой кар- ствующем сайте.
те. Здесь я допустил ошибку, помня, что сетевая карта Для настройки ltsp нам понадобятся следующие паке-
NE2000 совместимая, просто скачал образ для NE. И ты, которые можно взять с http://prdownloads.sourceforge.net/
вполне естественно, при загрузке получил что-то вро- ltsp/, все они доступны как в виде перекомпилированных
де «не могу найти NE*-карту». Пришлось раскрывать пакетов в формате rpm или deb, так и в виде исходников.
корпус одного из компьютеров и смотреть, что там та- Какие устанавливать – дело вкуса и опыта. Я скачал в
кое установлено, заодно и сам узнал марку чипа – формате tgz. Итак, какие необходимо скачать пакеты (вер-
rtl8029. В меню «Choose ROM output format» выберите сию не указываю специально, так как к моменту выхода
интересующий формат. Доступны следующие вариан- статьи все может измениться, плюс уже давно ходит в
ты образов: бетах версия 4):
 Floppy Bootable ROM Image (.lzdsk) – загрузчик с дис-  ltsp_core – основной пакет, необходимый для работы;
кеты (на первом этапе лучше воспользоваться имен-  ltsp_kernel – ядро, загружаемое на клиентский компьютер;
но им).  ltsp_x_core – пакет, необходимый для запуска X-
 Binary ROM Image (.lzrom) – прошивка ПЗУ сетевой карты. Window версии 4.х на клиентском компьютере;
 LILO Bootable ROM (.lzlilo) – загрузка с использованием  ltsp_x_fonts – пакет со шрифтами (скачал по рекомен-
LILO. дации на сайте, но вполне можно обойтись и без него).

86
образование
Если видеокарта не поддерживается в версии 4.х, не- Для начала о некоторых допущениях, связанных с кон-
обходимо дополнительно выбрать пакет с версией сер- фигурацией локальной сети. В сети 192.168.0.0/255.255.255.0
вера 3.3.6 применительно к видеокарте, установленной для бездисковых терминалов выделены адреса с
на ваших клиентских компьютерах (в моем случае это 192.168.0.100 по 192.168.0.254. Серверы DHCP и LTSP
ltsp_x336_s3), или, если нет, то ltsp_x336_svga, но при находятся на компьютере 192.168.0.1. Тогда файл /etc/
этом не будут работать TrueType-шрифты и сглажива- dhcpd.conf будет иметь такой вид:
ние. На сайте также доступны пакеты для поддержки
звука, сканера, веб-камер и wireless-устройств на тер- subnet 192.168.0.0 netmask 255.255.255.0 {
range 192.168.0.2 192.168.0.100;
минале, пакеты для организации Windows-терминала и option subnet-mask 255.255.255.0;
еще много чего. Первым обязательно должен быть ус- option broadcast-address 192.168.0.255;
option routers 192.168.0.1;
тановлен пакет ltsp_core. Установка заключается в рас- option domain-name-servers 192.168.0.1;
паковке (tar xvzf) и запуске инсталляционного скрипта option domain-name "server.org";
option log-servers 192.168.0.1;
(cd ltsp_ххх, ./install.sh). Остальные устанавливаются host term1 {
аналогично. Для rpm-пакетов просто дайте команду: hardware ethernet 00-02-44-07-FC-C4;
fixed-address 192.168.0.100;
option host-name "term1";
option root-path "192.168.0.1:/opt/ltsp/i386";
# rpm -ivh ltsp_core-3.0.9-0.i386.rpm filename "lts/vmlinuz-2.4.21-ltsp-1";
}
и аналогичную для остальных. При запуске скрипта уста-
новки ltsp_core выдается информация, которая подразу- Небольшое пояснение. В начале конфигурационного
мевается по умолчанию, все настройки можно изменить файла расположены инструкции, относящиеся ко всем
в файле config, желательно до начала инсталляции, а то компьютерам сети. Их смысл очевиден. Поскольку на
потом придется править во всех файлах по отдельности: терминалах нет жесткого диска, то демону журналиро-
вания syslogd в строке option log-servers 192.168.0.1 ука-
Good! We have found RedHat version 7.3 зывается удаленный сервер, который будет записывать
About to install LTSP, using the following settings:
# êàòàëîã, â êîòîðûé óñòàíàâëèâàþòñÿ ïàêåòû от него сообщения. Для того чтобы демон syslogd на сер-
LTSP_DIR = /opt/ltsp вере мог принимать сообщения от терминалов, в файле
SWAP_DIR = /var/opt/ltsp/swapfiles
# êàòàëîã äëÿ çàãðóæàåìîãî ÿäðà конфигурации /etc/sysconfig/syslog, должен использо-
TFTP_DIR = /tftpboot ваться ключ -r:
# àäðåñ ñåòè
IP_NETWORK = 192.168.0.0
# àäðåñ ñåðâåðà # Options to syslogd
IP_SERVER = 192.168.0.1 # -m 0 disables 'MARK' messages.
# ìàñêà ñåòè # -r enables logging from remote machines
IP_NETMASK = 255.255.255.0 # -x disables DNS lookups on messages recieved with -r
# øèðîêîâåùàòåëüíûé àäðåñ ñåòè # See syslogd(8) for more details
IP_BROADCAST = 192.168.0.255 SYSLOGD_OPTIONS="-m 0 -r "

После установки всех пакетов перейдите в каталог /opt/ Далее идут индивидуальные настройки для каждо-
ltsp/templates/ и запустите скрипт ./ltsp_initialize, который го компьютера клиента. Здесь можно переопределить
внесет необходимые изменения в конфигурационные фай- настройки сервера индивидуально. В строке hardware
лы вышеперечисленных сервисов. Внимательно читайте ethernet 00-02-44-07-FC-C4 указывается аппаратный
выходные данные, если что-то у вас не установлено, то МАС-адрес сетевой карты, а в строке fixed-address
скрипт выдаст сообщение об ошибке. Теперь давайте пе- 192.168.0.100 за ним статически закрепляется IP-адрес.
рейдем к ручной доводке сервисов. Теперь при запросе клиента с указанным МАС-адресом
Сервис dhcp настраивается в файле /etc/dhcpd.conf, ему всегда будет выдаваться IP-адрес 192.168.0.100.
который при установке в большинстве дистрибутивов не Остальным же он будет назначаться на общих прави-
создается, поэтому первоначально может потребоваться лах, из таблицы свободных адресов. Строка option root-
его создать: path указывает на раздел, который будет смонтирован
в качестве корневого с помощью службы NFS, его мож-
#touch /etc/dhcpd.conf но прописать и в глобальной секции, но только в том
случае, если в данной сети используются только без-
Для того чтобы правильно его настроить, необходи- дисковые станции, иначе ноутбук шефа будет загружать
мо знать MAC-адрес сетевой карты, IP-адрес сервера и что попало. Для того чтобы данный ресурс был виден в
сетевую маску. Для выяснения MAC-адреса я нашел в сети, необходимо в файле /etc/exports сервера LTSP ука-
Интернете множество программ, написал одну на Perl, зать каталоги, доступные для сетевого монтирования:
воспользовавшись модулем с CPAN, затем вспомнил, что
демон arpd сохраняет информацию о всех MAC-адресах /opt/ltsp/i386 192.168.0.0/255.255.255.0 (ro, no_root_squash)
/var/opt/ltsp/swapfiles (rw, no_root_squash)
и их IP-адресах в пределах локальной сети, а проблема
решилась проще, чем я думал, при запуске образа, ко- Слева указаны каталоги, которые экспортирует сер-
торый мы приготовили на дискете раньше, выдается тре- вер, первая строка – корневую систему, а вторая – раз-
буемый MAC-адрес сетевой карты, установленной на дел свопирования, если в нем есть необходимость. Спра-
компьютере. ва указаны опции. Флаги ro и rw указывают на доступ толь-

№12(13), декабрь 2003 87


образование
ко для чтения и для записи и чтения соответственно. А вы полностью доверяете всем компьютерам, а от внешних
no_root_squash заменяет пользователя root более безо- собратьев закрыться firewall.
бидным nobody. Параметры ro и no_root_squash, исполь- Файл /etc/xinet.d/tftp будет иметь такой вид:
зуются в файле по умолчанию, и поэтому их можно смело
опустить, но так как-то нагляднее. service tftp
{
Ядро может автоматически определить только PCI се- socket_type = dgram
тевую карту, если у вас ISA, то добавьте следующие стро- protocol = udp
wait = yes
ки для каждого описываемого клиента. user = root
server = /usr/sbin/in.tftpd
server_args = -s /tftpboot
option option-128 e4:45:74:68:00:00; disable = no
option option-129 "NIC=ne IO=0x300"; per_source = 11
cps = 100 2
Здесь хочется отметить, что «option-128» в этом слу- }
чае не является mac-адресом, это специальный ключ для
загрузки Etherboot. Параметр «option-129» указывает На этом настройки данных серверов можно считать за-
ядру, какой именно драйвер сетевой карты необходимо конченными. Желательно проверить их работу перед при-
загружать. Параметр filename указывает путь к ядру, менением.
который необходимо загружать. Пакет LTSP поставля-
ется с двумя ядрами, поддерживающими большинство [root@grinder root]# tftp grinder
tftp> get lts/vmlinuz-2.4.21-ltsp-1
сетевых карт: одно описано выше, а второе с префик- Received 1062469 bytes in 0.9 seconds
сом lpp (Linux Progress Patch) в имени. При использова- tftp> quit
нии последнего ядра на компьютере клиента при загрузке
отображается статус-бар, данное ядро рекомендуется Имя файла указано так потому, что корневой каталог
использовать, после того как удалось все настроить и для этого сервиса определен в файле /etc/xinet.d/tftp как
загрузиться с обычного. server_args= -s /tftpboot, т.е. каталог /tftpboot делается кор-
Дополнительно может понадобиться для экспорта до- невым (chroot), и поэтому если указать полный путь, то
машних каталогов пользователей /home добавить следу- сервер просто не найдет необходимый файл.
ющие строки в файл /etc/exports: Меньше всего возни с настройкой сервера шриф-
тов было в дистрибутиве Red Hat. А с настройкой в ос-
/home 192.168.0.0/255.255.255.0 (rw) тальных мне очень помог разобраться документ http://
www.ltsp.org/contrib/AbiWordfont.txt. В файле /etc/X11/fs/
а в файл /opt/ltsp/i386/etc/fstab: config в строке «client-limit = 10» установите число компь-
ютеров клиентов, рекомендуемое не более сорока. В фай-
ltsp-server:/home/ /home nfs defaults,rsize=8192,wsize=8192 0 0 ле /etc/X11/XF86Config (или XF86Config-4, если вы исполь-
зуете четвертую версию сервера) замените строку:
И обязательно добавьте в файл /etc/hosts описание
компьютеров сервера и клиентов для нормальной рабо- FontPath "unix/:-1"
ты службы NFS. Например:
на
/etc/hosts
127.0.0.1 localhost.localdomain localhost
… FontPath "tcp/localhost:7100"
192.168.0.1 server.org
192.168.0.100 term1
А в файле /etc/rc.d/init.d/xfs замените строку:
Теперь необходимо перезапустить сервис dhcpd:
daemon --check xfs xfs -port -1 -daemon -droppriv -user xfs
[root@grinder etc]# /etc/init.d/dhcpd restart
Îñòàíàâëèâàåòñÿ dhcpd: [ ÑÁÎÉ ]
Çàïóñêàåòñÿ dhcpd: [ ÎÊ ] на
[root@grinder etc]# /etc/init.d/dhcpd status
dhcpd (pid 979) âûïîëíÿåòñÿ... daemon --check xfs xfs -port 7100 -daemon -droppriv -user xfs
На этом настройку dhcpd можно считать законченной.
Теперь о настройках остальных сервисов. Общим для и строку:
некоторых из них является то, что если сервис запускает-
ся с помощью xinetd (tftp, telnet), то он обязательно дол- daemon --check xfs su xfs -c \"xfs -port -1\" -s /bin/sh
жен быть разрешен (в файлах /etc/xinet.d/tftp и /etc/xinet.d/
telnet), для этого требуется заменить disable = yes на на
disable = no. Также в целях улучшения безопасности мо-
гут быть определены IP-адреса, с которых разрешен дос- daemon --check xfs su xfs -c \"xfs -port 7100\" -s /bin/sh
туп к данному сервису (по умолчанию localhost), т.е. в на-
шем случае only_from = 192.168.0.0. Кстати, вообще вы- Перезапустите сервер и проверьте, слушает ли он порт
шеописанное желательно проводить в сетях, в которых под номером 7100. Для того чтобы терминалы могли зап-

88
образование
рашивать у сервера сеанс XDM, требуемый для регист- X_MOUSE_BUTTONS = 2 # êîëè÷åñòâî êíîïîê ìûøè
рации пользователя и запуска пользовательской сессии, # âêëþ÷åíèå ýìóëÿöèè òðåòüåé êíîïêè ìûøè
# (íàæàòèåì äâóõ èìåþùèõñÿ îäíîâðåìåííî)
необходимый при использовании X-Window, требуется в X_MOUSE_EMULATE3BTN = Y
конфигурационном файле /etc/X11/xdm/xdm-config на сер- X_MOUSE_BAUD = 1200
RUNLEVEL = 3
вере LTSP внести соответствующие изменения:
Уровень инициализации (RUNLEVEL) 3 загружает ко-
! SECURITY: do not listen for XDMCP or Chooser requests мандную строку bash_shell в консоли, этот параметр же-
! Comment out this line if you want to manage X terminals with xdm
# ýòîò ïóíêò îáÿçàòåëüíî çàêîììåíòèðîâàòü лательно установить первым для отладки работы серви-
! DisplayManager.requestPort: 0 сов, и если все получилось, то использовать либо 4 для
# Ýòó ñòðî÷êó äîáàâèòü, ïðàâäà íåîáÿçàòåëüíî. Îñòàëüíûå
# ìîæíî íå òðîãàòü. telnet-сессии, позволяющей открывать несколько терми-
DisplayManager.*.setup:/etc/X11/xdm/Xsetup_workstation налов на сервере и переключаться между ними по Alt-F1
Ñêðèïò Xsetup_workstation èìååò òàêîé âèä:
#! /bin/sh до Alt-F9, либо 5 для автоматического старта X-Windows.
/usr/X11R6/bin/xsetroot -solid "#356390" Для каждого клиента, как видите, есть возможность оп-
if [- x /usr/bin/xsri]; then
/usr/bin/xsri -geometry +5 +5 -avoid 300x250 ↵ ределить индивидуальные параметры Х-сервера в сек-
-keepaspect /etc/X11/xdm/ltsp.gif ции, но возможен и другой вариант, он особенно удо-
fi
бен, если имеется несколько клиентов с одинаковыми
И остался «последний и решительный бой». Правка видеокартами.
самого главного конфигурационного файла LTSP /opt/ Для этого необходимо указать в параметре
ltsp/i386/etc/lts.conf. Наиболее подробную информацию XF86CONFIG_FILE = XF86Config.term1 имя конфигура-
о настройках тех или иных параметров можно узнать ционного файла для данного клиента и поместить его
из файла /opt/ltsp/i386/etc/lts.conf.readme. Данный файл в каталог /opt/ltsp/i386/etc/X11/ (предварительно создав
состоит из раздела [Default], в котором определяются каталог Х11). Мне в этом смысле немного повезло, на
общие для всех клиентов параметры, и разделов, оп- одном из клиентских компьютеров до этого стоял Linux,
ределяющих индивидуальные для каждого клиента, в поэтому генерировать данный файл заново не при-
них при необходимости можно переопределить те или шлось. Если у вас другая ситуация, то попробуйте ис-
иные глобальные установки. Благодаря такой схеме пользовать программу /usr/X11R6/bin/xf86config на сер-
появляется возможность более гибкой адаптации к ап- вере, установив туда нужную видеокарту (не забудьте
паратной конфигурации терминалов. Итак, пример фай- сохранить при этом оригинальные файлы). Дополни-
ла lts.conf: тельно можно переопределить параметры клавиатуры,
используемые по умолчанию. Для этого предназначе-
[Default] ны следующие опции:
SERVER = 192.168.0.1
# êîìïüþòåð, âûñòóïàþùèé â ðîëè ñåðâåðà ãðàôè÷åñêèõ ïðèëîæåíèé  XkbModel – модель клавиатуры, наиболее распрост-
XSERVER = auto раненные – pc 101, pc 102, pc 105;
# óêàçûâàåò íà òî, ÷òî ñèñòåìà ñàìà îïðåäåëÿåò òèï çàãðóæàåìîãî
# XFree86-ñåðâåðà  XkbLayout – раскладка клавиатуры, например us (по
X_MOUSE_PROTOCOL = "IMPS/2" умолчанию), ru, ru(winkeys);
# íàçâàíèå ïðîòîêîëà ìàíèïóëÿòîðà ìûøè
# â äàííîì ñëó÷àå èñïîëüçóåòñÿ ìûøü ñî ñêðîëëèíãîì, åñëè  XkbSymbols – таблица скан-кодов, по умолчанию
# îáûêíîâåííàÿ ìûøü ïîäêëþ÷àåìàÿ ê ïîðòó PS/2, òî ïîïðîáóéòå «us(pc 101)», но можно заменить, например на
# ïðîñòî PS/2
X_MOUSE_DEVICE = "/dev/psaux" «us(pc105) + ru».
# óêàçûâàåò íà ïîðò PS/2
X_MOUSE_RESOLUTION = 50
X_MOUSE_BUTTONS = 3 Раз уже коснулись раскладки клавиатуры, то два сло-
LOCAL_APPS = N ва о том, как использовать русскую. Для установки и пе-
USE_XFS = Y # èñïîëüçóåòñÿ ñåòåâîé ñåðâåð øðèôòîâ
RUNLEVEL = 5 реключения на русский вариант (в рассматриваемом слу-
SOUND = Y чае) раскладки клавиатуры в XFree86 применяется два
VOLUME = 75
параметра XkbLayout и XkbOptions. Первый, как уже от-
И секция для клиента. В качестве ее названия может мечалось, можно переопределить, а вот для того чтобы
выступать имя хоста, МАС- или IP-адрес, т.е. [term1], была возможность переключаться между раскладками,
[192.168.0.100] или [00-02-44-07-FC-C4]. необходимо выполнить еще некоторые действия. Все на-
стройки, касающиеся параметров XFree86 во всех Linux
[term1] производятся в файле XF86Config для версии 3 и в
XSERVER = XF86_SVGA
# Òèï X-ñåðâåðà, êîòîðûé áóäåò âûïîëíÿòüñÿ íà êëèåíòñêîé XF86Config-4 для четвертой версии. Но для терминалов
# ñòàíöèè. Äëÿ ÷åòâåðòîé âåðñèè óêàçûâàåòñÿ âèäåîìîäóëü, таких файлов изначально не существует, они генериру-
# íàïðèìåð nv. Äëÿ XFree86 3.3.6 óêàçûâàåòñÿ èìÿ ñåðâåðà
# XF86_SVGA, XF86_S3 è ò.ä. ются динамически при запуске. Для этих целей использу-
X_MODE_0 = 800x600 40 800 840 968 1056 600 601 605 628 ↵ ется скрипт /opt/ltsp/i386/etc/rc.setupx3 для клиентов с вер-
+hsync +vsync
# óñòàíîâêà ïàðàìåòðîâ âûâîäà íà ýêðàí, èõ ìîæåò áûòü сией 3 и /opt/ltsp/i386/etc/rc.setupx для четвертой версии,
# íåñêîëüêî îò X_MODE_0 äî X_MODE_10 которые, кстати, берут основные параметры для настрой-
X_VIDEORAM = 4096 # êîëè÷åñòâî âèäåîïàìÿòè
X_MOUSE_PROTOCOL = "Microsoft" ки из файла lts.conf. Так вот, для того чтобы переключа-
# ìûøü ñ ïîñëåäîâàòåëüíûì èíòåðôåéñîì тель заработал, необходимо после строки XkbLayout
X_MOUSE_DEVICE = "/dev/ttyS0"
# ìûøü, ïîäêëþ÷àåìàÿ ê ïàðàëëåëüíîìó ïîðòó «${XkbLayout}» для rc.setupx3 или Option «XkbLayout»
X_MOUSE_RESOLUTION = 50 «${XkbLayout:-»us»}» для rc.setupx прописать параметр,

№12(13), декабрь 2003 89


образование
устанавливающий комбинацию для изменения расклад- для работы openmosix-tools. Все это можно найти на
ки, например: странице http://prdownloads.sourceforge.net/openmosix/,
 XkbOptions «grp:caps_toggle» – переключение по Caps где доступны как сами патчи, так и уже перекомпили-
Lock; рованые (серверные) ядра для разных платформ, при-
 XkbOptions «grp:alt_shift_toggle» – более привычное для чем уже доступны патчи для ядер серии 2.6. Мы будем
пользователей Windows переключение по Alt + Shift. устанавливать при помощи патча, самостоятельно ком-
пилируя все ядра.
Вот и все. Самое интересное, что это действительно Для этого берем ядро 2.4.22:
работает. На клиентском компьютере загрузить даже
KDE с OpenOffice и причем с вполне терпимой скорос- # wget -c http://www.kernel.org/pub/linux/kernel/v2.4/ ↵
linux-2.4.22.tar.bz2
тью, после перехода на оконный менеджер IceWM и за- # wget -c http://tab.tuxfamily.org/download/openmosix/ ↵
пуска аналога OpenWritera от GnomeOffice – AbiWord си- patch-2.4.22-om-20030811.bz2
стема вообще летала. Конечно, при увеличении количе-
ства клиентов до 10 желателен сервер помощнее, как Теперь все разархивируем:
минимум оперативной памяти 512 Мб. Наиболее очевид-
ное применение данной технологии – это наши учебные # tar -xjvf - linux-2.4.22.tar.bz2
# cd linux-2.4.22
заведения со старыми компьютерными классами, где до- # bzcat ../patch-2.4.22-om-20030825.bz2|patch -p1
бавление одного мощного компьютера позволит рабо- # ln -sf /path/to/linux-2.4.22 /usr/src/linux
тать с современным ПО. В организации интернет-кафе
с помощью технологии LTSP поможет скрипт: http:// Теперь заходим в него:
prdownloads.sourceforge.net/ltsp/ltsp_phpSiCafe-0.0.1.tgz,
назначение которого – учет времени, проведенного # cd /usr/src/linux
пользователями за компьютером. Заинтересовавшимся
советую также заглянуть еще на два сайта. Первый Конфигурируем серверное ядро:
http://k12ltsp.org/, этот проект предназначен для уста-
новки терминального сервера, разработанного для школ, # make xconfig {menuconfig, gconfig}
базируется на дистрибутиве Red Hat. Второй http://
www.ltsp.ru/, как видно из названия, русский сайт проек- И смотрим, чтобы следующие пункты были включены
та. Здесь уже можно найти переводную документацию в ядро, а не в виде модулей:
по работе с бездисковыми станциями, описание установ-
ки виртуальной машины VMWare для запуска приложе- openMosix ---
openMosix process migration support
ний, написанных под Windows. openMosix File-System
Все это, конечно, интересно и работает уже более
Networking options ---
года, но совсем недавно познакомившись с проектом Packet Socket
OpenMosix (http://openmosix.sourceforge.net/), предлага- Socket Filtering
TCP/IP networking
ющим OpenSource-решение создания кластерных сис- IP: multicasting
тем на основе компьютеров, соединенных в единую сеть.
File systems ---
OpenMosix представляет собой расширение к обычному /proc file system support
ядру Linux, при его установке узлы в кластере начинают
Network File Systems ---
«общаться» с друг другом, и кластер адаптирует себя к NFS file system support
рабочей нагрузке. Процессы, обрабатывающиеся на лю- NFS server support
Provide NFSv3 server support
бом из узлов, при увеличении нагрузки данного компь-
ютера по сравнению с другими способны передаваться И компилируем новое ядро:
на любой другой компьютер кластера. OpenMosix посто-
янно пытается оптимизировать распределение ресурса # make dep
# make bzImage && make modules && make modules_install
между машинами, при этом новый узел может быть до-
бавлен «на лету» и автоматически будет подхвачен кла- Для ядер серии 2.6 достаточно ввести make all.
стером. Так как все openMosix расширения выполняют- Копируем ядро на свое место:
ся внутри ядра, каждое из приложений, автоматически
извлекает выгоду из распределенной вычислительной # mv arch/i386/boot/bzImage /boot/vmlinuz-openmosix
концепции openMosix. Кластер ведет себя фактически
как многопроцессорная система, правда без ограниче- Конфигурируем загрузчик для работы с новым ядром,
ния на их максимальное число. И естественно возникло и после перезагрузки система будет готова. Если уста-
желание испытать это все в деле, тем более что боль- новка производится при помощи перекомпилированных
шая часть работы уже проделана. пакетов, все вышеописанное (кроме настройки загруз-
Как и в приведенном выше примере, один из компь- чика) будет в систему добавленно автоматически. Для
ютеров играет роль главного (master), а остальные, этого вводим:
сколько есть, подчиненные (slave). Для работы понадо-
бятся сами ядра с патчем от openMosix и инструменты # rpm -ivh openmosix-kernel-2.4.22-openmosix1.i686.rpm

90
образование
Установка slave-ядра которые будут задействованы в кластере. Каждая строка
Для начала сохраняем конфигурационный файл основ- в этом файле состоит из трех частей:
ного ядра.
1 192.168.0.1 1
# cp /usr/src/linux/.config /usr/src/linux/.config_master 2 192.168.0.100 10

Первым идет openMosix node-number узла в указанном


Само slave-ядро лучше собирать без поддержки моду- диапазоне, второй строкой – IP-адрес или имя, описанное в
лей, т.к. настройка их загрузки через сеть – довольно хло- файле /etc/hosts, и третьей – количество узлов в этом диа-
потное дело, также желательно побеспокоиться о компак- пазоне. В данном примере нашему серверу присвоен
тности, отключив как можно больше ненужных функций. openMosix node-number 1, а десяти узлам в диапазоне
Следующие опции нужно включить в ядро. 192.168.0.100-192.168.0.109, номера 2-11. Если бы IP-ад-
реса шли подряд, то можно было бы обойтись и одной
openMosix --- строкой. После правки файла делаем его доступным и
openMosix process migration support
openMosix File-System другим узлам.
Networking options ---
TCP/IP networking # cp /etc/openmosix.map /opt/ltsp/i386/etc/
IP: kernel level auto-configuration
IP: DHCP support
IP: BOOTP support Туда же копируем и бинарные файлы openmosix-tools.
File systems ---
/proc file system support # cp /sbin/setpe /opt/ltsp/i386/sbin/
# cp /bin/mosrun /opt/ltsp/i386/bin/
# cp /bin/mosmon /opt/ltsp/i386/bin/
Network File Systems ---
NFS file system support # cp /bin/mosctl /opt/ltsp/i386/bin/
Provide NFSv3 client support # cp /bin/migrate /opt/ltsp/i386/bin/
Root file system on NFS # cp /etc/rc.d/init.d/openmosix /opt/ltsp/i386/etc/rc.openmosix

Но получившееся в результате ядро копируем в дру- И запускаем openМosix:


гое место, а именно в каталог /tftpboot. Например:
# /etc/init.d/openmosix start
# cp /usr/src/linux/arch/i386/boot/bzImage ↵
/tftpboot/lts/vmlinuz-openmosix-slave
После перезагрузки slave-узлов работу можно прокон-
И настраиваем его загрузку описанным выше спосо- тролировать при помощи утилиты mosctl, введя номер
бом. В принципе для этого не обязательно иметь установ- нужного:
ленный полный пакет ltsp, а все необходимое создать вруч-
ную, как это все сделать, можно найти в дополнительной # mosctl status 2
литературе, указаной в конце статьи. Но все равно, для того
чтобы избежать большого количества ручной работы, сове- А в файле /etc/inittab рекомендуется строку:
тую в таком случае скачать файл ltsp_initrd_kit и ltsp_util_src
(http://prdownloads.sourceforge.net/ltsp/ltsp_initrd_kit-3.0.11- si::sysinit:/etc/rc.d/rc.sysinit
i386.tgz и http://prdownloads.sourceforge.net/ltsp/ltsp_util_src-
3.0.0-i386.tgz). заменить на:
Все, что мы делали до сих пор, фактически не отличается
от предыдущего варианта ядра. Чтобы заставить компьюте- si::sysinit:/bin/mosrun -h /etc/rc.d/rc.sysinit
ры работать в одной связке и обмениваться нагрузкой, необ-
ходимо установить пакет openmosix-tools. Его также можно Чтобы избежать проблем при использовании сервиса
получить уже в виде перекомпилированных пакетов или все SSH в файле /etc/rc.d/init.d/sshd в функции start(), добавь-
это проделать самому. Ничего особенного в компиляции нет: те следующую линию:

# ./configure –with-kerneldir=/usr/src/linux test -f /proc/$$/lock && echo 0 > /proc/$$/lock

Флагом -with-kerneldir указываем путь к исходным фай- Вот и все. Остается пожелать успехов, и я надеюсь,
лам ядра, по умолчанию /usr/src/linux-openmosix: эта статья кому-то поможет.

# make && make install Кроме документации на сайтах проектов LTSP и openMosix
советую просмотреть еще и следующие документы:
Или строим пакет для rpm-based дистрибутивов: 1. Колисниченко Д. Загрузка по сети. – //журнал «Сис-
темный администратор», №9(10), 2003 г. – 47-49 с.
# rpmbuild -ta openmosix-tools-0.3.4.tar.gz 2. LTSP + openMosix: Integration How-To:
http://home.onestop.net/jjensen/ltsp-om5r3c.html
После окончания установки приступаем к настройке. 3. openMosix and Diskless Nodes:
Для начала в файле /etc/openmosix.map, определим узлы, http://www.gentoo.org/doc/en/openmosix-howto.xml

№12(13), декабрь 2003 91


cодержание журнала за 2003 год

Содержание журнала

Построение программных RAID-массивов в Linux Дмитрий Рожков №5(6)


АДМИНИСТРИРОВАНИЕ № Почтовая система для среднего и малого офиса Андрей Бешков №5(6)
Практика OpenSSL Всеволод Стахов №2(3)
FreeBSD. Компиляция Александр Прокошев №4(5) Процессы и нити Всеволод Стахов №5(6)
Ipfw и управление трафиком в FreeBSD Игорь Чубин №6(7) Разводной мост на Linux (Bridging Firewalls) Павел Закляков №4(5)
IPSec через NAT: проблемы и решения Татьяна Антипова №3(4) Решение задач инвентаризации в сети Иван Коробко №12(13)
IRC-сервер Александр Слободской №7(8) Свой собственный модуль Денис Колисниченко №10(11)
Milter = Mail + Filter Роман Сузи №2(3) Система фильтрации интернет-трафика Андрей Бешков №4(5)
NetBSD: установка и настройка Андрей Бешков №8(9) Скрипты для подсчета трафика: пример реализации в FreeBSD
OpenBSD. Первые шаги Денис Назаров №8(9) Денис Пеплин №6(7)
Postfix+...+SpamAssassin. Mini-howto Андрей Мозговой №9(10) Создаем VPN на основе vtun Андрей Бешков №4(5)
Python в администрировании сервера: почему бы и нет? Роман Сузи №1 Создание PDC (основного контроллера домена) для Windows
RADIUS Всеволод Стахов №4(5) на базе SAMBA 2.2.5 Андрей Гуселетов №1(2)
SMTP AUTN in da Postfix + ... Андрей Мозговой №10(11) Создание загрузочных дискет и CD-дисков Linux Всеволод Стахов №6(7)
TACACS Всеволод Стахов №3(4) Создание простейшей биллинговой системы Денис Мясниченко №2(3)
Windows Server 2003: взгляд системного администратора Стартовые скрипты FreeBSD Денис Пеплин №7(8)
Алексей Доля, Михаил Мельников №11(12) Статическая маршрутизация в Linux iproute2. Часть1 Всеволод Стахов №5(6)
Абсолютно все о ATM Сергей Ропчан №4(5) Статическая маршрутизация в Linux iproute2. Часть2 Всеволод Стахов №6(7)
Абсолютно все о Frame Relay Сергей Ропчан №3(4) Теория и практика OpenSSL Всеволод Стахов №1(2)
Абсолютно все о Х.25 Сергей Ропчан №1(2) Удаленное резервное копирование: пример реализации в FreeBSD
Абсолютно все о технологии ISDN Сергей Ропчан №2(3) Денис Пеплин №5(6)
Архитектура файловой системы ext2 Владимир Мешков №11(12) Удобная почтовая система Вячеслав Калошин №1
Аудит учетных записей пользователей в Active Directory Максим Костышин №11(12) Управление сетевыми принтерами домена Иван Коробко №10(11)
Борьба за системные ресурсы Денис Колисниченко №4(5) Устанавливаем Multiple-Device-дозвон в Windows XP Татьяна Антипова №2(3)
Введение в OpenBSD Денис Назаров №6(7) Установка FreeBSD Сергей Яремчук №3(4)
Виртуальный компьютер Денис Колисниченко №6(7) Установка IMAP4-сервера на базе cyrus-imapd + sendmail Денис Шергин №10(11)
Виртуальный полигон для администратора и разработчика Андрей Бешков №9(10) Установка Nagios Андрей Бешков №2(3)
Виртуальный полигон для разработчика и администратора Установка и настройка сервера Jabber на платформе Linux Сергей Индлин №4(5)
на основе Linux и VMWare Андрей Бешков №11(12) Учет работы Dialup-пользователей в системе FreeBSD Сергей Супрунов №12(13)
Восстановление данных с лазерных дисков Крис Касперски №8(9) Учет трафика с помощью программ MRTG и LAN Billing Денис Колисниченко №6(7)
Восстановление загрузки операционной системы Linux Андрей Шевченко №2(3) Файловые системы Linux Сергей Яремчук №11(12)
Дистанционное управление в Linux Денис Колисниченко №5(6) Хеви Хардвэр. Установка и настройка коммутаторов CISCO CATALYST
Загрузка по сети Денис Колисниченко №9(10) серий 2900XL и 3500 Всеволод Стахов №1
Империя Cisco Денис Еланский №2(3) Что такое SAMBA? Сергей Яремчук №1
Интеграция SQUID + LDAP Марк Кричмар №11(12) Ы.Ы.Р. Особенности работы и настройки протокола SSH Всеволод Стахов №1(2)
Искажение TOC как средство борьбы с несанкционированным Это должен знать каждый, или Четыре базовых принципа
копированием диска Крис Касперски №9(10) выбора коммутатора ЛВС Геннадий Карпов №5(6)
Использование IPSec в Windows 200x Максим Костышин №6(7) Эффективная почтовая система на базе Exim Денис Мысенко №8(9)
Использование LVM Сергей Яремчук №10(11)
Использование бездисковых маршрутизаторов Андрей Мозговой
Как бороться с баннерами в ICQ Дмитрий Репин
№11(12)
№10(11)
СЕТИ №
Как выключить ESMTP-команды в Exchange 2000 Server Татьяна Антипова №3(4) NETFILTER Владимир Мешков №8(9)
Как пингвин говорит по телефону, или Настройка dialin-сервера Powerline: Интернет из розетки Денис Колисниченко №7(8)
для доступа Интернет и аварийной консоли Андрей Мозговой №2(3) Анализатор сетевого трафика Владимир Мешков №1
Контроль последовательных портов в Linux Денис Колисниченко №7(8) Дальняя связь. Как это бывает Денис Еланский №6(7)
Конфигурирование DHCP Денис Колисниченко №5(6) Планируем переезд сети Вячеслав Калошин №7(8)
Крепость для пингвина Сергей Яремчук №12(13) Программирование сокетов Всеволод Стахов №1
Маленький Linux в качестве firewall Сергей Яремчук №9(10) Протокол V.90 Денис Колисниченко №8(9)
Мечта сисадмина Сергей Яремчук №10(11) Сканер портов: пример реализации Владимир Мешков №1
Миграция с Windows на Linux Дмитрий Галышев №1
Мифы и легенды современной ОCологии…
или «ОС – это большой полосатый мух?» Александр Потемкин №2(3)
БЕЗОПАСНОСТЬ №
Мониторинг Windows-серверов с помощью Nagios. Часть 1 Андрей Бешков №7(8) LIDS Сергей Яремчук №4(5)
Мониторинг Windows-серверов с помощью Nagios. Часть 2 Андрей Бешков №8(9) OpenLDAP и защита данных Всеволод Стахов №2(3)
Настраиваем ASPLinux 7.3 Server Edition Александр Шибенко №10(11) SELinux Сергей Яремчук №5(6)
Настройка Incoming Connection в Linux Сергей Ропчан №4(5) Анализ защиты программ и рекомендации по ее усилению Станислав Гошко №10(11)
Настройка сервера SSH Денис Колисниченко №7(8) Атака на переполнение буфера через неисполнимый стек
Новые средства OC FreeBSD 5 Всеволод Стахов №8(9) в Windows NT/2000/XP Станислав Гошко №9(10)
Организация доступа в Интернет на предприятиях Алексей Федоров №5(6) Безопасность технологии виртуальных карт Сергей Ропчан №2(3)
Осваиваем Nagios Андрей Бешков №12(13) Борьба с вирусами: опыт контртеррористических операций Крис Касперски №10(11)
Пингвин с одного пинка Сергей Яремчук №8(9) Защитим электронную почту! Всеволод Стахов №1(2)

92
содержание журнала за 2003 год

за 2003 год

Защитник сети Сергей Яремчук №11(12) Управление сессиями в ColdFusion, или Здравствуйте, я – ваша тетя
Киберкоп, или Конец виртуального мира Дмитрий Аксенов №1(2) Александр Меженков №1(2)
Контрольная сумма на защите Linux/FreeBSD Сергей Яремчук №6(7) Эффективное использование памяти в Perl при работе
Минимум усилий на защиту DNS Сергей Ропчан №1(2) с большими строками Даниил Алиевский №1
Неявный самоконтроль как средство создания неломаемых защит
Крис Касперски
Обнаружение телекоммуникационных атак: теория и практика, snort
№7(8) ОБРАЗОВАНИЕ №
Павел Закляков №10(11) CommerceML – стандарт обмена коммерческой информацией
Общий обзор наиболее часто применяемых техник компьютерных атак в формате XML Елена Ртищева №1
и защиты от них Александр Потемкин №1(2) LTSP – вторая жизнь старых компьютеров Сергей Яремчук №12(13)
Очередная веская причина задуматься о переходе Mac OS X или То, что должен знать каждый про Macintosh, Apple
с ОС Windows на альтернативу Виктор Игнатьев №9(10) и операционные системы Александр Потемкин №7(8)
Переполнение буфера в Windows NT/2000/XP Станислав Гошко №8(9) Взаимные функциональные зависимости Андрей Филиппович №1
Перехват Shell через YaBB Виктор Игнатьев №6(7) Доступный Linux в каждую школу! Виктор Мельников, Андрей Шевченко №1(2)
Построение переносимого Shell-кода для Windows-систем Станислав Гошко №9(10) Коды Рида-Соломона в практических реализациях, или Информация,
Система криптографической защиты информации Владимир Мешков №4(5) воскресшая из пепла III Крис Касперски №11(12)
Советы по безопасной веб-аутентификации Игорь Тетерин №5(6) ЛВС: управляемость, надежность, масштабируемость Денис Еланский №3(4)
Сравнение сетевых сканеров безопасности Дмитрий Никсов, Петр Рудель №1(2) Могущество кодов Рида-Соломона, или Информация,
Технологии протоколирования Honeypot в обеспечении воскресшая из пепла Крис Касперски №8(9)
безопасности сетевых Unix-систем Антон Даниленко №5(6) Обучающие ситуационные центры Андрей Филиппович №5(6)
Три составных части защиты Сергей Яремчук №7(8) Обучение через Интернет – это возможно? Ольга Игошина №7(8)
Удобнее, эффективнее, лучше: snort + MySQL Павел Закляков №11(12) Пингвин идет в школу Сергей Голубев №1(2)
Полиномиальная арифметика и поля Галуа, или Информация,
HARDWARE № воскресшая из пепла II Крис Касперски
Скупой платит дважды, а умный использует GNU Public License
№10(11)

Вторая жизнь модемов Павел Закляков №12(13) Павел Закляков №9(10)


Глубоководное погружение в чипсет Intel 875P Крис Касперски №6(7)
Основы систем хранения данных Алексей Серебряков
Плохое электропитание, или «Грабли» с UPS Павел Закляков
№3(4)
№8(9)
WEB №
Работа с жестким диском на программном уровне Владимир Мешков №9(10) Fusebox в помощь веб-программисту Андрей Уваров, Дмитрий Горяинов №11(12)
PHP Сергей Яремчук №5(6)
ПРОГРАММИРОВАНИЕ № Выбор веб-сервера: почему Apache? Дмитрий Галышев
Интернет-операционные системы Игорь Тетерин
№4(5)
№4(5)
ColdFusion или, возможно, лучшее решение для создания Конвертирование из Excel в HTML: корректно, качественно, просто
динамических сайтов Александр Меженков №1 Алексей Мичурин №12(13)
Java - магия отражений Даниил Алиевский №1
Javа: магия отражений. Часть II. ClassLoader – скрытые возможности
Даниил Алиевский №1(2)
IMHO №
Java: магия отражений. Часть III. Компиляция Java средствами Java Вооруженное до зубов перемирие, или Я – то, чего не может быть!
Даниил Алиевский №2(3) Татьяна Ильченко №10(11)
Java: работа с файлами Даниил Алиевский №7(8) Почему OpenSource? (Точка зрения разработчика) Владимир Попов №3(4)
Python глазами DBA Олег Попов №7(8) Рецепты правильного трудоустройства Крис Касперски №9(10)
Брандмауэр Владимир Мешков №1(2) Этика сисадмина Андрей Гуселетов №2(3)
Брандмауэр. Часть II Владимир Мешков №2(3)
История одной разработки, или Как мы делали siteMETA Андрей Коваленко
Итоги акции «Задай свой вопрос разработчикам поисковых систем»,
№1(2) ПОЛЕЗНЫЕ СОВЕТЫ №
проводимой совместно с Всероссийским Клубом Веб-разработ