Философия Perl
«Стеммер» — программа морфологического анализа
Оптимизация работы с памятью в Perl
Java – магия отражения
БЕСПЛАТНАЯ
РЕКЛАМА
БЕСПЛАТНОГО
ПРОДУКТА
WWW.KERNEL.ORG
Давайте знакомиться — «Системный администратор». В октябре вышел
в свет первый номер нового журнала, который, как я надеюсь, облегчит жизнь
не только системным администраторам, но и программистам сетевых и сервер-
ных приложений, вебмастерам, любознательным студентам и всем тем, кто не
мыслит своей жизни без Интернета.
В этом номере Вы найдете полезные советы, касающиеся программирова-
ния на языках Perl и Java. Ведущий разработчик системы «Рамблер» Андрей
Коваленко делится своим опытом в области морфологического анализа. Дани-
ил Алиевский откроет секреты магии Java в статье «Java - магия отражений». С
помощью материала Вячеслава Калошина Вы сможете своими руками устано-
вить и настроить удобный почтовый сервер. Проектировщикам и студентам стар-
ших курсов будет интересна рубрика «Образование» — в ней представлен об-
ширный теоретический материал-исследование, посвященный проектированию
реляционных баз данных. Роман Сузи решает некоторые задачи администри-
рования с помощью языка Python.
Современные дамы настроены не менее решительно: удастся ли им отвое-
вать место в нише компьютерных «гуру», давно и весьма основательно занятой
мужчинами? Обо всем об этом — на страницах первого номера. Впрочем, все
что Вы будете читать - это результат творческой деятельности авторов. А воп-
рос, почему они используют тот или иной продукт, Вы можете задать им лично
на форуме нашего сайта www.samag.ru . Не сомневаюсь, что и Вам есть чем
поделиться, поэтому ждем Ваших статей и интересных материалов.
Успехов!
Искренне Ваш,
Александр Михалев
СОДЕРЖАНИЕ СОДЕРЖАНИЕ
АДМИНИСТРИРОВАНИЕ ПРОГРАММИРОВАНИЕ
Хеви Хардвэр Работа с текстом, или философия Perl
Установка и настройка коммутаторов Коновалов Евгений
CISCO CATALYST серий 2900XL и 3500 34-41
Всеволод Стахов
8-13 Эффективное использование памяти
в Perl при работе с большими строками
Удобная почтовая система Даниил Алиевский
Вячеслав Калошин 42-45
В статье «Удобная почтовая система»
подробно описывается установка и настройка «Стеммер»
почтового сервера на базе связки postfix+imap Морфологический анализ для
через СУБД mySQL. небольших поисковых систем
14-19 Андрей Коваленко
46-49
Миграция с Windows на Linux
Дмитрий Галышев Java - магия отражений
Автор материала «Миграция c Windows на Linux» Даниил Алиевский
рассматривает последовательность действий, не- 50-57
обходимо для переноса файлового сервера из
Windows NT на Linux и требования к установке ColdFusion или, возможно, лучшее
SAMBA-сервера. решение для создания динамических
20-23 сайтов
Александр Меженков
Что такое SAMBA? 58-61
Сергей Еремчук
24-27 Программирование сервисов в Windows
2000
Python в администрировании сервера: Всеволод Стахов
почему бы и нет? 62-66
Роман Сузи
28-32
2
СОДЕРЖАНИЕ СОДЕРЖАНИЕ
СЕТИ ОБРАЗОВАНИЕ
Анализатор сетевого трафика Взаимные функциональные
Владимир Мешков зависимости
68-71 Андрей Филиппович
Сканер портов: пример реализации «Взаимные функциональные зависимости» —
Владимир Мешков исследование проведено по наиболее распростра-
«Сканер портов» - Целью данной статьи является ненным учебникам, посвященным проектированию
описание принципов функционирования и внутрен- реляционных баз данных. Рассматриваются ошиб-
него устройства простого сканера портов TCP про- ки и нетривиальные моменты, освещаемые
токола. в подобной литературе.
72-76
84-89
Программирование сокетов
Всеволод Стахов CommerceML - стандарт обмена
78-82 коммерческой информацией
в формате XML
Елена Ртищева
90-93
Женщина и компьютер
ТЕНДЕНЦИИ Уступите место женщине
4-5 Евгения Саблина
94
Почему мало женщин в
компьютерных компаниях
FAQ PERL Вячеслав Михалев
95
6, 77
Анонс
96
№1, октябрь 2002 3
тенденции
4
тенденции
Чем отличается Как сделать так, чтобы Как сделать так, чтобы
синтаксис скриптов на скрипт работал в программа
UNIX и WIN платформах? фоновом режиме, как гарантированно
демон? работала только в одном
Юниксовые скрипты плохо вос- экземпляре?
принимает досовский перевод стро- Варианта два. Первый - восполь-
ки — CR LF. Если открыть такой зоваться модулем Proc::Daemon, Способ первый, принятый в
файл в vi в конце строк будут ^M. второй — сделать все самому, при- мире Unix:
Удалить их можно, например таким мерно так:
скриптом: $pidfile = /var/run/mydaemon.pid;
use strict;
#!/bin/bash require sys/syscall.ph; if (-e $pidfile) {
install -d -m 0775 orig # aha, pid file is here, but process
cp $1 orig/$1.orig.date +%m-%d-%H.%M # Óñòàíàâëèâàåì ïóòü ïî óìîë÷àíèþ could be dead
sed -e «s/^M//g» $1 >oooo $ENV{PATH} = /bin:/usr/bin; by now
mv -f oooo $1 my $myfile=file_name($0);
# ×èñòî äëÿ ïðèêîëà unless (open(PIDFILE,$pidfile)) {
$0=mydaemon; # too dangerous to start because
I cant read old
# Îòäåëÿåìñÿ îò ðîäèòåëÿ PID
fork() && exit; exit 1;
Как мне получить }
# Îòêëþ÷àåìñÿ îò òåðìèíàëà my $oldpid=<PIDFILE>;
зашифрованный close STDOUT; close STDERR; close close PIDFILE;
пароль? # see if there is a process with
STDIN; such pid
# Äåëàåì êîðåíü òåêóæèì êàòàëîãîì if ($oldpid > 1 && kill(0,$oldpid))
Стандартной функцией crypt(), {
chdir /; # another proccess is running
например вот так: already
# Ñîçäàåì íîâóþ ñåññèþ è ñòàíîâèìñÿ exit 1;
ëèäåðîì } else {
# Calculate salt value for crypt # ãðóïïû ïðîöåññîâ, ÷òîá íàñ ñëó÷àéíî
function íå ïðèáèëè # that process is long dead
}
@saltair= split // syscall(&SYS_setsid); }
,»ABCDEFGHIJKLMNOPQRSTUVWXYZ
abcedfghijklmnopqrstuvwxyz0123456789.»; # Ïåðåõâàòûâàåì ñèãíàëû, äëÿ êîððåê- # write pid file
òíîãî âûõîäà open (PID, «>$pidfile») or die;
sub get_salt { $SIG{INT} = $SIG{QUIT} =
srand(); $SIG{TERM} = quit; print PID $$;
close(PID);
$iOff = int(rand($#saltair)); $SIG{HUP} = ignore;
$iOff2 = int(rand($#saltair));
return join(«»,$saltair[$iOff], # Äåëàåì íàøè òåìíûå äåëà # do some work
...
$saltair[$iOff2]); ...
}
# Âûõîäèì # remove pid file
unlink $pidfile;
$crypted_passwd = quit(); exit(0);
crypt($plain_passwd,get_salt());
sub quit {
# Ïîìåùàåì ñþäà êîä äëÿ êîððåêòíîãî Способ второй, основанный на
# ïðåêðàùåíèÿ ðàáîòû блокировании файлов:
...
exit(0);
} # make a lock
$lockfilename=»/tmp/mydaemon.lock»;
unless (open
А как мне проверить Если Вы хотите написать демо- (LOCKFILE,»>$lockfilename»)) {
die «cannot open lock file\n»;
соответствие на, реализующего работу через }
введенного пароля сеть, рекомендуем ознакомиться с unless (flock
(LOCKFILE,LOCK_EX|LOCK_NB)){
зашифрованному? модулем Net::Daemon. print «my copy is already
running\n»;
exit(0);
Первых два символа пароля со- }
джержат шифровальный ключ.
# do some work
Если, взяв их, зашифровать прове- ...
ряемый пароль, то зашифрованные Как защитить мою # unlock lock file
строки должны совпасть. Пример: программу, чтобы никто close(LOCKFILE);
не смог её прочитать? unlink($lockfilename);
if (crypt($entered_passwd,
subst($crypted_passwd,0,2))
eq $crypted_passwd) { Perl-сценарий представляет со-
# Ïàðîëü âåðåí бой открыто распространяемый
} else {
# Ïàðîëü íå âåðåí код. по материалам www.xpoint.ru
} составил Дмитрий Горяинов
6
АДМИНИСТРИРОВАНИЕ
администрирование
УСТАНОВКА И НАСТРОЙКА
КОММУТАТОРОВ CISCO CATALYST СЕРИЙ
2900XL И 3500 ВСЕВОЛОД СТАХОВ
В данной статье я буду преимуще- сов (ARP cache) — 2048 mac адре- (>1500$), они предлагают широкий
ственно говорить о версии 12.0.x. сов для Catalyst 2900XL и 8192 для выбор сервисных функций и обеспе-
(отличия версий, в основном, в веб- Catalyst 3500, поддерживают клас- чивают хорошую пропускную спо-
интерфейсе и поддержке тех или теризацию и виртуальные сети собность. Наиболее привлекатель-
иных технологий). На каждый из (VLAN), предоставляют аппаратную ными возможностями данных свит-
коммутаторов может быть установ- безопасность портов (к порту может чей являются: организация вирту-
лено программное обеспечение быть подключено только устройство альных сетей (в дальнейшем VLAN),
стандартного (Standard Edition) и с определённым mac адресом), под- полностью изолированных друг от
расширенного типа (Enterprise держивают протокол SNMP для уп- друга, но синхронизированных меж-
Edition). равления, используют удалённое уп- ду свитчами в сети, и возможность
В enterprise edition входят: под- равление через веб-интерфейс и кластеризации для единого входа в
держка магистралей 802.1Q, прото- через командную строку (т.е. через систему управления свитчами и на-
кол TACACS+ для единой авториза- telnet или модемный порт). Кроме глядного изображения топологии
ции на свитчах, модифицированная этого, имеется возможность монито- сети (для веб-интерфейса). Перс-
технология ускоренного выбора ринга портов, т.е. трафик с одного пективным является использование
Spanning Tree (Cisco Uplink Fast) и порта (или портов) отслеживается многопортового свитча в качестве
др. Здесь я преимущественно буду на другом. Многим покажется полез- центрального элемента сети (в звез-
описывать настройку свитчей с по- ной возможность ограничивать ши- дообразной архитектуре). Хотя свит-
мощью интерфейса командной стро- роковещательный трафик на портах, чи поставляются с подробной доку-
ки (CLI). Данные свитчи предостав- предотвращая тем самым чрезмер- ментацией, но она вся на английс-
ляют множество сервисных возмож- ную загрузку сети подобными паке- ком языке и нередко не сообщает
ностей. Кроме этого, они идеально тами. Исходя из всего этого, можно некоторых вещей, а иногда, напро-
подходят для крупных сетей, так как утверж дать, что выбор свитчей тив, бывает слишком избыточной.
имеют высокую пропускную способ- Cisco Catalyst является идеальным Для начала хотел бы рассказать о
ность — до 3-х миллионов пакетов для крупных и средних сетей, так как первоначальной настройке свитча.
в секунду, большие таблицы адре- несмотря на высокую стоимость Итак, Quick Start.
8
администрирование
Присоединение Шаг 2. Введите IP адрес: рировать его через веб-интерфейс с
консольного кабеля помощью Cisco Visual Switch или че-
Enter IP address: рез консоль (Telnet или модемный
n Подключите поставляемый плос- порт). Выбор средства настройки —
кий провод в разъём на задней па- Шаг 3. Введите маску подсети и ваш выбор, но учтите, что веб-интер-
нели коммутатора с маркой нажмите Enter: фейс обладает сильной «тормознуто-
console. стью», так как основан целиком на
n Подключите другой конец кабеля Enter IP netmask: апплетах Java (не забудьте включить
к com-порту компьютера через со- поддержку Java в браузере). Кроме
ответствующий переходник и запу- Шаг 4. Введите, есть ли у вас этого Cisco Visual Switch работает
стите программу-эмулятор терми- шлюз по умолчанию N/Y, если есть, только в браузерах Microsoft IE и
нала (например, HyperTerminal или то наберите его IP адрес после нажа- Netscape (хотя у меня в Netscape 6.0
ZOC). тия Y: ничего не работало). К достоинствам
Порт консоли имеет следующие этого типа настройки можно отнести
характеристики: Would you like to enter a default наглядность, простоту и возможность
n а) 9600 бод; gateway address? [yes]: y получить помощь по всем пунктам.
n b) Нет чётности; Интерфейс командной строки являет-
n c) 8 бит данных; Шаг 5. Введите IP адрес шлюза: ся немного сложным для тех, кто ред-
n d) 1 бит остановки. ко работает с консолью, но настрой-
Важное замечание для кластера IP address of the default gateway: ка через командную строку является
(объединения нескольких коммутато- очень быстрой и предоставляет до-
ров): если вы хотите использовать Шаг 6. Введите имя хоста комму- полнительные возможности. Альтер-
коммутатор в качестве члена класте- татора: нативным способом настройки явля-
ра, то можно не присваивать ему IP ется веб-консоль. В ней показывают-
адрес и не запускать построитель кла- Enter a host name: ся в виде гиперссылок допустимые
стера. В случае командного свитча, команды CLI, и вы можете собрать
вам необходимо выполнить следую- Шаг 7. Введите пароль. Кроме это- нужную последовательность команд
щий пункт. го, затем на вопрос о пароле для как бы из кирпичиков.
n Присвоение IP коммутатору Telnet ответьте Y и введите пароль для Далее, можно настроить VLAN,
В первый раз, когда вы запускае- доступа через Telnet, так как иначе вообще термин VLAN — виртуальная
те свитч, то он запрашивает IP адрес. возможны странности работы с telnet. локальная сеть. Такая сеть отличает-
Если вы назначаете ему оный, что У меня, к примеру, подключение ся от физической LAN лишь тем, что
весьма желательно, то он может кон- Telnet к свитчу обрывалось по причи- организуется разделение пакетов в
фигурироваться через Telnet. не: пароль нужен, но не определён: единой локальной сети так, как если
бы это были разные подсети. Таким
Необходимые Enter enable secret: образом, с помощью VLAN можно
требования к IP организовать деление локальной
Создался следующий файл конфи- сети на отдельные участки. При этом
Перед установкой необходимо гурации: существует возможность регулиро-
знать следующую информацию о вать взаимодействие VLAN весьма
сети: Initial configuration: широко.
n IP адрес свитча. interface VLAN1
n Маска подсети. ip address 172.16.01.24 255.255.0.0
ip default-gateway 172.16.01.01
Типы VLAN
n Шлюз по умолчанию (его может и enable secret 5 $1$M3pS$cXtAlkyR3/
не быть). 6Cn8/ Нет нужды говорить, что суще-
snmp community private rw
n Ну и пароль для свитча (хотя, ско- snmp community public ro ствует несколько типов организации
рее всего лучше это придумать са- end VLAN в сети. Самый простой из них -
мому). Use this configuration? [yes/no]: статический. Вы назначаете каждому
порту какой-либо номер VLAN, и тра-
Первый запуск Шаг 8. Если всё нормально - жми- фик будет передаваться только на те
те Y; нет - N (только учтите, что па- порты, что принадлежат тому же
Выполняйте следующие действия роль хранится в зашифрованном
для присвоения коммутатору IP адре- виде).
са:
Шаг 1. Нажмите Y при первой под- Открытие Cisco Visual
сказке системы: Switch Manager Software
Continue with configuration dialog? После того, как вы присвоили IP
[yes/no]: y
коммутатору, то вы можете конфигу-
10
администрирование
Если вы планируете использовать
маршрутизацию в сети, то добавьте
следующее:
12
администрирование
универсальных порта 10/100 Коммутаторы семейств 2900XL, ко и эффективно конфигурировать
Mbps Ethernet с автоматическим 3500XL, а также Catalyst 1900/2820 коммутаторы для подключения к
определением скорости и режи- могут объединяться в стеки (до 16 каналам требуемого типа.
ма передачи; устройств) при помощи соединений На каждый из коммутаторов мо-
3) WS-C2924M-XL — содержит 24 Fast Ethernet, Fast EtherChannel (аг- жет быть установлено программное
универсальных порта 10/100 грегирование Fast Ethernet по 2 или обеспечение стандартного (Standard
Mbps Ethernet с автоматическим 4 канала), а также Gigabit Ethernet и Edition) и расширенного типа
определением скорости и режи- Gigabit EtherChannel. Максимальное (Enterprise Edition). Расширенная ре-
ма передачи, а также два слота количество портов, которое может дакция дополнительно поддержива-
для установки дополнительных быть установлено в одном стеке рав- ет транкинг (ISL/802.1Q), протокол
интерфейсных карт; но 380. Такой стек является единым TACACS+ для регламентации досту-
4) WS-C2924С-XL — содержит 22 объектом сетевого управления, ко- па к коммутаторам, модифициро-
универсальных порта 10/100 торое может выполняться как при ванную технологию ускоренного вы-
Mbps Ethernet с автоматическим помощи командного языка CLI с кон- бора Spanning Tree (Cisco Uplink
определением скорости и режи- соли или при помощи протокола Fast) и др.
ма передачи, а также два опти- telnet, так и при помощи специали-
ческих порта 100 Mbps Fast зированных систем управления типа Технические
Ethernet; CWSI (Cisco Works for Switched спецификации
5) WS-C2912MF-XL — содержит 12 Internetworks), так и при помощи
оптических портов 100 Mbps WEB-технологии c любой рабочей Производительность:
Ethernet, а также два слота для станции, оснащенной программами 1) 3.2 Gbps — коммутирующих мо-
установки дополнительных ин- просмотра Netscape или Internet дуль (для моделей Catalyst
терфейсных карт. Explorer. 2900XL);
Как и все коммутаторы, входя- 2) 10.0 Gbps — коммутирующих мо-
В состав семейства коммутато- щие в семейство Catalyst устройства дуль (для моделей Catalyst
ров Catalyst 3500XL входит три мо- 2900/3500 обеспечивают построе- 3500XL);
дели: ние виртуальных сетей (в варианте 3) 3.0 million-pps пропускная спо-
1) WS-C3512-XL — содержит 12 программного обеспечения собность (64-х байтовые пакеты,
универсальных портов 10/100 Enterprise), режим безопасности, Catalyst 2900XL);
Mbps Ethernet с автоматическим при котором к коммутатору могут 4) 7.5 million-pps пропускная спо-
определением скорости и режи- быть подключены только станции с собность (64-х байтовые пакеты,
ма передачи, а также два порта указанными MAC-адресами, 4 груп- Catalyst 3500XL);
Gigabit Ethernet; пы RMON, специальный порт для 5) 4-MB разделяемая память;
2) WS-C3524-XL — содержит 24 контроля трафика, проходящего че- 6) 8-MB DRAM and 4 MB Флэш-па-
универсальных порта 10/100 рез группу портов или в заданном мять;
Mbps Ethernet с автоматическим VLANе и др. 7) 2048 MAC-адресов (Catalyst
определением скорости и режи- Модульные модели коммутато- 2900XL);
ма передачи, а также два порта ров (WS-C2924M-XL, WS-C2912FM- 8) 8192 MAC-адресов (Catalyst
Gigabit Ethernet; XL) позволяют устанавливать допол- 3500XL).
3) WS-C3508G-XL — содержит 8 нительные 4-х портовые модули 10/
портов Gigabit Ethernet. 100 Mbps Ethernet (витая пара), 2-х Управление:
и 4-х портовые 100 Mbps Ethernet SNMP Management Information
Комму таторы этих семейс тв (оптика мультимод), однопортовые Base (MIB) II, SNMP MIB extensions,
предназначены для работы в каче- модули Gigabit Ethernet (мультимод, Bridging MIB (RFC 1493).
стве сетевого оборудования рабо- мономод), а также однопортовые
чих групп среднего и малого разме- модули ATM 155 Mbps (витая пара, Поддерживаемые стандарты:
ра и имеют для своего класса очень мультимод, мономод). Мономодовые 1) IEEE 802.3x full duplex;
высокую производительность — до модули для ATM и Gigabit Ethernet 2) IEEE 802.1D Spanning-Tree
3-х миллионов пакетов в секунду, ко- могут быть выполнены в различных Protocol;
торая обеспечивается мощным мо- вариантах дальности, при этом пре- 3) IEEE 802.1Q VLAN;
дулем коммутации архитектурой дельная длина оптических каналов 4) IEEE 802.3z, IEEE 802.3x;
коммутатора, использующей разде- может достигать 70 км. Трансиверы 5) IEEE 802.3u 100BaseTX and
ляемую память, беспрецендентные Gigabit Ethernet (GBIC — Gigabit 100BaseFX specification;
механизмы управления и контроля Interface Converter), устанавливае- 6) IEEE 802.3 10BaseT specification;
за работой устройства и т.п. Высо- мые в комму таторах семейства 7) IEEE 802.3z, IEEE 802.3x
кая производительнос ть серии Catalyst 3500XL, а также в соответ- 1000BaseX specification;
2900XL подтверждена в серии испы- ствующих модулях для коммутато- 8) 1000BaseX (GBIC) —
таний таких тестовых лабораторий ров семейства Catalyst 2900XL явля- 1000BaseSX, 1000BaseLX/LH,
как Mier, ZDnet и др. ются сменными, что позволяет гиб- 1000BaseZX.
УДОБНАЯ
ПОЧТОВАЯ СИСТЕМА ВЯЧЕСЛАВ КАЛОШИН
Итак, задача - завести почтовую систему, в которой вся информация о
пользователях, доменах и прочем лежала бы в базе данных. Зачем это нужно?
Лично для меня это стало актуально после того, как в поддерживаемых мной
системах пользователи начали плодиться как кролики. Заводить на каждого свой
аккаунт, смотреть, чтобы они не пересекались и не пользовались чужими
доменами и так далее. Наконец, мне все надоело и я решил сделать ЭТО.
До сих пор возникает множество воп- на других системах. Все необходимые вирус. Нет такой толпы глюков, на ко-
росов по установке и настройке почто- программы и пакеты вы сможете найти торые бы я периодически не напары-
вой системы на основе Postfix, Cyrus- в окрестностях freshmeat.net. вался, глядя на AVP. Тем более, что он
SASL, MySQL, Courier-IMAP, Dr.Web, Если вы желаете задать мне воп- даже с тривиальной лицензией спокой-
SquirrelMail. рос, задавайте по мылу: но выполняет работу почтового фильт-
Если использовать приведенный multik@multik.ru, но прежде прочтите ра. Правда, с купленной лицензией бу-
ниже опус в качестве банальной инструк- хотя бы PostfixFAQ на www.postfix.org — дет гораздо спокойнее — вирусы даже
ции, у вас должна получиться легко мас- ответы на 90% вопросов, на которые я в архивах не пройдут. Но — если нет
штабируемая и управляемая система, ко- не отвечаю, есть там. Еще одно усло- лицензии, то — нет.
торая без проблем — как со стороны ад- вие — сначала обдумайте и прочтите — SquirrelMail — это просто един-
мина, так и со стороны железа — спо- все сообщения системы в /var/log/ ственная система Web-based почты, ко-
койно будет тянуть по 5-10 тысяч почто- messages и /var/log/maillog — обычно торая не вызывает брезгливой реакции
вых пользователей. При этом нет раз- там есть исчерпывающая информация, при первом, главное, при последующих
ницы: сколько почтовых доменов заве- почему не работает что-либо. взглядах. Плюс, она приемлемо рабо-
дено в системе, как называются пользо- Для нормальных: Просто мне тает с русским языком.
ватели и так далее. Ибо с системными ОЧЕНЬ надоели письма вида: «А чего Теперь устанавливаем SASL. К со-
они никак не коррелируют. оно не работает, когда я сделал все так, жалению, установить его из RPM не по-
Пользователи же получат стандар- как ты написал?». лучится. Все, что я видел до этого, со-
тный набор сервисов: SMTP с аутенти- И последнее — специально для тех, брано либо не так, либо не туда. В об-
фикацией, pop и imap сервисы, доступ кто задается вопросом: «Почему я выб- щем, неработоспособное. Но вы може-
к почте через браузер, плюс, чистую от рал postfix? Ведь есть стандарт-де-фак- те попытать удачу.
вирусов почту. то sendmail. Есть еще exim,qmail и куча
Теперь оговорки. Данный текст на- других почтовых серверов». Отвечаю: # tar zxvf cyrus-sasl-1.5.27.tar.gz
писан в расчете на тех, кто уже пони- — Sendmail я вынужден сразу ски- # cd cyrus-sasl-1.5.27.
мает механизмы, происходящие внут- нуть со счетов. То, что описывается
ри Linux. Если вы неделю как постави- ниже, sendmail не способен выполнить. Заберите патч для поддержки
ли Linux и желаете с помощью этого до- Или способен, но с очень большими уси- MySQL и LDAP отсюда: http://
кумента поставить свой hotmail.com, то лиями администратора системы. Я, по- www.surf.org.uk/downloads/sasl-1.5.27-
я ни за что, как обычно, не отвечаю. Все чему-то органически не могу смотреть ldap-ssl-filter-mysql-patch4.tgz.
логи и прочее были взяты с моей рабо- на творение djb. Ну а exim я просто не Распакуйте полученный архив и по-
чей системы. Я ничего не выдумывал и видел. ложите sasl-ldap+mysql.patch в корень
не придумывал — это все работает ре- — Courier-IMAP выбран по другой дерева исходников SASL.
ально. причине: где-то с полгода назад он ока-
В качестве базовой системы исполь- зался единственным IMAP сервером, # patch -b -p1 < sasl-ldap+mysql.patch
# autoheader
зовался RedHat 7.2. Но аналогично по- который смог собраться на моей маши- # autoconf
строенные системы работают и на не и работать под нагрузкой, не требуя # automake -i.
RedHat6.2, и ASPLinux 7.2. Поэтому не к себе внимания.
вижу причин, почему бы им не работать — Dr.WEB — просто хороший анти- Вот и все, патч установлен. Да-
14
администрирование
вайте сконфигурируем SASL. # tar zxvf postfix-1.1.11.tar.gz setgid_group: [postdrop]
# cd postfix-1.1.11. manpage_directory: [/usr/local/man]
# ./configure with-mysql=/usr/ sample_directory: [/etc/postfix]
include/mysql enable-login. readme_directory: [no]
Следующие строчки — это одна
Соберем и установим его: команда. Ее следует вводить в один Ура. Postfix встал. Теперь наша за-
прием. дача его отконфигурировать.
# make
# make install
# ln -s /usr/local/lib/sasl /usr/lib/ # make -f Makefile.init makefiles # cd /etc/postfix/
sasl # mcedit main.cf
«CCARGS=-DHAS_MYSQL -DUSE_SASL_AUTH
# echo /usr/lib/sasl >> /etc/ -I/usr/include/mysql
ld.so.conf -I/usr/local/include Весто mcedit может быть vi, emacs
# ldconfig -L /usr/local/lib -lsasl
# cd .. -lmysqlclient» или любой другой предпочитаемый
вами текстовый редактор — это не-
Устанавливаем методы аутенти- Собираем и устанавливаем: критично.
фикации: Редактируем главный файл кон-
# make фигурации postfix, обращая внимание
# cat > /usr/local/lib/sasl/smtpd.conf # adduser postfix
pwcheck_method: mysql # groupadd postdrop на следующие строчки:
mysql_user: postfix # make install
mysql_passwd: postfix
mysql_host: localhost broken_sasl_auth_clients = yes
mysql_database: mail smtpd_sasl_auth_enable = yes
Вот ответы, которые я дал инстал- transport_maps = mysql:/etc/postfix/
mysql_table: aliases
mysql_uidcol: alias лятору: transport.cf
mysql_pwdcol: password virtual_mailbox_base = /
^D virtual_uid_maps = mysql:/etc/postfix/
install _ root: [/] ids.cf
tempdir: [/usr/src/post/postfix- virtual_gid_maps = mysql:/etc/postfix/
Теперь пришла очередь postfix. 1.1.11] /tmp gids.cf
Здесь ситуация та же. В принципе по config_directory: [/etc/postfix] virtual_mailbox_maps = mysql:/etc/
daemon_directory: [/usr/libexec/ postfix/aliases.cf
сети бродит много rpm, которые со- postfix] virtual_maps = mysql:/etc/postfix/
держат в себе откомпилированный command_directory: [/usr/sbin] remote_aliases.cf
queue_directory: [/var/spool/postfix] relay_domains = $transport_maps
postfix с поддержкой MySQL. Я пред- sendmail_path: [/usr/sbin/sendmail] smtpd_recipient_restrictions =
почитаю собрать его сам, и быть newaliases_path: [/usr/bin/newaliases] p e r m i t _ m y n e t w o r k s ,
mailq_path: [/usr/bin/mailq] permit_sasl_authenticated,check_relay_domains
«чуть-чуть» уверенным в том, что я mail_owner: [postfix] disable_vrfy_command = yes
знаю, что собрал.
Установка и настройка MySQL права пользователю root без пароля и позволяет де-
из исходных текстов лать все с базами test и test_*, кроме раздачи при-
вилегий);
Для установки MySQL, необходимо: n chown -R root:mysql /usr/local/mysql (как root);
n иметь gcc выше, чем 2.8.1 (egcc 1.0.2), рекомендуется n chown -R mysql /usr/local/mysql/data (и отдельную ди-
2.95.2; ректорию для mysql.sockets с правами чтения для
n создать директорию для сборки, распаковать в нее всех; mysql не нужны права на запись для my.cnf);
mysql-3.23.32.tar.gz/mysql-3.23.37.tar.gz (взять на n support-files/mysql.server в /etc/rc.d/init.d для автома-
http://download.sourceforge.net/mirrors/mysql/); тического запуска и дать ему права на исполнение
n для версии ранее 3.23.34 распаковать туда db- и сделать линк K00mysql из rc0.d и rc6.d на него,
3.2.3h.tar.gz (это специальная версия bdb для MySQL) S99mysql из rc2.d, rc3.d и rc5.d на него;
n создать группу mysql; n скопировать my-medium.cnf в /usr/local/mysql/data/
n создать пользователя mysql (в группе mysql) (зачем ему my.cnf и слегка отредактировать [mysqld]:
bash?); • socket=имя-файла под Unix-socket (и в раздел [client]
n ./configure —prefix=/usr/local/mysql — localstatedir=/ тоже);
usr/local/mysql/data — with-unix-socket-path=путь — • skip-locking (не блокировать доступ к данным от ДРУ-
with-mysqld-user=mysql — disable-large-files — with- ГИХ процессов);
libwrap — without-debug — with-charset=cp1251 — • log-bin #журнал изменений для репликации;
with-extra-charsets=all; • log-slow-queries;
n make (70MB/91MB); • log-update #журнал изменений;
n если upgrade, то остановить mysql, сохранить базы дан- • skip-networking #если не нужен доступ по TCP/IP (а еще
ных и my.cfg (не забыть потом удалить!); лучше использовать ssh + port forward);
n make install (как root)(16 MB, из них 5МБ - тест): • safe-show-database;
• /usr/local/mysql/lib/mysql — эту директорию указывать • skip-show-database.
для libtool, либо занести в /etc/ld.so.conf. n тестовый запуск: /usr/local/mysql/bin/safe_mysqld —
n при первой установке: scripts/mysql_install_db (как user=mysql (как root)(или сразу /etc/rc.d/rc3.d/S99mysql
root — создание таблиц с правами доступа, дает все start);
Что они означают и каково их дей- # cat > remote_aliases.cf дется разбираться, что не понрави-
ствие, вы можете прочитать в доку- user = postfix лось системе.
password = postfix
ментации по postfix или в FAQ.Теперь dbname = mail Теперь необходимо создать
разбираемся, где и что у нас лежит. table = remote_aliases пользователя и все необходимые таб-
select_field = rcpt
where_field = alias лицы с помощью вызова mysql — p:
# cat > transport.cf hosts = localhost
user = postfix ^D
password = postfix mysql> create database mail;
dbname = mail Обратите внимание на отсутствие Query OK, 1 row affected (0.62 sec)
table = transport mysql> grant insert, select, delete,
select_field = transport лишних пробелов и других невидимых update on mail.* to postfix@localhost
where_field = domain знаков в концах строчек — это важно! identified by «postfix»;
hosts = localhost Query OK, 0 rows affected (0.72 sec)
^D Как, наверное, стало понятно из mysql> use mail;
# cat > ids.cf вышеприведенных файлов, я указал Database changed
user = postfix
password = postfix postfix искать MySQL на localhost, под- mysql> create table transport (domain
dbname = mail ключаться пользователем postfix с па- varchar(255) PRIMARY KEY, transport
table = aliases char(8));
select_field = id ролем postfix, использовать базу дан- Здесь будет храниться информация о
where_field = alias ных mail. Конечно, эти данные всего
hosts = localhost доменах, обслуживаемых postfix.
^D лишь для примера — вы должны или
# cat > gids.cf их изменить или понять чем грозит ис- mysql> create table aliases (id int(6),
user = postfix gid int(6), alias varchar(255) PRIMARY
password = postfix пользование паролей, сходными с ло-
KEY, maildir varchar(255), password
dbname = mail гинами. Понятно, что эти файлы не- varchar(128), infovarchar(128));
table = aliases
select_field = gid зачем читать всем (намек на правиль- Здесь информация о почтовых пользо-
where_field = alias ный chmod). вателях системы.
hosts = localhost
^D. Проверяем, все ли в порядке.
# cat > aliases.cf mysql> create table remote_aliases
user = postfix (alias varchar(255) PRIMARY KEY,
password = postfix # postfix check. rcptvarchar(255));
dbname = mail А здесь информация о почтовых пере-
table = aliases
select_field = maildir Команда должна отработать без адресациях и прочем. Небольшие списки
where_field = alias каких-либо сообщений об ошибках. рассылки тоже можно включать сюда.
hosts = localhost
^D Если все-таки она что-то вывела, при-
16
администрирование
Проверьте, имеет ли пользователь В /var/log/messages должны по- # authlib/authinfo
postfix доступ к MySQL. явиться аналогичные строчки: AUTHENTICATION_MODULES=«authdaemon»
AUTHDAEMONMODULELIST=«authcustom
# mysql -u postfix -p authcram authmysql authuserdb authpam»
Jun 28 16:24:21 multik postfix/ SASL_AUTHENTICATION_MODULES=«CRAM-
smtpd[21863]: connect frommultik.ip- SHA1 CRAM-MD5 PLAIN LOGIN»
Запускаем postfix. tel.int[127.0.0.1]
Jun 28 16:24:23 multik postfix/
# postfix start smtpd[21863]: 252BFEEAE6: Обращаем внимание на наличие
postfix/postfix-script: starting the client=multik.ip-tel.int[127.0.0.1]
Postfix mail system Jun 28 16:24:32 multik postfix/ authmysql. Иначе разбираемся, поче-
cleanup[21919]: 252BFEEAE6:message- му не так.
id=<20020628122423.252BFEEAE6@mail.test.ru>
И в консоли MySQL добавляем до- Jun 28 16:24:32 multik postfix/ Выходим из-под пользователя
мен test.ru. qmgr[21762]: 252BFEEAE6: courier и устанавливаем демонов:
from=<multik@test.ru>,size=340, nrcpt=1
(queue active)
Jun 28 16:24:32 multik postfix/ # exit
mysql> insert into transport values virtual[21921]: 252BFEEAE6: # make install
(test.ru,virtual:); to=<multik@test.ru>,relay=virtual, # make install_configure
delay=9, status=sent (maildir)
И пользователя multik@test.ru. Об- А теперь отдадим дань конфигури-
ратите внимание на путь к почтовому Если мы посмотрим в почтовый рованию:
каталогу пользователя и на заверша- спул, то увидим, что письмо принято
ющий «/» в конце строки. и дожидается своей очереди. # cd /usr/lib/courier-imap/etc/
# cp authdaemonrc.dist authdaemonrc
mysql> insert into aliases # ls -lR /var/spool/vmail
values(1000,12,multik@test.ru,/var/ /var/spool/vmail:
spool/vmail/test.ru_multik/ Редактируем authdaemonrc — на-
èòîãî 4
,testpassword,info); drwx 5 1000 mail 4096 ходим строчку:
Èþí 28 16:26 test.ru_multik
Число 1000 я взял из головы — /var/spool/vmail/test.ru_multik: authmodulelist=«authcustom authcram
главное, что бы оно было больше пос- èòîãî 12 authuserdb authmysql authpam»
drwx 2 1000 mail 4096
леднего UID в системе. В RedHat Èþí 28 16:26 cur
пользовательские UID начинаются с drwx 2 1000 mail 4096 и оставляем от нее только такой вот
Èþí 28 16:26 new
500, поэтому я думаю, что 500 локаль- drwx 2 1000 mail 4096 огрызок:
ных пользователей вполне достаточ- Èþí 28 16:26 tmp
/var/spool/vmail/test.ru_multik/cur:
но. А 12 — это GID группы mail на моей èòîãî 0 authmodulelist=«authmysql»
системе.
/var/spool/vmail/test.ru_multik/new:
Проверяем, что у нас получилось. èòîãî 4 Другие строки НЕ ТРОГАЕМ.
Заметьте, мы добавили пользователя -rw 1 1000 mail 389 Теперь указываем, где искать
Èþí 28
без затрагивания postfix и других под- 16:261025267217.21935_0.multik.ip- MySQL и информацию о пользовате-
систем — это открывает большой про- tel.int лях:
стор для написания различных управ- /var/spool/vmail/test.ru_multik/tmp:
ляющих почтовой системой про- èòîãî 0 # cat > authmysqlrc
грамм. MYSQL_SERVER localhost
MYSQL_USERNAME postfix
Создаем каталог, где будет хра- Теперь подошла очередь установ- MYSQL_PASSWORD postfix
ниться почта и устанавливаем на него ки IMAP и POP3 демонов. Иначе MYSQL_PORT 3306
MYSQL_DATABASE mail
права. пользователям не через что будет по- MYSQL_USER_TABLE aliases
лучать почту. (Из одного письма: «А MYSQL_CLEAR_PWFIELD password
DEFAULT_DOMAIN test.ru
# mkdir /var/spool/vmail чего у меня sendmail не отдает по pop3 MYSQL_UID_FIELD id
# chown nobody.mail /var/spool/vmail MYSQL_GID_FIELD gid
# chmod 770 /var/spool/vmail почту Outlook’у ?»). MYSQL_LOGIN_FIELD alias
Распаковываем и собираем MYSQL_HOME_FIELD maildir
И проверяем, как у нас работает Courier-IMAP. MYSQL_NAME_FIELD info
MYSQL_MAILDIR_FIELD maildir
прием почты: ^D
# tar zxvf courier-imap-1.5.1.tar.gz
$ telnet localhost 25 # adduser courier
# chown courier.courier courier-imap- Опция DEFAULT_DOMAIN указы-
Trying 127.0.0.1...
Connected to localhost. 1.5.1 вает, что добавлять к логину, если
Escape character is ^]. # cd courier-imap-1.5.1
# su - courier пользователь пытается ввести логин
220 mail.test.ru ESMTP Postfix
mail from: multik@test.ru # cd /{êóäà ðàñïàêîâûâàëè}/courier- без доменной части. Остальное, я ду-
250 Ok imap-1.5.1
# ./configure маю, понятно из названия и описаний.
rcpt to: multik@test.ru
250 Ok # make И запускаем pop3.
data
354 End data with <CR><LF>.<CR><LF>
hello Тут останавливаемся и проверяем, /usr/lib/courier-imap/libexec/
. что у нас есть из демонов, которые бу- pop3d.rc start
250 Ok: queued as 252BFEEAE6
дут проверять почту:
18
администрирование
CRC32-1.2.tar.gz, и установил: ся не буду. Не забудьте — для $ telnet localhost 25
SquirellMail необходим запущенный Trying 127.0.0.1...
# tar zxvf String-CRC32-1.2.tar.gz Connected to localhost.
# cd String-CRC32-1.2 imap демон — так что не оплошайте. Escape character is ^].
# perl Makefile.PL Для завершения нашей эпопеи ос- 220 mail.test.ru ESMTP Postfix
# make ehlo multik
# make test талось всего два шага: 250-mail.test.ru
# make install 250-PIPELINING
250-SIZE 10240000
n Проверьте, все ли заработает при 250-ETRN
Проверяем: запуске системы. Если есть воз- 250-AUTH LOGIN PLAIN
250-AUTH=LOGIN PLAIN
можность — перезагрузитесь и 250-XVERP250 8BITMIMEÊ
# cd /opt/drweb/update проверьте, запустился ли Dr.WEB,
# ./update.pl postfix, courier pop3 и/или imap c
mysql. Отрабатывает ли update’р К вашему большому сожалению
update.pl должен сходить в инет на новые обновления и так далее. вы не увидите строчек:
сайт Dr.WEB, забрать все обновления Просмотрите все конфигурацион-
и перезапустить drwebd, если он есть. ные файлы еще раз — не остави- 250-AUTH LOGIN PLAIN DIGEST-MD5 CRAM-
MD5
В логах после запуска вы должны ли ли вы где-нибудь ляпов или «со- 250-AUTH=LOGIN PLAIN DIGEST-MD5 CRAM-
увидеть следующее: плей»? Для самостоятельной ра- MD5
боты можете посмотреть на анти-
Key file: /opt/drweb/drweb.key спамерные возможности drweb. Либо вы увидите эти строчки, но
Registration info:
0100003942 n Проверьте, прикрыт ли MySQL и почему-то нормальные почтовые кли-
Evaluation Key (ID Anti-Virus Lab. Dr.WEB от посторонних людей. енты (к примеру, TheBat или stuphead)
Ltd, St.Petersburg)
This is an EVALUATION version with не смогут авторизоваться для отправ-
limited functionality! В общем все. Можете откинуться ки почты. Только для отправки! В чем
To get your registration key, call
regional dealer. на спинку кресла и наблюдать, как ра- же дело ?
Loading /var/drweb/bases/drwtoday.vdb ботает почта. Дело в одной маленькой библио-
- Ok, virus records: 173
Loading /var/drweb/bases/drw42807.vdb Но для меня это еще не все. Раз теке, называемой Cyrus-SASL. К со-
- Ok, virus records: 33Loading /var/ все равно для пользователей стоит жалению, ее писали люди, которые
drweb/bases/drw42806.vdb - Ok, virus
records: 57 Apache с PHP, то я написал простень- писали ее неправильно. Метод sasldb
Loading /var/drweb/bases/drw42805.vdb кую WWW — утилитку для управле- в ней важнее всех.
- Ok, virus records: 133
Loading /var/drweb/bases/drw42804.vdb ния почтовыми пользователями. Для Внимание, если /etc/sasldb не пус-
- Ok, virus records: 123 ее работы необходимо создать в той (смотреть вывод sasldblistusers),
Loading /var/drweb/bases/drw42803.vdb
- Ok, virus records: 73 MySQL такую таблицу: то в выводе postfix появляются строч-
Loading /var/drweb/bases/drw42802.vdb ки про DIGEST-MD5 и CRAM-MD5.
- Ok, virus records: 143 mysql> create table admins (login
Loading /var/drweb/bases/drw42801.vdb Если пустой -то не появляются. Если
varchar(20) NOT NULL, password
- Ok, virus records: 76 varchar(20),rights int(6)); в sasldb есть хоть одна запись, то
Loading /var/drweb/bases/drwebase.vdb
- Ok, virus records: 29405 аутентификация с участием методов
И руками занести туда значения LOGIN, DIGEST-MD5 и CRAM-MD5
Видите, появились свежие обнов- вроде “admin”, ’password’,0. идет через sasldb, НЕВЗИРАЯ на то,
ления для drweb с новыми вирусами. Эта таблица у меня используется что написано после pwcheck_method.
Теперь со спокойной душой запихи- в других внутрикорпоративных серви- Поэтому, если у вас есть активно миг-
ваем вызов update.pl в crontab. У меня сах, поэтому желающие могут залезть рирующие пользователи с нормаль-
он вызывается каждую ночь. Одно в код и все исправить. ными почтовыми клиентами (Outlook
НО: Необходимо периодически вруч- По адресу www.samag.ru/2002/01/ и Mozilla — не подходят — они оба ис-
ную отслеживать выход новых версий multik/ лежат 3 файла auth.php, пользуют только метод PLAIN), то для
drweb. Потому что как только выйдет global.php, index.php. Просто положи- отправки почты с таких клиентов их
новый DrWeb, ваш автоматически пе- те эти три файла в один каталог, дос- надо заводить вручную, используя ко-
рестанет получать новые вирусные тупный вам. Поправьте значения в манду аналогичную этой:
дополнения. global.php. Все, можете вызывать и
И последний шаг — установка пользоваться. Логин и пароль — те, saslpasswd -c -u `postconf -h
www-почты: которые вы вручную добавили в таб- myhostname` username
Я взял последнюю версию лицу admins.
SquirellMail с http://www.squirrelmail.org/ Ну а дальше, я думаю, вы пойме- Вот такой вот SASL. Правда, обе-
и установил согласно прилагающимся те. Утилитка писалась «на коленке», щают, что в v2 будет все по честному,
инструкциям. Для ее работы необхо- поэтому я вполне понимаю, что мож- но пока v2 не выбралась из бета-со-
дим настроенный Apache c PHP. Как но написать лучше и красивее. Пи- стояния, да и postfix в стабильных вер-
это делать я уже писал несколько раз. шите. Удачи ! сиях не поддерживает Cyrus-SASL v2.
Да и в сети куча документов, посвя- А тем, кто до сюда дочитал — ма- Courier-IMAP использует SASL по
щенным этому вопросу. Установка ленький бонус. другому, поэтому с ним все в поряд-
простая, поэтому я тут останавливать- Если вы поглядите на это: ке. Вот теперь точно все. Удачи!
МИГРАЦИЯ
С WINDOWS НА LINUX
Данная статья предназначена в пер- Linux по нескольким критериям, не ную техническую поддержку заре-
вую очередь для тех, кто, считая, что претендуя на детальное сравнение, гистрированных пользователей,
«качественный продукт не может быть которому посвящено уже много ста- но не несет ответственности за
бесплатным», доверил управление тей. потери данных, произошедшие
своими серверами дорогой операци- из-за ошибок в коде ОС, и полу-
онной системе и вынужден периоди- Windows NT: ченный ущерб в случае чего при-
чески смотреть на «синий экран смер- дется доказывать в суде.
ти», терять время на перезагрузки и n Является коммерческим ПО, за ис- n В комплект поставки входит опе-
иногда на восстановление самой ОС. пользование каждой его копии не- рационная система, утилиты ад-
Приведем сравнение операцион- обходимо платить. министрирования, набор простых
ных систем Microsoft Windows NT и n Производитель обещает бесплат- игр, www- и ftp-сервер IIS.
20
администрирование
n Нужные Вам утилиты, не входя- или нетерпеливы, эта ОС не для Вас. ляет делать резервные копии уда-
щие в состав OС, приобретаются Не испугались? По прежнему полны ленных ресурсов.
отдельно. решимости? Ну что же, начнем осва- n Утилиты командной строки, под-
n Документация к системе приобре- ивать новую ось. В любом случае до- держивающие некоторые возмож-
тается отдельно. говоримся, что все работающие сер- ности администрирования NT, ко-
n Выполнение отдельных задач кли- вера остаются работать до тех пор, торые могут быть использованы в
ентом на сервере невозможно. пока к ним обращается хотя бы один Samba, NT workstation и NT server.
пользователь.
Linux: Для начала рассмотрим задачу ос- Вы можете получить больше инфор-
вобождения сервера под управлени- мации на нашем сайте: http://samba.org/
n Является свободно распространя- ем Windows NT от обязанностей ос- samba».
емым ПО, и, имея одну копию, Вы новного контроллера домена (PDC). Если Samba еще не установлена,
можете использовать ее на любом Основное преимущество доменной обращаемся к компакт-диску с дист-
количестве компьютеров и тира- структуры — выполнение скриптов, рибутивом и устанавливаем все па-
жировать без ограничений. определенных администратором для кеты, содержащие в имени слово
n Ядро ОС и поставляемые с ним выполнения при входе и выходе «samba». Типичные настройки обыч-
программы Вы используете на свой пользователя домена. Также, с помо- но описаны в файле /etc/samba/
страх и риск без каких-либо гаран- щью Samba, мы возьмем на себя за- smb.conf-sample и подходят большин-
тий. Это не значит, что техническая дачи файл-сервера — предоставле- ству пользователей.
поддержка отсутствует — вы може- ние коллективного доступа к своим Рассмотрим его поподробнее.
те обратиться за ней к автору про- файлам и папкам. Файл состоит из секций, которые оп-
граммы. Применить здесь понятие «к ре- ределяются именем в квадратных
n В дистрибутив входит комплект ин- сурсам» было бы не совсем коррект- скобках.
тернет-утилит как серверной, так но, так как к ресурсам относятся вре- В секции [global] объявляются об-
и клиентской направленности, ин- мя процессора, память и так далее. щие переменные, влияющие на рабо-
струменты для разработки сетево- Удаленные пользователи могут ис- ту демонов.
го взаимодействия с другими ОС, пользовать и их, но Windows NT та- В секции [homes] предоставляет-
игры и многое другое. кой возможности не предусматрива- ся возможность монтирования уда-
n Если какого-то нужного Вам паке- ет. ленными пользователями своих лич-
та нет в дистрибутиве, Вы можете Системы Microsoft Windows 3.11, 9х ных папок, находящихся на сервере.
бесплатно получить его с сайта и NT используют для предоставления Секция [printers] открывает дос-
разработчика. совместного доступа к файлам, пап- туп ко всем установленным в систе-
n В состав каждого дистрибутива кам и принтерам протокол Server ме принтерам.
входит комплект документации по Message Block (SMB). В Linux за рабо- Переименуем файл /etc/samba/
ОС и всем установленным про- ту с SMB отвечает пакет Samba. О нем smb.conf-sample в smb.conf и начнем
граммам. его создатели пишут следующее: его править под себя.
n Пользователи могут не только вы- «Вот короткий список того, что дела- Полезными могут оказаться «под-
полнять задачи на сервере, но и ет Samba. Для многих сетей можно становочные переменные», которые
планировать их выполнение в свое сказать коротко: «Samba предостав- при чтении заменяются актуальными
отсутствие. ляет полноценную замену серверам для сеанса значениями. Например,
Windows NT, Warp, NFS или Netware». «%u» будет заменено именем подклю-
Если Вы хотите узнать больше, чающегося пользователя, а «%L» —
обратитесь к статье «Microsoft n SMB сервер для предоставления NetBIOS-именем сервера. Полный спи-
Windows NT Server 4.0 против UNIX» доступа к файлам и принтерам, сок этих переменных Вы найдете в
Джона Кирха, сетевого консультанта клиентам с рабочих станций man-руководстве к smb.conf.
и сертифицированного специалиста Windows 95, Warp Server и подоб- Вот некоторые глобальные пара-
Microsoft (Windows NT) на http:// ным. метры, на которые стоит обратить
www.linux.org.ru/books/unix-nt.html. n Сервер имен NetBIOS, который ко внимание:
Статья датирована 1998 годом, и с всему прочему поддерживает спи- workgroup — задает имя рабочей
тех пор многое изменилось, но рас- сок доступных компьютеров в групппы или домена, в который вхо-
становка сил осталась прежней. сети. Samba может выступать в дит компьютер.
Управление Linux основано не на роли главного обозревателя Ва- hosts allow — список компьютеров
«интуитивно понятном интерфейсе», шей сети. и сетей, которым разрешен доступ,
а на правке различных конфигураци- n SMB клиент позволяет пользовать- разделенный пробелами.
онных файлов после чтения докумен- ся ресурсами других компьютеров guest account — имя пользовате-
тации, которая написана в основном сети (как файлами, так и принте- ля с правами гостя. По умолчанию —
на английском языке, хотя переводов рами) из Unix, Netware и других это nobody.
с каждым годом становится больше ОС. Пользователь должен быть заре-
и больше. Если Вы нелюбознательны n Расширение клиента «tar» позво- гистрирован в системе. Можно ука-
22
администрирование
сываем их в базе Samba командой Если в Вашей сети используются ляется NetBIOS-имя рабочей станции
smbpasswd дважды: с ключом «-a» — домены, проверьте smb.conf сервера: домена.
для занесения в базу, с ключом «-e» — Второй метод рекомендован раз-
для снятия блокировки с записи. n Шифрование паролей должно работчиками Samba как более безо-
Хорошо, если новая операционная быть включено. пасный и требует лишь добавления
система ставится на специально куп- в секцию [global] строки:
ленный сервер, еще лучше, если сер- [global]
...
вер куплен с предустановленной нуж- domain master = yes add user script = /usr/bin/
ной нам ОС. Но как быть, если сер- ... adduserscript %u
вер один и нельзя его трогать до тех
пор, пока все пользователи не смогут n Сервер должен поддерживать Это подразумевает, что в ката-
получить гарантированный доступ к вход пользователей в домен и пре- логе /usr/bin сущес твует скрипт
своим файлам? Придется использо- доставлять разделяемый ресурс adduserscript примерно следующего
вать любой доступный компьютер как NETLOGON. содержания:
«временный сервер». На него ставим
тот же дистрибутив, что предполага- [global] #!/bin/sh
... /usr/sbin/useradd -d /dev/null -g 100
ем ставить на основной сервер, и по- domain logons = yes -s /bin/false -m $1
степенно перенесем все ресурсы, пре- ...
[netlogon]
доставляемые старым сервером. path = /usr/local/samba/lib/ После этого с добавляемой рабо-
Какая машина справится с этой netlogon чей станции заходим в домен как
read only = yes
работой зависит от предполагаемой write list = ntadmin привелигированный пользователь
нагрузки. Достоверно известно, что (root, если не указан другой парамет-
Celeron 700/196Mb RAM/30Gb HDD в n Сервер должен быть главным обо- ром admin user), и создаем учетную
состоянии обслуживать 15 клиентов, зревателем домена. запись рабочей станции домена.
интенсивно работающих с большим Пока это не сделано, попытки зайти
количеством файлов при средней на- [global] как обычный пользователь провалят-
грузке ~10%. ... ся, даже если пользователь суще-
encrypt passwords = yes
Разделяемые SMB ресурсы делим на: ... ствует.
После того, как вся нагрузка бу-
n Общедоступные (папка с драйве- Если все в порядке, можно добав- дет перенесена на «временный» сер-
рами и дистрибутивами программ, лять рабочие станции в домен. вер, а старый сервер — выключен,
«помойка»). Рабочие станции, функционирую- подождем денёк-другой возникнове-
n Доступные группе (папки с данны- щие под управлением Windows NT/ ния проблем и только послеэтого на-
ми, с которыми работает ограни- 2000, используют так называемые чинаем установку Linux на основной
ченное количество лиц, например «машинные» учетные записи — метод сервер. После установки системы
папка с базами бухгалтерской про- проверки подлинности рабочей стан- конфигурационные файлы и файлы
граммы). ции (не пользователя), чтобы избе- пользователей просто переносятся с
n Домашние (папки привилегиро- жать входа в домен рабочей станции «временного» сервера.
ванных пользователей, доступные с таким же именем NetBIOS и получе- Итак, все готово, начинаем. При-
только им). ния прав пользователя домена. Рабо- кидываем время на переброску всех
чие станции, функционирующие под необходимых файлов со старого сер-
Наиболее часто допускаемая управлением Windows 9x/Me, таких вера на новый и объявляем профи-
ошибка на этапе переноса данных — учетных записей не используют, по- лактику на нужное время плюс 10 ми-
невнимательность к атрибутам вновь этому не могут считаться полноправ- нут на неожиданности (если мы не
перенесенных файлов. Владельцем ными членами домена. допустили оплошностей при подго-
для них лучше всего назначить Существует два метода создания товке, работа возобновится как толь-
пользователя root, а группу-владель- «машинных» учетных записей — руч- ко файлы будут скопированы).
ца — ту, что будет с этими файлами ной и автоматический. Старому серверу меняем NetBIOS-
работать. Ну и не забыть позволить Первый метод подразумевает вы- имя и перезапускаем Samba. Новому
перезаписывать файлы членам груп- полнение вручную трех команд на сер- присваиваем имя старого. Перезапус-
пы-владельца. вере для каждой рабочей станции до- каем Samba.
Необходимо пройтись по пользова- мена: Все. Можем переходить к замене
телям и проверить доступ с их рабо- любимого лакомства для Nimda и
чих станций к новому серверу: чтение/ root# useradd -g 100 -d /dev/null -c CodeRed — Microsoft Information
запись в папку; чтение/запись в фай- <èìÿ_ìàøèíû> -s /bin/false <èìÿ_ìàøè- Server на самый популярный в
íû>$
лы, созданные другими членами груп- root# passwd -l <èìÿ_ìàøèíû>$ Internet www-сервер Apache, прокси-
пы, а также членами групп, имеющих root# smbpasswd -a -m <èìÿ_ìàøèíû> сервер Squid и ftp-сервер proftpd.
смежный доступ в папку; отсутствие Но это уже немного другая исто-
доступа в неразрешенные папки. Вместо <имя_машины> подстав- рия...
ЧТО ТАКОЕ
SAMBA? СЕРГЕЙ ЯРЕМЧУК
GRINDER@UA.FM
администрирование
Я думаю, что утверждение о том, Windows машин? Во-первых, контроль n только для чтения - чтение, запись
что самой популярной операционной доступа, который может быть реали- для владельца;
системой для клиентских машин яв- зован либо на уровне ресурсов (share n архивный - выполнение для вла-
ляется Windows, не вызовет больших level), когда какому-либо ресурсу в дельца;
споров. Хотя с появлением таких про- сети назначается пароль и соответ- n системный - выполнение для груп-
дуктов, как OpenOffice.ru, и активно- ствующие правила использования пы;
му продвижению своих продуктов («только для чтения», например), при- n скрытый - выполнение для группы.
компаниями AltLinux и ASPLinux, по- этом имя пользователя не имеет аб- Вот с проблемами так или иначе
ложение несколько изменилось, но до солютно никакого значения. Либо бо- разобрались. Давайте разберемся
массовости еще дело не дошло. По- лее совершенная и гибкая организа- теперь конкретно с реализацией и на-
этому большинство пользователей ция на уровне пользователя, когда стройкой SAMBA в Linux. Для работы
продолжают набирать документы в для каждого пользователя создается Samba необходимо, чтобы были запу-
Word’e и бродить по Интернету с по- учетная запись, где помимо имени и щены два демона: smbd обеспечива-
мощью Internet Explorer. А вот в каче- пароля содержится вся необходимая ет работу службы печати и разделе-
стве сервера положение последней информация о правах доступа к ре- ния файлов для клиентов Samba, та-
уже не так однозначно, здесь уже иг- сурсу. И прежде чем получить доступ ких как Windows всех мастей; демон
рают роль NetWare от Novell и, конеч- к требуемому ресурсу каждый пользо- nmbd обеспечивает работу службы
но же, Unix. Плюс за последний год ватель проходит аутентификацию, имен NetBIOS, а также может исполь-
пришлось всем потесниться из-за по- после успешного прохождения кото- зоваться для запроса других демонов
явления новых «игроков» на этом рой ему и предоставляется права на служб имен. Для доступа к клиентам
рынке - операционных систем с откры- использование согласно учетным за- используется протокол TCP/IP. Как
тым кодом - Linux, FreeBSD и писям. Во-вторых, необходима эмуля- правило, Samba устанавливается
OpenBSD, которые уже сейчас зани- ция прав доступа, определяемых фай- вместе с дистрибутивом Linux. Как
мают немалый процент рынка серве- ловой системой. Все дело в том, что проверить? Просто дайте команду:
ров. Прежде всего по причине своей у рассматриваемых систем права до-
надежности, устойчивости, совмести- ступа к файлам и каталогам на диске sergej@grinder sergej]$ whereis samba
мости со множеством платформ и бе- организованы по-разному. В Unix тра-
зопасности. Поэтому сейчас систем- диционно существует три категории и вы должны получить что-то вроде
ному администратору приходится ча- пользователей файла - владелец этого:
сто решать вопросы интеграции сер- (owner), группа (group) и остальные
веров под управлением Linux/Unix в (other). Каждому из этих субъектов samba: /usr/sbin/samba /etc/samba /
сеть, где преобладают клиентские usr/share/man/man7/samba.7.gz
могут быть предоставлены права на
машины от Microsoft, особенно в ка- чтение (read), запись(write) и выпол-
честве файл-серверов или серверов нение ( execute). В Windows NT систе- Если нет, то идите на ftp://
печати. ма доступа несколько гибче, доступ f tp.samba.org/pub/samba/samba-
Так как чуда от Microsoft особенно предоставляется нескольким группам latest.tar.gz или практически на любой
ждать не приходится и Windows вряд- или пользователям, причем соответ- сервер с программами для Linux и ка-
ли научится работать с сетевой фай- ствующие права доступа определяют- чайте в виде rpm или исходников. Па-
ловой системой Unix (NFS) стандарт- ся раздельно для каждого субъекта. кет прост в установке, поэтому, что-
ными средствами, то по принципу Поэтому полноценно эмулировать бы не занимать места, будем считать,
горы и Магомета, просто научили Unix средствами SAMBA права доступа что он у вас установлен. Теперь да-
притворяться, будто бы он - Windows заложенные в NTFS, невозможно. А вайте проверим, запущен ли демон:
NT. с клиентами, работающими под уп-
Взаимодействие компьютеров в равлением Windows 9x, дело обстоит [sergej@grinder sergej]$ ps -aux | grep
smbd
сети Windows построено на использо- иначе. Еще со времен дедушки ДОС, root 1122 0.0 0.6 4440 380 ?
вании протокола SMB (Server Message по причине того, что система одно- S 16:36 0:00 smbd -D
Block - блоки серверных сообщений), пользовательская и ни о каких пользо-
который обеспечивает выполнение вателях, а тем более группах, не мог- У меня уже запущен. Если у вас
всех необходимых в этих случаях за- ло быть и речи, для файловой систе- нет, то в Linux Mandrake, например,
дач по открытию и закрытию, чтению мы FAT определено всего четыре ат- чтобы он запускался при старте от-
и записи, поиску файлов, созданию и рибута - только чтение (read only), си- метьте нужный пункт в: DrakConf -
удалению каталогов, постановке за- стемный (system), архивный (archive) стартовые сервисы или control-panel
дания на печать и удалению его отту- и скрытый (hidden). Плюс ко всему в - Servise Configuration в Red Hat, обыч-
да. Все необходимые для этого дей- Windows, в отличие от Unix, имеет осо- но этого бывает достаточно, или за-
ствия реализуются в Unix-подобных бое значение расширение файла, так пускайте вручную: ./etc/rc.d/init.d/smb
операционных системах посредством файлы, предназначенные для выпол- start. Единственный конфигурацион-
использования пакета SAMBA. Что же нения, имеют расширение - exe, com, ный файл Samba называется smb.conf
должен обеспечить SAMBA сервер bat. Соответствия между правами до- и находится в каталоге /етс иногда
для нормальной работы в сети ступа Unix и DOS выражаются так: (в AltLinux, например, в каталоге /etc/
26
администрирование
ности (возможности удаления) файла ние о закрытии ресурса должен при- ным исключением, параметр printable
(каталога) используйте параметры: нять сервер и все потому, что клиен- = yes. Например:
veto files и delete veto files. С CD-ROM ты, как правило, не извещают об этом.
дисками дело обстоит несколько Но наиболее частой причиной явля- [printers]
сложнее. ется то, что ресурсом могут одновре- path = /var/spool/samba # óêàçûâàåò
íà êàòàëîã â êîòîðûé ïîìåùàþòñÿ çàäà
Все дело в том, что в Unix-подоб- менно пользоваться сразу несколько íèÿ íà ïå÷àòü
ных системах понятие диска отсут- пользователей или на одном компью- browseable = yes
printable = yes
ствует как таковое, и для того чтобы тере оставлен открытый файл на дан- read only = yes
получить доступ к нужному устрой- ном ресурсе. Поэтому CD-ROM авто-
ству, оно первоначально должно быть матически не размонтируется, един- После создания файла протести-
смонтировано в дерево каталогов (# ственный приемлемый способ, чтобы руйте его с помощью утилиты
mount -t iso9660 /dev/cdrom /mnt/ освободить ресурс - посмотреть с по- testparm, но при помощи данной про-
cdrom). А после использования, что- мощью утилиты smbstatus номер про- граммы можно обнаружить лишь син-
бы не разрушить файловую систему, цесса, использующего данный ресурс, таксические ошибки, а не логические,
должно быть размонтировано (# и убить его командой # kill pid_number поэтому нет никакой гарантии, что
umount /dev/cdrom), иначе устройство (или kill -s HUP pid_number). описанные в файле сервисы будут
просто не отдаст диск. Если у вас на Установив необходимую конфигу- корректно работать (при тестирова-
сервере запущен демон autofs, то про- рацию необходимо теперь создать нии будут выведены все установки -
блема решается просто. Для того что- учетные записи пользователей (за даже те, которые установлены по-
бы устройство которое не использу- исключением гостевого входа с мини- умолчанию). Но если программа не
ется в течении некоторого времени, мальными правами nobody). Для ин- ругается, можете надеяться, что при
было автоматически размонтировано, тентификации пользователей SAMBA запуске файл будет загружен без про-
установите нужное значение парамет- используется файл /etc/samba/ блем. А правильность установки прин-
ра timeout в файле /etc/auto.master, smbpasswd, в котором содержатся тера можно проверить с помощью
например: имена и зашифрованные пароли утилиты - testprns. Плюс не забывай-
пользователей. Так как механизм те о log-файлах - при возникновении
/mnt /etc/auto.misc timeout=60 шифрования в сетях Windows-машин проблем там иногда можно найти ре-
не совместим со стандартными Unix шение.
А затем установите параметры для механизмами, то для заполнения фай- Теперь немного о хорошем. Кон-
соответствующего устройства в фай- ла паролей используется отдельная фигурирование Samba - довольно
ле /etc/auto.misc: утилита - smbpasswd. сложная процедура, но с дистрибути-
вом поставляется инструмент админи-
cdrom # useradd -s /bin/false -d /home/samba/ стрирования на основе Web, который
fstype=iso9660,ro,nosuid,nodev : / sergej -g sales sergej
dev/cdrom # smbpasswd -a sergej называется swat (Samba Web
Administration Tool). Swat запускается
После всего прописываем в /etc/ В этом примере добавляется но- в виде сервиса или с помощью сер-
smb.conf следующие строки, чтобы вый пользователь sergej с фиктивной вера Apache, и предназначен для ре-
сделать доступным данный ресурс: оболочкой, принадлежащий группе дактирования файла smb.conf, а так-
sales и домашним каталогом /home/ же для проверки состояния, запуска
[cdrom] samba/sergej. Затем создается пароль и остановки демонов Samba. Для ра-
path = /mnt/cdrom
writable = no для пользователя sergej. боты в виде сервиса в файле /etc/
С помощью SAMBA можно органи- services должна быть обязательно
Второй вариант состоит в исполь- зовать возможность сетевой печати с строка swat 901/tcp, а в файле /etc/
зовании директив preexec и postexec, компьютеров под управлением inetd.conf - swat stream tcp nowait.400
которые указывают какие команды Windows (если планируется отдель- root /usr/local/samba/bin/swat swat. Те-
необходимо выполнить при обраще- ный сервер печати, то для этого бы- перь для запуска Swat в окне браузе-
нии к ресурсу и после отсоединения вает достаточно и машины на базе ра введите:
от него. 486 процессора).
http://localhost:901
[cdrom]
Для этого в секции [global] необ-
path = /mnt/cdrom ходимо записать такие строки: После всех изменений в файле
read only = yes smb.conf иногда потребуется пере-
root preexec = mount /mnt/cdrom #ìîí-
òèðîâàòü ðåñóðñà èìååò ïðàâî òîëüêî root printcap name = /etc/printcap # ôàéë запустить демон smb: /etc/rc.d/init.d/
root postexec = umount /mnt/cdrom # îïèñàíèÿ ïðèíòåðîâ, ïîäêëþ÷åííûõ ê ñèñ-
åñòåñòâåííî ýòè òî÷êè ìîíòèðîâàíèÿ äîë- òåìå smb restart.
æíû áûòü îïèñàíû â ôàéëå /etc/fstab èíà÷å load printers = yes #, óêàçûâàåò íà Если после всех перечисленных
íåîáõîäèìî óêàçàòü è îñòàëüíûå äàííûå. íåîáõîäèìîñòü àâòîìàòè÷åñêîãî âêëþ÷åíèÿ
â ñïèñîê ñåòåâûõ ðåñóðñîâ действий так и не удалось организо-
Теперь при обращении к ресурсу printing = lprng # ñèñòåìà ïå÷àòè вать доступ к ресурсам SAMBA, то в
(äëÿ Linux ìîæåò åùå èñïîëüçîâàòüñÿ bsd)
автоматически монтируется CD-ROM. дальнейшей настройке помогут такие
А в идеальных случаях и размонтиру- Далее каждый принтер описывает- утилиты, как ping, nmblookup или на
ется. Вся проблема в том, что реше- ся как дисковый ресурс с единствен- крайний случай tcpdump. Вот и все.
В
АДМИНИСТРИРОВАНИИ
СЕРВЕРА: ПОЧЕМУ БЫ
И НЕТ?
РОМАН СУЗИ
Стандартных решений не существует. Каждый сис- ками при решении как повседневных, так и одноразо-
темный администратор рано или поздно начинает пи- вых задач.
сать свои скрипты, которые облегчают его работу, из- Python — интерпретируемый язык с развитыми вы-
бавляя от рутины. Для автоматизации в Unix-системах сокоуровневыми структурами данных, имеющий все не-
традиционно применяются командные оболочки (типа обходимое для вызова функций POSIX-совместимых си-
bash или ksh, разновидностей оболочек достаточно стем. Впрочем, Python является многоплатформенным
много) и язык Perl. Причем, следуя философии Unix, эти языком, так что его можно с успехом использовать и, к
оболочки используют для решения проблемы целый примеру, в среде Windows. Однако не буду долго гово-
набор инструментов, выполняющих небольшие частные рить о происхождении и синтаксисе языка: об этом за-
задачи: ls, wc, sort, grep, diff, tar, ... интересованный читатель узнает на http://python.ru или
Обычно простые задачи выполняются в командной из книги Сузи Р.А. Python. — СПб.: БХВ-Петербург,
оболочке запуcком соответствующих инструментов и 2002; а сразу перейду к делу.
организацией потока данных. Для более сложных за- Начнем с небольшого примера, в котором нам тре-
дач требуются и более сложные инструменты, напри- буется установить права и принадлежность файлов, что-
мер, awk, sed или даже Perl. Так принято. бы имена совпадали с именами пользователей в сис-
Однако хотелось бы обратить внимание системных теме (для простоты будем считать, что имена пользо-
администраторов на такой сценарный (скриптовый) вателей доступны из файла /etc/passwd). Подобная за-
язык как Python. Этот язык, благодаря своим хорошим дача может возникнуть, например, в каталоге с почто-
качествам, о которых поговорим далее, уверенно заво- выми ящиками, где каждый ящик должен принадлежать
евывает популярность, в том числе для задач систем- соответствующему его названию пользователю.
ного администрирования. Например, именно его при-
меняет Red Hat в инструменте под названием anaconda #!/usr/bin/python
для обеспечения начальной установки своего дистри-
import os, string
бутива Linux.
Конечно, системные администраторы — натуры users = {}
for line in open("/etc/passwd").readlines():
весьма консервативные, и потому я решил написать эту rec = string.split(line, ":")
статью, показывающую, что Python действительно име- users[rec[0]] = int(rec[2]), int(rec[3]) # uid è gid
for file in os.listdir("."):
ет преимущества по сравнению с языком Perl и оболоч-
28
администрирование
try: файлов, содержащих в имени точку, пробел или дефис
uid, gid = users[file] в начале!
except:
print "Ñèðîòà: ", file Я более чем уверен, что программу можно перепи-
uid, gid = 0, 0 # root сать, экранировав символы должным образом. Но тем
os.chmod(file, 0600)
os.chown(file, uid, gid) не менее, зная Python, можно быстрее написать скрипт,
решающий ту же задачу без скользких текстовых под-
В самом начале мы импортируем модуль для рабо- становок.
ты с функциями ОС (os) и работы со строками (string). Из приведенных примеров уже видна особенность
Перед началом цикла по строкам файла /etc/passwd сло- языка Python, не всеми воспринимаемая хорошо: для
варь users пуст. В цикле по строкам файла /etc/passwd выделения фрагментов кода в составных операторах
мы делаем следующее. Именем rec обозначаем кортеж используется единообразный отступ. Тем самым интер-
значений записи passwd-файла. Мы знаем, что первое претатор Python требует от программиста визуально вы-
поле этой записи — имя пользователя. Имя пользова- делять структуру программы, что положительно сказы-
теля и станет ключом в словаре users. В качестве зна- вается на читаемости кода. И это немаловажно, ведь
чения для данного ключа мы берем приведенные к це- написанный скрипт может пригодиться для похожей за-
лому типу поля 2 и 3, соответствующие идентификато- дачи.
рам пользователя и группы. Таким образом в первом В следующем примере мы рассмотрим еще одну ча-
цикле формируется отображение имени пользователя сто возникающую задачу: проверка работоспособнос-
и его идентификаторов. Во втором цикле, по именам ти POP3-сервиса и отправка сообщения электронной
файлов в текущем каталоге, пытаемся (try) найти вла- почты в случае неудачи. Заметьте, что приведенный
дельца файла, обращаясь к словарю users. Если это не пример одинаково хорошо подходит и для Unix, и для
удается, мы пишем на стандартный вывод соответству- NT.
ющую диагностику. В этом случае владельцем файла
станет root. Последние две команды, думается, ясны и #!/usr/bin/python
без комментариев. import smtplib, poplib
В приведенном на листинге примере были исполь-
try:
зованы очевидные решения, не требующие особого зна- p = poplib.POP3("mymail")
ния стандартной библиотеки Python. p.quit()
except:
Для любознательных укажем и второй путь реше- error = "connection"
ния, в котором используются «правильные» средства: try:
s = SMTP("othermail")
s.sendmail("admin@mymail", "admin@othermail",
#!/usr/bin/python """From: admin@mymail
To: admin@othermail
import os, pwd, glob Subject: POP3 down!!!
30
администрирование
на «сырые» логи Sendmail не всегда можно увидеть date, session_id, addr = found["date"], found["session"],
проблему. Во всяком случае, для этого требуется неко- found["addr"]
торое напряжение глаз. direc = found.get("direc", "to") # ïî óìîë÷àíèþ "to"
stat = found.get("stat", "") # ïî óìîë÷àíèþ - ïóñòàÿ
Наша небольшая программа на Python будет соби- ñòðîêà
рать данные о сеансах и показывать только сеансы с if direc == "to" and stat[:4] != "Sent" and stat !=
большим числом получателей. В логе эта информация "User unknown":
сильно размазана, поэтому простого применения инст- continue # òàêèå ñîîáùåíèÿ íå èíòåðåñóþò
румента вроде grep здесь оказывается недостаточно. if direc == "to": # â çàâèñèìîñòè îò íàïðàâëåíèÿ
Накапливаемые данные мы будем сохранять в фай- if t.has_key(session_id):
t[session_id] = t[session_id] + addr + ";"
лах-хэшах (аналогичных тем, в которых хранятся, на- else:
пример, псевдонимы), благо в Python есть для этого t[session_id] = addr + ";"
else:
нужные модули. (Конечно, в Python можно использовать f[session_id] = addr
и полновесные базы данных с языком запросов SQL, r[session_id] = found.get("relay_ip", "") or
found.get("relay", "")
однако это непринципиально). d[date + session_id] = session_id
Задача распадается на две: сбор данных из лога в input_file.close()
базу данных и выборка из базы данных. f.close(); t.close(); r.close(); d.close()
32
ПРОГРАММИРОВАНИЕ
ЕВГЕНИЙ КОНОВАЛОВ
РАБОТА
С
ТЕКСТОМ
ИЛИ
ФИЛОСОФИЯ
PERL
программирование
Есть два основных аспекта, которые легли в ление пользователю возможности их раздельного про-
основу этой статьи. смотра. Это связано с сегодняшней философией жизни в
Первый - это периодически возникающая Интернет, например, с «диалапными» скоростями досту-
перед большинством Web-программистов па (впрочем, не только с этим).
проблема переноса тех или иных документов Подытоживая сказанное, Вашему вниманию представ-
в базу данных (БД), используемую, ляется задача, решенная в рамках разработки подсисте-
например, при генерации страниц скриптами. мы информационного наполнения БД.
Проблема эта из разряда концептуальных и Исходные данные:
решается по-разному: в зависимости от n тип вносимой информации - HTML-код значительного
рабочей среды, окружающей разработчика объема;
плотным кольцом всевозможных n весь HTML-код заключен в едином документе;
требований, условий и согласований. n документ необходимо разбить на составные части, ко-
Вторая идея, попавшая в фокус обсуждения - торые размещаются в БД (с тем же успехом их можно
использование Perl для решения сохранить в файл).
любопытной задачи, связанной с упомянутой Основная трудность решения: в результате разбиения
выше проблемой. Собственно об этом и документа необходимо получить фрагменты HTML-кода,
пойдет речь в дальнейшем. (Примечание: имеющие корректную HTML-структуру. Такого рода кор-
данная статья, пожалуй, рассматривается ректность подразумевает:
именно как посылка для обсуждения - иные n соответствие каждому начальному HTML-тегу завер-
подходы не имеют и половины такой же шающего HTML-тега (для HTML-элементов, обязатель-
привлекательности.) но обозначаемых именно парой тегов);
n переработку внутренних гиперссылок (для случаев,
Вместо лирического вступления когда сама ссылка оказывается в одном фрагменте, а
то место в оригинальном документе, на которое она
На всякий случай автор искренне просит не рассмат- ссылается, - в другом фрагменте).
ривать эту статью как очередное «УРА» в честь наиболее
развитого и удобного, свободного, попросту приятного и Отправная точка: исходные данные в
даже замечательного языка для работы с текстом и про- подробностях
граммирования в Web (разумеется, речь идет о Perl).
«Начинать нужно с чего-то...», - и с этим трудно не согласиться.
Сильным духом программистам Чтобы стало понятным все, о чем пойдет речь в даль-
посвящается... нейшем, необходимо внести большую ясность в то, что
касается исходных данных. На вход описанного ниже про-
«Если ты едешь тише - дольше ехать тебе. Если поспешишь, то не
разглядишь идей» граммного модуля, поступают должным образом подго-
товленные оглавление и текст HTML-документа. Далее
Следуя этой нехитрой идее, хочется без излишних под- приведено описание правил, по которым осуществляется
робностей, но, тем не менее, вдумчиво изложить уважае- такого рода подготовка документа.
мому читателю идеи, которые, вполне возможно, приго- Говоря коротко, необходимо иметь HTML-документ с
дятся в работе или просто послужат поводом для размыш- гипертекстовым оглавлением (в оглавлении должны ис-
лений. пользоваться внутренние гиперссылки - то есть те, значе-
Сначала несколько слов об истоках рассматриваемой ния атрибутов href которых начинаются со знака решетки
проблемы. Сегодня адаптация документов различных «#»). Такой подход достаточно удобен. Теперь о том же
форматов для внесения их в БД Web-сайта - занятие при- самом, но уже более подробно.
вычное во многих организациях, имеющих собственную Дабы исключить путаницу в терминах введем несколь-
«точку присутствия» в сети Интернет. Зачастую это свя- ко понятий.
зано с возможностью простой реализации полнотексто- «Внутренняя гиперссылка» - ссылка, при нажатии на
вого поиска в таблицах БД и простотой реализации меха- которую выполняется переход на анкер (см. ниже), распо-
низмадоступа к информации. ложенный в том же HTML-документе, в теле которого на-
Так или иначе, все выглядит достаточно просто и по- ходится и сама ссылка; значение атрибута HREF такой
нятно, когда речь заходит о небольших объемах данных, гиперссылки начинается со знака решетки #. Например:
особенно, если они подготавливаются централизовано
одним-двумя сотрудниками. Сложности возникают при <A HREF=»#Part1">1. Introduction</A>.
работе с документами больших размеров.{1} Что также
может осложняться острым желанием предоставить ад- «Анкер» - тег, размещаемый в том месте HTML-доку-
министратору БД и многочисленным контент-менеджерам мента, куда необходимо осуществить перемещение по на-
удобную методику для работы с данными. жатию на внутреннюю гиперссылку. Например:
Одновременно специфика Web, конечно же, делает
предпочтительной разбивку крупных документов на от- <A NAME=»Part1">
дельные составляющие (например, главы), и предостав-
36
программирование
данных (см. далее), позволяющих описать документ с точ- $attrseq, $origtext) и end($tag, $origtext). Первый из них
ки зрения типов тегов, содержащихся в нем, и их количе- вызывается при обнаружении начального HTML-тега, пе-
ства. На основе такой количественной статистики произ- редаваемые ему параметры: $tag - имя тега, $attr - хэш с
водится анализ корректности HTML-структуры всего до- именем атрибута тега в качестве ключа и значением ат-
кумента и глав, на которые он будет разделен в дальней- рибута в качестве значения хэша, $attrseq - массив имен
шем. атрибутов тега, $origtext - HTML-код тега. Второй метод
Идея проста: анализ сводится к подсчету количества выполняется при обнаружении завершающего HTML-тега:
стартовых и завершающих тегов и сравнении полученных $tag - имя тега, $origtext - HTML-код тега.
величин, исправление обнаруженных ошибок заключает- В программе методы start и end перегружаются (за-
ся в добавлении недостающих стартовых и завершающих мещаются). Именно в рамках этих процедур производит-
тегов. ся потеговый анализ документа и собирается упомянутая
Остановимся на этом чуть подробнее. Суть заключа- выше статистика, характеризующая его HTML-структуру.
ется в том, что первоначально для каждой главы из тех, на
которые разбивается документ подсчитывается число на- Программирование: основные
чальных и завершающих тегов (назовем их «Величина-1» структуры данных
и «Величина-2»). Затем при обнаружении несоответствия «Структура структурной структуризации структурирует
между этими значениями начинается итерационный поиск структурную типизацию», - и все это не случайно.
недостающего парного тега: последовательно перебира-
ются последующие главы и для каждой такой главы к ве- Речь идет о структурах данных объектов класса
личине-1 и величине-2 соответственно прибавляются чис- Manual_Parser - в них накапливается статистика, позво-
ла начальных и завершающих тегов этой главы. Условием ляющая проанализировать HTML-структуру документа.
успешного окончания поиска недостающего парного тега Существует три основные структуры данных:
является равенство величины-1 и величины-2. $Doc_Info, $Work_Container и массив @Pages_Info. Сразу
Если назвать главу, в которой обнаружилось несоот- же следует заметить, что речь идет о сложных, вложен-
ветствие, стартовой (Главой итерационного поиска); главу ных структурах данных. Их понимание играет ключевую
в которой был найден недостающий парный концевой тег - роль.
заключительной, а все главы между ними - промежуточ- Каждый элемент массива @Pages_Info представляет
ными, то процесс коррекции HTML-структуры глав можно собой структуру данных, с элементами в виде скаляров,
описать достаточно просто. Необходимо дополнить стар- списков и хэшей, описывающих HTML-структуру одной
товую главу концевым HTML-тегом, заключительную гла- главы (замечание в рамках борьбы с несозвучностью на-
ву - стартовым HTML-тегом, промежуточные главы - стар- званий и терминологии: под «Page» понимается HTML-
товым и концевым HTML-тегами. страница, соответствующая главе).
38
программирование
Анализ HTML-документа: тег за тегом #Ïðîâåðêà: íàéäåííûé òåã - Âíóòðåííÿÿ Ãèïåðññûëêà
Далее подробно комментируется программная реали- if ($attr->{href} =~ /^#/ )
{
зация решения описанной выше задачи. Приведенный my $Temp2 = $attr->{href};
наже программный код относится к классу Manual_Parser. $Temp2 =~ s/#//;
$self->{Pages_Info}[$self->{Current_Page}]-
@Array - массив (инициализируется в конструкторе при >{Local_Links}{$Temp2}=$self->{Current_Page};
создании объекта), в котором содержатся имена анкеров.
}
Разметки, полученные в виде результирующего списка на }
стадии подготовки к анализу документа (см. ранее). }
Процедура start() - замещает процедуру start() класса #Îáíîâëåíèå ñòàòèñòèêè ïî íàéäåííîìó òåãó â ñòðóêòóðå äàí-
HTML::Parser, вызывается при нахождении стартового (на- íûõ ïî òåêóùåé Ãëàâå
$self->{Pages_Info}[$self->{Current_Page}]-
чального) HTML-тега. Процедура работает со всем тек- >{Num_Of_Tags}++;
стом документа, «физического» разбиения на главы на $self->{Pages_Info}[$self->{Current_Page}]->{Tags}{«$tag»}-
>{Start_Tag_Num}++;
данном этапе не произодится - каждая глава рассматри- $self->{Pages_Info}[$self->{Current_Page}]-
вается как составная часть документа. >{Tags_Seq_Page}{$self->{Tag_Num_In_Curr_Page}}-
>{Tag_Name}=$tag;
$self->{Pages_Info}[$self->{Current_Page}]-
sub start >{Tags_Seq_Page}{$self->{Tag_Num_In_Curr_Page}}-
{ >{Tag_Num_In_Doc} = $self->{Tag_Num_In_Doc};
my $self = shift;
#Îáíîâëåíèå ñòàòèñòèêè ïî íàéäåííîìó òåãó â ñòðóêòóðå äàí-
#Ïîëó÷åíèå ïàðàìåòðîâ òåãà (îïèñàíèå ñì. ðàíåå) íûõ ïî Äîêóìåíòó
my ($tag, $attr, $attrseq, $origtext) = @_; $self->{Doc_Info}->{Tags}{«$tag»}->{Start_Tag_Num}++;
$self->{Doc_Info}->{Tags_Seq_Doc}{$self->{Tag_Num_In_Doc}}-
my @Temp_Cont_HREFs = @{$self->{Contents_HREFs}}; >{Tag_Name}=$tag;
$self->{Doc_Info}->{Tags_Seq_Doc}{$self->{Tag_Num_In_Doc}}-
#Ïðîâåðêà: âõîäèò ëè íàéäåííûé ñòàðòîâûé òåã â ñïèñîê òåõ >{Tag_Orig_Text}=$origtext;
òåãîâ, äëÿ êîòîðûõ íå îáÿçàòåëüíî óêàçûâàòü ïàðíûé êîíöåâîé $self->{Doc_Info}->{Tags_Seq_Doc}{$self->{Tag_Num_In_Doc}}-
òåã >{Tag_Num_In_Page}=$self->{Tag_Num_In_Curr_Page};
if (!($self->Tag_Is_Exception_Check($tag))) $self->{Doc_Info}->{Tags_Seq_Doc}{$self->{Tag_Num_In_Doc}}-
{ >{Tag_Page_Num}=$self->{Current_Page};
$self->{Doc_Info}->{All_Start_Tags_Num}++;
#Ïðîâåðêà: ÿâëÿåòñÿ ëè íàéäåííûé òåã ãèïåðññûëêîé èëè
àíêåðîì $self->{Tag_Num_In_Curr_Page}++;
if ($tag eq a) #Ñ÷åò÷èê ÷èñëà òåãîâ âäîêóìåíòå (èíèöèàëèçèðóåòñÿ â êîíñò-
{ ðóêòîðå ïðè ñîçäàíèè îáúåêòà)
my $Last_Tag_Is_Cont_Href=0; $self->{Tag_Num_In_Doc}++;
#Äëÿ êàæäîãî èìåíè Àíêåðà Ðàçìåòêè }
foreach $Temp (@Array) }
{
#Ïðîâåðêà: íàéäåííûé òåã - Àíêåð Ðàçìåòêè
if ($attr->{name} eq $Temp && $attr->{name} ne )
Âûñòàâëåíèå ôëàãîâ, èçìåíåíèÿ ñ÷åò÷èêîâ
{
#Ñ÷åò÷èê ÷èñëà òåãîâ â Ãëàâå (èíèöèàëèçèðóåòñÿ â êîíñò-
ðóêòîðå ïðè ñîçäàíèè îáúåêòà) - çíà÷åíèå ðàâíî ïîðÿäêîâîìó
íîìåðó (â Ãëàâå) àíàëèçèðóåìîãî òåãà
$self->{Tag_Num_In_Curr_Page}=0;
#Ñ÷åò÷èê ÷èñëà ñòðàíèö (èíèöèàëèçèðóåòñÿ â êîíñòðóêòîðå ïðè
ñîçäàíèè îáúåêòà) - çíà÷åíèå ðàâíî ïîðÿäêîâîìó íîìåðó òåêóùåé
àíàëèçèðóåìîé Ãëàâû
$self->{Current_Page}++;
$Last_Tag_Is_Cont_Href=1;
last;
}
#Ïðîâåðêà: íàéäåííûé òåã - ãèïåðññûëêà íà îäíó èç Ãëàâ
elsif ($attr->{href} eq join(,#,$Temp))
{
#Ñîõðàíèòü â ñòðóêòóðå äàííûå î íàéäåííîé Âíóòðåííåé
Ãèïåðññûëêå íà îäíó èç Ãëàâ
my $Temp2 = $attr->{href};
$Temp2 =~ s/#//;
$self->{Pages_Info}[$self->{Current_Page}]-
>{Local_Links_To_Pages}{$Temp2}=$self->{Current_Page};
$Last_Tag_Is_Cont_Href=1;
}
}
#Ïðîâåðêà: ïîñëåäíèé íàéäåííûé òåã - íå Àíêåð Ðàçìåòêè è
íå Âíóòðåííÿÿ Ãèïåðññûëêà íà îäíó èç Ãëàâ
if ($Last_Tag_Is_Cont_Href==0)
{
40
программирование
push (@{$self->{Pages_Info}[$k]->{End_Tags_To_Add}}, {
$self->{Work_Container}->{Tag_Num_In_Doc}); $Manual_Parts[$i] =~ s/
$self->{Pages_Info}[$k]->{Tags}{$Current_Tag_Name}- (<\s*?a\s{1}.*?href\s*?=\s*?»?)#$key(«?\s?.*?>)/$1ñòðîêà_http-
>{End_Tag_Num}++; çàïðîñà_óêàçûâàþùàÿ_ ïóòü_ñ_òî÷íîñòüþ_äî_äîêóìåíòà&page=$i$2/
$self->{Doc_Info}->{Tags}{$Current_Tag_Name}- is;
>{End_Tag_Num}++; }
}
#Äëÿ çàêëþ÷èòåëüíîé Ãëàâû èòåðàöèîííîãî ïîèñêà #Êîððåêòèðîâêà ïðî÷èõ Âíóòðåííèõ Ãèïåðññûëîê
elsif ($k == $Current_Page_Num) foreach $key (keys %{$self->{Pages_Info}[$i]->{Local_Links}})
{ {
#Çàïîìíèòü ïîðÿäêîâûé íîìåð òåãà â Äîêóìåíòå, äëÿ êî- $Manual_Parts[$i] =~ s/
òîðîãî íåîáõîäèìî äîáàâèòü ïàðíûé ñòàðòîâûé òåã â Ãëàâå (<\s*?a\s{1}.*?href\s*?=\s*?»?)(#$key»?\s?.*?>)/$1ñòðîêà_http-
push (@{$self->{Pages_Info}[$k]->{Start_Tags_To_Add}}, çàïðîñà_óêàçûâàþùàÿ_ ïóòü_ñ_òî÷íîñòüþ_äî_äîêóìåíòà&page=$self-
$self->{Work_Container}->{Tag_Num_In_Doc}); >{Doc_Info}->{Local_Anchors}{$key}$2/is;
$self->{Doc_Info}->{Tags}{$Current_Tag_Name}- }
>{Start_Tag_Num}++;
$self->{Pages_Info}[$k]->{Tags}{$Current_Tag_Name}-
>{Start_Tag_Num}++; Примечание: если ограничиться таким способом при-
}
#Äëÿ ïðîìåæóòî÷íûõ Ãëàâ èòåðàöèîííîãî ïîèñêà менения элементов Local_Links и Local_Links_To_Pages из
else структуры данных Pages_Info (см. ранее), то вместо хэ-
{
#Çàïîìíèòü ïîðÿäêîâûé íîìåð òåãà â Äîêóìåíòå, ñòàðòî- шей могут быть использованы обычные списки.
âûé è êîíöåâîé òåãè êîòîðãî áóäóò äîáàâëåíû â ïðîìåæóòî÷íóþ
ñòðàíèöó
push (@{$self->{Pages_Info}[$k]->{Start_Tags_To_Add}}, Вместо заключения
$self->{Work_Container}->{Tag_Num_In_Doc});
$self->{Doc_Info}->{Tags}{$Current_Tag_Name}-
>{Start_Tag_Num}++; Возможности Perl по работе с текстом действительно
$self->{Pages_Info}[$k]->{Tags}{$Current_Tag_Name}- велики. Это прописная истина, и в ней можно убеждаться
>{Start_Tag_Num}++;
снова и снова.
push (@{$self->{Pages_Info}[$k]->{End_Tags_To_Add}},
$self->{Work_Container}->{Tag_Num_In_Doc});
$self->{Doc_Info}->{Tags}{$Current_Tag_Name}- {1} Хранение крупных страниц целиком в БД - это, по-
>{End_Tag_Num}++; жалуй, не всегда является оптимальным решением. Иног-
$self->{Pages_Info}[$k]->{Tags}{$Current_Tag_Name}-
>{End_Tag_Num}++; да гораздо приятнее иметь структурированный HTML-ар-
} хив в файлах на диске, а для удобства поиска размещать
}
} результаты его индексирования в БД.
}
}
}
#Äëÿ âñåõ Ãëàâ
for (my $i=0; $i<=$#Manual_Parts; $i++)
#Âûïîëíèòü äîáàâëåíèå íåäîñòàþùèõ ñòàðòîâûõ è êîíöåâûõ òå-
ãîâ (êîððåêòèðîâêà HTML-ñòðóêòóðû)
{
@{$self->{Pages_Info}[$i]->{Start_Tags_To_Add}}= sort {$b
<=> $a} @{$self->{Pages_Info}[$i]->{Start_Tags_To_Add}};
@{$self->{Pages_Info}[$i]->{End_Tags_To_Add}} = sort {$b
<=> $a} @{$self->{Pages_Info}[$i]->{End_Tags_To_Add}};
#Äîáàâèòü ñòàðòîâûå òåãè
foreach my $value (@{$self->{Pages_Info}[$i]-
>{Start_Tags_To_Add}})
{
$Manual_Parts[$i]=join (, $self->{Doc_Info}-
>{Tags_Seq_Doc}{$value}->{Tag_Orig_Text}, $Manual_Parts[$i]);
}
ЭФФЕКТИВНОЕ
42
программирование
шенно отличная от традиционной 1.Как завести внутри undef $$v; #îñâîáîæäàåì ïàìÿòü, îòâå-
практики в языках без сборки мусо- функции большую временную äåííóþ ôóíêöèåé a
ра типа C++ или Pascal, когда все ра- текстовую переменную, а
бочие переменные, созданные внут- перед выходом из функции Такой код "съест" только 1 мега-
ри функции, уничтожаются при вы- освободить память из-под байт, который освободится при вызо-
ходе из функции.) нее? ве undef.
Это не так важно в обычном CGI- Неправильное решение: Проблема на самом деле доволь-
скрипте, исполняемом внешним ин- но общая: никогда не следует писать
терпретатором Perl. По завершении sub a { выражение, результат которого - боль-
my $text= "very large string.... (1 MB)";
скрипта процесс будет полностью ðàáîòàåì ñ $text; шая строка. Нельзя писать даже так:
уничтожен вместе со всей своей па- #ïðîñòî âûõîäèì èç ôóíêöèè, ïðåäïîëà-
ãàÿ,
мятью. Но в mod_perl или FastCGI, #÷òî ñáîðùèê ìóñîðà àâòîìàòè÷åñêè îñâî- my $v= $text."\n";
или в независимых приложениях, áîäèò
#ïàìÿòü èç-ïîä $text (êàê ýòî ïðîèñõî-
или серверах на Perl это очень су- äèò если строка $text потенциально может
щественно. #ñî ñòåêîâûìè ïåðåìåííûìè â C++ è Pascal) быть большой (десятки килобайт или
}
Обратите внимание - описанная больше).
проблема НЕ ЕСТЬ истинная утеч- Правильное решение - добавить
ка памяти. Встроенный сборщик му- перед выходом вызов undef: 3.Как передать большую
сора действительно обеспечивает строку в функцию?
утилизацию ненужных переменных. sub a { Неправильное решение:
my $text= "very large string.... (1 MB)";
Просто он делает это не совсем так, ðàáîòàåì ñ $text;
как можно было бы ожидать. А имен- undef $text; sub a {
} my $text= $_[0]; #ïàðàìåòð $_[0]
но: занятая память будет использо- ñîäåðæèò ñòðîêó äëèíîé 1 MB
вана повторно ПРИ СЛЕДУЮЩЕМ Вызов undef освободит память, за- ðàáîòàåì ñ $text;
undef $text;
ВЫЗОВЕ той же самой функции, т.е. нятую переменной $text. Без такого }
многократные повторные вызовы вызова получаем общую проблему II). my $text= "very large string.... (1 MB)";
a($text);
функции не будут приводить к посте-
пенному исчерпанию RAM - явле- 2.Функция должна создать В этом примере общей проблемы II
нию, которое традиционно называ- большую строку и вернуть ее нет, но память расходуется напрасно.
ется утечкой памяти. Зато много- в результате. Оператор присваивания $text= $_[0]
кратные вызовы приведут к друго- Неправильное решение: расходует второй мегабайт под копию
му: со временем будет занят наи- $text переменной $_[0] (который осво-
больший объем памяти из всех, ко- sub a { бождается в конце вызовом "undef").
my $text= "very large string.... (1 MB)";
торые были нужны при различных return $text; Если есть возможность, лучше ра-
вариантах вызова этой функции. В } ботать непосредственно с $_[0] - т.е.
my $v= a();
моем случае, после того как мои ðàáîòàåì ñ $v; с алиасом внешней переменной. А
Perl-функции один раз обработали еще лучше - нагляднее - всегда пере-
HTML-страницу размером 10 MB и Такой Perl-код "съест" не 1 мега- давать большие строки по ссылке.
соответствующий процесс с байт, действительно необходимый Предлагаемое правильное реше-
mod_perl "съел" 100 MB, он так и про- для сохранения переменной $v, а 2 ние:
должал всегда занимать 100 MB, мегабайта. Лишний мегабайт будет
хотя все последующие обрабатыва- занят интерпертатором Perl при вы- sub a {
my $text= $_[0]; #ïàðàìåòð $_[0]
емые страницы были небольшими. числении строкового выражения "a()" ñîäåðæèò ÑÑÛËÊÓ íà ñòðîêó
Внешне такое поведение очень по- для последующего копирования этих ðàáîòàåì ñ $$text;
}
хоже на утечку - объем памяти, за- данных в переменную $v. my $text= "very large string.... (1 MB)";
нятый процессом, никогда не умень- Мегабайт, занятый $v, можно впос- a(\$text);
шается, но постепенно медленно ледствии освободить вызовом "undef
увеличивается - по мере того как $v", но мегабайт, занятый при вычис- 4.Как выполнить
этому процессу случайно попадают- лении строкового выражения в пра- конкатенацию нескольких
ся данные все большего размера. вой части, по-моему, уже не освобо- строк, одна из которых
Теперь рассмотрим конкретные дить никак. может быть очень большой?
типовые задачи, возникающие при Правильное решение - функция Неправильное решение:
обработке данных в Perl. Я приведу должна вернуть ссылку на созданную
примеры традиционного решения большую строку: my $newtext= "$a$text$b";
этих задач - неправильного в свете
описанных проблем - и возможные sub a { или
my $text= "very large string.... (1 MB)";
варианты аккуратного решения, не return \$text;
приводящие к перерасходу памяти. } my $newtext= $a.$text.$b;
my $v= a();
ðàáîòàåì ñ $$v;
44
программирование
рекомендациям, на самом деле он на NT 4.0 и в стандартном Perl из или в любом другом смысле - никогда
все-таки может привести к проблеме. FreeBSD 4.2. Под ActivePerl 5.6 в не стоит полностью полагаться на до-
А именно, если общий объем читае- Windows 2000 все оказалось несколь- кументацию, общие рекомендации и
мого текста порядка 1 MB, то в про- ко хуже: undef не освобождает память. советы. В том числе, приведенные в
цессе чтения в пике может израсхо- (По крайней мере, TaskManager не по- этой статье. Всегда измеряйте эффек-
доваться не 1, а 2 мегабайта. Второй казывает сокращения памяти у процес- тивность сами! Если реальная эффек-
мегабайт потом обычно освобождает- са Perl, пока длится 10-секундный sleep, тивность программы не соответствует
ся, но не гарантированно. следующий за вызовом undef.) Впро- вашим априорным оценкам, ищите "уз-
Эта тонкая проблема, по-видимо- чем, к моменту, когда вы будете читать кое место" - тот "плохой оператор", ко-
му, связана с механикой переотведе- эту статью, возможно, этот недостаток торый отвечает за перерасход памяти
ния памяти в Perl. Оператор "$text.= уже будет исправлен фирмой или долгое выполнение. После чего
$buf" время от времени увеличивает ActiveState. создайте тест - минимальную програм-
память, занятую переменной $text. В В завершение хотелось бы сделать му, в которой "плохой оператор" прояв-
процессе такого переотведения ин- небольшое замечание. Если вас дей- ляет свои скверные качества, - и ищи-
терпретатору Perl, вероятно, требует- ствительно интересует эффективность те более качественное эквивалентное
ся двойной объем памяти: под пре- работы вашей программы - в плане эко- решение. Именно так были найдены все
жнюю строку $text и под новый, уве- номии памяти, в плане быстродействия описанные выше приемы.
личенный буфер для этой перемен-
ной. В этот момент процесс и занима-
ет лишний мегабайт. Видимо, если
переотведение происходит в конце
цикла, второй мегабайт может и не
освободиться: в соответствии в общей
идеологией Perl "запасать буфера
памяти на будущее повторное исполь-
зование".
Правильное решение описанной
задачи - взять отведение памяти на
себя. Например:
«СТЕММЕР»
МОРФОЛОГИЧЕСКИЙ
АНАЛИЗ
ДЛЯ НЕБОЛЬШИХ ПОИСКОВЫХ СИСТЕМ
Сейчас уже никого не удивишь поисковой системой со встроенным
русским, украинским или английским морфологическим анализатором,
однако такой модуль достаточно дорог, и использование его в небольших
продуктах не всегда коммерчески оправданно.
Поисковые и не только поисковые Один достаточно иллюстративный та под конкретного заказчика, когда
системы Интернет столь популярны диалог произошел на выставке бюджет проекта не сильно превыша-
сегодня, что люди проводят часы, об- SofTool в 1995 году. Компания «Ага- ет эту сумму - не самая лучшая идея.
суждая достоинства и недостатки той ма», где я в тот момент работал, пред- Что же делать в такой ситуации?
или иной, алгоритмы и программы для ставляла одноименную систему поис- Есть два решения. Первое - не исполь-
поиска полнотекстовой информации ка информации, размещенной на ло- зовать лингвистических алгоритмов
на тех или иных носителях. И все это кальных дисках компьютера. Надо вообще, если это возможно. Второе -
время не утихают горячие споры «про- сказать, эта поисковая система уже остановиться на стемминге, то есть на
фи» поиска и «ленивых пользовате- тогда, несмотря на убогость DOS, под формальном выделении основы - ста-
лей». Первые - сторонники чисто «ме- управлением коего она работала, уже бильной, графически неизменной при
ханических» машин, поисковых сис- делала полноценный словарный мор- склонении или спряжении, части сло-
тем, которые вычисляют строгие ло- фологический анализ обрабатывае- ва.
гические запросы и поддерживают мых текстов и поисковых запросов, то Программы, выполняющие стем-
усечение слова справа «звёздочкой»; есть умела искать с учетом всех форм минг, или стеммеры, также существу-
они убеждены, что лучше всяких ал- русских слов. И вот одна дама, про- ют примерно столько же, сколько и
горитмов сформулируют, что же им тестировав систему и побеседовав о поисковые системы. И, надо отметить,
нужно найти. Другие - наоборот, ста- морфологической обработке текстов в случае английского языка, (доста-
раются отдать на откуп алгоритмам с господином Пархоменко, идеологом точно простого и не склонного к из-
поисковика все магические преобра- и руководителем проекта, воскликну- лишней флективности, то есть измен-
зования исходного запроса и не за- ла на весь зал: «Да ведь это никому чивости слов), стеммеры успешно
думываться о том, что же там проис- не нужно! Я сама прекрасно все най- справляются с поставленной перед
ходит внутри. ду, дайте мне только оператор усече- ними задачей. Так, классический
Обе точки зрения имеют право на ния!». На беду, оператор усечения, «портеровский» алгоритм, хоть он и
существование, и я даже знаю не- как и весь традиционный набор логи- грешит сведением упоминавшейся
скольких таких профи, которые спо- ческих операторов, в языке запросов аббревиатуры DOS к формальной
собны действительно грамотно сфор- присутствовал. После получаса стуча- основе - глаголу do, тем не менее дает
мулировать логический запрос на по- ния по клавишам дама со словами: вполне корректное значение отноше-
иск нужной информации, корректно «Вы меня не убедили!», - покинула ния «сигнал/шум» в случае поиска ин-
расставив скобки и применив соответ- стенд. формации.
ствующие усечения. Однако подавля- Действительно, лицензировать Хуже обстоит дело со славянски-
ющее большинство пользователей, к систему морфологического анализа ми языками. Выделить правила, по
коим я отношу и себя, все-таки ско- за несколько тысяч долларов для ис- которым можно отсечь часть слова
рее «лентяи». пользования ее в разработке продук- справа, да так, чтобы не породить
46
программирование
сильного шума, очень сложно, и по- внутренним соображениям. Именно в ловии, что оно встретилось после
строение такого набора правил срав- силу указанных недостатков и было фрагмента -ор-.
нимо по трудоемкости с построением принято решение о разработке свое- Далее была изготовлена програм-
полноценного словарного морфологи- го алгоритма и правил стемминга. ма обработки массивов полнотексто-
ческого анализатора, чем обычно и Отмечу сразу, что мыслей разра- вой информации, которая, разбив
заканчиваются доведенные до логи- батывать вручную правила усечения текст на слова, выполняла обработку
ческого завершения разработки в русских слов не было даже изначаль- очередной потенциальной словофор-
этой области. Приведем простой при- но, но было большое желание изго- мы точным морфологическим анали-
мер - слово кровать. До сих пор все товить алгоритм, который учитывал затором; при этом неизвестные сло-
программы стемминга для русского бы и сочетаемость букв в слове на варному анализатору строки игнори-
языка успешно и совершенно логич- границе возможного усечения, и час- ровались, что является допустимой
но признавали это слово изменяю- тотность такой модели словоизмене- погрешностью, поскольку, имея базу
щимся по модели глагола, выделяя ния. Поэтому было принято решение более 150,000 основ и распознавая
или формальную основу «кр» или в строить правила стемминга автомати- более четырех миллионов различных
лучше случае, «кров». Уважаемый чи- чески, обрабатывая большие масси- форм русских слов, анализатор игно-
татель, мне кажется, по достоинству вы русских текстов. Задача сильно об- рирует менее одного процента встре-
оценит такой глагол - «я крую/кроваю, легчалась наличием русского морфо- тившихся строк, которые по большей
он кровает/круёт». логического анализатора, разрабо- части оказываются либо орфографи-
Однако за истекший год в этом танного еще в 1994 году во время ра- ческими ошибками, либо аббревиату-
направлении были сделаны серьез- боты над проектом «Пропись 4.0». рами, либо экзотическими названия-
ные шаги. Мартин Портер (Martin Анализатор этот работает и поныне в ми или именами собственными. Для
Porter) сделал доступными свои нара- поисковых системах Апорт! опознанных же словоформ выделя-
ботки в области стемминга, наборы (www.aport.ru),Рамблер лась их точная основа, то есть часть
правил и инструменты для работы с (www.rambler.ru), <META> (www.meta- слова, остающаяся неизменной при
ними, для открытого сетевого сооб- ukraine.com), хотя и пережил несколь- склонении или спряжении; выделен-
щества, опубликовав проект на ко преобразований, в результате чего ное таким способом окончание вкупе
S o u r c e F o r g e ( h t t p : / / словарь уже придирчиво выверен, а с последними двумя символами фор-
snowball.sourceforge.net/).Проект код позволяет обрабатывать до 20 - мальной основы поступало в накопи-
представляет собой специализиро- 30 тысяч слов в секунду. Подробнее с тель, который либо регистрировал
ванный язык обработки строк, пред- этим анализатором и условиями его новое правило, либо увеличивал вес
назначенный для изготовления алго- распространения можно ознакомить- уже существующего правила отщеп-
ритмов стемминга в информационном ся на странице автора (linguist.nm.ru). ления окончания.
поиске. Довольно быстро проект стал Для представления автоматичес- По завершении работы сканера
расширяться, и сейчас доступны в ких правил усечения слов была выб- текстов получившийся массив данных
исходных текстах стеммеры для анг- рана модель хранения возможного был отранжирован в соответствии с
лийского, французского, испанского, окончания с двумя предшествующи- убыванием вероятности встретить
португальского, итальянского, немец- ми буквами неизменяемой части сло- каждую из присутствующих моделей
кого, датского, шведского и норвежс- ва. Так, например, словоформа сло- словоизменения, после чего модели,
кого языков. Русский поначалу остал- варями порождает правило, разреша- вероятность реализации которых со-
ся в стороне, однако недавно появи- ющее отщепление окончания -ями ставляла менее 10-4, были отброше-
лась поддержка и для него (http:// при условии, что ему предшествует ны как редкие и потенциально опас-
snowball.sourceforge.net/russian/ последовательность -ар-. Аналогично, ные, т. е. способные породить избы-
stemmer.html). встретив словоформу морями, мы по- точный шум.
Тем не менее, по ряду причин, родим правило о возможном отщеп- Результат - набор потенциальных
часть из которых обсуждалась выше, лении того же окончания (-ями) при ус- окончаний с условиями на предше-
стеммер Snowball все равно далек от
идеала. И основная причина заклю-
чается в том, что он базируется на
обобщенных правилах, составленных
людьми, в лучшем случае - лингвис-
тами. А как известно, любое общее
правило имеет исключения, приводя-
щие в данном случае к неправильно-
му выделению основы. Еще одно на-
рекание - это «убежденность алгорит-
ма в собственной непогрешимости»:
алгоритм всегда дает один-един-
ственный вариант формальной осно-
вы слова, игнорируя все остальные по
48
ОПРЕДЕЛЕНИЕ ©1990
Графический лист из серии Художник Игорь УСКОВ
«Смыслограммы» www.igus.nm.ru
JAVA:
МАГИЯ ОТРАЖЕНИЙ
ЧАСТЬ I. ОСНОВЫ
ДАНИИЛ АЛИЕВСКИЙ
программирование
Один из самых удивительных и ярких механизмов языка но узнать списки членов класса — полей, методов, конст-
Java — технология «отражения» (Java Reflection). К сожале- рукторов, а также обратиться к этим членам. Кроме того,
нию, в популярных учебниках нелегко найти подробную ин- класс Class содержит ряд статических методов, обеспечи-
формацию об этой интереснейшей области. А тем более — вающих взаимодействие с внутренними механизмами Java,
о подводных камнях и неожиданных возможностях, возни- отвечающими за загрузку и управление классами.
кающих при программировании с использованием отраже- Как получить экземпляр Class, соответствующий дан-
ний. Между тем, именно отражения позволяют Java с непод- ному классу (или интерфейсу) — например, классу
ражаемым изяществом справляться с задачами, традици- java.io.File? Для этого есть два основных способа.
онно непростыми в других языках — такими, как создание A. Просто добавляем к имени класса суффикс «.class»,
оболочки для компиляции Java-проектов (наподобие Borland например:
JavaBuilder или NetBeans), визуальное проектирование гра-
фических компонентов (JavaBeans), сериализация объектов Class clazz= byte.class
и распределенные вычисления (RMI), и многие другие.
Мне бы хотелось предложить Вам небольшую экскур- («clazz» — сознательно искаженное от «class»: компиля-
сию по миру отражений Java. По ходу дела я буду пока- тор не позволяет использовать в качестве идентификато-
зывать, как использовать мощь этой технологии для изящ- ра зарезервированное слово «class».)
ного решения различных практических задач. B. Если мы располагаем экземпляром некоторого клас-
Мы начнем с простых вещей — простых для Java, но не са, может быть даже неизвестного в данной точке програм-
столь тривиальных в других языках. Пример такой «простой мы, можно вызвать метод getClass(), присутствующий в
вещи» — динамическое расширение вашей программы но- каждом Java-объекте (унаследованный от класса Object):
выми классами от сторонних разработчиков, не требущее
переписывания и даже перекомпиляции вашей системы. По void myFunction(Object o) {
Class clazz= o.getClass();
мере знакомства с отражениями, задачи будут усложнять- ÷òî-òî äåëàåì ñ îáüåêòîì clazz;
ся. В качестве завершающего примера, полностью исполь- }
...
зующего возможности отражений, я расскажу, как реализо- java.io.File f= new java.io.File("/tmp/1.txt");
вать высокоэффективный интерпертатор выражения (фор- myFunction(f);
...
мулы), написанного на языке Java — эквивалент оператора
eval() в скриптовых языках типа Perl или JavaScript.
Все написанное ниже относится к последней (на мо- Здесь есть любопытный нюанс. Вообще-то, примитивные
мент написания статьи) версии Java: Sun Java SDK 1.4. типы Java — boolean, char, byte, short, int, long, float, double —
обычно не считаются полноценными классами. Они не унас-
Где искать мир отражений? ледованы от Object, для них не работает наследование и т.д.
Отражения в Java — это два класса Class и Тем не менее, с ними тоже ассоциированы экземпляры Class,
ClassLoader, расположенных в пакете java.lang, и специ- которые можно получить способом A, например:
альный пакет java.lang.reflect, содержащий (в версии Java
SDK 1.4) 12 вспомогательных классов: Array, Member, Class clazz= java.io.File.class;
Constructor, Field, Method, Modifier, InvocationHandler, Proxy,
ReflectAccess, ReflectPermission, InvocationTargetException, Существует даже специальный объект void.class — он
UndeclaredThrowableExceptioCfn. используется в довольно экзотических ситуациях при вы-
Проще всего осваивать технику отражений, начиная с зове методов через отражения. Экземпляры типа Class
класса Class. Более сложные вещи потребуют применения есть также у любого массива, например:
классов из пакета java.lang.reflect, прежде всего классов,
описывающих: Constructor, Field и Method. «Высший пило- Class clazz= byte[].class
èëè
таж» работы с отражениями — это, пожалуй, создание гра- byte[] v= new byte[34]; Class clazz= v.getClass();
мотных наследников ClassLoader, позволяющих реализовать
собственную систему загрузки классов. Что же можно сделать, располагая переменной типа
В этой статье я покажу, как грамотно использовать эти Class для некоторого класса?
классы и их методы. Прежде всего, можно получить полное имя класса (ска-
В любом случае, статья не заменяет справочную до- жем, для отладочной печати) методом getName(). Например:
кументацию фирмы Sun. Самую полную и свежую фир- String.class.getName() возвращает «java.lang.String».
менную документацию можно найти в Internet по адресу: Интересно посмотреть на имена классов для прими-
http://java.sun.com/ тивных типов и для массивов:
52
программирование
ку. Все элементы массива преобразуются (стандартным изображения, обычно существуют более удобные спосо-
образом) в строки и конкатенируются через разделитель бы прочитать ресурс — например, метод getImage() клас-
separator, заданный в качестве параметра функции. Вот са java.applet.Applet. Но для текстовых файлов и файлов
текст этой функции: нестандартного формата getResourceAsStream(), как пра-
вило, — самое разумное решение.
public static String toS(Object v, String separator) { Вот пример законченного класса, использующего эту
if (v==null) return «»;
if (v.getClass().isArray()) { технику:
int len;
if ((len=java.lang.reflect.Array.getLength(v))==0) return «»;
StringBuffer result= new StringBuffer(); import java.io.*;
for (int k=0; k<len; k++) { public class MyClassWithResource {
if (k>0) result.append(separator); public static final String myTextResourceName= «mydata.txt»;
result.append(String.valueOf( public static final String myTextResource;
java.lang.reflect.Array.get(v,k))); static {
} String s= «»;
return result.toString(); try {
} InputStream stream= MyClassWithResource.class
return String.valueOf(v); .getResourceAsStream(myTextResourceName);
} if (stream==null)
throw new FileNotFoundException(myTextResourceName+» not
found»);
Если аргумент v не является массивом, действие toS StringBuffer sb= new StringBuffer(stream.available());
InputStreamReader reader= new InputStreamReader(stream);
не отличается от стандартного метода v.toString(). Если char[] buf= new char[32768];
v==null, возвращается пустая строка (обычно это удобнее int len;
while ((len=reader.read(buf,0,buf.length))>=0) {
стандартной реакции — возврата строки «null»). sb.append(buf,0,len);
Без класса Array пришлось бы написать 9 вариантов }
s= sb.toString();
такой функции — для 8 примитивных типов и для масси- } catch (IOException e) {
ва объектов произвольного типа Object[]. e.printStackTrace();
}
Здесь нужно сделать одно важное замечание. Хотя myTextResource= s;
класс Array действительно позволяет существенно эконо- }
public static void main(String[] args) {
мить текст программы и не писать разные варианты мето- System.out.println(«Loaded resource:»);
да для массивов разных типов, следует иметь в виду — System.out.println(myTextResource);
}
получаемый код сравнительно неэффективен. Скажем, }
цикл суммирования всех элементов числового массива
через вызов java.lang.reflect.Array.getDouble() будет рабо- В этом примере файл «mydata.txt» должен быть рас-
тать на порядок дольше банального: положен в том же каталоге, что и class-файл
«MyClassWithResource.class».
double s= 0.0; Файл ресурса необязательно размещать в том же ката-
for (int k=0; k<v.length; k++) s+= v[k]; логе, что и class-файл. Если он расположен в одном из под-
каталогов этого каталога, в качестве имени ресурса нужно
В случае функции toS() разница была бы непринципи- передать относительный путь, разделяя имена подкатало-
альной, так как преобразование числа в строку — срав- гов символом «/» (как это принято в Internet и Unix). Можно
нительно медленная операция. также указать в качестве имени ресурса «абсолютный»
путь, начинающийся с символа «/». Тогда Java будет ис-
Class.getResourceAsStream()- ресурсы кать ресурс во всех каталогах, перечисленных в путях по-
Один из самых очевидных примеров использования иска классов CLASSPATH — т.е. по тем же правилам, по
класса Class — загрузка ресурсов. которым отыскиваются class-файлы программы.
Ресурс в Java — это файл с данными, прилагаемый к Может возникнуть вопрос — зачем нужен специаль-
Вашей программе и обычно размещаемый «рядом» с ный метод класса Class, когда можно прочитать файл ре-
class-файлами. В графических приложениях и апплетах сурса обычными средствами файлового ввода/вывода?
это чаще всего изображения (jpg- или gif-файлы), но с Основная причина — использование метода
таким же успехом это может быть и файл специального getResourceAsStream() является гораздо более общим ре-
формата — например, содержащий справочные таблицы шением, работающим в большем числе ситуаций.
или какие-либо ваши объекты. Например, по традиции, законченные наборы классов —
Наиболее общий способ прочитать файл-ресурс произ- Java-приложения или библиотеки — принято упаковывать в
вольного формата, расположенный «рядом» с некоторым архивы JAR и устанавливать на компьютер именно в таком
классом — обратиться к методу getResourceAsStream() виде. Классы Java прекрасно загружаются непосредствен-
объекта Class, соответствующего данному классу. В ка- но из архива JAR, без предварительной распаковки. То же
честве параметра этому методу нужно передать путь к фай- самое относится и к ресурсам, загружаемым методом
лу ресурса относительно каталога, в котором размещен ваш getResourceAsStream() — или более специальными метода-
класс. В качестве результата getResourceAsStream() вернет ми типа java.applet.Applet.getImage(). В то же время, обыч-
объект InputStream, с помощью которого можно прочитать ные средства файлового ввода/вывода для чтения ресурса
файл ресурса стандартными средствами ввода/вывода Java. из JAR уже непригодны — нужно использовать специаль-
Для наиболее популярных типов ресурсов, таких как ные классы для анализа и чтения JAR-файлов.
54
программирование
са должен существовать пустой конструктор (без аргумен- (заранее неизвестный) класс и создать его экземпляр. Можно
тов), либо — что по существу то же самое — не должно получить полный список всех конструкторов, полей и мето-
быть описано вообще никаких конструкторов. В противном дов класса и обратиться к любому из них, передав (в случае
случае будет возбуждено исключение InstantiationException. конструктора или метода) список всех параметров. Для это-
Конечно, этого еще мало, чтобы работать с полученным го служат следующие методы класса Class:
объектом. Если вы не знаете, что умеет делать класс — ка-
кие у него есть методы, что они ожидают получить на входе public Constructor[] getConstructors(),
public Field[] getFields(),
и для чего они предназначены — вы не сможете извлечь из public Method[] getMethods(),
него ничего полезного. Для формального определения, что public Constructor[] getDeclaredConstructors(),
public Field[] getDeclaredFields(),
«умеет» класс, в Java существует стандартный механизм — public Method[] getDeclaredMethods()
интерфейсы. Остается просто применить этот механизм.
Например, предположим, ваша программа должна в Перечисленные методы возвращают массивы объек-
некоторые моменты выполнять перевод с одного языка тов типа Constructor, Field и Method. Эти классы содер-
на другой. Формально это можно описать интерфейсом: жатся в пакете java.lang.reflect и обеспечивают исчерпы-
вающий доступ к полям, конструкторам и методам.
public interface LanguageTranslator { Сразу бросается в глаза наличие двух версий методов:
public String translate(String source,
String sourceLanguage, getXXX и getDeclaredXXX (где XXX — «Constructors»,
String targetLanguage); «Fields» или «Methods»). Поначалу это может даже несколь-
// ïåðåâîäèò òåêñò source ñ ÿçûêà sourceLanguage
// íà ÿçûê targetLanguage ко сбить с толку — какой версией следует пользоваться?
} getDeclaredXXX возвращает список членов класса (кон-
структоров, полей или методов), объявленных при описа-
Пусть Ваша программа сама по себе не умеет выпол- нии класса, но не унаследованных от классов-предков. При
нять перевод, но ее можно расширить классами сторон- этом в список включаются все члены, независимо от их
них разработчиков, которые эту задачу решать умеют. Все уровня защиты — т.е. public, protected, private и друже-
эти классы реализуют интерфейс LanguageTranslator и ственные члены.
имеют конструктор без параметров (либо лишены конст- getXXX возвращает полный список членов, объявленных
руктора). В настройках Вашей программы пользователь в самом классе либо унаследованных от одного из предков.
указывает имя такого класса, независимо инсталлирован- Но в этот список уже попадают только public-члены.
ного в систему (или выбирает из списка классов), после При желании, конечно, можно получить и максимально
чего для выполнения перевода ваша программа исполь- полную информацию — список всех членов, объявленных
зует следующие операторы: в самом классе либо в любом из его предков. Для этого
достаточно организовать цикл по цепочке классов-пред-
String source= «òåêñò, òðåáóþùèé ïåðåâîäà»; ков, пользуясь специальным методом Class.getSuperclass().
String sourceLanguage= «Russian»;
String targetLanguage= «English»; Кроме получения полного списка, можно также отыс-
Class clazz= Class.forName(«ïîëíîå_èìÿ_êëàññà_ïåðåâîä÷èêà»); кать в классе конкретный член. Для этого служат методы:
Object object= clazz.newInstance();
if (!(object instanceof LanguageTranslator)) {
throw new Exception(«...»); public Constructor getConstructor(Class[] parameterTypes),
// ñîîáùàåì îá îøèáêå: óêàçàííûé êëàññ public Field getField(String name),
// íå ðåàëèçóåò òðåáóåìûé èíòåðôåéñ, public Method getMethod(String name, Class[]
// ò.å. íå ÿâëÿåòñÿ ïåðåâîä÷èêîì parameterTypes),
} public Constructor getDeclaredConstructor(Class[]
String result= ((LanguageTranslator)object) parameterTypes),
.translate(source,sourceLanguage,targetLanguage); public Field getDeclaredField(String name),
public Method getDeclaredMethod(String name, Class[]
parameterTypes)
Описанная техника может оказаться очень полезной
практически в любой достаточно большой и серьезной си- (Собственно, чаще используются как раз эти методы,
стеме, рассчитанной на разработку многими участника- а не описанные выше методы получения списков.)
ми. Многие компоненты таких систем являются достаточ- Аргумент name в этих методах должен содержать имя
но изолированными, и их набор может быть совершенно требуемого члена. Аргумент parameterTypes связан с воз-
неизвестен на этапе компиляции основной программы — можностью Java перегружать конструкторы и методы —
известны лишь интерфейсы, который они обязуются реа- определять несколько конструкторов, либо несколько ме-
лизовывать. Например, так обычно строятся системы тодов с одинаковым именем, отличающихся только типа-
plugin’ов — модулей, добавляемых к уже работающей си- ми параметров. (В случае конструкторов это единствен-
стеме. В подобных случаях механизм отражений — мето- ный способ создать много конструкторов класса.) В каче-
ды Class.forName() и Class.newInstance() — становится стве parameterTypes нужно отдать массив объектов типа
единственным грамотным решением. Class, соответствующих типам всех параметров конструк-
тора или метода.
Constructor, Field, Method — работа с Разница между вариантами getXXX и getDeclaredXXX
классами через отражения здесь та же самая, что и в случае методов получения
На самом деле технология отражений позволяет сделать списков.
гораздо больше, чем просто загрузить по имени некоторый Здесь я бы порекомендовал написать небольшой тест,
56
программирование
Обход защиты Java Приведем два примера. Во-первых, в Java поддержива-
В очень многих учебниках по Java подчеркивается, что ется механизм сериализации. Достаточно реализовать в
модификаторы protected и private вместе с «дружествен- вашем классе пустой интерфейс-индикатор
ным» уровнем доступа (отсутствие модификаторов) по- java.io.Serializable, и появляется возможность полностью (т.е.
зволяют обеспечить «100-процентную защиту» ваших по- со всеми полями и вложенными объектами) записать этот
лей и методов от использования посторонними класса- объект в поток java.io.ObjectOutputStream и впоследствии
ми. Например, вы никогда не сможете добраться до поля прочитать из потока java.io.ObjectInputStream.
Те, кто изучал механизм сериализации Java, согласят-
private char value[];
ся — во многом этот механизм напоминает черную магию.
объявленного в исходном коде класса String и представ- Каким-то образом классы java.io.ObjectInputStream и
ляющего реальное содержимое строки. java.io.ObjectOutputStream, без всяких дополнительных под-
На самом деле все это не так. Смотрите, как можно сказок со стороны разработчика класса, «догадываются»,
добраться до этого самого поля и «нелегально» изменить как записать или прочитать все поля объекта, включая
строку — вопреки известному утверждению, что тип String private-поля. Более того, для «подсказки», когда она все
является абсолютно неизменяемым: же требуется, используются private-методы writeObject() и
readObject() — классы java.io.ObjectOutputStream и
import java.lang.reflect.*; java.io.ObjectInputStream каким-то образом обнаруживают
public class HackString {
public static void main(String[] args) throws Exception { и вызывают эти методы.
String s= «Hello!»; Конечно же, в действительности эта «черная магия» —
System.out.println(s);
Field f= s.getClass().getDeclaredField(«value»); не что иное, как магия отражений. Описанные выше техно-
// Èìåííî getDeclaredField, à íå getField: логии, в том числе метод setAccessible(), в принципе, позво-
// ïîñëåäíèé ìåòîä ïðîñòî íå íàøåë áû ñêðûòîãî ïîëÿ
f.setAccessible(true); ляют даже разработать свою собственную схему сериали-
char[] value= (char[])f.get(s); зации, отличную отстандартной, предлагаемой фирмой Sun.
value[5]= ?;
System.out.println(s); Второй пример — технология RMI. Это чрезвычайно
} мощный механизм, позволяющий распределять вычисле-
}
ния по сети — так, чтобы с точки зрения кода Java вызов
Здесь «магический» метод — setAccessible(). Этот ме- метода выглядел, как обычно, а на самом деле этот ме-
тод (и симметричный getAccessible()) имеется у всех клас- тод отрабатывался на другом компьютере. Здесь тоже не
сов Constructor, Field, Method и предназначен специально обойтись без технологий отражения. Только они позволя-
для того, чтобы отключить стандартную проверку моди- ют динамически превратить объект (со всеми своими по-
фикаторов, осуществляемую Java-машиной. лями) в поток данных, передать его по сети, реконструи-
(Естественно, все это сработает только при условии, ровать объект на другом компьютере и вызвать нужный
что в вашей версии Sun Java SDK реализация класса String метод — и все это скрыто от пользователя класса.
точно так же основана на private-поле «char value[]». Так Конечно, все это не повод, чтобы использовать отра-
как это поле скрытое, фирма Sun вправе в любой момент жения не по назначению для «взлома» защиты Java. От-
переименовать его или вообще заменить чем-нибудь дру- ражения следует использовать только тогда, когда без это-
гим.) Спрашивается — зачем же это сделано? И разве го нельзя обойтись — иначе вы потеряете все преимуще-
это не является брешью в системе безопасности? ства, которые дает идеология объектно-ориентированно-
Что до второго вопроса — разумеется, метод го программирования.
setAccessible() контролируется менеджером безопаснос-
ти Java (так же как, например, работа с файлами), и ни- Заключение
какая мало-мальски защищенная Java-система не позво- Я постарался описать самые, на мой взгляд, важные и
лит злоупотребить подобной возможностью. интересные аспекты технологии отражений. Статья — не
А чтобы понять, зачем это нужно, взгляните на любую справочник и не учебник. Многие вещи «остались за бор-
среду разработки Java-проектов — скажем, NetBeans или том». Не все методы классов были описаны; некоторые спе-
JavaBuilder. Традиционная возможность подобных сред — цифичные классы, такие как java.lang.reflect.Proxy, я вооб-
показать все поля и методы некоторого класса, напри- ще не рассматривал. Чтобы получить полную и точную ин-
мер, визуальной компоненты — в том числе и скрытые, а формацию, всегда лучше обращаться к первоисточнику —
в некоторых случаях — дать возможность отредактиро- документации фирмы Sun. Кроме сайта http://java.sun.com,
вать значения полей. Язык Java уникален в том отноше- документацию почти всегда можно найти в комплекте по-
нии, что подобные действия можно легко выполнить со- ставки Java или извлечь из комментариев к исходным тек-
вершенно законными средствами самого языка, не при- стам фирмы Sun.
бегая, скажем, к анализу исходного текста программы. Я также хотел бы порекомендовать книгу: «Язык Про-
На самом деле неограниченный доступ ко всем конст- граммирования Java», К.Арнолд, Дж.Гослинг, Д.Холмс, Из-
рукторам, полям и методам даже гораздо более ценен. дательский дом «Вильямс», Москва — С.-Петербург —
Этот механизм мира отражений дает возможность удоб- Киев, 2001. Это наиболее грамотная из попадавшихся мне
но и естественно реализовать чрезвычайно мощные тех- книг на русском языке. Она написана сотрудниками фир-
нологии, нереализуемые (или крайне сложно реализуе- мы Sun, участвовавшими в разработке технологии Java —
мые) другими способами. т.е. в некотором роде является первоисточником.
Эта статья – первая в серии, адресованной читателям, де- (взаимодействия, обмена данными, если угодно) между
лающим первые шаги в программировании на ColdFusion, Web-сервером и прикладными программами, выполняющи-
а также тем, кто все еще не определился с выбором ми ту или иную задачу. По существу, написанные вами CGI
средств, позволяющих создавать динамические сайты, уп- программы расширяют возможности Web-сервера, допол-
равляемые данными. няя его нужной вам функциональностью. Отсюда, собствен-
Сколько раз вам приходилось слышать или самим за- но и второе название CGI программ – серверные расшире-
давать вопросы типа “как я могу сохранить информацию ния. В принципе, CGI программа может быть написана на
из HTML-форм на своих Web-страницах?” или “как мне сде- любом языке: C/C++, Perl, TCL, Visual Basic, Clipper, Fortran.
лать счетчик посещений?” или, наконец, “как мне защитить Все зависит от того, какая у вас система и в какой среде
код своих Web-страниц от всеобщего обозрения?” В самом программирования вы чувствуете себя более комфортно.
языке HTML нет никаких простых способов обработки дан- Главное, чтобы ваша программа обеспечивала средства
ных HTML-форм. Броузер может лишь собрать информа- общения с Web-сервером, или, говоря иначе, удовлетворя-
цию из форм и передать ее на Web-сервер. Обработка ин- ла стандарту CGI. Естественно, если вы пишите на С, то
формации может быть возложена на CGI серверные рас- перед запуском вам нужно скомпилировать программу.
ширения. Одно название чего стоит! А ведь их еще нужно Если же вы используете один из языков-сценариев типа
написать и отладить своими руками, потратив немало вре- Perl, TCL или Unix shell, то все, что вам надо сделать перед
мени на изучение различных стандартов и протоколов! Бе- запуском, это поместить файлы в каталог /cgi-bin, где по
зусловно, это полезное, с точки зрения общего развития, умолчанию их будет искать Web-сервер. В чем же недоста-
занятие. Кто из нас не проходил на первых курсах институ- ток CGI программ? Во-первых, не каждый специалист по
та сопромат или теорию машин и механизмов, с тем, что- электронной торговле или Web-дизайнер знает С или Visual
бы позже получить диплом программиста или специалиста Basic. Во-вторых, CGI программы слишком расточительны
по микропроцессорам?! Так ли уж это было необходимо? по отношению к системным ресурсам. При каждом обра-
Пара слов пояснений для тех, кто не совсем в курсе. щении на вашу страницу и, соответственно, при каждом
Хотя бы для того, чтобы понять от чего Вас может уберечь запуске CGI программы, система порождает новый поток,
ColdFusion. выделяя для него в оперативной памяти компьютера но-
CGI, или Common Gateway Interface, - это стандартный вое пространство. И если у вашего сайта много посетите-
шлюзовый интерфейс. Проще говоря – это некоторый стан- лей (а ведь именно для этого вы и создаете сайт), то легко
дарт или набор правил, определяющий порядок общения может сложиться ситуация, когда в памяти сервера одно-
программирование
временно будет находиться много копий одной и той же название ColdFusion – сервер Web-приложений, но в зави-
CGI программы, что, в свою очередь, очень быстро исчер- симости от того, как вы решите его использовать, он мо-
пает всю оперативную. Наконец, при создании CGI про- жет быть средством разработки Web-страниц, сервером баз
грамм немало усилий будет затрачено на программирова- данных или вашим счастливым билетом в благополучную
ние рутинных задач ввода/вывода, вместо того чтобы на- жизнь. От версии к версии ColdFusion предлагал все боль-
править в созидательное русло решения прикладных за- ше возможностей. Версия 1.5 в 1996 году содержала всего
дач сайта. лишь 35 тегов, обеспечивавших простейшие функции дос-
Однако вернемся к теме статьи... тупа к базам данных и поддержки электронной почты. Се-
Вначале немного истории. В далеком (по меркам Сети) годня 5-я версия ColdFusion предоставляет более 80 тегов
1995 году два брата Дж.Дж. И Джереми Эллейр (J.J. И и 255 функций для решения практически любой задачи,
Jeremy Allaire) в США (ну а где же еще?) основали новую которая может возникнуть в Web-программировании.
компанию «Allaire Corporation» для продвижения первого в ColdFusion позволяет начать создание нового приложе-
мире сервера Web-приложений, который они назвали ния на основе прочного фундамента развитого и полнос-
ColdFusion. Одной из причин создания ColdFusion как раз тью ориентированного на Web-среду языка программиро-
и была сложность создания сайтов, управляемых данными вания, обеспеченного серьезной поддержкой солидной ком-
с помощью CGI программ. Перед одним из братьев – Дже- пании (Macromedia), ее бизнес - партнерами и тысячами
реми – стояла задача периодического обновления элект- разработчиков, публикующих свои решения на специаль-
ронной версии издававшегося в печатном виде журнала. ном Web-ресурсе под названием Developers exchange. Этот
Занятие это было крайне утомительным, и Джереми обра- ресурс настолько богат, что прежде, чем приступать к раз-
тился к своему брату-программисту с просьбой написать работке решения какой–бы то ни было задачи, имеет смысл
для него какое-нибудь приложение, которое избавило бы заглянуть сюда. Очень часто здесь можно найти совершен-
его от излишней траты времени и сил, и позволило бы ему но бесплатно готовое решение.
сосредоточиться на основной задаче – собственно, обнов- Конечно, на рынке существует много других техноло-
лению электронной версии журнала. Когда проект был за- гий, которые вы можете использовать для создания дина-
вершен, оба брата осознали, что они испекли горячий пи- мических Web-приложений. Диапазон их достаточно ши-
рожок, который наверняка многим придется по вкусу. Не- рок: от “open source” технологий, таких как Perl и PHP, до
долго думая, братья основали новую компанию и, не мудр- коммерческих Java Server Pages (JSP) или Microsoft Active
ствуя лукаво, дали ей свою фамилию. Вложив в свое дети- Server Pages (ASP). При таком богатстве выбора, что нас
ще 18 тысяч долларов личных сбережений, шестью года- может побудить использовать ColdFusion, который, кстати
ми позже, в 2001 году, братья Эллейр продали его корпо- сказать, является коммерческим и весьма недешевым про-
рации Macromedia более чем за 360 миллионов долларов. дуктом. Его цена больше $1,000. Но пусть вас это не сму-
У вас еще осталось желание писать низкоуровневые про- щает. Во-первых, его покупают, как правило, не частные
цедуры ввода/вывода? лица, а фирмы. А во-вторых, практика показывает, что сто-
Что же представляет собой этот чудесный продукт, ко- имость конечного продукта или, говоря другими словами,
торый принес своим создателям такую прибыль? Безус- “стоимость владения” (Total Cost of Ownership), включаю-
ловно, вам знакомы термины hardware и software. Так вот, щая, помимо цены инструментальных средств, стоимость
ColdFusion – это middleware. Термином middleware называ- разработки алгоритмов, кодирования и отладки, часто ока-
ют программное обеспечение, осуществляющее некоторые зывается ниже, чем стоимость приложения, разработанно-
преобразования. В самом общем смысле сервер приложе- го с помощью “бесплатных” средств. Деньги, вложенные в
ний ColdFusion является посредником, преобразующим ваш ColdFusion окупаются очень быстро.
код, написанный на языке высокого уровня, называемом Одной из главных причин, побуждающих, выбирать
CFML (ColdFusion Markup Language) в теги HTML-докумен- ColdFusion в качестве рабочего инструмента является лег-
та, который может отобразить Web-броузер. Официальное кость разработки. В отличие от большинства упоминавших-
программирование
ся технологий, вам не нужно быть гуру программирования Вот лишь несколько из них: работа с почтой, встроенные
для того, чтобы начать работу с ColdFusion и успешно за- HTTP, POP и FTP клиенты, встроенный поисковый меха-
вершить свой первый проект, который приятно удивит ва- низм. Это ни в коем случае не агитация в пользу ColdFusion,
шего шефа. Эта простота использования отнюдь не озна- просто объективная попытка познакомить с малоизвест-
чает отсутствия мощи и функциональной гибкости. Просто ным в России пакетом.
благодаря усилиям программистов из Allaire, а теперь и Технология ASP, в свою очередь, также имеет преиму-
Macromedia, многие сложные вещи происходят за сценой. щества. Но это уже тема другой статьи.
ColdFusion упрощает решение большинства задач, таких За названием ColdFusion на самом деле скрываются два
как обработка данных форм или выполнение запросов баз понятия: собственно сервер Web-приложений ColdFusion и
данных. Однако когда у вас возникает нужда выполнения язык программирования ColdFusion, называемый CFML
более сложных операций, ColdFusion предоставляет вам (ColdFusion Markup Language). Файлы приложения
такие возможности. В компаниях, использующих ColdFusion имеют расширение .cfm и называются шабло-
ColdFusion, сложные задачи, сборку всего приложения и нами (templates). Шаблоны ColdFusion наряду с тегами и
его отладку осуществляет, как правило, действительно функциями CFML могут содержать обычные HTML-теги и
классный высокооплачиваемый специалист, тогда как про- встроенные JavaScript и/или VBScript сценарии. CFML часть
стые операции возлагаются на новичков, которые еще толь- шаблона обрабатывается сервером приложений, в резуль-
ко учатся программированию. тате чего динамически генерируется часть выходной стра-
Другим важным достоинством ColdFusion является на- ницы основанная на данных формы, базы данных и так
личие версий для всех популярных систем и Web-серве- далее, которая позже объединяется со статической его
ров. Неважно, на чем вы работаете: Windows 95/98/NT/2000, частью, представленной HTML-тегами и сценариями
Solaris, Linux или HP-UX. ColdFuison совместим с большин- JavaScript/VBScript в единый выходной HTML-документ, пе-
ством известных Web-серверов: Netscape Enterprise и редаваемый Web-серверу.
iPlanet, Microsoft IIS и PWS, O’Reilly Website, Apache. Вы Рассмотрим, как ColdFusion обрабатывает пользова-
можете переносить ColdFusion приложения с платформы тельские запросы.
на платформу и легко переключаться между различными 1. Web-броузер направляет запрос к Web-серверу с
системами управления базами данных. требованием открыть файл ColdFusion. Эти файлы имеют
Наиболее близким конкурентом ColdFusion является расширение .cfm.
технология ASP. Какими, качествами кроме межплатфор- 2. Получив запрос, Web-сервер перенаправляет его
менной совместимости, может еще похвастать ColdFusion? серверу приложений ColdFusion.
Легкость и простота. Языком ASP является VBScript – под- 3. Сервер приложений анализирует шаблон и выпол-
множество Visual Basic, который сложнее ColdFusion. Срав- няет действия, предписанные встретившимися тегами и
ним, например, два фрагмента кода. Вначале на ASP функциями CFML, взаимодействуя, если надо, с другими
(VBScript): службами и приложениями, например источниками данных
или почтовым сервером. В результате динамически созда-
1. <% ется часть результирующей HTML страницы.
2. Dim RandomFraction
3. Randomize 4. Далее сервер приложений собирает воедино только
4. RandomFraction = Rnd что созданную динамическую часть страницы со статичес-
5. Response.Write(RandomFraction)
6. %> кой частью исходного шаблона и возвращает результиру-
ющую страницу Web-серверу.
Теперь то же самое на ColdFusion: 5. Web-сервер отправляет полученную от сервера
ColdFusion страницу на пославшую запрос клиентскую ма-
1. <cfset RandomFraction = Rand()> шину.
2. <cfoutput>#RandomFraction#</cfoutput>
В заключение приведем полезные ссылки, а также при-
Что проще – решать вам. меры сайтов, построенных с использованием ColdFusion.
При использовании ASP одной распространенной про-
блемой является необходимость закрывать базы данных 1. Îôèöèàëüíàÿ ñòðàíèöà îïèñàíèÿ ñòàíäàðòà CGI
http://www.w3.org/CGI/
после окончания работы с ними. Часто программисты за-
бывают это делать. Конечно, если все делать без ошибок, 2. Äîêóìåíòàöèÿ è ïðèìåðû CGI ïðîãðàìì
http://hoohoo.ncsa.uiuc.edu/cgi/
эта проблема не возникает.
Но покажите мне программиста, который пишет без 3. Ïðîãðàììíûå ïðîäóêòû Macromedia - íûíåøíåãî âëàäåëüöà
ColdFusion.
ошибок. Подобная забывчивость приводит к тому, что про- Îòñþäà æå ìîæíî ñêà÷àòü ïðîáíûå (trial)âåðñèè
странство памяти, занимаемое объектом базы данных, не http://www.macromedia.com/software/
освобождается. Страницы с таким кодом, обращение к ко- 4. Developer's exchange. Êîëëåêöèÿ ãîòîâûõ ðåøåíèé íà ColdFusion
торым происходит несколько раз в минуту, весьма интен- http://devex.macromedia.com/developer/gallery/index.cfm
сивно расходуют оперативную память, что очень скоро 5. ColdFusion ôîðóìû
может привести к зависанию сервера. ColdFusion отсле- http://webforums.macromedia.com/coldfusion/
живает подобные ситуации автоматически. В части функ- 7. On-line äîêóìåíòàöèÿ ïî ColdFusion
циональных возможностей (без привлечения продуктов сто- http://www.macromedia.com/support/coldfusion/documentation.html
ронних фирм) ColdFusion также дает некоторую фору ASP.
60
программирование
программирование
Недавно я занимался разработкой утилитки, позволяющей запускать с сервера по сети некоторые
программы на определённое время. При этом обмен происходил через UDP-сокеты. Для написания
клиентской части необходимы были требования, чтобы она работала под управлением Windows
2000, и обычный непривилегированный пользователь не мог выключить или включить её.
ПРОГРАММИРОВАНИЕ
СЕРВИСОВ
В WINDOWS 2000 ВСЕВОЛОД СТАХОВ
62
программирование
Для этой цели идеально подходят сервисы — слу- функции открытия базы данных сервисов:
жебные программы, выполняющиеся в фоновом режи-
ме и без возможности завершения процесса через дис- SC_HANDLE OpenSCManager (const char *MachineName, const char*
петчер задач. Для управления сервисами используется DatabaseName, DWORD Desired Access);
админис тративный компонент Windows NT —
services.msc (находится в папке «Администрирование» Функция возвращает дескриптор базы данных серви-
панели управления). Как сервисы организовано множе- сов с именем DatabaseName, если данный параметр ра-
ство системных служб Windows, таких как сетевые кли- вен NULL, то используется база данных по умолчанию (для
енты и серверы, утилиты управления оборудованием этой же цели можно использовать константу
(пресловутый Plug and Play), а также драйверы ядра. SERVICES_ACTIVE_DATABASE) на компьютере
Из компонента управления сервисами можно изменять MachineName или на локальном компьютере, если дан-
режим работы сервисов. Сервис характеризуется со- ный параметр NULL. Параметр DesiredAccess определя-
стоянием: запущен, остановлен, приостановлен. Для ет режим доступа к файлу. Обычно используются констан-
управления сервисами используются соответствующие ты GENERIC_READ, для чтения GENERIC_WRITE для со-
кнопки: запустить, остановить, приостановить (доступ- здания новых сервисов или изменения параметров ста-
но лишь для некоторых сервисов), перезапустить. Мож- рых и GENERIC_EXECUTE разрешение на выполнение
но сделать, чтобы некоторые сервисы запускались при сервисов. При ошибке возвращается NULL, иначе — дес-
запуске компьютера. Для этого существует три режи- криптор базы данных.
ма запуска сервиса: автоматический (auto) — сервис Далее происходит регистрация сервиса функцией
запускается при входе в систему вручную, (manual) — CreateService, которая возвращает дескриптор сервиса
сервис запускается по требованию пользователя или для использования в данном процессе:
системы, отключено (disabled) — сервис вообще не бу-
дет запускаться. SC_HANDLE CreateService(
Для изменения режима запуска откройте диалог SC_HANDLE hSCManager,
свойств сервиса и на вкладке «Общие» выберите нуж- LPCTSTR lpServiceName,
LPCTSTR lpDisplayName,
ный режим. На данной вкладке также показано имя и DWORD dwDesiredAccess,
описание сервиса (их можно изменить), а также путь к DWORD dwServiceType,
DWORD dwStartType,
исполняемому файлу сервиса. Кроме того, можно из- DWORD dwErrorControl,
менять и другие параметры сервиса. Для этого смотри- LPCTSTR lpBinaryPathName,
LPCTSTR lpLoadOrderGroup,
те встроенную справку Windows. При любых манипуля- LPDWORD lpdwTagId,
циях с сервисами учтите, что изменение базы данных LPCTSTR lpDependencies,
LPCTSTR lpServiceStartName,
сервисов доступно только администраторам. Кроме это- LPCTSTR lpPassword
го, возможна модификация сервисов на членах NT до-
);
мена через MMC (Microsoft Management Console —
mmc.exe) пользователем, имеющим права администра-
тора домена. Итак, поподробнее о параметрах, так как я не думаю,
Создание сервиса в ОС Windows — задача нетриви- что их названия говорят сами за себя.
альная. Например, создание демона в ОС Unix намно- SC_HANDLE hSCManager — дескриптор базы дан-
го проще, хотя, я думаю, система сервисов лучше про- ных сервисов, полученный функцией OpenSCManager.
думана и более централизована. Для создания нового LPCTSTR lpServiceName — строка (до 256 символов),
сервиса, прежде всего, его нужно зарегистрировать в реальное имя сервиса в базе данных.
базе данных сервисов. Для этого открывается база дан- LPCTSTR lpDisplayName — данный параметр — имя
ных сервисов функцией OpenSCManager для записи-со- сервиса, которое показывается в инструменте управ-
здания, далее добавляется сам сервис функцией ления сервисами.
CreateService. После этого система может запустить DWORD dwDesiredAccess — флаг доступа к серви-
приложение, зарегистрировавшее себя сервисом, но за- су. Может принимать любые значения доступа.
пуск идёт несколько необычным образом: запускается Обычно используются константы GENERIC_READ,
не WinMain, а ServiceMain, которая определяет обра- GENERIC_WRITE, GENERIC_EXECUTE, а также значе-
ботчики событий сервиса (таких как запуск, пауза, ос- ние SERVICE_ALL_ACCESS для предоставления полно-
тановка) функцией RegisterServiceCtrlHandler, устанав- го доступа к сервису.
ливает текущее состояние сервиса SetServiceStatus и DWORD dwServiceType — флаг типа сервиса, то есть
выполняет функцию StartService для каждого зарегист- то, как он будет выполняться системой.
рированного сервиса (их может быть несколько). Не- Возможные значения:
много сложновато, не так ли? Но реально создать сер- SERVICE_WIN32_OWN_PROCESS — сервис суще-
вис ещё сложнее, так как данные функции принимают ствует в виде отдельного процесса;
очень много параметров, например функция SERVICE_WIN32_SHARE_PROCESS — сервис раз-
CreateProcess принимает аж 13 (!) параметров. Но я всё деляет процесс под названием services с другими сер-
же попытаюсь вкратце рассказать о каждой функции и висами;
приведу конкретный пример сервиса. Итак, начнём с SERVICE_WIN32_KERNEL_DRIVER — сервис явля-
64
программирование
Äîïóñòèìûå êîíñòàíòû:
}
if(argc == 2){ // Ïåðåäàí îäèí ïàðàìåòð SERVICE_ACCEPT_STOP - ñåðâèñ ìîæåò áûòü îñòàíîâëåí;
if(strcmp(argv[1], -i))
install_service(); // Óñòàíîâêà ñåðâèñà åñëè àð- SERVICE_ACCEPT_PAUSE_CONTINUE - ñåðâèñ ìîæåò áûòü ïîñòàâëåí
ãóìåíò -i è ñíÿò ñ ïàóçû;
if(strcmp(argv[1], -u)) SERVICE_ACCEPT_SHUTDOWN - ñåðâèñ áóäåò îïîâåù¸í ïðè âûõîäå
uninstall_service(); // Óäàëåíèå ñåðâèñà åñëè àð- èç ñèñòåìû.
ãóìåíò -u
} DWORD dwWin32ExitCode; ýòîò ïàðàìåòð ñîîáùàåò ñèñòåìå
else{ çíà÷åíèå, êîòîðîå âîçâðàùàåò ñåðâèñ ïðè îøèáêå, ïîäðîáíåå îøèáêà
write_to_log(Bad usage); îïðåäåëÿåòñÿ ñëåäóþùèì ïàðàìåòðîì.
return -1; DWORD dwServiceSpecificExitCode; êîíêðåòíàÿ îøèáêà, ïðî-
} èçîøåäøàÿ â ñåðâèñå.
return 0; DWORD dwCheckPoint; à ýòî ïîëîæåíèå ïðîãðåññ-áàðà ïðè
çàïóñêå-îñòàíîâêå ñåðâèñà, èñïîëüçóåòñÿ äëÿ âèçóàëèçàöèè ïðî-
} öåññà çàïóñêà ñåðâèñà.
DWORD dwWaitHint; âðåìÿ â ìèëëèñåêóíäàõ, êîòîðîå æä¸ò
âûçûâàþùàÿ ïðîãðàììà äî èçìåíåíèÿ ëèáî òåêóùåãî ñòàòóñà, ëèáî
dwCheckPoint. Åñëè ýòîãî íå ñëó÷èëîñü, òî ñ÷èòàåòñÿ, ÷òî çà-
В принципе, всё не так уж и сложно, хотя я кое-чего ïóñê ñåðâèñà áûë íåóäà÷åí. Åñëè äàííîå çíà÷åíèå íîëü, òî óáè-
не рассказал. Во-первых, функция OpenService служит åíèÿ íå ïðîèñõîäèò.
для загрузки сервиса в память. Функция принимает три
параметра: дескриптор базы сервисов, имя сервиса и тип };
доступа – тут всё понятно. Для удаления сервиса исполь-
зуется функция DeleteService(SC_HANDLE sh), которая Итак, обычно вначале устанавливается значение ста-
возвращает ноль в случае ошибки. При использовании туса SERVICE_START_PENDING, затем устанавливает-
данной функции учтите, что при открытии сервиса фун- ся обработчик сообщений, инициализация сервиса и
кцией OpenService, вы должны указать в правах досту- только после этого статус сервиса устанавливается в
па единственный флаг DELETE для удаления его из базы. SERVICE_RUNNING. При данных действиях не забудьте
Для запуска самого сервиса используется функция корректно установить dwWaitHint, иначе система сочтёт,
StartServiceCtrlDispatcher(LPSERVICE_TABLE_ENTRY что ваш сервис не успел запуститься, и замочит его без
lpServiceStartTable). Функция принимает единственный сожаления. Для регистрации обработчика событий ис-
аргумент — массив строк, содержащий две строки — имя пользуется функция SERVICE_STATUS_HANDLE
сервиса и имя функции-обработчика, заканчивается спи- RegisterServiceCtrlHandler(LPCTSTR service_name,
сок двумя пустыми строками. После этого начинается LPHANDLER_FUNCTION handler_function) — первый па-
обработка функции сервиса ServiceMain. раметр — имя сервиса, второй — указатель на функ-
Итак, начало самого интересного — написание фун- цию-обработчик, данная функция возвращает дескрип-
кции ServiceMain. Данная функция служит для запуска, тор состояния сервиса для функции SetServiceStatus или
инициализации и изменения статуса сервиса. Поведе- NULL в случае ошибки. Для установки текущего состоя-
ние данной функции строго регламентировано: во-пер- ния сервиса используется функция SetServiceStatus
вых, она должна заполнить поля струк т уры (SERVICE_STATUS_HANDLE ssh, LPSERVICE_STATUS
SERVICE_STATUS значениями параметров данного сер- status) — первый параметр — дескриптор состояния, а
виса; во-вторых — зарегистрировать обработчик собы- второй — указатель на структуру статуса. После этого
тий сервиса функцией RegisterServiceCtrlHandler; и, в- приведу простенький пример главной функции:
третьих — выполнить действия по инициализации сер-
виса и ус тановить сос тояние сервиса функцией void MyServiceStart (DWORD argc, LPTSTR *argv)
{
SetServiceStatus. Итак, обо всём по порядку. Думаю, от- DWORD status;
дельного описания заслу живает струк т ура DWORD specificError;
SERVICE_STATUS MyServiceStatus; //Ýòà òà ñàìàÿ
SERVICE_STATUS: ñòðóêòóðà ñòàòóñà
// À âîò ìû å¸ çàïîëíÿåì
MyServiceStatus.dwServiceType =
struct SERVICE_STATUS { SERVICE_WIN32_OWN_PROCESS;
DWORD dwServiceType; ýòî ïîëå îçíà÷àåò òî æå, ÷òî è â MyServiceStatus.dwCurrentState =
ôóíêöèè CreateService, ò.å. òèï ïðèëîæåíèÿ ñåðâèñà(îòäåëüíûé, SERVICE_START_PENDING;
äðàéâåð ÿäðà, äðàéâåð ÔÑ). MyServiceStatus.dwControlsAccepted =
DWORD dwCurrentState; à âîò ýòî ñïåöèôè÷åñêîå ïîëå - SERVICE_ACCEPT_STOP;
ñîäåðæèò òåêóùåå ñîñòîÿíèå ñåðâèñà, èìåííî åãî äîëæíà óñòà- MyServiceStatus.dwWin32ExitCode = 0;
íàâëèâàòü ServiceMain. MyServiceStatus.dwServiceSpecificExitCode = 0;
MyServiceStatus.dwCheckPoint = 0;
Äîïóñòèìûå çíà÷åíèÿ: MyServiceStatus.dwWaitHint = 5000;
SERVICE_STOPPED - ñåðâèñ îñòàíîâëåí; //Ðåãèñòðèðóåì îáðàáîò÷èê ñîáûòèé
SERVICE_START_PENDING - ñåðâèñ çàïóñêàåòñÿ; MyServiceStatusHandle =
SERVICE_STOP_PENDING - ñåðâèñ îñòàíàâëèâàåòñÿ; RegisterServiceCtrlHandler(«MyService»,
SERVICE_RUNNING - ñåðâèñ óæå çàïóùåí;
SERVICE_CONTINUE_PENDING - ñåðâèñ ïðîäîëæàåò ðàáîòó; MyServiceCtrlHandler);
SERVICE_PAUSE_PENDING - ñåðâèñ ïåðåõîäèò â ðåæèì ïàóçû;
SERVICE_PAUSED - ñåðâèñ íàõîäèòñÿ â ðåæèìå ïàóçû. if (MyServiceStatusHandle == (SERVICE_STATUS_HANDLE)0)
66
СЕТИ
сети
АНАЛИЗАТОР
СЕТЕВОГО
ТРАФИКА
Введение На уровне протокола Ethernet маршру- ся сокет. Обычно используются значения
Если Вы - системный администратор, тизация отсутствует. Другими словами, кадр, PF_UNIX для соединений, ограниченных
специалист по безопасности, или Вам про- отправленный хостом-отправителем, не локальной машиной, и PF_INET для соеди-
сто интересно, что происходит в Вашей ло- попадает напрямую хосту-получателю, а бу- нений, базирующихся на протоколе IPv4.
кальной сети, то перехват и анализ несколь- дет доступен для всех хостов, объединен- Аргумент type определяет тип создаваемо-
ких сетевых пакетов может быть полезным ных в сеть. Каждая сетевая карта принима- го сокета и имеет несколько значений. Зна-
упражнением. При помощи небольшой про- ет кадр и считывает из него первые 6 байт. чение SOCK_STREAM указывается при со-
граммы на языке С и базовых знаний сете- Эти байты содержат MAC-адрес хоста-по- здании сокета для работы в режиме вирту-
вых технологий Вы сможете перехватить лучателя, но только одна карта в сети опре- альных соединений (протокол TCP), а зна-
данные сетевого траффика, даже если они делит его как свой собственный и передаст чение SOCK_DGRAM - для работы в режи-
адресованы не Вам. В данной статье мы кадр для дальнейшей обработки сетевому ме пересылки дейтаграмм (протокол UDP).
рассмотрим, как это можно сделать в сети драйверу. Сетевой драйвер проверит поле Последний параметр protocol определяет
Ethernet - наиболее распространенной на «Тип протокола» заголовка кадра и, осно- используемый протокол (в соответствии с
данный момент технологии построения ло- вываясь на этом значении, направит инкап- IEEE 802.3).
кальных компьютерных сетей. сулированный пакет соответствующей при- В версиях LINUX, начиная с 2.2, появил-
емной функции данного протокола. В боль- ся новый тип сокетов - пакетные сокеты.
Обзор технологии шинстве случаев это протокол IP. Прием- Пакетные сокеты используются для отправ-
Ethernet ная функция изымает IP заголовок из при- ления и приема пакетов на уровне драйве-
Для начала вспомним, как функциони- нятой дейтаграммы и передает инкапсули- ров устройств. Сокеты данного типа созда-
рует сеть Ethernet (те из вас, кто уже знаком рованное сообщение соответствующему ются вызовом socket (SOCK_PACKET, int
с данным вопросом, могут пропустить этот модулю протокола транспортного уровня type, int protocol). Параметр type равен или
параграф). IP-пакеты (дейтаграммы), источ- (например, TCP или UDP). Эти протоколы, SOCK_RAW, или SOCK_DGRAM.
ником которых является приложение в свою очередь, обрабатывают свои заго- Пакеты типа SOCK_RAW передаются
пользователя, инкапсулируются в Ethernet- ловки и передают данные протоколам при- драйверу устройства и принимаются от него
кадры (пакеты Ethernet-протокола, переда- кладного уровня. В течение этой «экскур- без всяких изменений данных пакета.
ваемые в сети). Каждый кадр содержит ис- сии» по различным уровням сетевого стека SOCK_DGRAM работает на более вы-
ходный IP-пакет и другую информацию, не- исходный пакет теряет все служебные поля соком уровне. Физический заголовок (MAC-
обходимую для доставки его адресату, в протоколов и, в конце концов, данные, пе- адрес) удаляется перед тем, как пакет от-
частности, 6-ти байтовый Ethernet-адрес редаваемые в пакете, принимаются пользо- правляется на обработку пользователю.
(MAC-адрес) назначения, который при по- вательским приложением.
мощи протокола ARP ставится в соответ- Пример реализации
ствие IP-адресу назначения. Таким образом, Пакетные сокеты Итак, приступим непосредственно к со-
сформированный кадр, содержащий пакет, При создании сокета стандартным вы- зданию анализатора. Для этого нам необ-
начинает свое путешествие от хоста-отпра- зовом socket (int domain, int type, int protocol) ходимо:
вителя к хосту-получателю через кабельное параметр domain определяет коммуникаци- - определить необходимые переменные;
соединение. онный домен, в котором будет использовать- - получить параметры сетевого интер-
68
сети
фейса (IP-адрес, маску подсети, номер под- Функция получения Получим маску подсети:
сети, размер MTU, индекс (номер) интер- параметров сетевого
фейса); интерфейса if (ioctl (fd, SIOCGIFNETMASK, ifr) <0 )
{
- создать пакетный сокет и привязать perror («ioctl»);
его к определенному интерфейсу; #include «ip.h» return (-1);
#include <sys/ioctl.h> }
- принять сетевой пакет и проанализи- int getifconfig (struct ifreq *ifr, char memset(&s, 0, sizeof (struct
ровать его структуру. Этим будет занимать- *intf, struct ifparam *ifp) sockaddr_in));
{ memcpy(&s, &ifr->ifr_netmask, sizeof
ся главная функция программы. (struct sockaddr));
Для удобства каждый из пунктов офор- int fd; - дескриптор сокета. memcpy(&ifp-mask, &to.sin_addr.s_addr,
sizeof (u_long));
мим в виде отдельной функции или заголо- Создадим сокет:
вочного файла. Получим номер подсети:
if (( fd= socket (AF_INET, SOCK_DGRAM,
0)) <0 ) {
Переменные perror ( «socket» );
ifp->sunbet = check_subnet(ifp->mask,
ifp->ip);
Необходимые заголовочные файлы: return ( - 1 );
}
#include <stdio.h> Получим размер MTU:
#include <sys/types.h> Скопируем имя интерфейса в поле
#include <sys/socket.h> if (ioctl (fd, SIOCGIFMTU, ifr) <0 ) {
#include <errno.h> ifr_name структуры ifr: perror («ioctl»);
#include <linux/if.h> return (-1);
#include <linux/if_ether.h> }
#include <linux/in.h> sprintf (ifr->ifr_name, «%s»,
intf); ifp -> mtu = ifr -> ifr_mtu;
#include <linux/ip.h>
Структура для хранения принятого IP - Получим IP адрес интерфейса: Получим индекс (номер) интерфейса:
пакета:
if (ioctl (fd, SIOCGIFADDR, ifr) <0 ) {
perror («ioctl»); if ( ioctl (fd, SIOCGIFINDEX, ifr) <0 )
struct ip_packet { return (-1); {
struct iphdr ip; } perror («ioctl»);
char *ip_data; memset(&s, 0, sizeof (struct return (-1);
} ip_pack; sockaddr_in)); }
memcpy(&s, &ifr->ifr_addr, sizeof (struct ifp -> index = ifr -> ifr_ifindex;
Cтруктура для хранения параметров sockaddr));
сетевого интерфейса: memcpy(&ifp-ip, &to.sin_addr.s_addr, Переведем интерфейс в неразборчи-
sizeof (u_long));
вый режим. Для этого получим значение
struct ifreq ifr;
struct sockaddr_in s;
struct ifparam {
u_long ip;
u_long mask;
u_long subnet;
int mtu;
int index;
} ifp;
SECTION .text
Выделим память для структуры struct Выделим память:
check_subnet: sockaddr_ll s_ll:
push ebp - ñîõðàíèì buff = (char *) malloc (ifp.mtu + 18);
àäðåñ âîçâðàòà èç ôóíêöèè memset(&ip, 0, sizeof (struct
mov ebp, esp memset (&s_ll, 0, sizeof (struct ip_packet));
mov edx, [ebp+8] - ïåðâûé ïà- sockaddr_ll)); ip_pack.ip_data = (char *) malloc (
ðàìåòð - ìàñêà ïîäñåòè ifp.mtu - sizeof (struct iphdr));
mov eax, [ebp+12] - âòîðîé ïà- ip=(struct iphdr *)&ip_pack.ip;
ðàìåòð - IP àäðåñ Заполним поля структуры s_ll необхо-
mov cx, 32 - ÷èñëî ðàç-
ðÿäîâ â IP àäðåñå â ôîðìàòå IPv4 димыми значениями: Получим дескриптор пакетного сокета:
push cx - ñîõðàíèì çíà÷åíèå
â ñòåêå
xor esi, esi - îáíóëèì s_ll.sll_family = PF_PACKET; if ((e0_r = getsock_recv (ifp.index)) <0
ñ÷åò÷èê - òèï ñîêåòà ) {
.label s_ll.sll_protocol = htons (ETH_P_ALL); perror («getsock_recv»);
bt edx, esi - ñêàíèðóåì - òèï ïðèíèìàåìîãî ïðîòîêîëà exit(1);
ìàñêó â ïîèñêàõ 1 s_ll.sll_ifindex = index; }
jnc .msk - âûõîä èç - íîìåð èíòåðôåéñà
öèêëà ïðè ñîâïàäåíèè s_ll.sll_pkttype = PACKET_HOST; Цикл приема пакетов:
inc esi - èíêðåìåíò - òèï ïàêåòà (äëÿ ëîêàëüíîé ìàøèíû)
ñ÷åò÷èêà
loop .label - ïðîäîëæèòü Привяжем сокет к интерфейсу: for (;;) {
ïîèñê
.mask Îáíóëèì áóôåð:
pop cx - èçâëå÷ü if ((bind (fd, (struct sockaddr bzero (buff, ifp.mtu+18);
ðàíåå ñîõðàíåííîå çíà÷åíèå èç ñòåêà *) &s_ll, sizeof (struct sockaddr_ll)) rec = 0;
sub cx, si - ÷èñëî ðàçðÿäîâ â <0 ) { Принять пакет:
àäðåñå, îòâåäåííûõ ïîä õîñòîâóþ ÷àñòü perror («bind»);
close (fd); rec=recvfrom (e0_r, (char
shl eax, cl - ëîãè÷åñêèé ñäâèã *)buff, ifp.mtu+18, 0, NULL, NULL);
íà ýòî çíà÷åíèå return (-1);
} if (rec<0) {
mov esp, ebp perror («recvfrom»);
pop ebp - âîññòàíîâèì ñòåê Возвратим дескриптор сокета в вызы- exit(1);
ret - âîçâðàò èç ôóíê- }
öèè вающую функцию:
70
сети
Число принятых байт (длина принято- inet_ntoa (ip -> saddr)); - à ä ð å ñ # Êîìïèëÿòîð Ñ
го пакета): èñòî÷íèêà CC = gcc
printf («%s \n», inet_ntoa # Êîìïèëÿòîð àññåìáëåðà
(ip -> daddr)); - àäðåñ NASM = nasm
íàçíà÷åíèÿ # Èìÿ èñïîëíÿåìîãî ìîäóëÿ
printf («\nrec = %d\n», rec);
name = ip
} IP = ip.o check_snet.o
Первые 12 байт в принятом буфере return (1); getsock_recv.o getifconf.o
} $(name): $(IP)
содержат MAC - адреса отправителя и по- $(CC) -g -o $(name) $(IP)
лучателя. Заполним структуру struct ethhdr ip.o: ip.c
$(CC) -c ip.c
eth адресной информацией: Прием пакетов осуществляется с по- check_snet.o: check_snet.asm
мощью функции recvfrom. Эта функция $(NASM) -f elf
check_snet.asm
memcpy ((char *) ð, buff, 12); принимает данные через дескриптор e0_r. getsock_recv.o: getsock_recv.c
Принятое сообщение копируется в струк- $(CC) -c getsock_recv.c
getifconf.o: getifconf.c
По смещению 14 в данном буфере рас- туру ip_pack. $(CC) -c getifconf.c
положены данные Ethernet-кадра - IP-па- В принятом пакете первым следует за- clean:
rm -f *.o
кет: головок Ethernet-кадра. По смещению 14
расположен IP-пакет. Поле «Версия» ука- В файле ip.c находится главная функция
memcpy ((char *)&ip.pack, (buff + 14), зывает тип данного пакета. Для IPv4-па- программы. Командой make мы получим ис-
ifp.mtu );
кета данное поле содержит значение 4 в полняемый модуль ip. Команда make clean
Проведем анализ принятого Ethernet- двоичной форме. Значение длины заголов- удалит все объектные файлы. Результаты
кадра. ка лежит в диапазоне между 20 и 60 байта- работы программы будут отображаться на
ми и находится в поле «Длина заголовка». консоли. Иногда это не совсем удобно, по-
if ((ip -> version) !=4)
continue; Поле «Протокол» содержит идентифика- этому, немного модифицировав программу,
цию протокола следующего, более высо- результаты можно сохранять в файле.
версия IP-протокола MAC-адрес отправи- кого уровня, содержащегося в разделе дан- Компиляцию производим с ключем -g для
теля: ных (т.е. в теле сообщения) данного IP- возможности последующей отладки. Наде-
пакета. В документе RFC 1700 перечисле- юсь, что читателю это не понадобится, но
printf (« %.2x: %.2x: %.2x: %.2x: %.2x: ны все значения, которые могут содержать- все-таки хочу показать простой прием поис-
%.2x \t -> \t «,
eth.h_source[0], eth.h_source[1], ся в поле «Протокол» в заголовке IP-паке- ка неисправностей в программе (не только в
eth.h_source[2], та. Поле «Адрес источника» и поле «Адрес этой). Иногда программа, хотя и компилиру-
eth.h_source[3], eth.h_source[4],
eth.h_source[5]); назначения» содержат соответственно IP- ется без ошибок, при запуске выдает сооб-
адрес отправителя пакета и IP-адрес пред- щение Segmentation fault и завершается. Для
MAC-адрес получателя: полагаемого получателя. нашего примера, если программа работает
Дальнейшая обработка принятого па- некорректно, запустите исполняемый файл
printf (« %.2x: %.2x: %.2x: %.2x: %.2x:
%.2x», кета зависит от полей «Длина заголовка» ip на отладку командой gdb ip. В командной
eth.h_dest[0], eth.h_ dest[1], eth.h_ и «Протокол». В принятом буфере по сме- строке отладчика наберите run и изучите
dest[2],
eth.h_ dest[3], eth.h_ dest[4], eth.h_ щению, указанном в поле «Длина заго- информацию, которую выдаст отладчик. Он
dest[5]); ловка» (с учетом заголовка кадра Ethernet) укажет место, где программа аварийно за-
printf («%d \n», ip -> ihl);
- äëèíà çàãîëîâêà IP-ïàêåòà будет расположен заголовок протокола вершилась, и Вам останется только устра-
printf («%d \n», ntohs (ip следующего уровня. Его анализ аналоги- нить неисправность. Если все в порядке, то
-> tot_len));
- äëèíà âñåãî ïàêåòà чен вышеприведенному анализу заголов- перекомпилируйте программу с ключем -s.
printf («%d \n», ip -> ка IP. В следующей статье мы рассмотрим, как
protocol); - ïðîòîêîë
âåðõíåãî óðîâíÿ Для получения исполняемого модуля можно передать принятый пакет, создав, тем
printf («%s \t -> \t», создадим Makefile следующего содержания: самым, простейший шлюз.
сети
СКАНЕР ПОРТОВ:
ПРИМЕР
РЕАЛИЗАЦИИ
ВЛАДИМИР МЕШКОВ
Введение Процесс, получающий или отправ- ходится в состоянии LISTEN (прослу-
Подавляющее большинство сете- ляющий данные, идентифицируется шиваться). Быстро определить состо-
вых служб использует при работе про- на этом уровне номером, который на- яние порта позволяет специальное
токол TCP. Согласно модели OSI, ТСР зывается номером порта, или просто программное обеспечение - сканер
является протоколом транспортного портом. Другими словами, порт опре- портов.
уровня. Он обеспечивает надежное деляет сетевую службу, которой пред- Сканирование портов выполняет-
двунаправленное соединение между назначен пакет. ся, как правило, для того, чтобы най-
двумя процессами; данные передают- Для возможности установления ти на узле службу, уязвимую с точки
ся в обоих направлениях без ошибок, соединения с какой-либо сетевой зрения безопасности сети. Это свое-
пакеты не теряются и не дублируют- службой соответствующий ей порт го рода разведка, которая может осу-
ся, последовательность передачи дан- должен быть открыт, или, выражаясь ществляться как администратором
ных не нарушается. терминологией TCP-соединения, на- сети, так и злоумышленником.
72
сети
Целью данной статьи является читать в статье «NESSUS - современ- добятся следующие header-файлы:
описание принципов функционирова- ный анализ безопасности, методы
ния и внутреннего устройства просто- сканирования»(http://www.hack #include <stdio.h>
#include <stdlib.h>
го сканера портов TCP протокола. zone.ru/articles/nessus.htm#scan), а #include <errno.h>
также в документации на сканер #include <sys/types.h>
#include <sys/socket.h>
Порядок установления Nmap (http://www.insecure.org/nmap). #include <sys/ioctl.h>
TCP соединения Мы рассмотрим один из методов - #include <linux/in.h>
#include <linux/ip.h>
SYN-сканирование. Этот метод часто #include <linux/tcp.h>
Для понимания принципа работы называют half-open (полуоткрытым) #include <linux/if.h>
#include <linux/if_ether.h>
сканера необходимо знать, каким об- сканированием, т.к. полное TCP-со-
разом устанавливается TCP соедине- единение с портом сканируемой ма- структуры:
ние. шины не устанавливается. Суть дан- struct ifreq *ifr - ñòðóêòóðà äëÿ
При установлении соединения за- ного метода заключается в следую- õðàíåíèÿ ïàðàìåòðîâ ñåòåâîãî èíòåðôåéñà
действуются поля «Порядковый но- щем. Вы посылаете TCP-пакет с ус- struct iphdr *ih - ñòðóêòóðà, ñîäåð-
æàùàÿ çàãîëîâîê IP-ïàêåòà
мер» (SEQ), «Номер подтверждения» тановленным флагом SYN, как если sturct tcphdr *th - ñòðóêòóðà, ñîäåð-
(ACK-SEQ), флаги SYN, ACK и RST бы собирались установить реальное æàùàÿ çàãîëîâîê TCP-ïàêåòà
struct sockaddr_in local - ñòðóêòóðà,
заголовка TCP-пакета. Флаг SYN яв- соединение с выбранным портом, и ñîäåðæàùàÿ àäðåñíóþ èíôîðìàöèþ î ëîêàëü-
ляется флагом синхронизации. Он ожидаете ответ. Принятый пакет с ус- íîé ñèñòåìå
struct sockaddr_in dest - ñòðóêòóðà,
используется при установлении со- тановленными флагами SYN и ACK ñîäåðæàùàÿ àäðåñíóþ èíôîðìàöèþ îá óäà-
единения и устанавливает начальный указывает на то, что выбранный порт ëåííîé ñèñòåìå
struct p_header {
порядковый номер, используемый для открыт и ожидает соединения. Флаг u_long s_addr;
последующей передачи данных. Флаг RST означает обратное. Если получен u_long d_addr;
u_char zer0;
ACK указывает на то, что поле номе- SYN|ACK-пакет, следует немедленно u_char protocol;
ра подтверждения содержит досто- отправить пакет с флагом RST для u_int lenght;
}
верные данные. Флаг RST использу- сброса соединения, хотя реально за *pseudo - ïñåâäîçàãîëîâîê. Íåîáõî-
ется для сброса соединения. вас это сделает ядро. Преимуществом äèì ïðè ðàñ÷åòå êîíòðîëüíîé ñóììû TCP-
ïàêåòà (âçÿò èç èñõîäíûõ òåêñòîâ ñêàíå-
Соединение устанавливается в 3 данной технологии является отсут- ðà Nmap)
этапа: ствие в log-файлах сканируемой ма-
n инициатор соединения (клиент) шины записей о попытках установле- и переменные:
формирует SYN-пакет (TCP-пакет ния соединения с ней. Недостаток -
с установленным флагом SYN), за- необходимость наличия прав root для int fd - äåñêðèïòîð âñïîìîãàòåëüíîãî
ñîêåòà
полняет поле SEQ и передает па- формирования SYN-пакета. e0_s- äåñêðèïòîð ñîêåòà äëÿ ïåðåäà÷è
кет серверу; e0_r- äåñêðèïòîð ñîêåòà äëÿ ïðèåìà
sent- ÷èñëî ïåðåäàííûõ áàéò
n если порт, на который пришел зап- Пример реализации rec- ÷èñëî ïðèíÿòûõ áàéò
рос на соединение, открыт, сервер сканера port- íîìåð ñêàíèðóåìîãî ïîðòà
index- èíäåêñ èíòåðôåéñà, ÷åðåç êîòî
формирует SYN|ACK-пакет, запол- ðûé îñóùåñòâëÿåòñÿ ñêàíèðîâàíèå.
няет поля SEQ, ACK-SEQ и пере- Приведенный ниже код был разра- u_char *packet- ïàêåò, ïåðåäàâàåìûé â
ñåòü.
дает пакет клиенту. Значение поля ботан и протестирован в ОС GNU/
ACK-SEQ равно значению поля Linux, дистрибутив Slackware 7.1, ком-
SEQ из пакета клиента, увеличен- пилятор gcc-2.95.2. Сокет для передачи
ному на 1 (т.е. ACK-SEQ-сервера Алгоритм реализации следующий:
= SEQ-клиента + 1). Если порт зак- n определить необходимые пере- Дескриптор сокета для передачи
рыт, клиенту отправляется RST- менные и заголовочные файлы; получим при помощи функции
пакет; n создать сокеты для приема и пе- getsock_send, приведенной ниже.
n получив SYN|ACK-пакет, клиент редачи пакетов;
проверяет поле ACK-SEQ и высы- n сформировать SYN-пакет и отпра- Необходимые заголовочные файлы:
лает серверу ACK-пакет. После вить его сканируемому хосту; #include <errno.h>
этого соединение считается уста- n принять ответный пакет и проана- #include <sys/types.h>
#include <sys/socket.h>
новленным и переходит в фазу лизировать состояние флагов #include <linux/in.h>
обмена данными между клиентом SYN, ACK, RST; #include <linux/if.h>
#include <linux/if_ether.h>
и сервером. n сделать вывод о статусе проверя- int getsock_send ( char *intf)
емого порта. - âûçîâ ôóíêöèè
Методы сканирования
Заголовочные файлы и Функция getsock_send принимает
Существует достаточно большое переменные строковое значение (имя интерфейса)
число методов сканирования, каждый и возвращает дескриптор сокета в
из которых имеет свои преимущества Заголовочные файлы и перемен- случае положительного завершения
и, соответственно, недостатки. Под- ные разместим в файле, который на- или -1, если произошла ошибка.
робнее о каждом из них можно про- зовем scan.h. Для работы нам пона-
74
сети
при запуске программы, это прове- p_header )); - îáíóëèì ñòðóêòó- printf ( «IP-àäðåñ íàçíà÷åíèÿ \t -\t
рить, все ли необходимые параметры ðó %s \n «, inet_ntoa ( ih -> daddr ));
pseudo -> s_addr = printf ( «IP-àäðåñ èñòî÷íèêà \t -
указаны: local.sin_addr.s_addr; - \t %s \n «, inet_ntoa ( ih -> saddr ));
àäðåñ ëîêàëüíîãî õîñòà printf ( «Ïîðò íàçíà÷åíèÿ \t \t -
if ( argc != 3 ) { pseudo -> d_addr = \t %d \n «, ntohs ( th -> dest ));
usage (); dest.sin_addr.s_addr; - printf ( «Ïîðò èñòî÷íèêà \t\t - \t
exit ( 1 ); àäðåñ óäàëåííîãî õîñòà %d \n «, ntohs ( th -> source ));
} pseudo -> protocol = 6;
- ïðîòîêîë (TCP)
Преобразуем введенные строко- pseudo -> lenght = htons ( sizeof Создадим сокеты для передачи и
( struct tcphdr )); - äëèíà ïñåâäîçàãî-
вые значения адреса и порта в сете- ëîâêà приема пакетов.
вой формат и заполним адресную
структуру удаленной системы: Сформируем TCP заголовок. if (( e0_s = getsock_send ( «eth0» ))
< 0 ) {
perror ( «getsock_send» );
port = atoi ( argv [2] ); memset ( th, 0, sizeof ( struct tcphdr exit ( 1 );
memset ( &dest, 0, sizeof ( struct )); - îáíóëèì ñòðóêòóðó }
sockaddr_in )); th -> source = local.sin_port; -
dest.sin_addr.s_addr = inet_ntoa ( argv ëîêàëüíûé ïîðò if (( e0_r = getsock_recv ( index
[1] ); th -> dest = dest.sin_port; )) < 0 ) {
dest.sin_port = htons ( port ); - óäàëåííûé ïîðò perror ( «getsock_recv» );
th -> seq = htonl ( 1156270349 ); exit ( 1 );
- íà÷àëüíûé ïîðÿäêîâûé íîìåð }
Тоже самое проделаем для ло- th -> ack_seq = 0; -
кального хоста. íîìåð ïîäòâåðæäåíèÿ Передадим сформированный
th -> doff = 5; -
äëèíà çàãîëîâêà ( â 32-õ ðàçðÿäíûõ ñëî- SYN-пакет хосту назначения.
memset ( &local, 0, sizeof ( struct âàõ )
sockaddr_in )); th -> syn = 1; - dest.sin_family = AF_INET;
óñòàíîâèòü ôëàã SYN sent = sendto ( e0_s, (char *)
th -> window = htons ( 3072 ); - packet, ntohs ( ih -> tot_len), 0, (
ðàçìåð îêíà struct sockaddr *)&dest,
Получим IP-адрес интерфейса и th -> check = 0; - sizeof (struct
занесем его в адресную структуру îáíóëèòü ïîëå êîíòðîëüíîé ñóììû sockaddr_in));
th -> check = in_cksum (( u_short if ( sent <= 0 ) {
local: *)pseudo, sizeof ( struct tcphdr) + sizeof perror ( «sendto» );
( struct p_header)); exit ( 1 );
fd = socket ( AF_INET, SOCK_DGRAM, 0 }
); printf ( «\n Ïåðåäàíî %d áàéò \n»,
sprintf ( ifr -> ifr_name, «%s», Алгоритм расчета контрольной sent );
«eth0»); суммы для заголовков TCP и IP оди-
octl ( fd, SIOCGIFADDR, ifr );
memcpy (( char *) &local, ( char *)&( наковый и будет изложен ниже. Примем ответ на наш запрос. При-
ifr -> ifr_addr ), sizeof ( struct Сформируем IP заголовок. ем будем осуществлять в бесконеч-
sockaddr ));
local.sin_port = htons (53); ном цикле, каждый раз обнуляя при-
memset ( ih, 0, sizeof ( struct iphdr емный буфер.
)); - îáíóëèì ñòðóêòóðó
Получим индекс интерфейса: ih -> version = 4;
- âåðñèÿ ïðîòîêîëà for ( ; ; ) {
ioctl ( fd, SIOCGIFINDEX, ifr ); ih -> ihl = 5; -
index = ifr -> ifindex; äëèíà çàãîëîâêà (÷èñëî 32-õ áèòíûõ ñëîâ) bzero ( packet, sizeof (packet));
ih -> tot_len = htons (sizeof rec = 0;
(struct iphdr)+sizeof(struct tcphdr));
Выделим память для хранения - äëèíà ïàêåòà rec = recvfrom ( e0_r, (char *)
данных, передаваемых и принимае- ih -> id = 3290; packet, sizeof ( struct iphdr ) + sizeof
- ïîðÿäêîâûé íîìåð ïàêåòà (èäåíòèôèêà- ( struct tcphdr ),
мых из сети. Пакет будет состоять öèÿ) 0, NULL,
только из заголовков IP и TCP прото- ih -> ttl = 42; NULL );
- âðåìÿ æèçíè if ( rec <0 || rec > 1500 ) {
колов. ih -> protocol = 6; perror ( «recvfrom» );
- òðàíñïîðòíûé ïðîòîêîë (TCP) exit ( 1 );
packet = ( u_char * )malloc( sizeof ( ih -> saddr = }
struct iphdr ) + sizeof ( struct tcphdr local.sin_addr.s_addr; - ëîêàëüíûé
)); àäðåñ Число 1500 определяет макси-
ih -> daddr = dest.sin_addr.s_addr;
- óäàëåííûé àäðåñ мальный размер MTU для сети
Внутри общего пакета разместим ih -> check = in_cksum (( u_short Ethernet. Больше этого значения в
*) ih, sizeof (struct iphdr )); -
служебные заголовки IP и TCP прото- êîíòðîëüíàÿ ñóììà одном пакете принять мы не можем,
колов, а также псевдозаголовок. и любое превышение данного преде-
Некоторые поля заголовков (на- ла трактуется как ошибка.
in = ( struct iphdr * ) packet; пример, поле «Начальный порядко- Теперь займемся анализом приня-
th = ( struct tcphdr * ) (packet +
sizeof ( struct iphdr )); вый номер» TCP заголовка и поле того пакета.
pseudo = (struct p_header *) ( packet «Идентификация» заголовка IP) были Для начала проверим соответ-
+ sizeof ( struct iphdr) - sizeof ( struct
p_header )); выбраны совершенно произвольно, ствие версии протокола IP. Поле
т.к. в данном случае эти значения ни «Версия» должно содержать 4. Если
Заполним поля псевдозаголовка на что не влияют. это не так (к нам мог поступить ARP-
необходимыми значениями. Отобразим для контроля имеющу- запрос, который мы не собираемся
memset ( pseudo, 0, sizeof ( struct юся адресную информацию: обрабатывать), то принятый пакет от-
76
FAQ PERL
по материалам www.xpoint.ru
составил Дмитрий Горяинов
79
сети
можно получить средствами операционной системы. (172.16.163.89) либо в символьном формате
При успешной работе возвращается 0. Сокет, однажды (myhost.com). Для преобразования первого служит фун-
связанный, чаще всего не может быть связан снова, так, кция inet_addr (const char *ip_addr), а для второго — фун-
например, происходит в протоколе ip. Параметр sock_fd кция gethostbyname (const char *host). Рассмотрим обе
задаёт дескриптор сокета, структура serv_addr назна- из них:
чает удалённый адрес конечной точки, addr_len содер-
жит длину serv_addr (тип socketlen_t имеет историчес- u_int32_t inet_addr(const char *ip_addr)
кое происхождение, обычно он совпадает с типом int).
Самый важный параметр в этой функции — адрес уда- — возвращает сразу же целое, пригодное для исполь-
лённого сокета. Он, естественно, неодинаков для раз- зования в структуре sockaddr_in по ip адресу, передан-
ных протоколов, поэтому я опишу здесь структуру ад- ному ей в формате x.x.x.x. При возникновении ошибки
реса только для ip(v4) протокола. Для этого использу- возвращается значение INADDR_NONE.
ется специализированная структура sockaddr_in (её не-
обходимо прямо приводить к типу sockaddr при вызове struct HOSTENT* gethostbyname(const char *host_name)
connect). Поля данной структуры выглядят следующим
образом: — возвращает структуру информации о хосте, исходя
из его имени. В случае неудачи возвращает NULL. По-
struct sockaddr_in{ иск имени происходит вначале в файле hosts, а затем в
sa_family_t sin_family; DNS. Структура HOSTENT предоставляет информацию
îïðåäåëÿåò ñåìåéñòâî àäðåñîâ, âñåãäà äîëæíî áûòü AF_INET
u_int16_t sin_port; о требуемом хосте. Из всех её полей наиболее значи-
ïîðò ñîêåòà â ñåòåâîì ïîðÿäêå áàéò тельным является поле char **h_addr_list, представля-
struct in_addr sin_addr;
ñòðóêòóðà, ñîäåðæàùàÿ ip àäðåñ ющее список ip адресов данного хоста. Обычно исполь-
}; зуется h_addr_list[0], представляющая первый ip адрес
Ñòðóêòóðà, îïèñûâàþùàÿ ip-àäðåñ:
struct in_addr{ хоста, для этого можно также использовать выражение
u_int32_t s_addr; h_addr. После выполнения функции gethostbyname в
ip àäðåñ ñîêåòà â ñåòåâîì ïîðÿäêå áàéò
}; списке h_addr_list структуры HOSTENT оказываются
простые символические ip адреса, поэтому необходи-
Обратите внимание на особый порядок байт во всех мо воспользоваться дополнительно функцией inet_addr
целых полях. Для перевода номера порта в сетевой по- для преобразования в формат sockaddr_in.
рядок байт можно воспользоваться макросом htons Итак, мы связали клиентский сокет с серверным фун-
(unsigned short port). Очень важно использовать имен- кцией connect. Далее можно использовать функции пе-
но этот тип целого — беззнаковое короткое целое. редачи данных. Для этого можно использовать либо
Адреса IPv4 делятся на одиночные, широковеща- стандартные функции низкоуровневого ввода/вывода
тельные (broadcast) и групповые (multicast). Каждый для файлов, так как сокет — это, по сути дела файло-
одиночный адрес указывает на один интерфейс хоста, вый дескриптор. К сожалению, для разных операцион-
широковещательные адреса указывают на все хосты в ных систем функции низкоуровневой работы с файла-
сети, а групповые адреса соответствуют всем хостам ми могут различаться, поэтому надо посмотреть руко-
в группе (multicast group). В структуре in_addr можно водство к своей операционной системе. Учтите, что пе-
назначать любой из этих адресов. Но для сокетных кли- редача данных по сети может закончиться сигналом
ентов в подавляющем большинстве случаев присваи- SIGPIPE, и функции чтения/записи вернут ошибку. Все-
вают одиночный адрес. Исключением является тот слу- гда нужно помнить о проверке ошибок, кроме того,
чай, когда необходимо просканировать всю локальную нельзя забывать о том, что передача данных по сети
сеть в поисках сервера, тогда можно использовать в может быть очень медленной, а функции ввода/вывода
качестве адреса широковещательный. Затем, скорее являются синхронными, и это может вызвать существен-
всего, сервер должен сообщить свой реальный ip ад- ные задержки в работе программы.
рес и сокет для дальнейшей передачи данных должен Для передачи данных между сокетами существуют
присоединяться именно к нему. Передача данных че- специальные функции, единые для всех ОС — это фун-
рез широковещательные адреса не есть хорошая идея, кции семейства recv и send. Формат их очень похож:
так как неизвестно, какой именно сервер обрабатыва-
ет запрос. Поэтому в настоящее время сокеты, ориен- int send(int sockfd, void *data, size_t len, int flags);
тированные на соединение, могут использовать лишь îòïðàâëÿåò áóôåð data
одиночные адреса. Для сокетных серверов, ориентиро- int recv(int sockfd, void *data, size_t len, int flags);
ванных на прослушивание адреса, наблюдается другая ïðèíèìàåò áóôåð data
ситуация: здесь разрешено использовать широковеща-
тельные адреса, чтобы сразу же ответить клиенту на Первый аргумент — дескриптор сокета, второй —
запрос о местоположении сервера. Но обо всём по по- указатель на данные для передачи, третий — длина
рядку. Как вы заметили, в структуре sockaddr_in поле буфера и четвёртый — флаги. В случае успеха возвра-
ip адреса представлено как беззнаковое длинное це- щается число переданных байт, в случае неудачи — от-
лое, а мы привыкли к адресам либо в формате x.x.x.x рицательный код ошибки. Флаги позволяют изменить
80
сети
параметры передачи (например, включить асинхронный сокет, затем ему присваивается локальный адрес фун-
режим работы), но для большинства задач достаточно кцией bind, при этом можно присвоить сокету широко-
оставить поле флагов нулевым для обычного режима вещательный адрес. Затем начинается прослушивание
передачи. При отсылке или приёме данных функции адреса функцией listen, запросы на соединение поме-
блокируют выполнение программы до того, как будет щаются в очередь. То есть функция listen выполняет
отослан весь буфер. А при использовании протокола инициализацию сокета для приёма сообщений. После
tcp/ip от удалённого сокета должен прийти ответ об ус- этого нужно применить функцию accept, которая воз-
пешной отправке или приёме данных, иначе пакет пе- вращает новый, уже связанный с клиентом сокет. Обыч-
ресылается ещё раз. При пересылке данных учитывай- но для серверов характерно принимать много соедине-
те MTU сети (максимальный размер передаваемого за ний через небольшие промежутки времени. Поэтому
один раз кадра). Для разных сетей он может быть раз- нужно постоянно проверять очередь входящих соеди-
ным, например, для сети Ethernet он равен 1500. нений функцией accept. Для организации такого пове-
Итак, для полноты изложения приведу самый про- дения чаще всего прибегают к возможностям операци-
стенький пример программы на Си, реализующей со- онной системы. Для ОС Windows чаще используется
кетного клиента: многопоточный вариант работы сервера (multi-threaded),
после принятия соединения происходит создание ново-
#include <sys/socket.h> го потока в программе, который и обрабатывает сокет.
/* Ñòàíäàðòíûå áèáëèîòåêè ñîêåòîâ äëÿ Linux */ В *nix системах чаще используется порождение дочер-
#include <net/netinet.h>
/* Äëÿ ÎÑ Windows èñïîëüçóéòå #include<winsock.h> */ него процесса функцией fork. При этом накладные рас-
#include <stdio.h> ходы уменьшены за счёт того, что фактически проис-
int main(){ ходит копия процесса в файловой системе proc. При
int sockfd = -1; этом все переменные дочернего процесса совпадают с
/* Äåñêðèïòîð ñîêåòà */
char buf[128]; родителем. И дочерний процесс может сразу же обра-
/* Óêàçàòåëü íà áóôåð äëÿ ïðè¸ìà */ батывать входящее соединение. Родительский же про-
char s[] = "Client ready\n";
/* Ñòðîêà äëÿ ïåðåäà÷è ñåðâåðó */ цесс продолжает прослушивание. Учтите, что порты с
HOSTENT *h = NULL; номерами от 1 до 1024 являются привилегированными
/* Ñòðóêòóðà äëÿ ïîëó÷åíèÿ ip àäðåñà */
sockaddr_in addr; и их прослушивание не всегда возможно. Ещё один мо-
/* Còðóêòóðà tcp/ip ïðîòîêîëà */ мент: нельзя, чтобы два разных сокета прослушивали
unsigned short port = 80;
/* Çàïîëíÿåì ïîëÿ ñòðóêòóðû: */ один и тот же порт по одному и тому же адресу! Для
addr.sin_family = AF_INET; начала рассмотрим форматы вышеописанных функций
addr.sin_port = htons(port);
для создания серверного сокета:
sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
/* Ñîçäà¸ì ñîêåò */ int bind(int sockfd, const struct *sockaddr, socklen_t
if(sockfd == -1) addr_len);
/* Ñîçäàí ëè ñîêåò */
return -1;
h = gethostbyname("www.myhost.com");
— присваивает сокету локальный адрес для обеспече-
/* Ïîëó÷àåì àäðåñ õîñòà */ ния возможности принимать входящие соединения. Для
if(h == NULL) адреса можно использовать константу INADDR_ANY, ко-
/* À åñòü ëè òàêîé àäðåñ? */
return -1; торая позволяет принимать входящие соединения со
addr.sin_addr.s_addr = inet_addr(h->h_addr_list[0]); всех адресов в данной подсети. Формат функции ана-
/* Ïåðåâîäèì ip àäðåñ â ÷èñëî */
логичен connect. В случае ошибки возвращает отрица-
if(connect(sockfd, (sockaddr*) &addr, sizeof(addr))) тельное значение.
/* Ïûòàåìñÿ ñîåäèíèòñÿ ñ óäàë¸ííûì ñîêåòîì */
return -1;
/* Ñîåäèíåíèå ïðîøëî óñïåøíî - ïðîäîëæàåì */ int listen(int sockfd, int backlog);
if(send(sockfd, s, sizeof(s), 0) < 0)
/* Ïîñûëàåì óäàë¸ííîìó ñîêåòó ñòðîêó s */ — функция создаёт очередь входящих сокетов (коли-
return -1;
чество подключений определяется параметром backlog,
if(recv(sockfd, buf, sizeof(buf), 0) < 0) оно не должно превышать числа SOMAXCONN, кото-
/* Ïîëó÷àåì îòâåò îò óäàë¸ííîãî ñåðâåðà */
return -1; рое зависит от ОС). После создания очереди можно
printf("Recieved string was: %s", buf);
ожидать соединения функцией accept. Сокеты обычно
/* Âûâîä áóôåðà íà ñòàíäàðòíûé âûâîä */ являются блокирующими, поэтому выполнение програм-
close(sockfd); мы приостанавливается, пока соединение не будет при-
/* Çàêðûâàåì ñîêåò */
нято. В случае ошибки возвращается -1.
/* Äëÿ Windows ïðèìåíÿåòñÿ ôóíêöèÿ closesocket(s) */
return 0;
} int accept(int sockfd, struct *sockaddr, socklen_t addr_len)
Вот видите, использовать сокеты не так трудно. В — функция дожидается входящего соединения (или из-
серверных приложениях используются совершенно дру- влекает его из очереди соединений) и возвращает но-
гие принципы работы с сокетами. Вначале создается вый сокет, уже связанный с удалённым клиентом. При
82
ОБРАЗОВАНИЕ
образование
ВЗАИМНЫЕ
ФУНКЦИОНАЛЬНЫЕ
ЗАВИСИМОСТИ АНДРЕЙ ФИЛИППОВИЧ
84
образование
Обычно к системному администратору Однако ни в одной из них не говорится об ограниченности
обращаются по самым разным вопросам, их использования. Рассмотрим пример использования пра-
при возникновении любой проблемы: будь вила объединения:
это забытый пароль, неработающая Если A→B, A→С то A→BС.
программа, нечитающаяся дискета или Пусть имеется два простейших отношения ЗАРПЛАТА(-
пропавшие неизвестно куда данные. Этот Сотрудник, Зарплата) и СЧЕТА(Сотрудник, N_Кредитки). Во
список можно продолжать бесконечно. второй таблице задаются номера кредитных карточек со-
Мне хотелось бы остановиться на трудников. Предположим, что у Невезинского нет кредитки.
ошибках, которые возникают при работе с Специалист по БД решил оптимизировать структуру и уст-
СУБД. Статья посвящена тем, кому ранить избыточность, пользуясь вышеупомянутым правилом.
приходится заниматься вопросами Если Сотрудник → Зарплата, Сотрудник → N_Кредитки
проектирования или реструктурирования то Сотрудник → {Зарплата, N_Кредитки}.
реляционных баз данных.
·ÔØÖÙÊÓÎÐ ÆÖÕÑÆØÆ ·ÔØÖÙÊÓÎÐ 1B°ÖËÊÎØÐÎ
³ËÈËÍÎÓ×ÐÎÏ µÔÝØÔÈ
В настоящее время базы данных являются частью практи-
µÔÝØÔÈ ·ÆÖÐÎ×âåÓ
чески любой информационной системы. Современные БД ·ÆÖÐÎ×âåÓ ¸ÖÎÚÔÓÔÈ
характеризуются большой размерностью и сложной струк- ¸ÖÎÚÔÓÔÈ
турой, поэтому для их разработки используются специаль-
·ÔØÖÙÊÓÎÐ ÆÖÕÑÆØÆ 1B°ÖËÊÎØÐÎ
ные программные средства. Они позволяют не только упро-
³ËÈËÍÎÓ×ÐÎÏ 1XOO
стить и ускорить процесс проектирования, но и выполнять µÔÝØÔÈ
некоторые функции по оптимизации БД. Наиболее популяр- ·ÆÖÐÎ×âåÓ
ным является подход, в котором осуществляется нормали- ¸ÖÎÚÔÓÔÈ
зация.
Теория нормализации (зависимостей) появилась одно- Сразу после «оптимизации» в результирующем отноше-
временно с теорией реляционной алгебры. Коддом были нии появится кортеж, который имеет пустое (неопределен-
предложены первые нормальные формы. Впоследствии, ное) значение. Реляционное отношение, да и ФЗ (A→BС)
третья нормальная форма была уточнена и названа нормаль- таких кортежей не поддерживают, поэтому такая запись дол-
ной формой Бойса-Кодда (НФБК). Позже Фэйджином (Fagin) жна автоматически удалиться1.
были предложены 4 и 5 нормальная формы, а также альтер- Большинство современных СУБД поддерживают трех-
нативная доменно-ключевая нормальная форма [3]. Суще- значную логику (с использованием Null значений), поэтому
ствуют и другие нормальные формы, но наиболее популяр- запись может не пропасть. Однако наличие неопределен-
ной является 3НФ и НФБК. ных значений приводит к появлению неоднозначности в зап-
В основе теории нормализации лежат различные поня- росах и программах.
тия зависимостей между атрибутами БД. В теории Кодда Таким образом, свободно применять правила Армстрон-
используется понятие функциональной зависимости (ФЗ), га можно только для проектируемой БД, не имеющей дан-
реляционный аналог математической функции. Рассмотре- ных. При реструктуризации необходимо использовать Null-
ние основных вопросов статьи требует четкого определе- значения.
ния понятия ФЗ, поэтому приведем формальное определе- Это замечание существенно для баз данных с динами-
ние ФЗ из 6-ого издания книги Дейта [4]. Отметим сразу, что чески изменяемой структурой, к которым можно отнести
статья ориентирована на читателя, знакомого с основными современные объектно-реляционные разработки. Функцио-
понятиями реляционной алгебры и теории нормализации. нальные зависимости являются одними из простейших се-
Пусть R — это отношение, а X и Y — произвольные под- мантических ограничений, поэтому можно смело утверждать,
множества множества атрибутов отношения R. Тогда Y фун- что все рассматриваемые вопросы будут актуальны и для
кционально зависимо от X (X→Y), тогда и только тогда, ког- объектных СУБД.
да каждое значение множества X отношения R связано в
точности с одним значением множества Y отношения R. Проблемы 3НФ и НФБК
Иначе говоря, если два кортежа отношения совпадают по X Приведение отношений в 3НФ и НФБК направлено на
[t1(X) = t2(X)], то они также совпадают и по Y [t1(Y) = t2(Y)]. избавление от транзитивных зависимостей (A→B, B→C =>
X→Y o [t1(X) = t2(X)] => [t1(Y) = t2(Y)] A→C). 3НФ позволяет удалить транзитивные зависимости
неключевого атрибута (C) от ключевого (A) через другой
Возможность применения правил неключевой (B). В НФБК запрещаются все зависимости сре-
Армстронга ди ключевых атрибутов и любой неключевой атрибут дол-
Проектирование схемы базы данных начинается с опре- жен напрямую (нетранзитивно) зависеть от ключа, т.е. от всех
деления универсального отношения, в которое входят все ключевых атрибутов.
атрибуты. Для предметной области задается множество ог- Рассмотрим пример приведения отношения в третью
раничений с помощью функциональных, многозначных и нормальную форму, предложенный Ульманом[18] и пробле-
других зависимостей. Для вывода новых ФЗ или сокраще- мы, которые при этом возникают.
ния их числа используются правила Армстронга. Эти прави- Пусть задана схема отношений R и множество функцио-
ла общеизвестны и приводятся почти в каждой книге по БД. нальных зависимостей F. Звездочкой (*) помечены функци-
Для приведения схемы отношения в 3НФ необходимо Рассмотрим основное свойство ВФЗ. Из функциональ-
найти минимальное покрытие множества функциональных ной зависимости A→B вытекает утверждение 1. Кроме того,
зависимостей. В описываемом примере оно будет представ- может существовать множество кортежей с разными значе-
лено следующим образом[18]: ниями в атрибуте А и одинаковыми значениями в атрибуте
F = {A→B, CD→A, CB→D, AE→T, CE→D} B (утверждение 2):
Далее, осуществим декомпозицию схемы отношения: (1) A→B o [ti(A) = tj(A)] => [ti(B) = tj(B)]
r={AB, CDA, CBD, AET, CED} (2) [∀ ti(B)] ∃ {t(A)} , |{t(A)}|?1
Данная схема находится в НФБК и декомпозируется из Аналогично определим соотношения для ФЗ B→A:
исходной схемы с сохранением зависимостей. Недостатком (3) B→A o [ti(B) = tj(B)] => [ti(A) = tj(A)]
этой декомпозиции является зависимость проекций (по тер- (4) [∀ti(A)] ∃ {t(B)} , |{t(B)}|?1
минологии Риссанена). Отсюда следует, что схема может
обладать аномалиями. Проиллюстрируем это на примере: Соединяя условия (1), (4) и (2), (3) получаем следующие ут-
На рис.1. представлены три таблицы из полученной схе- верждения:
мы отношений. Звездочками отмечены ключевые поля. (5) [∀ ti(A)] ∃ {t(B)} , |{t(B)}|=1
Пусть в БД хранится информация, что в 10 часов в 12 и 13 (6) [∀ ti(B)] ∃ {t(A)} , |{t(A)}|=1
аудиториях должны читаться кур-
·
'
$
сы «Базы данных» и «Операци- Основным свойством ВФЗ является взаимная однознач-
онные системы» (CDA). Извест- ность значений для атрибутов левой и правой части, т.е. каж-
§ÆÍáªÆÓÓáÛ
но, что эти курсы читают соответ- дый кортеж должен иметь уникальные значения полей, вхо-
´ÕËÖ×Îר ственно преподаватели Иванов и дящих во ВФЗ.
Петров (AB). При этом оба пре- Для задания ВФЗ в СУБД необходимо атрибуты A и B
$
% подавателя должны проводить объединить в одном отношении (таблице) и задать уникаль-
§ÆÍáªÆÓÓáÛ ®ÈÆÓÔÈ
занятия одновременно в одной ность каждого атрибута. Если части ВФЗ более одного ат-
аудитории (CBD). Данная инфор- рибута, то можно использовать первичный и альтернатив-
´ÕËÖ×Îר µËØÖÔÈ
мация является противоречивой, ный ключ (с обязательным заданием уникальности).
·
%
'
несмотря на то, что схема отно- Надо отметить, что алгоритмы нахождения минимально-
шений находится в НФБК и все го покрытия Мейера [11] и Бернштейна [19] учитывают ВФЗ,
®ÈÆÓÔÈ
условия ФЗ соблюдены. но только в рамках сокращения размера покрытия.
µËØÖÔÈ Представим теперь, что D — Для дальнейшего рассмотрения материала введем по-
Рис.1. Противоречивость БД. это номер посадочной полосы са- нятие условной ВФЗ (УВФЗ).
86
образование
Условной взаимной функциональной зависимостью ат- При наборе условных атрибутов (C1,.. Cn) конструкция
рибутов A и B называется пара функциональных зависимо- Where изменится:
стей вида СB→A, СA→B, где С — набор атрибутов (усло-
вие) такой, что CCA=?, CCB=?. WHERE (Pse1.C1= Pse2.C1) &(Pse1.C2= Pse2.C2) &
& (Pse1.Cn=
Будем обозначать УВФЗ как С|A↔B. Pse2.Cn)
& (Pse1.A<> Pse2.A) & (Pse1.B<> Pse2.B)
88
образование
4
{ Программа ERWIN позволяет использовать на ста-
Right_Part := Y[i]; дии проектирования рекурсивные неидентифицирую-
delete X[i]®Y[i]; //äàííàÿ ÔÇ óäàëÿåòñÿ èç S
n:=n-1; //êîëè÷åñòâî ÔÇ óìåíüøàåòñÿ щие связи.
function_1(Left_Part, Right_Part, Usl);
} 5
Здесь очень хорошо бы подошло слово замыкание
} или рекурсивная связь, но они уже используются и не-
}
сут несколько другую смысловую нагрузку. См. также
циклические БД.
Выводы
1. Нахождение ВФЗ позволяет избавиться от проти-
воречивости хранимой информации в БД. Ëèòåðàòóðà:
2. Одним из способов учета ВФЗ является наложе- 1. Àðñåíüåâ Á.Ï., ßêîâëåâ Ñ.À. Èíòåãðàöèÿ ðàñïðåäåëåííûõ
ние ограничений на целостность БД. Для этого введем ÁÄ, ÑÏá, Ëàíü, 2001, - 464 ñ. Òåîðèÿ íîðìàëèçàöèè (ñòð. 37-41).
2. Âåðáîâåöêèé À.À. Îñíîâû ïðîåêòèðîâàíèÿ áàç äàííûõ., Ðà-
понятие «целостности по взаимозависимости». äèî è ñâÿçü, 2000, - 88 ñ. Òåîðèÿ íîðìàëèçàöèè (ñòð. 25-28).
3. Вторым способом учета ВФЗ является нормали- 3. Ãîëîñîâ À.Î. Àíîìàëèè â ðåëÿöèîííûõ áàçàõ äàííûõ. Æóðíàë
ÑÓÁÄ, âûïóñê 1.06.1996.
зация отношений, т.е. приведение БД к соответствую- 4. Äåéò Ê.Äæ. Ââåäåíèå â ñèñòåìû áàç äàííûõ, 6-å èçäàíèå.
щей структуре (схеме). Введем понятие взаимно-неза- Ê., Ì., ÑÏá.: Èçäàòåëüñêèé äîì «Âèëüÿìñ», 2000. - 848 ñ. Òåîðèÿ
íîðìàëèçàöèè (ñòð. 269-347). Îäíà èç íàèáîëåå ïîëíûõ êíèã íà
висимой нормальной формы, если схема отношений не ðóññêîì ÿçûêå. Çàòðàãèâàþòñÿ âîïðîñû àòîìàðíûõ îòíîøåíèé è
имеет ВФЗ. ВННФ можно рассматривать как синоним ÄÊÍÔ. Â 7-îì èçäàíèè áîëåå ïîäðîáíî ðàññìàòðèâàþòñÿ âîïðîñû 4
è 5ÍÔ.
понятия ациклической БД. 5. Äóíàåâ Ñ. Äîñòóï ê ÁÄ è òåõíèêà ðàáîòû â ñåòè. Ì., Äèà-
4. Приведение отношения к ВННФ можно осуществ- ëîã-ÌÈÔÈ, 2000, - 416 ñ.
6. Êàëèíè÷åíêî Ë.À. Ìåòîäû è ñðåäñòâà èíòåãðàöèè íåîäíîðîä-
лять независимо от приведения отношения в 1НФ, 2НФ, íûõ áàç äàííûõ. Ì.: Íàóêà, 1983 - 424 ñ.
3НФ, НФБК. Рекомендуется выявлять ВФЗ на этапе на- 7. Êàðïîâà Ò. Áàçû äàííûõ, ìîäåëè, ðàçðàáîòêà, ðåàëèçàöèÿ,
ÑÏá., Ïèòåð, 2001, - 304 ñ. Òåîðèÿ íîðìàëèçàöèè (ñòð. 110-120).
хождения минимального покрытия. 1-5ÍÔ, î÷åíü êðàòêî.
5. В последующих нормальных формах используют- 8. Êîííîëëè Ò., Áåãã Ê., Ñòðà÷àí À. Áàçû äàííûõ. Ïðîåêòèðî-
âàíèå, ðåàëèçàöèÿ è ñîïðîâîæäåíèå. Òåîðèÿ è ïðàêòèêà, 2-å èçä.,
ся несколько другие зависимости. В данной работе эти Ì.:»Âèëüÿìñ», 2000, - 1120 ñ. Òåîðèÿ íîðìàëèçàöèè (ñòð. 222-
вопросы не проработаны. 258). 1-5ÍÔ, î÷åíü êðàòêî, â îñíîâíîì, ïðèìåðû.
9. Êîðíååâ Â.Â., Ãàðååâ À.Ô., Âàñþòèí Ñ.Â., Ðàéõ Â.Â. Áàçû
6. Автор не считает, что вопросы, затронутые в этой äàííûõ. Èíòåëëåêòóàëüíàÿ îáðàáîòêà èíôîðìàöèè. Ì.: «Íîëèäæ». -
работе являются научной новизной. Более того, автор 352 ñ.
10. Êóëüáà Â.Â., Êîâàëåâñêèé Ñ.Ñ., Êàÿ÷åíêî Ñ.À., Ñèðîòþê
уверен, что за такой продолжительный срок существо- Â.Î. Òåîðåòè÷åñêèå îñíîâû ïðîåêòèðîâàíèÿ îïòèìàëüíûõ ñòðóêòóð
вания теории баз данных и теории нормализации, про- ðàñïðåäåëåííûõ ÁÄ., Ì., Ñèíòåã, 1999, 660 ñ. Òåîðèÿ íîðìàëèçà-
öèè (ñòð. 116-124). 1-3ÍÔ, Ôîðìàëüíîå îïèñàíèå îñóùåñòâëåíî â
блемы ВФЗ были затронуты, а может, и решены. К со- òåðìèíàõ êíèãè.
жалению, из всех современных книг по БД, только в кни- 11. Ìåéåð Ä. Òåîðèÿ ðåëÿöèîííûõ áàç äàííûõ. Ì.: Ìèð, 1987. -
608 ñ. Òåîðèÿ íîðìàëèçàöèè ðàñêðûâàåòñÿ â ýòîé êíèãå íàèáîëåå
ге Дейта и Мейера отдаленно затрагивается этот воп- ïîëíî. Î÷åíü ìíîãî ðåçóëüòàòîâ, ñâÿçàííûõ ñ ìíîãîçíà÷íûìè è
рос, несмотря на его первостепенную важность. Автор ñîåäèíèòåëüíûìè çàâèñèìîñòÿìè. Ðàññìàòðèâàþòñÿ êîëüöåâûå è
òàáëè÷íûå çàâèñèìîñòè, àëãîðèòìû ñèíòåçà, äåêîìïîçèöèè è ìíî-
осуществлял поиск и просмотрел большое количество ãèå äðóãèå âîïðîñû. Êíèãà äîñòàòî÷íà ñëîæíàÿ, ò.ê. ââîäèòñÿ
литературы. На поиск аналогичных разработок было по- ìíîæåñòâî äîïîëíèòåëüíûõ ïîíÿòèé, è ïåðåîïðåäåëÿþòñÿ íåêîòîðûå
ïðèâû÷íûå îïðåäåëåíèÿ.
трачено время, в 7-8 раз превышающее теоретическую 12. Ìàðòèí Äæ. Îðãàíèçàöèÿ áàç äàííûõ â âû÷èñëèòåëüíûõ ñèñ-
разработку проблемы ВФЗ. «Если теорему проще до- òåìàõ. 2-å èçä., Ì.: Ìèð, 1980.
13. Ðåâóíêîâ Ã.È., ×åòâåðèêîâ Â.Í., Ñàìîõâàëîâ Ý.Í. Áàçû è
казать, чем найти описание доказательства, то почему áàíêè äàííûõ. Ì.: Âûñøàÿ øêîëà, 1987. - 248 ñ.
это не сделать?» 14. Ôðîëîâ. À., Ôðîëîâ. Ã. Áàçû äàííûõ â Èíòåðåíåòå: ïðàêòè-
÷åñêîå ðóêîâîäñòâî ïî ñîçäàíèþ WEB-ïðèëîæåíèé ñ ÁÄ., èçä. 2-
Автор пытается акцентировать внимание на вопро- å., «Ðóññêàÿ Ðåäàêöèÿ», 2000, - 448 ñ.
сах ВФЗ. Если читатель имеет какую-либо информа- 15. Õàíñåí Ã., Õàíñåí Äæ. Áàçû äàííûõ. Ðàçðàáîòêà è óïðàâëå-
íèå, Ì., Áèíîì, 2000, - 704 ñ. Òåîðèÿ íîðìàëèçàöèè (ñòð. 200-
цию по данному вопросу, а также возражения, замеча- 210). 1-4ÍÔ, î÷åíü êðàòêî.
ния или дополнения, присылайте их по адресу 16. Öàëåíêî Ì.Ø. Ìîäåëèðîâàíèå ñåìàíòèêè â ÁÄ. Ì.: Íàóêà.
Ãë. ðåä. ôèç-ìàò.ëèò., 1989. - 288 ñ. - (Ïðîáëåìû èñêóññòâåí-
fil@ics.bmstu.ru. íîãî èíòåëëåêòà).
17. Óëüìàí Äæ., Óèäîì Äæ. Ââåäåíèå â ñèñòåìû ÁÄ. Ì.: Ëîðè,
1
2000, - 420 ñ. Òåîðèÿ íîðìàëèçàöèè (ñòð. 94-138). 1-5ÍÔ, Ïåðå-
Например, если использовать SQL-инструкцию èçäàíèå êíèãè 80 ãîäà ñ íåáîëüøèìè èçìåíåíèÿìè. Ïðèâîäÿòñÿ
Select Сотрудник, Зарплата, N_Кредитки àëãîðèòìû ïðèâåäåíèÿ â ÍÔ.
18. Óëüìàí Äæ. Îñíîâû ñèñòåì áàç äàííûõ. - Ì.: Ôèíàíñû è
From ЗАРПЛАТА AS R1, СЧЕТА AS R2 ñòàòèñòèêà, 1983. - 334 ñ. Òåîðèÿ íîðìàëèçàöèè (ñòð. 152-189).
Where R1. Сотрудник = R2. Сотрудник 1-4ÍÔ, Îäíà èç íåìíîãèõ êíèã, ñîäåðæàùàÿ ìíîæåñòâî àëãîðèòìîâ,
òåîðåì, àêñèîì äëÿ ôóíêöèîíàëüíûõ è ìíîãîçíà÷íûõ çàâèñèìîñòåé.
19. Bernstein P.A. Synthesising Third Normal Form Relations
2
Попытка создать описанную БД с заданием связей from Functional Dependencies // ACM Trans. on Database Systems.
- 1976. V. 1, ¹ 4. - Ð. 277-298.
в среде ERWin приведет к неудаче. 20. Rissanen J. Independent Components of Relations// ACM
Trans. on Database Systems. - 1977. - V. 2, ¹4. - Ð. 317-325.
3
21.Zaniolo C., Melkanoff M.A. A Formal Approach to the
Рекурсивные зависимости невозможны в реляци- Definition and the Design of Conceptual Schemata for Database
онной алгебре, называются тривиальными и исключа- Systems // ACM Trans. on Database Systems. - 1982. - V. 7, ¹.1,
- P. 24-59.
ются из множества ФЗ как избыточные. Следует раз-
личать рекурсивные и взаимные зависимости.
90
образование
компании, созданные непосредствен- широким кругом производителей лог. Каталог может быть «внутрен-
но для продажи услуг через Сеть, а экономического программного обес- ним», т.е. вложенным в тот же доку-
также фирмы, работающие в сфере печения и Интернет-компаний. Для мент, что и пакет предложений, и со-
информационных технологий. Есте- этого разработчики изначально со- ставленным непосредственно авто-
ственным путем, позволяющим вов- здавали стандарт независимо от осо- ром пакета предложений. Он также
лечь в Интернет–коммерцию широкий бенностей собственного программ- может быть «внешним» – составлен-
круг традиционных (off-line) торговых ного обеспечения или структур ин- ным одной из известных фирм. В этом
фирм, расширить сферу применения формационных баз и исходили из случае в пакете предложений огова-
Интернет–технологий и продемонст- общих принципов организации тор- ривается, на какой каталог (класси-
рировать преимущества этих техноло- говой деятельности. В то же время в фикатор) он ориентирован. Для одно-
гий продавцам и покупателям, явля- стандарте учтены различные особен- значного определения товара в пос-
ется публикация каталогов фирм на ности работы как Интернет-компа- леднем случае достаточно ссылки
специализированных Интернет-сай- ний, так и торгующих организаций. (идентификатора товара во внешнем
тах (Web-витринах). Поэтому количе- Например, решена проблема органи- каталоге), т.е. в тот же документ, что
ство Web-витрин растет, и Интернет- зации обмена информацией при не- и пакет предложений, каталог товаров
компании заинтересованы в привле- зависимой классификации товаров у можно вообще не включать. Таким об-
чении как можно большего числа тор- каждого участника обмена. разом, каталог товаров можно рас-
говых организаций. Однако этот про- Предлагаемый стандарт суще- сматривать как некий классификатор.
цесс сдерживается отсутствием стан- ственно отличается от иностранных Следовательно, в каталоге должен
дартов и готовых программно-аппа- аналогов, так как учитывает отече- быть оговорен список Свойств (по
ратных решений, а также большой ственную специфику и включает не- каким критериям производится клас-
трудоемкостью организации взаимо- сколько универсальных решений, не- сификация). Устойчивые сочетания
действия торговых организаций с обходимых для российских Интер- свойств удобно фиксировать в Набо-
Web-витринами. нет–компаний и торговых организа- ры свойств (например, «свойства ви-
ций. Вместе с тем, новый стандарт деомагнитофона», «свойства телеви-
Общее описание имеет много общего с решениями, зора»). Для указания, какие свойства
стандарта используемыми сейчас в наиболее (или наборы свойств) доступны (мо-
Разработанный стандарт позво- популярных отечественных системах гут быть определены, обязательно
ляет существенно снизить затраты на Интернет-торговли. должны быть указаны) для всего ка-
организацию информационного вза- талога, для его группы или для от-
имодействия за счет унификации об- Описание схемы дельного товара, используются Ссыл-
мена коммерческой информацией CommerceML ки на свойства (Ссылки на наборы
между различными организациями: Предусматривается использова- Свойств). Каталог (классификатор)
как выступающими на рынке Интер- ние данной схемы, в частности, для обычно создается многоуровневым
нет-коммерции, так и работающими обмена: (т.е. имеющим разветвленное дерево
в сфере традиционной (off-line) тор- n каталогами товаров; категорий (Групп), к которым можно
говли. n коммерческими предложениями; отнести товар). Иногда однозначная
Использование торговыми орга- n документами. классификация может вызвать зат-
низациями программного обеспече- руднения, поэтому для удобства раз-
ния, поддерживающего данный стан- Формирование решается включать товары сразу в
дарт, позволит им с минимальными коммерческих несколько категорий. Но при этом
усилиями и без привлечения про- предложений по одна из них должна быть выбрана в
граммистов организовать публика- каталогу качестве «основной». Например, ра-
цию своих предложений на любых Предложение практически совпа- дио-будильник можно отнести как к
поддерживающих этот стандарт Web- дает с одной строкой «обычного» категории «Радиоприемники», так и к
витринах, а также реализовать обмен прайс-листа. Предлагается такой-то категории «Будильники», но в первую
информацией между собой без спе- товар по такой-то цене, имеющийся в очередь, радио-будильник является
циальной доработки программ. На- наличии в таком-то количестве. Напри- радиоприемником. При разработке
пример, при оприходовании товаров мер, гречневая крупа по цене 200 руб- классификаторов принято для каждой
у покупателя информация о хозяй- лей за мешок, на складе имеется 125 позиции указывать Аналоги (напри-
ственной операции может быть авто- мешков. Предложения группируются в мер, для лекарства это – другие ле-
матически загружена из данных, по- Пакет предложений, в котором зада- карства аналогичного действия, для
лученных от продавца. ется общая часть всех предложений запчастей – запчасти, которые мож-
Разработчики стремились обес- (аналог «шапки» прайс-листа). но поставить вместо данной).
печить максимальную открытость Для того чтобы получатели пред- Указание, какими собственно
стандарта с тем, чтобы он в дальней- ложений могли понять, какой товар свойствами из заданных в каталоге
шем мог развиваться на основании предлагается, последний должен быть может обладать товар (или группа),
объективных потребностей рынка и описан. Описание товара и его клас- достигается с помощью Ссылки на
поддерживаться как можно более сификация «складываются» в Ката- свойство (при этом еще можно задать
92
образование
ко каталогов товаров, включая список °ÔÒÒËÖÝË×ÐÆå®ÓÚÔÖÒÆÜÎå
возможных свойств товаров в катало- >°ÔÒÒËÓØÆÖÎÏ VWULQJ@
ге, один или несколько пакетов пред- !
ложений. °ÔÓØÖÆÉËÓØ!@
Атрибуты: Таблица №1 > ·ÐÑÆÊ!@
×ÎÓØÆÐ×Î×
> §ÆÓÐ!@
Содержит: Каталог (0-*), ПакетП- VHT
> °ÆØÆÑÔÉ!@
редложений (0-*), Контрагент (0-*), > µÆÐËØµÖËÊÑÔÌËÓÎÏ!@
Документ (0-*), Банк (0-*), Склад (0-*). > ªÔÐÙÒËÓØ!@
°ÔÒÒËÖÝË×ÐÆå®ÓÚÔÖÒÆÜÎå!
РасчетныйСчет ×ÔרÆÈ HOW2QO\
(BankAccount) ÕÔÖåÊÔÐ VHT
Описание: Расчетный счет описы- ÈáÞËרÔåßÎË1RSDUHQWVIRXQG7KLVLVSUREDEO\WKHGRFXPHQWHOHPHQW
ÊÔÝËÖÓÎË §ÆÓЪÔÐÙÒËÓØ°ÆØÆÑÔɰÔÓØÖÆÉËÓØµÆÐËØµÖËÊÑÔÌËÓÎÏ·ÐÑÆÊ
вает банковский счет контрагента в
ÆØÖÎÇÙØá °ÔÒÒËÓØÆÖÎÏ
объеме, необходимом для оформле- ÒÔÊËÑâ RSHQÕÔÙÒÔÑÝÆÓÎä
ния (и передачи) документов.
Атрибуты: Таблица №2 <ElementType name=»Êîììåð÷åñêàÿÈíôîðìàöèÿ» content=»eltOnly» order=»seq»>
Содержит: ДополнительныйРек- <description> Ñîáèðàòåëüíûé ýëåìåíò äëÿ âñåãî, ÷òî ìîæåò áûòü óïîìÿíóòî â ïðîöåññå
îáìåíà</description>
визит (0-*). <AttributeType name=»Êîììåíòàðèé» dt:type=»string» required=»no»>
description>Ïðåäíàçíà÷åí äëÿ ïåðåäà÷è «ñîïðîâîäèòåëüíîé çàïèñêè» â âèäå ïðîèçâîëü-
íîé òåêñòîâîé èíôîðìàöèè ïî äîêóìåíòó.</description>
Контакт (Contact) </AttributeType>
Описание: Контакт предназначен <attribute type=»Êîììåíòàðèé»/>
<element type=»Êîíòðàãåíò» minOccurs=»0" maxOccurs=»*»/>
для ответа на вопросы: «Где найти?» <element type=»Ñêëàä» minOccurs=»0" maxOccurs=»*»/>
и «Кого спросить?». <element type=»Áàíê» minOccurs=»0" maxOccurs=»*»/>
<element type=»Êàòàëîã» minOccurs=»0" maxOccurs=»*»/>
Содержит список ФИО контактных <element type=»ÏàêåòÏðåäëîæåíèé» minOccurs=»0" maxOccurs=»*»/>
лиц (например, список сотрудников <element type=»Äîêóìåíò» minOccurs=»0" maxOccurs=»*»/>
</ElementType>
отдела продаж), список телефонов,
факсов, адресов электронной почты
контакта, ICQ. жет быть упомянуто в процессе обме- те. В стандарте учтены различные
Атрибуты: Таблица №3 на. аспекты работ как интернет-компа-
Содержит: КонтактноеЛицо (0-*), <description> - предназначен для пе- ний, так и обычных предприятий.
Телефон (0-*), Факс (0-*), Почта (0- редачи «сопроводительной записки» Стандарт предлагает подробную схе-
*), ICQ (0-*). в виде произвольной текстовой ин- му обмена с описанием атрибутов и
формации по документу. представлением её в виде кода
Пример структуры XML- Представленный стандарт обме- HTML. Это соглашение является важ-
схемы в формате HTML. на коммерческой информацией дает ным шагом, позволяющим расши-
<КоммерческаяИнформация> соби- возможность организациям обмени- рить сферу применения Интернет-
рательный элемент для всего, что мо- ваться информацией в одном форма- технологий на российском рынке.
женщина и компьютер
Уступите
место
женщине!
С древних времен отношения меж- Светлана через свое агентство нашла Для себя с Мариной мы отметили
ду полами складывались на основании нам несколько серьезных работодате- следующее: в этих фирмах никто не по-
физического превосходства. Такие от- лей и оформила нас на собеседования. интересовался нашим уровнем профес-
ношения остались и сегодня. До сих пор Вакансии были выбраны такие: систем- сионализма.
«положено», что мужчина – сильный ный администратор, тестировщик, про- Еще скажу пару слов о размерах
пол – занимается тяжелой работой и граммист. заработной платы: у женщин оплата
добыванием еды, а женщина – слабое Мы ожидали услышать байки про труда, в основном, все-таки ниже, чем
создание – должна рожать детей и дер- глупеньких девушек, которые готовы у мужчин. По данным все того же кад-
жать в порядке дом. Мужчина – силь- упасть в обморок, когда их просят дать рового агентства, средний уровень за-
ный, а женщина – мудрая. Только се- «подмышку», долго ищут ту кнопку, работной платы для мужчины-програм-
годня все немного перепуталось: для которая все выключает, или путает мо- миста Oracle составляет $600 - $800 в
добывания еды мужчине не надо боль- нитор с телевизором. Однако ответы месяц (в отдельных местах, до $1200),
ше ходить на охоту, а достаточно весь были совершенно неожиданными. а женщинам платят всего $200 - $400.
день просидеть у экрана монитора, на- Первый ответ был больше похож на Причем, малейшая профессиональная
жимая кнопочки. И чем эта работа та- отмазку: в объявлении говорилось, что ошибка, допущенная женщиной-про-
кая тяжелая и трудоемкая? Сегодня фирма не против взять студента стар- граммистом, рассматривается коллега-
такие профессии, как системный адми- ших курсов технического ВУЗа с базо- ми с пристальным вниманием.
нистратор или программист приобрели выми знаниями MS SQL 7.0/2000. В Наша собственная статистика тако-
метку сугубо мужского способа зара- фирме же мне сказали, что брать сту- ва: из 16 фирм, в которые были направ-
батывания кучи денег. Сегодня эти спе- дентку они не намерены, при этом не лены наши резюме, только восемь не
циальности очень престижны и высо- объясняя конкретной причины. С Мари- остались без ответа (учитывая, что кад-
кооплачиваемы в России (не совсем ной же была проведена беседа о «лич- ровое агентство уже проводило первич-
так, глав.ред.), а тем более за рубежом. ном», где подробно допытывались ин- ное собеседование), а из восьми ока-
А почему бы женщине не заняться та- формации о ее семейном положении. залось 6 отказов.
кой простой работой – и мудрость мож- В итоге ответ был весьма суров: «Де- Так что же теперь? Неужели нам,
но применить, и физической нагрузки вушку на работу не возьму… Девушка женщинам, так и не суждено найти ра-
практически никакой. Так почему же становится мамой, а программирова- боту по специальности? Напротив!
женщине так тяжело найти работу в ние – это…», и далее - длинный моно- Женщина своего добьется! В различ-
этих отраслях? Почему даму неохотно лог о непрерывности и качественности ного рода компаниях, занимающихся
берут на работу даже тестером, не го- интеллектуального процесса. разработками бухгалтерского про-
воря уже о программистах? В другом, исключительно мужс- граммного обеспечения, в торговых
Столкнувшись с такой дискримина- ком коллективе, честно признались, центрах, в банках, да и во многих дру-
цией по половому признаку, мы с под- что если в отделе будет постоянно гих местах успешно работают женщи-
ругой решили провести небольшое ис- находиться женщина (особенно мо- ны: WEB-дизайнеры, системные адми-
следование в этой области (а заодно и лодая), то работать будет тяжелее: нистраторы, координаторы техническо-
устроиться на работу), прибегнув к по- придется каждый день бриться, сле- го отдела, системные аналитики, да и
мощи приятельницы, которая работает дить за чистотой рубашек, контроли- программисты-разработчики тоже. Не-
в агентстве по трудоустройству. ровать свою речь и вообще соответ- смотря ни на что, самые настойчивые
Резюме выглядели следующим об- ствовать «стандарту». Вывод был и упрямые все-таки умудряются добить-
разом: я - студентка шестого курса однозначен – присутствие барышни, ся потрясающих результатов. И мы с
МГТУ им. Баумана, знания СУБД: безусловно, нарушит гармонию в Мариной тоже добились-таки того, к
Access, MS SQL 7.0, администрирова- этом коллективе, и нас здесь не чему стремились! Она стала работать
ние 1С-Предприятие 7.7; базовые зна- ждут… А Светлана со своей стороны в одной из ведущих компаний по раз-
ния бухучета, опыт Web-разработок, узнала от руководителя отдела, авто- работке программного обеспечения для
знание английского языка. Марина – в ра многочисленных научных публика- компаний сотовой связи, я же устрои-
этом году закончила МГТУ с красным ций с педагогическим образованием, лась системным администратором в
дипломом, имела разовый опыт разра- что русского литературного языка не торговый центр. Так что вывод один:
ботки программы для небольшой фир- хватает для постановки задачи, поэто- при правильном подходе выживет силь-
мы, знания: Delphi, MS SQL 7.0, базо- му он не сможет корректно поставить нейший — будь это мужчина или жен-
вые знания 1С, технический английский задачу женщине-программисту, т.е. щина, надо только быть настойчивым!
+ разговорный, начала изучение C++. без нормативной лексики… Евгения Саблина
94
женщина и компьютер
Почему их
мало
в компьютерных
компаниях
Бурно развивающийся бизнес в состав гормонов чувства и гормонов туации реагируют на ситуацию, а жен-
сфере компьютерных технологий инте- действия у мужчин и женщин, то карти- щины – на раздражитель. Мужчины ста-
ресует многих людей. Привлекатель- на будет выглядеть примерно так: на раются найти деловое решение, а жен-
ность работы в крупной компьютерной одну часть гормонов чувства у мужчин щины – выйти из ситуации с минималь-
фирме состоит из нескольких момен- приходится около тысячи частей гормо- ными потерями для себя.
тов. Один из них – реальная возмож- нов действия, а у женщин – с точнос- Ещё одна особенность таких фирм
ность заработать деньги. Второй – пер- тью до наоборот: на одну часть гормо- в том, что по роду деятельности про-
спектива достаточно быстрого продви- нов действия приходится в тысячу раз граммистам часто приходится рабо-
жения по служебной лестнице, третий - больше гормонов чувства. Получается, тать вдвоём, в «тандеме». И от взаи-
шанс показать себя, проявить свои спо- что основная деятельность женщин – моотношений друг с другом часто за-
собности. Именно так или подобным об- чувства, а основная деятельность муж- висит результат такой работы. Здесь
разом отвечают молодые люди в воз- чин – действие. И когда мужчина начи- тоже есть несколько моментов. При
расте 22-28 лет на вопрос о причинах, нает много чувствовать, а женщина – работе в паре один из специалистов
побудивших их к поиску работы в ком- много действовать, нарушается гормо- становится ведущим, другой – ведо-
пьютерной компании. Основной состав нальный баланс в организме. Ничего мым. При этом роли часто меняются.
персонала бурно развивающихся ком- хорошего из этого, как Вы сами пони- Мужская психика довольно спокойно
пьютерных фирм – именно такие моло- маете, выйти не может. Да и при рас- реагирует на смену ролей, так как
дые ребята, со свежими мозгами, оп- смотрении ситуации взаимоотношений дело важнее. А вот женская – нет.
тимизмом и желанием преобразовать в группе видно различное отношение Выше я уже писал, что для женщины
окружающий мир. Есть, правда, одна женского коллектива к мужчинам, при- важно отношение к ней. И по этой при-
особенность: женщин в такие компании сутствующих в нем, или мужского – к чине смена ролей для женщины не
берут на работу достаточно неохотно. 1-2 женщинам в том же положении. всегда происходит безболезненно.
Анализ состава компаний говорит о Если женщины в такой ситуации будут Часто эти перемены роли восприни-
том, что компьютерный бизнес преиму- чувствовать себя комфортно, то муж- маются как покушение на безопас-
щественно мужской. И причин для это- чины просто заработают невроз, пото- ность, что, соответственно, может
го достаточно много. Прежде всего, му что женщине важно отношение к вызвать совершенно непредсказуе-
различна мотивация. Для мужчин важ- ней, а мужчине – отношение к тому, что мую реакцию. По этой причине не-
но достижение поставленной цели, они, он делает. большие компании, состоящие из 5-7
собственно, для этого и предназначе- Специфика работы в компьютерной человек, являются достаточно замк-
ны – преобразовывать окружающий фирме такова, что часто персоналу при- нутыми сообществами мужчин, а в
мир. Для женщин же характерно жела- ходится работать в стрессовой ситуа- крупных компьютерных компаниях
ние сохранения жизни. И довольно ча- ции (например, сдача проекта, который женщины занимают должности, свя-
сто представительницы прекрасного по каким - либо причинам «не идёт»). А занные с административной работой.
пола идут на работу в такие компании восприятие стресса у мужчин и женщин Да простят меня воинствующие фе-
не от хорошей жизни. Медицинская ста- различно - мозг реагирует по-разному. министки, но для женщин есть много ра-
тистика, в свою очередь, показывает, У женщин в момент опасности, пусть бочих мест, где востребованы замеча-
что, как бы компьютеры не были совер- даже гипотетической, в работу включа- тельные женские качества: сострада-
шенны, они больше предназначены для ются все мозговые центры и отключа- ние, чувствительность, женская интуи-
мужчин, чем для женщин. В психологи- ются только после того, как опасность ция, умение эффективно работать в мо-
ческом плане, компьютерный бизнес перестаёт существовать. У мужчин в нотонном режиме (от которого мужчи-
предполагает больше работу в систе- момент опасности включается только ны сходят с ума), ассоциативное мыш-
ме «человек – знак» и требует именно один конкретный мозговой центр, дея- ление, стремление выжить, умение со-
логического мышления - правополу- тельность которого через 7-10 минут здать комфорт и уют. Без женщин не
шарного. Женщинам же больше свой- угасает, если опасность не подтверж- обходится ни одна сфера жизнедея-
ственно эмоциональное мышление - ле- дена другими центрами, отвечающими тельности, просто давайте заниматься
вополушарное. Даже гормональный со- за реагирование на конкретный вид тем, для чего мы предназначены.
став у мужчин и женщин сильно отли- раздражителя. И получается, что муж- Вячеслав Михалёв,
чается. Если сравнить количественный чины при возникновении стрессовой си- психолог.
РУКОВОДИТЕЛЬ ПРОЕКТА
НОМЕРЕ:
Петр Положевец
РЕДАКЦИЯ
Главный редактор Тема номера посторонними лицами для доступа к
Александр Михалев конфиденциальной информации и
chief@samag.ru БЕЗОПАСНОСТЬ нарушения работы системы, вплоть
Ответственный секретарь Интервью с начальником до полной потери данных и работос-
Наталья Хвостова «Управления Р» пособности.
sekretar@samag.ru Александром Слуцким Основными пользователями сис-
Был уже восьмой час вечера. В тем аудита безопасности являются
Художник кабинете начальника отдела по борь- профессионалы: сетевые админист-
Игорь Усков бе с компьютерными преступлениями раторы, специалисты по безопаснос-
igus@samag.ru Александра Слуцкого обсуждались ти и т.д. Простые пользователи тоже
Верстка детали завтрашнего «оперативного могут использовать сканеры, но ин-
Владимир Положевец мероприятия». Собирались брать ма- формация, выдаваемая такими про-
imposer@samag.ru терого хакера. Когда детали завтраш- граммами, как правило специфична,
Владимир Лукин него рейда намеченного между про- что ограничивает возможности ее ис-
maker_up@samag.ru чим на 6 утра были согласованы, пользования неподготовленным чело-
Александр Сергеевич извинился, до- веком.
РЕКЛАМНАЯ СЛУЖБА стал из сумки котлету и начал устало
тел./факс:(095) 298-0316 ее поглощать. «Вы меня извините, я МЫТАРСТВА
Наталья Хохлова еще не завтракал». Собственно я и БЛАЖЕННОГО
тел.:(095) 928-8253 (доб. 112) сам уже понял, что работа самого ин- СИСАДМИНА
Наталья Политыко теллектуального «хакерского» отдела Большинство системных админи-
reklama@samag.ru не сахар. страторов не выбирают эту карьеру,
она предназначена им судьбой.
103012, г. Москва, Ветошный Создание простейшей Меня судьба взяла за шкирку и по-
переулок, дом 13/15 статистики для Internet садила в сисадминское кресло со-
тел.: (095) 928-8253 (доб. 112) Service Providers вершенно случайно. Я работал про-
факс: (095) 928-8253 В большенстве случаев, при со- граммистом в одной государствен-
Е-mail: info@samag.ru здании ISP, самым главным вопро- ной конторе и однажды имел несча-
Internet: www.samag.ru сом становится — построение на пер- стье попасться на глаза шефа в не
вых порах простейшего биллинга: совсем трезвом состоянии. Дело
ИЗДАТЕЛЬ подсчет количества времени и денег, было в 10 часов утра — самое, что
ЗАО «Редакция «Учительской затраченных пользователем в ни на есть, рабочее время. Есте-
газеты» Internet’e. ственно, на следующий день меня
В этом нет ничего сверхсложно- вызвали на ковер и заявили, что
Отпечатано ЗАО «Холдинговая го, но попробуем разобраться, и по- быть мне отныне... ни за что не по-
компания «Блиц-информ». стараемся создать простейший бил- верите — «системным администра-
Образцовая типография «Блиц- линг. Добавлять что-либо Вы сможе- тором»!
принт» г. Киев, ул. Довженко, 3 те сами или наоборот — убирать: как
Тираж 5000 экз. Вам будет угодно. Продолжение статьи
про механизм отражений
Журнал зарегистрирован Cравнение сетевых в Java.
В Министерстве РФ по делам пе- сканеров безопасности «Я постараюсь рассказать о са-
чати, телерадиовещания и Сканер безопасности - это про- мом нетривиальном механизме мира
средств массовых коммуникаций граммное средство для удаленной или отражений — создании собственных
(свидетельство ПИ № 77-12542 локальной диагностики различных загрузчиков классов, а также о том,
от 24 апреля 2002 г.) элементов сети на предмет выявле- как компилировать новые классы из
ния в них различных уязвимостей, исходного Java-текста для передачи
которые могут быть использованы собственному загрузчику».
96