WWW.DISSERS.RU

БЕСПЛАТНАЯ ЭЛЕКТРОННАЯ БИБЛИОТЕКА

   Добро пожаловать!

Pages:     || 2 | 3 | 4 | 5 |   ...   | 7 |
-- [ Страница 1 ] --

Perl для системного администрирования Дэвид Я. Бланк-Эделъман Canlm /iCj Lx Lx '/ Дэвид Н. Бланк-Эдельман Perl для системного

администрирования Перевод!. Морозовой Главный редактор А. Галунов Зав. редакцией Н. Макарова Научный редактор В. Коновалов Редакторы Л. Ага, В. Овчинников Корректура С. Беляева, С. Журавина Верстка Н. Гриценко Дэвид Н. Бланк-Эдельман Perl для системного администрирования. - Пер. с англ. - СПб: Символ-Плюс, 2001.-496 с., ил.

ISBN 5-93286-024-3 Эта книга будет полезна администраторам с различным уровнем опыта- от обычных пользователей Linux до администраторов крупных систем. Автор рас сматривает основные платформы, включая Unix, Windows NT/2000 и MacOS.

При наличии некоторого опыта программирования на Perl вы узнаете, как при помощи этого языка повысить производительность во многих областях, включая: управление учетными записями пользователей;

наблюдение за файловой системой и отслеживание процессов;

работу с сетевыми службами имен NIS и DNS;

администрирование баз данных при помощи DBI и ODBC;

ра боту со службами каталогов LDAP и ADSI;

обработку и анализ файлов журна лов регистрации;

поддержку защищенной сети;

наблюдение за удаленными устройствами средствами SNMP.

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

ISBN 5-93286-024- ISBN 0-56592-609-9(англ) © Издательство Символ-Плюс, 2001 "" ^^- Authorized translation of the English edition © 2000 O'Reilly & Associates Inc. This translation is published and sold by permission of O'Reilly & Associates Inc., the own er of all rights to publish and sell the same.

Все права на данное издание защищены Законодательством РФ, включая право на полное или час тичное воспроизведение в любой форме. Все товарные знаки или зарегистрированные товарные зна ки, упоминаемые в настоящем издании, являются собственностью соответствующих фирм.

Издательство «Символ-Плюс». 193148, Санкт-Петербург, ул. Пинегина, 4, тел. (812) 324-5353, edit@symbol.ru. Лицензия ЛП № 000054 от 25.12.98.

Подписано в печать 06.09.2001. Формат ТОхЮО1/^- Бумага офсетная.

Печать офсетная. Объем 31 печ. л. Тираж 3000 экз. Заказ № 1533.

Отпечатано с диапозитивов в ФГУП «Печатный двор» им. А. М. Горького Министерства РФ по делам печати, телерадиовещания и средств массовых коммуникаций.

197110, Санкт-Петербург, Чкаловский пр., 15.

Оглавление Предисловие 1. Введение Системное администрирование - это ремесло Какой помощи ждать от Perl Эта книга покажет вам, как Что вам нужно Поиск и установка модулей Нелегко быть всемогущим Ссылки на подробную информацию 2. Файловые системы Perl приходит на помощь Различия файловых систем Прогулка по файловой системе Обход файловой системы при помощи модуля File::Find Работа с дисковыми квотами Получение сведений об использовании файловой системы Информация о модулях из этой главы Источники подробной информации гп 3. Учетные записи пользователей ш Информация о пользователях в Unix Информация о пользователях в Windows NT/2000 Создание системы учетных записей для работы с пользователями <. Информация о модулях из этой главы Рекомендуемая дополнительная литература !':'.

4. Действия пользователей Управление процессами в MacOS Управление процессами в NT/2000 Управление процессами в Unix Отслеживание операций с файлами и сетью Оглавление Информация о модулях из этой главы Рекомендуемая дополнительная литература 5. Службы имен TCP/IP Файлы узлов NIS, NIS+ и WINS Служба доменных имен (DNS) Информация о модулях из этой главы Рекомендуемая дополнительная литература 6. Службы каталогов Что такое каталог? Finger: простая служба каталогов Служба каталогов WHOIS LDAP: сложная служба каталогов ADSI (Интерфейсы служб активных каталогов) Информация о модулях из этой главы Рекомендуемая дополнительная литература 7. Администрирование баз данных SQL Взаимодействие с SQL-сервером из Perl Использование DBI Использование ODBC Документирование сервера Учетные записи баз данных Мониторинг состояния сервера Информация о модулях из этой главы Рекомендуемая дополнительная литература 8. Электронная почта Отправка почты.'V Распространенные ошибки при отправке почты *.;

Получение почты Информация о модулях из этой главы Рекомендуемая дополнительная литература 9. Журналы Текстовые журналы Двоичные журналы Данные с состоянием и без Проблемы с пространством на диске Анализ журналов Оглавление Информация о модулях из этой главы Рекомендуемая дополнительная информация 10. Безопасность и наблюдение за сетью Обращаем внимание на неожиданные или несанкционированные изменения Обращайте внимание на подозрительную активность Протокол SNMP Опасность на проводе Предотвращение подозрительных действий Информация о модулях из этой главы Рекомендуемая дополнительная литература A. Пятиминутное руководство по RCS B. Десятиминутное руководство по LDAP C. Восьмиминутное руководство по XML D. Пятнадцатиминутное руководство по SQL E. Двадцатиминутное руководство по SNMP Алфавитный указатель Об авторе Дэвид Н. Бланк-Эделъман - директор по технологиям факультета вы числительной техники Северо-восточного Университета (Northeas tern University College of Computer Science). Последние 14 лет он рабо тал системным и сетевым администратором на больших многоплат форменных системах в Brandies University, в технологической группе Кэмбриджа (Cambridge Technology Group) и лаборатории MIT. Кроме того, он является главным техническим редактором журнала «The Perl Journal» и написал немало статей о музыке разных стран. В сво бодное время он учится играть на мбире - традиционном музыкальном инструменте Зимбабве.

Предисловие Perl - это мощный язык программирования, уходящий корнями в за дачи традиционного системного администрирования. В течение мно гих лет он адаптировался и расширялся для работы с новыми операци онными системами и новыми задачами. До сих пор, однако, не было ни одной книги, посвященной использованию Perl исключительно для системного администрирования, тем самым признавая факт глубокой исторической связи.

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

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

Глава 1 «Введение» Во введении описан материал, детально рассмотренный далее в кни ге, рассказано, как он может послужить и что нужно для того, чтобы получить от него максимальную пользу. В этой книге рассмотрен серьезный материал и считается, что он будет использован «влия тельными» пользователями (например, привилегированными поль зователями в Unix или администраторами Windows NT/2000). Кро ме того, введение содержит важные советы, помогающие писать бо лее безопасные программы на Perl.

Глава 2 «Файловые системы» Эта глава о том, как содержать в порядке и правильно использовать различные многоплатформенные файловые системы. Мы начнем с рассмотрения принципиальных различий между файловыми систе мами каждой из операционных систем. Затем мы рассмотрим про цесс исследования файловой системы средствами Perl и расскажем, когда это может оказаться полезным. И, наконец, мы узнаем, как работать с дисковыми квотами из Perl.

10 Предисловие Глава 3 «Учетные записи пользователей» В этой главе рассказано о том, что собой представляют учетные за писи на двух различных операционных системах. Основная часть главы - простейшая система ведения учетных записей, написанная на Perl. В процессе построения этой системы мы рассмотрим меха низмы, необходимые для записи учетных записей в простую базу данных, основанную на XML, а также механизмы для создания учетных записей и их удаления.

Глава 4 «Действия пользователей» В главе 4 рассмотрены различные механизмы управления процес сами для всех трех операционных систем от самых простых (напри мер, процессов в MacOS) до более сложных (в WinNT/2000). Мы ор ганизуем работу этих механизмов с помощью вспомогательных сце нариев. И, наконец, мы узнаем, как средствами Perl проследить за операциями с файлами и за сетью.

Глава 5 «Службы имен TCP/IP» Службы имен позволяют узлам в сети TCP/IP общаться друг с дру гом. В этой главе отражена вся история развития, начиная с файлов узлов, продолжая сетевой информационной службой (NIS) и закан чивая связующим звеном в Интернете - доменной службой имен (DNS). Для каждого шага такого пути мы покажем, как можно уп ростить профессиональную работу с этими службами при помощи Perl.

Глава 6 «Службы каталогов» По мере роста сложности рассматриваемой информации растет и важность служб каталогов, которые мы используем для доступа к этой информации. Хорошо, если системные администраторы будут не просто использовать эти службы, но и создавать собственные инструменты для работы с ними. В этой главе рассказано о некото рых из наиболее популярных служб, таких как LDAP и ADSI, а также показано, как с ними работать при помощи Perl.

Глава 7 «Администрирование баз данных SQL» Очень часто в сферу действий системного администратора попадает и работа с реляционными базами данных. А значит, системные ад министраторы должны быть знакомы с администрированием баз данных SQL. В этой главе рассмотрены два механизма для работы с базами данных - DBI и ODBC, а также приведены примеры их ис пользования.

Глава 8 «Электронная почта» В этой главе показано, как с помощью Perl лучше использовать электронную почту в качестве инструмента системного админист рирования. После обсуждения основ отправки и разбора электрон ной почты с помощью Perl мы рассмотрим несколько интересных Предисловие приложений, включая анализатор спама и средство обработки электронной почты в службу технической поддержки.

Глава 9 «Журналы» Системные администраторы зачастую просто утопают в море фай лов журналов. Каждая машина, операционная система и програм ма может вести (и часто это делает) журналы. В этой главе рассмот рены системы ведения журналов в Unix и в WinNT/2000. Мы обсу дим подходы к анализу такой информации с целью заставить ее ра ботать на вас.

Глава 10 «Безопасность и наблюдение за сетью» В последней главе мы обсудим вопросы, связанные с безопас ностью. Мы покажем, как Perl может помочь сделать сеть и отдель ные узлы в ней более защищенными. Кроме того, мы расскажем о некоторых технологиях контроля, включая использование прото кола SNMP (простой протокол управления сетью) и «прослушива ние» сети.

Приложения В некоторых главах предполагается, что у вас уже есть знания по определенным темам, в то время как этого может и не быть. Для тех, кто не знаком с отдельными темами этой книги, есть несколько мини-руководств, которые помогут быстро разобраться в их осно вах. В число этих руководств входят введение в систему контроля версий (RCS), введение в протокол LDAP (облегченный протокол доступа к каталогам), введение в SQL, XML и протокол SNMP.

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

Моноширинный шрифт Используется для выделения имен модулей и функций Perl, а так же примеров исходного кода и результатов выполнения команды.

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

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

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

O'Reilly & Associates, Inc.

101 Morris Street Sebastopol, CA (800) 998-9938 (в США и Канаде) (707) 829-0515 (международный/местный) (707) 829-0104 (факс) Кроме того, вы можете прислать нам письмо электронной почтой. Что бы подписаться на наш список рассылки или запросить каталог, по шлите письмо по адресу:

info@oreilly.com Чтобы задать технические вопросы или прислать комментарий к кни ге, пишите по адресу:

bookquestions@oreilly.com Кроме того, у нас есть веб-сайт, посвященный специально этой книге.

Там приведены примеры, список найденных ошибок и рассказано о плане следующих изданий. Эта информация доступна по адресу:

http://www.oreilly.com/catalog/perlsysadmin/ Подробную информацию об этой и других книгах вы найдете на веб сайте издательства O'Reilly:

http://www.oreilly.com Благодарности Работа над книгой оказалась жребием, очень напоминающим стро ительство классической арки. Она также начиналась с двух колонн в моей жизни, которые сошлись вместе, - технической и личной.

С технической «точки зрения» я глубоко признателен Ларри Уоллу, который не только создал Perl, но и вдохнул в него (да и во все сооб щество Perl-программистов) особый дух. Я благодарен великим учите лям - Тому Кристиансену и Рэндаллу Шварцу, которые помогли мне и бесчисленному количеству людей разобраться со всеми тонкостями языка. Выше по этой колонне стоят программисты, которые потратили уйму времени и энергии на работу с языком, а затем решили поделить ся со мной и со всем остальным сообществом Perl-программистов ре зультатами своей работы. При любой возможности я стараюсь упомя 14 Предисловие Я особенно благодарен членам группы CCS Systems, которые предоста вили мне пространство, время и терпение, необходимые для работы с этой книгой. Ларри Финкельштеин - декан колледжа компьютерных наук — также заслуживает особого упоминания. Я никогда не встречал человека вне системного администрирования, который лучше бы по нимал системных администраторов, их нужды и всю эту область в це лом. Он продолжает учить меня, особенно на примерах, что означает быть настоящим лидером.

Давайте вернемся к метафоре арки, поскольку мы уже почти на вер шине. Здесь мы найдем всю мою семью. Я благодарен всем им. Основа моей семьи - Майра, Джейсон и Стивен Бланк - это те люди, чей ха рактер и воспитание (и любовь) в течение многих лет позволили мне сейчас быть с вами. Мои благодарности - Шиммеру и Бендиру, неред ко составлявшим мне приятную компанию в написании этой книги, засиживаясь за компьютером до раннего утра. Большое спасибо Крис тену Портеру и Тому Доновану из ТСМ.

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

Эта книга посвящается Синди - любви всей моей жизни.

• Системное администрирование это ремесло • Чем может помочь Perl • Эта книга покажет вам, как • Что вам нужно • Поиск и установка модулей • Нелегко быть всемогущим • Ссылки на подробную информацию Введение Системное администрирование - это ремесло В моем городе есть несколько троллейбусных линий. Однажды, когда я поехал по незнакомому маршруту, я попросил водителя предупре дить меня, когда мы будем подъезжать к нужной мне улице. Но он от ветил: «Извините, я не смогу. Я ведь еду только по проводам».

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

Какой помощи ждать от Perl В работе системного администратора используется любой и всякий язык программирования, если его применение приносит пользу. Так почему же в этой книге выбран именно Perl?

16 Глава 1. Введение Ответ на этот вопрос слышится в самой природе системного админист рирования. Реми Эвард, мой друг и коллега, однажды описал работу системного администратора такими словами: «С одной стороны, у тебя есть набор ресурсов: компьютеры, сети, программное обеспечение и т. д. А с другой стороны, есть пользователи со своими нуждами и про ектами - люди, которые хотят, чтобы их работа выполнялась. Наша задача заключается в том, чтобы состыковать эти два множества опти мальным способом, являясь при необходимости посредником между кругом расплывчатых нужд людей и техническим миром».

Системное администрирование - это зачастую склеивание;

Perl - один из наиболее подходящих для этого языков. Perl использовался для системного администрирования задолго до того, как появился WWW со всеми своими требованиями к механизмам склеивания.

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

• Это очевидный потомок различных командных интерпретаторов Unix и языка С - то, чем многие системные администраторы уве ренно владеют.

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

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

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

• Многочисленное и преданное сообщество пользователей потратило несметное количество часов на создание модулей практически для каждой задачи. Как правило, эти модули тщательно организованы (мы вскоре к этому вернемся). Такая поддержка от сообщества мо жет быть очень значительной.

• На Perl просто интересно программировать.

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

• Механизм объектно-ориентированного программирования в Perl несколько странен. В этом отношении Python гораздо лучше.

• Perl доступен не везде. На только что установленной системе вы скорее найдете командный интерпретатор Борна, а не Perl.

• Perl не всегда прост и последователен и он довольно запутан. В Tel гораздо меньше сюрпризов.

Эта книга покажет вам, как • Perl достаточно непрост в использовании, чтобы заставить вас не раз наступить на грабли.

Мораль такова - всегда выбирайте подходящий инструмент. Таким инструментом для меня чаще всего бывал Perl, поэтому и появилась эта книга.

Эта книга покажет вам, как В телевизионном шоу «Бэтмэн», популярном в 1966-1968 годах, у энергичной парочки были чудо-пояса с инструментами. Если Бэтмэну и Робину нужно было взобраться на здание, Бэтмэн говорил: «Быст рый Робин, абордажный крюк!». Или же Бэтмэн говорил: «Быстрый Робин, нокаутирующий газ!», и тут же нужный инструмент для борь бы с плохими парнями оказывался в руках у каждого. Цель этой кни ги - снабдить читателя таким поясом, необходимым для того, чтобы хорошо выполнять работу системного администратора.

В каждой главе вы найдете:

Понятную и четкую информацию о сфере действий системного адми нистратора В каждой главе мы подробно рассказываем об одной из сфер дейст вий системного администрирования. Число возможных сфер дейст вий при многоплатформенном системном администрировании слиш ком велико, чтобы рассказать обо всем в одной книге. Лучшие кни ги по системному администрированию в Unix- «Essential System Administration» (Суть системного администрирования) Элен Фриш (ЛЕ1ееп Frisch) (O'Reilly & Associates) и «Unix System Administration Handbook» (UNIX: руководство системного администратора) Эви He мет (Evi Nemeth), Гарта Снайдера (Garth Snyder) и Трента Р. Хейна (Trent R. Hein) (Prentice-Hall) - одна в два, а другая в три раза больше этой работы. Мы же рассмотрим вопросы, относящиеся к трем различным операционным системам: Unix, Windows NT/ и MacOS.

В результате, приходилось выбирать, что включить в книгу, а что отложить. Были исключены темы, которые, на мой взгляд, приоб ретут существенно большее значение только в последующие пять лет. А такие важные технологии, как XML, были рассмотрены, по тому что в ближайшее время они, наверняка, окажут заметное вли яние на всю эту область. К сожалению, этот подход привел к тому, что такие вечные вопросы системного администрирования, как ре зервное копирование и печать, были вытеснены более новыми тема ми, подобными LDAP и SNMP. Навыки и инструменты, представ ленные в этой книге, могут помочь в тех областях, которые я про пустил, но детальные описания нужно искать где-то в другом месте.

БИБЛИОТЕКА Г Г'Х IB - Глава 1. Введение Я попытался собрать вместе достаточно информации о системном и сетевом администрировании для людей с различным уровнем опы та. Опытные профессионалы и новички могут почерпнуть из этой книги совершенно разную информацию, но каждый из них найдет для себя что-то интересное. В конце каждой главы приведен список источников информации, которые могут помочь глубже разоб раться с выбранной темой.

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

Технологии и подходы Perl, которые можно использовать в систем ном администрировании Чтобы извлечь из книги все возможное, необходимо владеть неко торыми основами Perl. В каждой главе достаточно много разных по сложности программ, иногда простых и доступных новичкам, а по рой требующих довольно серьезного знания Perl. Если будет встре чаться технология, структура данных или идиома среднего или по вышенного уровня сложности, я потрачу время, чтобы аккуратно рассмотреть ее шаг за шагом. Рассмотрев некоторые интересные технологии программирования на Perl, вы сможете включить их в свою практику. Я надеюсь, что программисты на Perl любого уров ня смогут чему-нибудь научиться на приведенных примерах. И, по мере роста вашего уровня, вы сможете вернуться к этой книге и на учиться чему-нибудь еще.

Чтобы еще больше расширить такой опыт обучения, я буду часто приводить несколько способов решения одной и той же задачи при помощи Perl, а не единственный из возможных. Запомните девиз Perl: «Существует более одного способа сделать это». Все примеры, отражающие различные подходы, придуманы для того, чтобы луч ше оснастить ваш пояс с инструментами: чем больше их будет у вас в руках, тем более правильный выбор вы сможете сделать, когда столкнетесь с новой проблемой.

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

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

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

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

Вы должны, немного знать Perl В этой книге недостаточно места, чтобы приводить основы языка Perl, поэтому перед дальнейшим чтением вы должны изучить их самостоятельно. Познакомившись с содержанием таких книг, как «Learning Perl» 1 (Изучаем Perl) Рэндала Шварца (Randal L. Schwartz) и Тома Кристиансена (Tom Christiansen) (O'Reilly) или «Learning Perl on Win32 Systems» (Изучаем Perl для Win32) Рэнда ла Шварца (Randal L. Schwartz), Эрика Олсона (Erik Olson) и Тома Кристиансена (Tom Christiansen) (O'Reilly), вы будете в хорошей форме, чтобы приступить к кодам из этой книги.

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

Вам может понадобиться знание особенностей вашей операционной системы (систем) Я предпринял попытку описать различия между основными опера ционными системами, но я не смог охватить все внутренние разли Рэндал Л. Шварц, Том Кристиансен «Изучаем Perl», издательская группа BHV, Киев, 2000 г.

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

Из технических ресурсов вам понадобятся только две вещи:

Perl Вам нужна копия Perl, установленная или доступная для каждой системы, которую вы хотите администрировать. С веб-сайта http:// www.perl.com вы можете загрузить дистрибутив либо с исходными кодами, либо в скомпилированном виде для конкретной операцион ной системы. В примерах этой книги применяется Perl 5.005 (в мо мент написания книги - это последняя стабильная версия1). В Unix мы используем дистрибутив Perl, скомпилированный из исходных кодов, на платформе Win32 - версию, распространяемую ActiveSta te (build 522), а на MacOS - дистрибутив MacPerl (5.2.0r4).

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

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

Поиск и установка модулей Основное преимущество использования Perl для системного адми нистрирования заключается в доступности свободного исходного кода модулей. Рассмотренные в этой книге модули можно найти в одном из трех источников:

Полная сеть Perl-архивов (Comprehensive Perl Archive Network, CPAN) CPAN - это огромный архив исходного кода на Perl, документации, сценариев и модулей, продублированных на сотне сайтов по всему миру. Эту информацию можно найти по адресу http://www.cpan.org.

Самый простой способ найти модули на CPAN - воспользоваться поисковой системой, разработанной и поддерживаемой Элэни Аш тоном (Elaine Ashton), Грэхемом Баром (Graham Barr) и Клифтоном На данный момент вышла версия 5.6.1. - Примеч. науч. ред.

модулей Поси (Clifton Posey) на http://search.cpan.org. Поле «CPAN Search: » облегчает задачу поиска нужных модулей.

Репозитории для скомпилированных пакетов Скоро мы познакомимся с менеджером пакетов Perl (Perl Package Manager, PPM), очень важным инструментом для пользователей Perl на Win32. Этот инструмент соединяется с репозиториями (са мый известный из которых расположен на ActiveState), чтобы по лучить собранные пакеты модулей. Адреса репозиториев можно найти в списке часто задаваемых вопросов о РРМ на http://www.ac tivestate.com/Products/ActivePerl/docs/faq/ActivePerl-faq2.html.

Если пакет для Win32 получен не с ActiveState, я обязательно ука жу на это. Пакеты для MacOS лучше всего искать на сайте MacPerl Module Porters по адресу http://pudge.net/mmp/.

Отдельные веб-сайты Некоторые модули не попадают на CPAN или в репозитории РРМ.

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

Как установить модуль после того, как вы его найдете? Ответ зависит от того, какую операционную систему вы используете. В дистрибутив Perl входит документация по установке, которую можно найти в файле perlmodinstall.pod (наберите perldoc perlmodinstall, если хотите ее прочитать). В следующем разделе я приведу краткое описание действий, которые необходимо выполнить в каждой из операционных систем, рассмотренных в этой книге.

Установка модулей в Unix В большинстве случаев этот процесс выглядит так:

1. Скачайте модуль и распакуйте его.

2. Запустите perl Makefile.? L, чтобы создать необходимый Makefile.

3. Запустите make, чтобы собрать пакет.

4. Запустите make test, чтобы выполнить все тестовые действия, включенные в модуль автором.

5. Запустите make install, чтобы установить модуль в отведенное на вашей системе место.

Если вы не хотите возиться с установкой вручную, то можете исполь зовать написанный Андреасом Кенигом (Andreas J. Kbnig) модуль CPAN (модуль входит в состав Perl). Этот модуль позволит выполнить все эти действия, набрав:

% perl -MCPAN -e shell cpan> install modulename 22 Глава! Введение Модуль CPAN достаточно «умен», чтобы обрабатывать зависимости (т. е.

если один модуль требует запуска другого модуля, то С PAN установит оба модуля автоматически). В С PAN, кроме того, есть функция для по иска связанных модулей и пакетов. Я рекомендую набрать perldoc CPAN, чтобы ознакомиться со всеми полезными возможностями этого модуля.

Установка модулей на Win Процесс установки модулей на платформе Win32 совпадает с процес сом установки модулей на Unix, но требует одного дополнительного шага -ррт. Если вы собираетесь устанавливать модули вручную, сле дуя инструкциям по Unix, то можете использовать программы, подоб ные WinZip (http://www.winzip.com), чтобы распаковать дистрибутив, и вмес nmake (ftp://ftp.microsoft.com/Softlib/MSLFILES/nmakel5.exe) то make - для сборки и установки модуля.

Некоторые модули в процессе сборки требуют компиляции исходных файлов на С. У многих пользователей Perl на Win32 нет нужного прог раммного обеспечения для компиляции, поэтому в ActiveState созда ли менеджер пакетов Perl для работы с дистрибутивами скомпилиро ванных модулей.

Система РРМ похожа на модуль CPAN. Для загрузки и установки специ альных файлов архивов из репозиториев РРМ используется програм ма ppm.pl, написанная на Perl. Вы можете запустить ее, либо набрав ррт, либо выполнив команду perl ppm.pl из каталога bin:

C:\Perl\bin>perl ppm.pl РРМ interactive shell (1.1.1) - type 'help' for available commands.

PPM> install module-name ррт, как и CPAN, может искать для вас список доступных и установлен ных модулей. Наберите help после приглашения ррт, чтобы получить информацию о том, как использовать эти команды.

Установка модулей на MacOS Установка модулей на MacOS - это странный гибрид уже рассмотрен ных методов. Крис Нандор (Chris Nandor) собрал дистрибутив срап тас (его можно найти либо на CPAN, либо на http://pudge.net/macperl), в состав которого входит перенесенная на MacOS версия CPAN, а также невероятное количество других модулей.

После установки дистрибутива срап-тас можно при помощи CPAN за гружать и устанавливать большинство модулей, реализованных исклю чительно на языке Perl. Нандор упростил эту задачу, написав неболь шое приложение installme. Архивные файлы (т. е. файлы.tar.gz), пере данные installme, будут разархивированы и установлены в стиле CPAN.

Нелегко быть всемогущим Подробности об установке модулей на MacOS можно найти в расши ренной версии документа perlmodinstall.pod, упомянутого ранее как macperl modinstall.pod. Его можно найти также и на http://pudge.net/ macperl.

Нелегко быть всемогущим Перед тем как продолжить, давайте отвлечемся на несколько минут и скажем пару предостерегающих слов. У программ, написанных для системного администрирования, есть одна характерная черта, которая отличает их от всех остальных программ. В Unix и Windows NT/ они зачастую выполняются с повышенными привилегиями, т. е. с пра вами пользователей root или Administrator. А такая сила подразумева ет ответственность. На нас, как на программистов, ложится дополни тельная ответственность писать безопасные программы. Мы пишем программы, которые могут обходить (и обходят) ограничения безопас ности, накладываемые на «простых смертных». Если мы не будем осто рожными, менее «нравственные» личности смогут использовать «ды ры» нашего кода в низких целях. Вот несколько моментов, о которых вы всегда должны помнить, применяя Perl в этих обстоятельствах.

Не делайте этого Конечно же, используйте Perl. Но, по возможности, старайтесь избе гать выполнения программ в привилегированном окружении. Боль шинство задач не требует привилегий пользователя root или Admi nistrator. Например, программа анализа журналов, вероятно, не должна выполняться с правами суперпользователя. Для выполнения этих автоматизированных действий создайте другого пользователя, наделенного меньшими привилегиями. Пусть у вас будет маленькая программа, наделенная привилегиями, которая будет передавать при необходимости данные этому пользователю, и затем этот пользователь будет выполнять анализ.

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

В программах на Perl, выполняющихся в Unix или Linux, можно уста новить переменные $< и $>:

К Навсегда избавиться от привилегий 24 Глава 1. Введение ($<,$>) = (getpwnam('nobody 1 ),getpwnam('nobody 1 ));

В результате, реальный и эффективный идентификаторы пользовате ля будут установлены равными идентификатору пользователя nobody, не являющемуся привилегированным пользователем. Если вы хотите подойти к проблеме более основательно, то можете также использо вать переменные $( и $) для смены реального и эффективного иденти фикатора группы.

В Windows NT и Windows 2000 вообще нет идентификаторов пользова телей, но для избавления от привилегий существует схожий процесс.

В Windows 2000 есть возможность, называемая «RunAs», которую можно использовать для запуска процесса от имени другого пользова теля. В Windows NT и Windows 2000 пользователи с правами Act as part of the operating system могут выдавать себя за других пользовате лей. Эти права можно установить с помощью программы User Mana ger или User Manager for Domains:

1. В меню Policies выберите пункт User Rights.

2. Отметьте пункт Show Advanced User Rights.

3. Выберите Act as part of the operating system из выпадающего списка.

4. Выберите пункт Add... и определите пользователей или группы, ко торых вы хотите наделить этими правами. Если вы хотите предос тавить такое право определенному пользователю, выберите пункт Show Users.

5. Вероятно, данному пользователю придется повторно зарегистриро ваться в системе, чтобы эти изменения вступили в силу.

Вам также понадобится добавить права Replace a process level token и, в некоторых случаях, Bypass traverse checking (см. документацию по W i n 3 2 : : AdminMisc). Как только вы присвоили эти права пользователю, он сможет запускать сценарии на Perl с функцией LogonAsllser() из мо дуля Дэвида Рота (David Roth) Win32: : AdminMisc, который можно найти на http://www.roth.net:

use Win32:

-.AdminMisc;

die "Невозможно персонализировать $user\n" if ('Win32::AdminMisc::LogonAsUser('',$user,$userpw);

Замечание: здесь существует некоторая опасность, поскольку в отли чие от предыдущего примера, вы должны передать пароль пользовате ля в функцию LogonAsUser().

Будьте осторожны при чтении данных При чтении важных данных, скажем, конфигурационных файлов, сначала протестируйте возможность небезопасных состояний. Напри Нелегко быть всемогущим мер, стоит проверить, запрещена ли запись в файл и каталоги, в кото рых он находится (иначе, кто угодно может их испортить). Хороший способ подобной проверки можно найти в главе 8 книги «Perl Cookbo ok»1 («Perl: библиотека программиста») Тома Кристиансена (Тот Christiansen) и Натана Торкингтона (Nathan Torkington) (O'Reilly).

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

Ввод пользователей может быть причиной еще более серьезных проб лем. Мой любимый пример - это использование нулевого байта «Po ison NULL Byte», о котором сообщалось в статье о проблемах Perl в CGI. Обязательно прочитайте всю статью (ссылка на нее есть в конце этой главы). Неприятности возникают из-за отличий в обработке ну левого байта (\000) в Perl и в системных библиотеках С. Для Perl этот символ ничем не примечателен. Однако в библиотеках этот символ ис пользуется для обозначения конца строки.

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

if ($user ne "root"){ <вызов соответствующей функции О} Если переменная $user установлена в значение root\000 (т. е. если за словом root следует нулевой байт), то приведенная выше проверка ока жется удачной. Когда эта строка будет передана библиотеке, она будет воспринята просто как root, и пользователю удастся обойти проверку.

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

$input =~ tr/\000//d;

Это всего лишь один пример того, как ввод пользователя может вы звать проблемы. Именно поэтому в Perl существует специальное сред ство предосторожности - режим пометки (taint mode). Изучите стра ницу руководстваperlsec, входящую в состав дистрибутива Perl, чтобы ознакомиться с отличным объяснением того, что такое отмеченные данные, а также с другими мерами предосторожности.

Том Кристиансен, Натан Торкингтон «Perl: библиотека программиста», издательство «Питер», 2000 г. - Примеч.ред.

26 Глава 1. Введение Будьте осторожны при записи данных Если ваша программа может записывать или дописывать данные в лю бой файл локальной файловой системы, вы должны особенно заботить ся о том, как, куда и когда записываются данные. В системах Unix это особенно важно, поскольку символические ссылки очень сильно упро щают подмену файлов и перенаправление. Если ваша программа на писана не очень аккуратно, может оказаться, что она пишет не в тот файл или устройство. Существует два класса программ, в которых это соображение особенно важно.

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

1. Используйте функцию stat() и обычные операторы проверки фай лов для проверки атрибутов файлов. Убедитесь, что файл не являет ся ни жесткой, ни символической ссылкой, что у него установлены нужные права и владельцы и т. д.

2. Откройте файл для дописывания.

3. Передайте файловый дескриптор функции stat ().

4. Сравните значения, полученные на шагах 1 и 3, чтобы убедиться, что открытый файловый дескриптор соответствует нужному вам файлу.

Смотрите программу bigbuffy из главы 9 «Журналы», которая соблю дает эту последовательность шагов.

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

open(TEMPFILE,">/tmp/temp.$$") or die "невозможно записать в /tmp/ temp.$$:$!\n";

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

В некоторых операционных системах есть библиотечные вызовы, ко торые генерируют имена временных файлов, используя современный алгоритм случайных значений. Чтобы проверить вашу операционную систему, вы можете запустить следующий код. Если получаемые име на кажутся вам достаточно случайными, вы можете полагаться на POSIX: :tmpnam(). Если нет, вы можете написать собственную функцию генерации случайных имен файлов:

use POSIX qw(tmpnam);

Нелегко быть всемогущим for (1..20M print POSIX: :tmpnam(), "\n";

} Как только у вас будет имя файла, которое нельзя отгадать, вам нужно будет открыть его безопасным образом:

sysopen(TEMPFILE,$tmpname,0_RDWR|0_CREAT|0_EXCL,0666);

Существует другой, более простой способ выполнить эти же два шага (получить имя и открыть временный файл). Метод 10: : File->new_tmpf i le() из модуля 10:: File не только подберет хорошее имя (если систем ные библиотеки это поддерживают), но и откроет файл для чтения и записи.

Примеры использования POSIX: : t m p n a m ( ) и 10:: File->new_tmpfile(), a также другую информацию по этой теме вы можете найти в главе книги рецептов «Perl Cookbook» («Perl: библиотека программиста»). В модуле File: :Temp Тима Дженнеса (Tim Jenness) также предпринима ются попытки обеспечить безопасные операции работы с временными файлами.

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

1. Ваша программа будет накапливать некоторые данные.

2. Ваша программа затем будет работать с этими данными.

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

Состояния перехвата часто возникают в программах системного адми нистрирования, которые на первом шаге сканируют файловую.систе му, а на втором шаге изменяют данные. Бесчестные пользователи мо гут внести изменения в файловую систему сразу после сканирования, чтобы изменения были внесены в неверный файл. Убедитесь, что в ва шем коде нет подобных «дыр».

Наслаждайтесь Очень важно помнить, что системное администрирование интересно.

Не всегда и не тогда, когда вам надо решать самые досаждающие проб лемы, но определенное наслаждение в этом можно найти. Есть настоя 28 Глава 1. Введение щее удовольствие в том, чтобы поддерживать других людей и созда вать инфраструктуру, которая улучшает жизнь всем. Когда созданные вами программы объединяют людей - это прекрасно.

Теперь, когда вы готовы, давайте поработаем над «теми самыми про водами».

Ссылки на подробную информацию http://dwheeler.com/secure-programs/Secure-Programs-HOWTO.html документ HOWTO (соображения «как сделать») о безопасном прог раммировании в Linux, но рассмотренные в нем концепции и техно логии применимы и в других ситуациях.

http:/'/www.cs.ucdavis.edu/-bishop/secprog.html содержит лучшие спо собы безопасного программирования от эксперта по безопасности Мэтта Бишопа (Matt Bishop).

http://www.homeport.org/~adam/review.html - список указаний по на писанию безопасного кода от Адама Шостака (Adam Shostack).

http://www.dnaco.net/~kragen/security-holes.html - хороший документ о том, как искать дыры в защите (особенно в собственном коде) от Крегена Ситэйкера (Kragen Sitaker).

http://www.shmoo.com/securecode/ предлагает отличную коллекцию ста тей о том, как писать безопасные программы.

«Perl CGI Problems», Rain Forest Puppy (Phrack Magazine, 1999). Элект ронный вариант можно найти на http://www.insecure.org/news/P55 07.txt или в архивах Phrack на http://www.phrack.com/archive.html.

«Perl Cookbook», Tom Christiansen, Nathan Torkington (O'Reilly, 1998) эта книга рецептов содержит много хороших советов по созданию безопасных программ.

• Perl приходит на помощь,,• Различия файловых систем •• Прогулка по файловой системе • Обход файловой системы при помощи модуля File::Find • Работа с дисковыми квотами • Получение сведений об использова нии файловой системы • Информация о модулях из этой главы • Источники подробной информации Файловые системы Perl приходит на помощь Лэптопы падают медленно. По крайней мере, это выглядело именно так, когда компьютер, с помощью которого я писал эту книгу, упал со стола на твердый деревянный пол. Когда я его поднял, он по-прежне му был цел и работал. Но в процессе проверки лэптопа на предмет на личия повреждений я заметил, что он начал работать все медленнее и медленнее. Мало того, время от времени он стал устрашающе гудеть и жужжать во время обращения к диску. Решив, что замедление было вызвано программной ошибкой, я выключил компьютер. Но выклю чаться корректно он отказывался. Это был плохой знак.

Еще хуже было нежелание компьютера загружаться. Он начинал про цесс загрузки Windows NT, но затем выдавал ошибку «файл не най ден» и замирал. Теперь стало ясно, что падение вызвало серьезное фи зическое повреждение жесткого диска. Вероятно, головки проскольз нули по поверхности диска, уничтожив файлы и каталоги, находив шиеся в открытом состоянии. Передо мной встал вопрос: «Остались ли неповрежденными хоть какие-то файлы? Выжили ли файлы этой кни ги?» Первым делом я попытался загрузить Linux, другую операционную систему, установленную на портативном компьютере. Linux загрузил ся нормально;

это меня подбодрило. Однако файлы этой книги находи лись в разделе NTFS, который не загружался. Используя драйвер NTFS для Linux, написанный Мартином фон Левисом (Martin von Low 30 Глава 2. Файловые системы is) и доступный на http://www.informatik.hu-berlin.de/~loewis/ntfs/ (те перь он поставляется вместе с ядрами Linux 2.2), я смонтировал раз дел и обрадовался, увидев, что все мои файлы казались неповрежден ными.

Мои попытки скопировать файлы из этого раздела проходили успеш но, но лишь до тех пор, пока я не достиг некоторого файла. Диск опять издал этот зловещий звук, и скопировать файл не удалось. Было ясно, что если я хочу спасти свои данные, мне нужно пропустить все повреж денные файлы на диске. Программа, которой я пользовался (gnutar), могла пропустить список файлов. Вопрос был только в том, какие фай лы следовало пропускать? Когда возникла эта неприятность, в файло вой системе было больше шестнадцати тысяч файлов. Как я мог ра зобраться, какие файлы были повреждены, а какие нет? Запускать gnutar снова и снова было отнюдь не лучшей стратегией. С такой зада чей мог справиться Perl!

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

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

Unix Все современные разновидности Unix поставляются с файловыми сис темами, семантика которых напоминает семантику их общего предка файловой системы Berkeley Fast File System. Различные производите ли по-разному расширяли свои файловые системы (так, в Solaris доба вили списки контроля доступа (Access Control Lists) для большей безо пасности, в Digital Unix стали применять файловую систему advfs, ос нованную на транзакциях, и т. д.). Мы будем писать код, «приведен ный к общему знаменателю», что позволит ему работать на различных Unix-платформах.

Вершина, или корень файловой системы, в Unix обозначается симво лом прямого слэша (/). Для того чтобы уникальным образом иденти фицировать файл или каталог в файловой системе, мы строим путь, начинающийся со слэша, и добавляем в него каталоги, разделяя их Различия файловых систем слэшами, по мере прохода «вглубь» файловой системы. Последний компонент пути - нужный каталог или файл. В современных вариан тах Unix имена каталогов и файлов чувствительны к регистру симво лов. При известном навыке в именах можно использовать практичес ки все ASCII-символы, но если ограничиться буквенно-цифровыми символами и некоторыми знаками пунктуации, то в дальнейшем мож но избежать лишних сложностей.

Microsoft Windows NT/ Windows NT (в данной книге речь идет о версии 4.0) поставляется с дву мя поддерживаемыми файловыми системами: файловой системой FAT (таблица размещения файлов) и NTFS (файловая система NT). В Win dows 2000 добавлена файловая система FAT32 - улучшенная версия FAT, позволяющая иметь разделы больших размеров и кластеры меньших размеров.

В Windows NT используется расширенная версия файловой системы FAT из DOS. Перед тем как рассматривать расширенную версию, очень важно разобраться в недостатках исходной. В обычной файловой системе (FAT реального режима) имена файлов должны соответство вать формату 8.3. Это означает, что имена файлов или каталогов могут содержать не более восьми символов, за которыми должна следовать точка, а затем суффикс длиной не более трех символов. В отличие от Unix, где точка в имени файла не имеет специального назначения, в FAT можно использовать только одну точку в качестве разделителя между именем файла и его расширением (суффиксом).

Позднее файловая система FAT была расширена до VFAT, или «FAT защищенного режима». Эта версия поддерживается в Windows NT и Windows 2000. VFAT скрывает от пользователей все ограничения, на кладываемые на имена. Более длинные имена файлов без разделите лей поддерживаются благодаря хитрому трюку. В VFAT используется цепь из нескольких стандартных слотов для имен файлов/каталогов, чтобы прозрачно встроить поддержку расширенных имен файлов в структуру обычной файловой системы FAT. В целях совместимости к каждому файлу и каталогу по-прежнему можно обратиться, используя псевдонимы в формате 8.3. Например, к каталогу с именем Downlo aded Program Files можно обратиться, используя имя DOWNLO~1.

Между VFAT и файловыми системами Unix существуют четыре основ ные различия:

1. Файловые системы FAT не чувствительны к регистру. В Unix по пытка открыть файл, используя неверный регистр символов (на пример MYFAVORITEFILE вместо ту favorite f i l e ), окончится не удачей. В FAT или VFAT это можно сделать без труда.

2. Второе различие - символы, выбранные для разделения компонент пути. В FAT в качестве разделителя вместо прямого слэша исполь 32 Глава 2. Файловые системы зуется обратный слэш. При программировании в Perl это следует учитывать. В Perl обратный слэш является специальным симво лом. Пути с одинарными разделителями, заключенные в одинар ные кавычки (т. е. $path=' \ d i r \ d i r \ f i l e n a m e ' ), не вызывают затруд нений. Однако необходимость поставить несколько обратных слэ шей рядом (например \\server\dir\file) может оказаться потенци ально опасной. В таких случаях будьте бдительны и не забывайте удваивать идущие подряд обратные слэши. Некоторые функции и модули могут принимать пути с прямыми слэшами, но при про граммировании на это лучше не полагаться. Лучше перестрахо ваться и написать \\\\winnt\\temp\\..., чем выяснить, что у вас ни чего не получилось из-за того, что преобразование не было выпол нено.

3. В FAT с файлами и каталогами связаны специальные флаги, назы ваемые атрибутами. Примеры атрибутов - «Read-only» (только для чтения) и «System» (системный).

4. Наконец, последнее отличие - указание корневого каталога. Ко рень в FAT начинается с указания буквы диска, на котором распо лагается эта файловая система. Например, абсолютный путь к фай лу может быть указан так c:\home\cindy\docs\resume\current.doc.

Файловые системы FAT32 и NTFS имеют ту же семантику, что и VFAT. В них одинаково реализована поддержка длинных имен файлов и используется один и тот же способ обозначения корневого каталога.

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

В NTFS также есть несколько функциональных особенностей, отлича ющих ее от других файловых систем Windows NT/2000 и основных файловых систем Unix. NTFS поддерживает понятие списков контроля доступа (ACL). ACL предоставляет хорошо разграниченный механизм прав доступа к файлам и каталогам. Позже в этой главе мы приведем пример кода, использующего преимущества некоторых из этих отли чий.

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

UNC - это соглашение о расположении объектов (в нашем случае фай лов и каталогов) в сетевом окружении. Вместо имени диска и двоето чия, с которых начинается абсолютный путь, часть имя диска: заменя ется на \\сервер\имя_ресурса. Это соглашение подвержено той же син таксической двусмысленности обратного слэша в Perl, о которой мы уже говорили. В результате нередко можно увидеть целый ряд косых черточек:

$path = "\\\\server\\sharename\\directory\\file" Различия файловых систем MacOS Несмотря на GUI-ориентированный подход, иерархическая файловая система MacOS (HFS, Hierarchical File System) также позволяет указы вать текстовые имена файлов, хотя для этого нужно немного излов читься. Абсолютные пути задаются в следующем виде: Диск/Имя_то ма:Папка:Папка:Папка:Имя_файла. Отсутствие двоеточий указыва ет на то, что файл находится в текущем каталоге.

В отличие от двух предыдущих операционных систем, пути в HFS счи таются абсолютными, если не начинаются с разделителя пути (:). Путь HFS, начинающийся с двоеточия, является относительным. Есть не большое отличие записи пути в MacOS по сравнению с другими файло выми системами - это количество разделителей, которое необходимо указывать при ссылке на объект, стоящий выше в иерархии катало гов. Например, в Unix используется../../FileName для обращения к файлу, находящемуся тремя уровнями выше текущего каталога. В MacOS понадобилось бы использовать четыре разделителя (т. е. ^."File Name), поскольку необходимо включить ссылку на текущий каталог помимо трех предыдущих уровней.

В HFS длина имен файлов и каталогов ограничена 31 символом. В MacOS версии 8.1 был введен альтернативный многосимвольный формат, на званный расширенным форматом MacOS, или HFS+, для поддержки Unicode в именах файлов длиной до 255 символов. И хотя файловая система HFS+ позволяет использовать такие длинные имена, на мо мент написания этой книги они еще не поддерживаются в MacOS.

Еще более заметным отличием от предыдущих двух файловых систем (по крайней мере, с точки зрения программирования на Perl) является использование в MacOS понятия «fork» (ветвление) при хранении фай лов. У каждого файла есть поток данных (data fork) и поток ресурсов (resource fork). В первом хранятся данные, а во втором содержатся раз личные ресурсы. В эти ресурсы могут входить исполняемый код (в слу чае, если это программа), определения пользовательского интерфейса (диалоговые окна, шрифты и т. д.) или любые другие компоненты, оп ределяемые программистом. И хотя в этой главе мы не будем рассмат ривать ветвления, в MacPerl есть возможность чтения и записи в оба потока.

В MacPerl основные операторы и функции работают толь ко с потоком данных. Например, оператор -s возвращает только размер потока данных файла. Если вы хотите обра титься к потоку ресурсов файла, вам придется использо вать дополнительные модули, входящие в состав Macin tosh Toolbox.

Каждый файл в файловой системе HFS также имеет два специальных тега: creator (создатель) и type (тип), позволяющие операционной Глава 2. Файловые системы системе идентифицировать, каким приложением был создан файл и какого он типа. Эти теги играют ту же роль, что и расширения, ис пользуемые в файловых системах FAT (например.doc или.ехе). Позже в этой главе мы увидим, как применять теги тип/создатель в собствен ных целях.

Сводка различий файловых систем Ниже представлены те различия, о которых мы только что говорили, и некоторые другие интересные факты (табл. 2.1).

Таблица 2.1. Сравнение файловых систем OS и файло- Разде- Чувстви- Формат Формат Уникаль Длина вая система литель тель- имени абсолют- относи- ные воз пути ность к ного пути тельно файла можности го пути регистру Unix (файло- / В зависи- Дополне /dir/file dir/file Да вая система мости от ния в зави Berkeley операцион- симости от Fast File Sys- ной систе- операцион ной систе мы tem и дру мы гие) MacOS (HFS) 31 символ Потоки :dir:file volume:

;

Да данных/ dir:file (или ресурсов, при ис пользова- атрибуты нии HFS+) создатель/ тип \ WinNT/2000 255 симво- Drive:\ dir\file ACL, атри Нет dir\file (NTFS) буты, Uni лов code в име нах файлов \ DOS (BASIC Drive:\ dir\file Атрибуты Нет 8. dir\file FAT) Учет различий файловых систем в Perl Perl может помочь создавать программы, в которых учитывается боль шинство особенностей файловых систем. В его состав входит модуль File: :Spec, позволяющий нивелировать некоторые различия между файловыми системами. Например, если мы передаем компоненты пу ти методу catf ile таким образом:

use File::Spec;

$path = File::Spec->catfile("home","cindy","docs","resume.doc");

Прогулка по файловой системе то в Windows NT/ 2000 переменная $path будет иметь значение ho me\cindy\docs\resume. doc, тогда как в Unix она будет иметь значение по me/cindy/docs/resume.doc и т. д. В модуле File: :Spec также есть методы, например c u r d i r и updir, возвращающие обозначения для текущего и родительского каталогов (например «. » и «., »). Методы этого модуля предоставляют абстрактный способ построения и манипулирования именами путей. Если вы предпочитаете не использовать объектно-ори ентированный синтаксис, то модуль File: :Spec: '.Functions предостав ляет более короткий путь к методам из File:: Spec.

Прогулка по файловой системе Наверняка вам уже не терпится посмотреть на какие-нибудь приложе ния, написанные на Perl. Начнем мы с «прогулки по файловой систе ме» - одной из наиболее часто встречающихся задач системного адми нистрирования, связанных с файловыми системами. Обычно этот про цесс состоит в поиске по всем деревьям каталогов и выполнении неко торого действия в зависимости от результатов поиска. Для этой задачи в каждой операционной системе есть свое средство. В Unix это команда find, в Windows NT/2000 - Find Files or Folders или Search For Files or Folders, а в MacOS - Find File или Sherlock. Все эти команды полезны для поиска, но выполнять произвольные сложные действия, по мере нахождения требуемых файлов, они не способны. Мы увидим, каким образом Perl позволяет писать более изысканные обзорные программы, начав с простейших и наращивая сложность по мере продвижения.

Для начала давайте рассмотрим простой сценарий, четко ставящий перед нами задачу, которую необходимо решить. В этом сценарии мы предстанем системным администратором Unix с переполненной фай ловой системой пользователей и исчерпанным дисковым пространст вом. (Мы начали с Unix, но вскоре рассмотрим и другие операционные системы.) Мы не можем добавить новое дисковое пространство, не имея на это денег, поэтому попытаемся рациональнее использовать существую щие ресурсы. Первый наш шаг - удалить из файловой системы все файлы, которые можно удалить. В Unix первые кандидаты на удале ние - это core-файлы, которые остаются после аварийных завершений программ. Большинство пользователей либо не замечают, что эти фай лы создаются, либо просто игнорируют их, оставляя напрасно заняты ми большие дисковые пространства. Нам нужно средство для поиска и удаления таких «пустышек» из файловой системы.

Обзор файловой системы мы начинаем с чтения содержимого какого либо каталога и затем продолжаем обход с этой точки. Давайте немно го упростим задачу и начнем с программы, которая изучает содержи мое текущего каталога и сообщает, были ли найдены в нем core-файлы и другие каталоги-кандидаты для поиска.

Глава 2. Файловые системы Начнем мы с того, что откроем каталог, используя примерно тот же синтаксис, что и для открытия файла. Если попытка была неудачной, мы выходим из программы и выводим сообщение об ошибке ($! ), уста новленное вызовом opendir():

opendir(DIR,".") or die "He могу открыть текущий каталог: $!\п";

Мы получаем дескриптор каталога, в нашем случае D I R, который мож но передать функции readdir(), чтобы получить список файлов и ката логов в текущем каталоге. Если r e a d d i r ( ) не может прочитать содер жимое каталога, выводится сообщение об ошибке (которое объясняет, почему попытка была неудачной) и программа завершает работу:

# читаем имена файлов/каталогов данного каталога в @names ©names = readdir(OIR) or die "Невозможно прочитать текущий каталог:$!\п";

Затем закрываем открытый дескриптор каталога:

closedir(DIR);

Теперь можно работать с полученными именами:

foreach $name (@names) { # пропускаем текущий каталог next if ($name eq ".");

П пропускаем родительский каталог next if ($name eq "..");

и является ли каталогом?

if (-d $name){ print "найден каталог: $name\n";

и можно перейти к следующему имени next;

и из цикла for if ($name eq "core") { П это файл с именем core?

print "найден!\n";

Теперь у нас есть очень простая программа, которая проверяет содер жимое одного каталога. Она не только не обходит файловую систему, но даже не «проползает» по ней. Чтобы пройти по файловой системе, мы должны зайти во все каталоги, которые нам встретятся, и посмот реть на их содержимое. Если в этих подкаталогах есть еще подкатало ги, в них мы тоже должны заглянуть.

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

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

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

Инструкция по раскраске матрешек могла бы выглядеть так:

1. Изучите куклу, которая находится перед вами. Внутри у нее есть кукла меньшего размера? Если да, то вытащите ее оттуда.

2. Повторяйте шаг 1 с вытащенными куклами до тех пор, пока не дойдете до центра.

3. Раскрасьте центральную куклу. Когда она высохнет, поместите ее во внешнюю по отношению к ней куклу и повторите шаг 3 со следу ющим контейнером.

Этот процесс одинаков на каждом шаге. Если у предмета, который вы держите в руках, есть «подпредметы», отложите предмет в сторону и займитесь сначала «подпредметом». Если же подпредметов у него нет, произведите с ним необходимые действия и займитесь последним от ложенным предметом.

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

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

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

По завершении сканирования подпрограмма возвращается в каталог, из которого она была вызвана. Вот новый вариант программы:

#!/usr/bin/perl -s П обратите внимание на использование ключа -s для обработки и параметров. В NT/2000 вам придется вызывать этот сценарий и ключом -s (т.е. perl -s script), если файловая ассоциация # в системе не настроена должным образом для файлов perl.

38 Глава 2. Файловые системы и и -s также считается устаревшим, многие программисты 8 предпочитают использовать отдельный модуль # (из семейства модулейОе1:ор1: : :) для разбора (анализа) параметров.

use Cwd;

и модуль для определения текущего рабочего каталога 8 Эта подпрограмма принимает имя каталога и рекурсивно 8 сканирует файловую систему, начиная с этого места, ищет 8 файлы с именем "core" sub ScanDirectory{ my ($workdir) = shift;

my (Sstartdir) = &cwd;

8 запомнить, откуда мы начали chdir($workdir) or die "Невозможно войти в каталог $workdir:$!\n";

opendir(DIR, ".") or die "Невозможно открыть $workdir:$!\n";

my ©names = readdir(DIR) or die "Невозможно прочитать $workdir:$!\n";

closedir(DIR);

foreach my $name (@names){ next if ($name eq ". ");

next if ($name eq ".. ");

if (-1 $name){ 8 пропускаем ссылки next;

} if (-d $name){ 8 это каталог?

&ScanDi rectory ($name);

next;

} if ($name eq "core") { 8 имя файла "core"?

8 если в командной строке указан ключ -г, на самом 8 деле удаляем этот файл if (defined $r){ unlink($name) or die "Невозможно удалить $name:$!\n";

} else { print "найден в $workdir!\n";

chdir($startdir) or die "Невозможно перейти к каталогу Sstartdir;

$!\n";

&ScanDirectory(". ");

Самое важное отличие от предыдущего примера заключается в изме' нении поведения программы в случае, если найден подкаталог внутри требуемого каталога. Теперь, если был найден каталог, вместо того Прогулка по файловой системе чтобы сообщать об этом, как было в предыдущем примере, наша про грамма рекурсивно вызывает себя, чтобы изучить сначала содержимое этого каталога. По окончании сканирования всего подкаталога (т. е.

вызов ScanDi recto гу () возвращает значение) программа возвращается к просмотру остального содержимого текущего каталога.

Для того чтобы сделать нашу программу полнофункциональным лик видатором core-файлов, мы добавили в нее функцию удаления файлов.

Обратите внимание на то, как это реализовано: файлы будут удалены, только если сценарий вызывается с определенным ключом -г (от «re move» - удаление) в командной строке.

В Perl мы указываем встроенный ключ -s в строке вызова (#! / u s r / b i n / perl -s) для автоматического разбора параметров. Это самый простой способ разбора параметров, переданных в командной строке. Искуше ния ради, мы могли бы использовать какой-либо модуль из семейства Getopt. Если в командной строке присутствует ключ (например -г), то при запуске сценария устанавливается глобальная скалярная пере менная с тем же именем (например $г). Если Perl вызывается без клю ча -г, мы вернемся к старому поведению подпрограммы - она будет лишь сообщать, что найдены core-файлы.

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

Теперь, чтобы ориентированные на NT/2000 читатели не подумали, что предыдущие примеры к ним не относятся, покажем, что эта про грамма может пригодиться и для них. Единственное изменение стро ки:

if (Sname eq "core") { на:

if (Sname eq "MSCREATE.DIR") { позволяет создать программу, которая удалит все раздражающие скрытые файлы нулевой длины, забытые инсталляторами некоторых программ Microsoft.

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

40 Глава 2. Файловые системы Вот какую программу я написал для этого:

use Cwd;

и модуль для определения текущего рабочего каталога $1=1;

и отключаем буферизацию ввода/вывода sub ScanDirectory { my ($workdir) = shift;

my($startdir) = &cwd;

и запоминаем, откуда мы начали chdir($workdir) or die "Невозможно зайти в каталог $workdir:$!\n";

opendir(DIR, ".") or die "Невозможно открыть каталог $workdir:$!\n";

my @names = readdir(DIR);

closedir(DIR);

foreach my $name (@names){ next if ($name eq ".");

next if ($name eq "..");

if (-d $name){ # это каталог?

&ScanDirectory($name);

next;

> unless (&CheckFile($name)){ print &cwd. "/".$name. "\n";

tt выводим имя п поврежденного файла } } chdir($startdir) or die "Невозможно перейти к каталогу $startdir:$!\n";

} sub CheckFile{ my($name) = shift;

print STDERR "Проверяется ". &cwd."/"-$name."\n";

# пытаемся получить состояние файла my @stat = stat($name);

if (!$stat[4] && !$stat[5] 8A !$stat[6] && !$stat[7] && !$stat[8]){ return 0;

} tt пытаемся открыть этот файл unless (open(T,"$name")){ return 0;

> tt читаем файл по байту за один раз for (my $1=0;

$i< $stat[7];

$!++){ my $r=sysread(T, $i, 1);

if ($r != 1) { close(T);

return 0;

Обход файловой системы при помощи модуля File::Find close(T);

return 1;

&ScanDirectory(".");

Различия между этой программой и последним примером заключают ся в наличии дополнительной подпрограммы для проверки каждого найденного файла. Для каждого файла мы вызываем функцию stat, чтобы проверить, можно ли прочитать информацию о файле (напри мер, его размер). Если мы сделать этого не можем, значит, файл по врежден. Если же прочитать эту информацию можно, мы предприни маем попытку открыть файл. А в качестве последней проверки пыта емся прочитать каждый байт из файла. Это не гарантирует, что файл не поврежден (его содержимое могло измениться), но это говорит о том, что файл можно прочитать.

Вы можете удивиться, зачем применять такую странную функцию, как sysread( ), для чтения файла, если можно применить о или read О, обычно используемые для этого в Perl. Дело в том, что sysread( ) позво ляет читать файл побайтно, не применяя обычную буферизацию. Если файл поврежден в позиции X, нет смысла ждать, пока будут прочита ны байты в позициях Х+1, Х+2, Х+3 и т. д., как это бывает при обращении к обычным библиотечным функциям. Мы хотим, чтобы попытки чи тать файл в таком случае прекратились немедленно. Обычно файл чи тается по кускам в целях повышения производительности, но это не желательно, т. к. в нашем случае компьютер будет издавать ужасаю щие звуки в течение длительного времени, когда наткнется на по врежденный файл.

Теперь, после рассмотрения использованной мною программы, я рас скажу, чем закончилась эта история. После того как рассмотренный сценарий проработал всю ночь (без преувеличений), он нашел 95 пов режденных файлов из 16000. К счастью, ни один из них не был фай лом из книги, которую вы сейчас читаете;

я снял копии со всех хоро ших файлов и перенес их в другое место. Perl просто спас положение.

Обход файловой системы при помощи модуля File::Find Теперь, когда вы познакомились с основами просмотра файловой сис темы, покажем более быстрый и изящный способ сделать то же самое.

В Perl есть модуль File : : Find, позволяющий эмулировать команду find из Unix. Самый простой способ начать работать с этим модулем - вос пользоваться командой find2perl для генерирования кода-прототипа Perl.

42 Глава 2. Файловые системы С find2perl не всегда легко работать в Perl в отличных от Unix-системах. Для ее выполнения пользователям MacOS, например, понадобится Macintosh Programmer's Work shop (MPW) либо им придется изменить исходный код, чтобы получать @ARGV в диалоговом окне. Вот пример кода, позаимствованный у Криса Нандора (Chris Nandor), соав тора «MacPerl: Power and Ease» (MacPerl: Сила и легкость):

@ARGV = @ARGV ? @ARGV :

split "\s", MacPerl::Ask("Arguments?");

Во всех перенесенных версиях есть модуль File: :Find, ко торый используют команды find2perl и find.pl, так что это не должно стать проблемой. Позже в этой главе мы пока жем, как вызвать его напрямую.

Предположим, что вам нужна программа для поиска файлов beesknees в каталоге /home. Вот командная строка, использующая команду Unix find:

% find /home -name beesknees -print Передадим те же параметры команде find2perl:

% find2perl /home -name beesknees -print и получим:

#!/usr/bin/perl eval 'exec /usr/bin/perl -S $0 ${1+"$@"}' if $running_under_some_sheH;

require "find.pl";

# Обходим нужные файловые системы &find('/home');

exit;

sub wanted { /~beesknees$/ && print("$name\n");

} Код, сгенерированный командой find2perl, довольно прямолинеен. Он загружает необходимую библиотеку find.pl при помощи оператора r e q u i r e, затем вызывает подпрограмму &f i n d ( ) с именем начального ка талога. Вскоре мы обсудим назначение подпрограммы & w a n t e d ( ), по скольку именно здесь будут находиться все интересные изменения, которые мы хотим изучить.

Обход файловой системы при помощи модуля File::Find Перед тем как вносить изменения в этот код, важно обратить внима ние на те немногие моменты, которые могут не показаться очевидны ми при рассмотрении приведенного фрагмента:

• Те, кто работал над модулем File:.Find, столкнулись с проблемой переносимости этого модуля на другие платформы. Внутренние подпрограммы модуля File:: Find действуют так, что один и тот же код работает и в Unix, и в MacOS, и в NT, и в VMS и т. д.

• Хотя код, сгенерированный find2perl, на первый взгляд похож на код Perl 4 (например, тут используется require для загрузки файла.pi), find.pl в действительности устанавливает несколько псевдони мов из PerlS. Обычно бывает полезно заглянуть «под завесу», прежде чем использовать модуль в собственной программе. Если вам нужен исходный код модуля, уже установленного в системе, то, выполнив команду perl -7или следующую команду, вы получи те список каталогов стандартных библиотек:

% perl-e 'print join("\n",@INC,"")' Давайте поговорим о подпрограмме &wanted(), которую мы изменим для своих нужд. Подпрограмма &wanted() вызывается для каждого найденного &f ind() (или &File:: Find: : f ind(), чтобы быть точным) файла или каталога при обходе файловой системы. Именно код из &wanted() должен выбирать «интересные» файлы или каталоги и работать с ни ми. В примере, приведенном выше, сначала проверяется соответствие имени файла или каталога строке beesknees. Если они совпадают, опе ратор && заставляет Perl выполнить оператор print, чтобы вывести имя найденного файла.

При создании собственных подпрограмм &wanted() нам придется учи тывать два практических момента. Поскольку &wanted() вызывается по одному разу для имени каждого файла или каталога, важно сделать этот код коротким и аккуратным. Чем быстрее мы сможем выйти из подпрограммы &wanted(), тем быстрее f i n d сможет перейти к новому файлу или каталогу и тем быстрее будет выполняться вся программа.

Также важно иметь в виду «закадровые» соображения совместимости, о которых мы недавно упоминали. Было бы позором одновременно иметь переносимый вызов & f i n d ( ) и системно-зависимую подпрограм му &wanted() (кроме случаев, где этого невозможно избежать). Несколь ко подсказок, помогающих избежать такой ситуации, можно полу чить, посмотрев на текст модуля File:: Find.

Для первого использования модуля F i l e : : F i n d давайте перепишем пример, созданный для удаления core-файлов, и затем немного его расширим. Для начала наберем:

% find2perl -name core -print что даст нам следующее:

44 Глава 2. Файловые системы обхс require "find.pl";

и Обходим нужные файловые системы &find('.');

exit;

sub wanted { /~core$/ && print("$name\n");

} Затем мы добавим -s к строке вызова Perl и изменим подпрограмму &wanted():

sub wanted { /~core$/ && print("$name\n") && defined $r && unlink($name);

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

sub wanted { /~core$/ && -s $name && print("$name\n") && defined $r && unlink($name);

} Теперь, перед тем как выводить имя файла или удалять его, мы прове ряем, не является ли размер файла core нулевым. Некоторые пользо ватели иногда создают ссылку на /dev/null с именем core в своем до машнем каталоге, чтобы core-файлы в нем не сохранялись. Параметр -s указывается для того, чтобы убедиться, что по ошибке не будут уда лены ссылки или файлы нулевой длины. Если мы хотим действовать ос торожнее, нам следует выполнить еще две дополнительные проверки:

1. Открыть файл и убедиться, что этот файл действительно является core-файлом. Сделать это можно как из Perl, так и вызвав команду Unix file. Определить, что файл действительно является core-фай лом, может оказаться достаточно сложно в случае, если файловые системы смонтированы по сети с компьютерами другой архитекту ры с иными форматами core-файлов.

2. Посмотреть на время изменения файла. Если кто-то в настоящий момент отлаживает программу, используя файл core, он вряд ли об радуется, если вы утащите этот файл прямо «из-под нее».

Давайте на время отдохнем от мира Unix и посмотрим на примеры.

имеющие отношение к MacOS и Windows NT/2000. Ранее в этой главе я уже говорил, что в MacOS у каждого файла есть два атрибута - созди' тель и тип, позволяющие операционной системе определить, какое )д файловой системы при помощи модуля File::Find приложение создало этот файл и какого он типа. Эти атрибуты хранят ся в виде четырехсимвольных строк. Например, для текстового доку мента, созданного приложением SimpleText, эти атрибуты будут иметь значения ttxt (для создателя) и TEXT (для типа). Из Perl (только для MacPerl) мы можем получить эту информацию при помощи функ ции MacPerl: :GetFileInfo(). Синтаксис ее таков:

$type = MacPerl:-.GetFilelnfo(filename);

или:

($creator,$type) = MacPerl::GetFileInfo(filename);

Чтобы найти все текстовые файлы в файловой системе MacOS, мы мо жем выполнить следующее:

use File::Find;

&File::Find::find(\&wanted,"Macintosh HD:");

sub wanted!

-f $_ && MacPerl::GetFileInfo($_) eq "TEXT" && print "$Find::File::name\n";

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

Мы просто вызываем процедуры из File: :Find напрямую, без find.pl.

Кроме того, мы используем переменную $name, определенную в про странстве имен File:: Find, чтобы вывести абсолютный путь файла, а не только его имя. Взгляните на полный список переменных, определяе мых File: :Find при обходе файловой системы (табл. 2.2).

Таблица 2.2. Переменные File::Find Смысл Переменная Имя текущего файла SFile::Find: :dir Имя текущего каталога $File::Find::name Полный путь для текущего файла (т. е. SFile:: Find:: dir/$_) Вот похожий пример, но для NT/2000:

use File::Find;

use W i n 3 2 : : F i l e ;

&File::Find::find(\&wanted, "\\");

sub wanted!

-f $ && 46 Глава 2. Файловые системы S значение переменной attr присваивается функцией и Win32::File::GetAttributes (Win32::File::GetAttributes($_,Sattr)) && (Sattr & HIDDEN) && print "$File::Find::name\n";

} Этот пример ищет по всей файловой системе на текущем диске все скрытые файлы (т. е. те файлы, у которых установлен атрибут HIDDEN).

Этот код работает и на NTFS и на ГАТ.

А вот пример для файловой системы NTFS, который ищет все файлы, если к ним разрешен полный доступ для специальной группы Everyone, и выводит их имена:

use File::Find;

use Win32::FileSecurity;

# Определяем маску DACL для полного доступа Sfullmask = Win32::FileSecurity::MakeMask(FULL);

&find(\&wanted,"\\");

sub wanted { # Win32::FileSecurity::Get не любит файл подкачки Я pagefile.sys, пропустить его next if ($_ eq "pagefile.sys");

(,-T ф_) 0 /fф\ && Win32::FileSecurity::Get($_, \%users) && (defined $users{"Everyone"}) && ($users{"Everyone"} == $fullmask) && print "$File::Find::name\n";

} В вышеприведенном коде мы запрашиваем все файлы у списка конт роля доступа ACL (кроме файла подкачки Windows NT). Затем мы проверяем, есть ли в этом списке запись для группы Everyone. Если есть, мы сравниваем запись Everyone со значением для полного доступа (полученным MakeMask()) и выводим абсолютный путь файла, если они совпадают.

А вот еще один пример из реальной жизни, демонстрирующий, на сколько полезным может оказаться даже самый простой код. Недавно я пытался дефрагментировать (заново перестроенный) раздел NT на диске своего портативного компьютера, но все закончилось сообщени ем об ошибке Metadata C o r r u p t i o n E r r o r (повреждение метаданных).

Внимательно изучая веб-сайт производителя программного обеспече ния, я нашел там замечание, что «такая ситуация может быть вызвана наличием файлов, длина имен которых превышает допустимую в Win dows NT». Там было предложено найти эти файлы, копируя каждый каталог на новое место и сравнивая количество файлов в оригинале и Обход файловой системы при помощи модуля File::Find копии. Если в копии каталога файлов меньше, необходимо найти те файлы, которые не были скопированы.

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

require "find.pl";

и Обходим нужные файловые системы &find(\&wanted, '. ')1;

print "max:$max\n";

exit;

sub wanted { return unless -f $_;

if (length($_) > $maxlength){ $max = $name;

$maxlength = length($_);

} if (length($name) > 200) { print $name,"\n";

} } В результате будут выведены имена файлов длиной более 200 симво лов, а также самое длинное найденное имя. Работа сделана, спасибо Perl.

Давайте снова вернемся к Unix, чтобы закончить этот раздел довольно сложным примером. Идея, которая представляется слишком простой в контексте системного администрирования, но в итоге может принес ти огромную пользу - это понятие наделения пользователя полномо чиями. Если ваши пользователи могут решить свои проблемы самос тоятельно при помощи средств, которые вы им предоставляете, от это го все только выиграют.

Большая часть этой главы посвящена решению проблем, возникаю щих при переполнении файловой системы. Зачастую это происходит из-за того, что пользователи недостаточно осведомлены о своем окру жении, либо из-за того, что слишком обременительно выполнять опе рации по управлению дисковым пространством. Множество писем в службу поддержки начинаются со слов «В моем домашнем каталоге больше нет свободного места, но я не знаю из-за чего». Вот скелет сце нария needspace, который может помочь пользователям, столкнув шимся с этой проблемой. Пользователь просто набирает needspace, и сценарий пытается найти в домашнем каталоге пользователя то, что \&wanted в оригинале пропущено. - Примеч. науч.ред.

Глава 2. файловые системы Когда не надо использовать модуль File::Find Когда метод File: : Find не подходит? На ум приходят четыре си туации:

1. Если файловая система, с которой вы работаете, не следует обычной семантике, вы не сможете применять этот модуль.

Например, драйвер файловой системы NTFS для Linux, кото рый я использовал при решении проблемы с упавшим ком пьютером, почему-то не выводил в пустых каталогах «. » или «,, ». Это очень мешало File: : F i n d.

2. Если вам нужно изменять имена каталогов во время обхода файловой системы, File: :Find теряется и начинает вести себя непредсказуемым образом.

3. Если вам нужно разыменовывать символические ссылки на каталоги (для Unix), File:: Find пропустит их.

4. Если вам нужно обойти файловую систему, смонтированную на вашей машине (например, файловую систему Unix, смон тированную через NFS на машине с Windows), File:. F i n d бу дет использовать семантику, принятую для «родной» файло вой системы.

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

можно удалить. Он ищет файлы двух типов: резервные копии и те файлы, которые можно автоматически создать заново. Давайте внима тельно рассмотрим код:

use File: :Find;

use File: :Basename;

# массив расширений файлов и расширений, из которых они могут # быть получены % derivations = (".dvi" => ".tex", ".aux" => ". tex", ".toe" => ",tex", ".o" => ",c", Мы начнем с того, что загрузим нужные нам библиотеки: знакомый уже модуль File: : F i n d и другую полезную библиотеку File: :Basename.

Эта библиотека пригодится при разборе путей файлов. Затем мы ини циализируем хэш-таблицу известными расширениями производных файлов;

например, мы знаем, что если выполнить команду ТеХ или LaTeX для файла happy.tex, мы можем получить файл happy.dvi, и что обход файловой системы при помощи модуля File::Find happy-0 можно получить, скорее всего, скомпилировав файл happy.c компилятором С. Выражение «скорее всего» употреблено потому, что иногда требуется несколько исходных файлов, чтобы сгенерировать один файл. Однако мы можем делать только простые предположения, основываясь на расширениях файлов. Обобщенный анализ зависимос тей - сложная задача, и мы даже не будем пытаться решать ее здесь.

Затем мы определяем местонахождение домашнего каталога пользова теля, получая идентификатор пользователя, выполняющего сценарий ($<), и передаем его функции getpwuidQ. g e t p w u i d ( ) возвращает инфор мацию из файла паролей в виде списка (подробности об этом позже);

индекс массива ([7]) выбирает из этого списка элемент, соответствую щий домашнему каталогу. Существуют способы получить эту инфор мацию при помощи данных из командного интерпретатора (например, обратившись к переменной окружения $НОМЕ), но в таком виде код пе реносится лучше.

Получив домашний каталог, мы переходим в него и начинаем сканиро вание, используя вызов & f i n d ( ) так же, как и в предыдущих примерах:

$homedir=(getpwuid($<))[7];

и находим домашний каталог пользователя cridir($homedir) or die "Невозможно войти в ваш домашний каталог $homedir:$!\n";

$|=1;

8 не буферизованный вывод в STDOUT print "Поиск";

find(\&wanted, ".");

и проходим по каталогам, &wanted выполняет # всю рабту Вот как выглядит вызываемая нами подпрограмма &wanted(). Сначала она ищет core-файлы, а также резервные копии и автосохраненные файлы, остающиеся после редактирования в emacs. Мы считаем, что эти файлы можно удалить, не проверяя существование исходных фай лов (вероятно, это небезопасное предположение). Если такие файлы найдены, их размеры и пути к ним сохраняются в хэше, ключами ко торого являются пути к файлам, а значениями — размеры этих файлов.

В остальной части подпрограммы подобным образом отыскиваются производные файлы. Мы вызываем подпрограмму &BaseFileExists(), для того чтобы убедиться, что эти файлы можно получить из других файлов этого же каталога. Если подпрограмма возвращает значение «истина», мы сохраняем имя файла и его размер для последующего использования:

sub wanted { # выводим точку для каждого каталога, чтобы пользователь # видел, что что-то происходит print "." if (-d $_);

# ищем только файлы return unless (-f $_);

50 Глава 2. Файловые системы # ищем core-файлы, сохраняем их в хэше %соге и возвращаемся $_ eq "core" && ($core{$File: : Find: : name} = (stat(_))[7]) && return;

# ищем резервные копии и автосохраненные файлы, оставшиеся # после редактирования файла в emacs (/"#.*»$/ | /-$/) && | ($emacs{$File: :Find: :name}=(stat(_))[7]) && return;

и ищем производные tex-файлов (/\.dvi$/ || /\.aux$/ | /\.toc$/) && &BaseFileExists($File: :Find: :name) && ($tex{$File: :Find: :name} = (stat(_))[7]) && return;

# ищем производные.о файлов /\.о$/ && &BaseFileExists($File: : Find: :name) && ($doto{$File::Find::name} = (stat(_))[7]) && return;

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

sub BaseFileExists { my($name, $path, Ssuffix) = &File: :Basename: :fileparse($_[0], '\., *' );

и если мы не знаем, как получить файл этого типа return 0 unless (defined $derivations{$suffix});

# все просто, мы видели исходный файл раньше return 1 if (defined $baseseen{$path.$name.$derivations{$suffix}});

П если файл (или ссылка на файл) существует и # имеет ненулевой размер return 1 if (-s $name. $derivations{$suffix} && ++$baseseen { Spat h.$name.$deri vat ions {$suf fix}});

print "готово.\n";

Вот как выполняется эта подпрограмма:

1. & F i l e : :Basename;

: f i l e p a r s e ( ) используется для выделения из имени файла, пути к файлу и его суффикса (например resume.dvi /home/cindy/docs/,.dvi).

Обход файловой системы при помощи модуля File::Find 2. Затем суффикс файла проверяется, чтобы определить, считаем мы этот файл производным или нет. Если нет, мы возвращаем значе ние 0 (т. е. «ложь» в скалярном контексте).

3. Затем мы проверяем, встречался ли нам файл, исходный (base file) по отношению к данному, и если да, то возвращаем значение «исти на». В некоторых ситуациях (в частности, в случае с TeX/LaTeX), из одного исходного файла можно получить несколько производ ных. Такая проверка ускоряет выполнение сценария, т. к. мы в этом случае избавлены от обхода файловой системы.

4. Если мы не встречали раньше исходный файл (с тем же именем, но другим расширением), то проверяем, существует ли он и больше ли нуля его размер. Если да, мы сохраняем информацию о файле и воз вращаем 1 (т. е. «истина» в скалярном контексте).

Теперь нам остается только вывести информацию, которую мы собра ли при обходе файловой системы:

foreach my $path (keys %core){ print "Найден core-файл, занимающий ".&BytesToMeg($core{$path}).

"MB в ".SFile: :Basename: :dirname($path). ".\n";

if (keys %emacs){ print "Следующие файлы, скорее всего, являются резервными копиями, созданными emacs:\n";

foreach my $path (keys %emacs){ Stempsize += $emacs{$path};

$path =" s/"$horoedir/~/;

# изменяем путь, чтобы ft вывод был аккуратнее print "Spath ($emacs{$path} байт)\п";

} print "\пОни занимают ",&BytesToMeg($tempsize). "MB в сумме. \п";

$tempsize=0;

if (keys %tex){ print "Следующие файлы, скорее всего, можно получить заново, если запустить 1_а/ТеХ:\п";

foreach my $path (keys %tex){ Stempsize += $tex{$path};

Spath =" s/~$homedir/~/;

tt изменяем путь, чтобы # вывод был аккуратнее print "$path ($tex{$path} байт)\п";

> print "\пОни занимают ".&BytesToMeg($tempsize). "MB в сумме. \n";

$tempsize=0;

if (keys %doto){ 52 Глава 2. Файловые системы print "Следующие файлы, скорее всего, можно получить, если вновь скомпилировать исходные файлы:\п";

foreach my Spath (keys %doto){ Stempsize += $doto{$path};

Spath =" s/"$homedir/"/;

n изменяем путь, чтобы и вывод был аккуратнее print "$path ($doto{$path} байт)\п";

} print "\пОни занимают ".&BytesToMeg($tempsize)."MB в сумме.\n";

$tempsize=0;

} sub BytesToMegf # преобразуем размер в байтах в формат Х.ХХМВ return sprintf("%.2f",($_[0]/1024000));

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

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

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

• Предложите пользователю удалить найденные файлы. Для удале ния файлов используйте оператор u n l i n k ( ) и подпрограмму rmpath из модуля File: :Path.

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

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

Существует другой, более активный подход: квоты на файловые систе мы. Квоты, или ограничения операционной системы, позволяют огра работа с дисковыми квотами ничить объем дискового пространства, отведенный определенному пользователю. Квоты существуют в Windows 2000 и во всех современ ных разновидностях Unix. В NT4 для этого необходимы продукты сто ронних разработчиков, а в MacOS для пользователей существует поня тие S.O.L. (Simply or Sore Out of Luck - просто не повезло). И хотя это активный подход, поддерживать его гораздо сложнее, чем «чистящие» сценарии, поскольку он применяется ко всем файлам, а не только к лишним, например, к core-файлам. Большинство систем ных администраторов считают лучшей стратегией использовать ком бинацию автоматических «чистящих» сценариев и дисковых квот.

Первое помогает ограничить использование второго.

В этом разделе мы поговорим о работе с дисковыми квотами в Unix средствами Perl. Перед тем как перейти к конкретному разговору, нужно понять, как квоты устанавливаются и как их можно ввести вручную. Чтобы сделать возможным применение квот в файловой сис теме, системный администратор Unix обычно добавляет запись в таб лицу смонтированных файловых систем (например файл /etc/fstab или /etc/vfstab) и перезагружает систему либо вручную вызывает ко манду, разрешающую использование квот (обычно quotaon).

Вот пример файла /etc/vfstab из Solaris:

«device device mount FS fsck mount mount #to mount to fsck point type pass at boot options /dev/dsk/cOtOdOs? /dev/dsk/cOdOtOdOs7 /home ufs 2 yes rq Параметр rq в последнем столбце включает квоты для файловой систе мы. Хранятся они для каждого пользователя отдельно. Для просмотра информации о квотах пользователя на всех смонтированных файло вых системах, на которых квоты применяются, надо вызвать команду quota:

$ quota -v sabrams чтобы получить данные, подобные этим:

Disk quotas for sabrams (uid 670):

Filesystem usage quota limit timeleft files quota limit timeleft /home/users 228731 250000 253000 0 0 В следующих нескольких примерах нас будут интересовать только первые три колонки этого вывода. Первое число - это объем занятого в настоящий момент дискового пространства пользователем sabrams на файловой системе, смонтированной как /home/users. Второе - это раз мер «мягкой квоты» пользователя. Мягкая квота - это объем дисково го пространства, после превышения которого операционная система в Здесь имеется в виду, что в MacOS дисковые квоты просто не предусмотре ны. - Примеч. науч. ред.

54 Глава 2. Файловые системы течение некоторого времени выдает предупреждения, но не ограничи вает выделение дискового пространства. Последнее число - это «жест кая квота», т. е. абсолютный верхний предел для объема пространст ва, занятого данным пользователем. Если программа попытается ис пользовать еще некоторое дисковое пространство после превышения пользователем квоты, операционная система отвергнет этот запрос и вернет сообщение об ошибке, подобное d i s k quota exceeded.

При желании изменить размеры квот вручную необходимо использо вать команду edquota, которая загружает небольшой временный файл с информацией о текущих размерах квот в редактор, определяемый переменной окружения EDITOR командного интерпретатора. Вот при мер такого файла с информацией об ограничениях для четырех файло вых систем, на которых применяются квоты. Скорее всего, домашний каталог этого пользователя находится в каталоге /exprt/server2, т. к.

только в этой файловой системе для него отведены квоты:

fs /exprt/serverl blocks (soft = 0, hard = 0) inodes (soft = 0, hard = 0) fs /exprt/server2 blocks (soft = 250000, hard = 253000) inodes (soft = 0, hard = 0) fs /exprt/server3 blocks (soft = 0, hard = 0) inodes (soft = 0, hard = 0) fs /exprt/server4 blocks (soft = 0, hard = 0) inodes (soft = 0, hard = 0) Использование edquota вручную может быть удобным способом редак тирования ограничений одного пользователя, но это совершенно не возможно в случае десятков, сотен и тысяч учетных записей пользова телей. Один из недостатков Unix - нехватка утилит командной строки для редактирования информации о квотах. В большинстве версий Unix есть функции библиотеки С для выполнения этой задачи, но нет ути лит командной строки для написания сценариев. И, следуя девизу Perl, что «Существует более одного способа сделать это» («There's Mo re Than One Way To Do It», TMTOWTDI, произносится как «тим-то ади», «tim-toady»), мы рассмотрим два различных способа установки квот из Perl.

Редактирование квот при помощи edquota Первый способ требует некоторой хитрости с нашей стороны. Совсем не давно мы упоминали процесс ручной установки дисковых квот: edquota вызывает редактор, в котором пользователь редактирует небольшой текстовый файл, после чего эти изменения используются для обновле ния информации о квотах. Не существует никаких указаний на то, ка кие данные необходимо вводить, чтобы внести изменения. В действи тельности, не существует даже ограничений на то, какой редактор бу дет применяться. Все, что нужно команде edquota, - это программа, которую можно запустить и которая необходимым образом изменит маленький текстовый файл. Подойдет любой допустимый путь (задан ный переменной окружения EDITOR) к такой программе. Почему бы не работа с дисковыми квотами указать программе edquota сценарий на Perl? Давайте и рассмотрим такой сценарий в нашем следующем примере.

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

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

«Вызывается редактор ui(l), если только в переменной EDITOR не указано иное». Идея передать аргументы командной строки через EDI TOR или другую переменную окружения довольно опасна хотя бы по тому, что мы не знаем, как на это отреагирует утилита edquota. Поэто му нам придется полагаться на один из методов межпроцессного вза имодействия, доступных в Perl. Например, два процесса могут:

• Передавать друг другу временный файл • Создать именованный канал и общаться по нему • Передавать AppleEvents (в MacOS) • Использовать объект синхронизации (mutex) или оговоренные ключи реестра (в NT/2000) • Общаться через сокеты • Использовать разделяемую память И так далее. От вас как от программиста зависит, какой метод вы вы берете, хотя зачастую определять выбор будут данные. Рассматривая их, вы будете принимать во внимание:

• Направление соединения (одно- или двунаправленное?) • Частоту соединения (будет передано одно сообщение или несколько кусочков?) • Размер данных (будет это 10-мегабайтный файл или 20 символов?) • Формат данных (будет это двоичный файл или просто текст фикси рованной ширины, разделенный определенным символом?) Наконец, учитывайте то, насколько сложным вы хотите сделать свой сценарий.

В нашем случае мы собираемся выбрать простой, но мощный метод об мена информацией. Так как первый процесс должен передать второму только набор инструкций по изменению информации (какие квоты из менять и на какие значения), мы установим между ними стандартный Глава 2. Файловые системы канал Unix.1 Первый процесс пошлет запрос на изменение в поток вы вода, а копия, запущенная программой edquota, прочитает эту инфор мацию со своего потока ввода.

,«П?",•"" '""''и,. г }_„_ Сценарий autoedquota запускает программу 1 '=^1 ш ! edquota с установленной : autoedquota edquota переменной окружения EDITOR.

;

EDITOR - autoedquota О /г = /г edquota записывает ^J——^J j ^J7 ^^я^^NW"x^^^ == временный файл v autoeciqijota edquota ^ i К autoedquota и затем запускает копию сценария.

Amp/file Копия autoedquota °^ ^ yk Я Г i ц изменяет autoedquota edquota * I [\ autoedquota временный файл.

Amp/file U^ Ш Л rr edquota заново считывает временный edquolaVN. =^ autoedquota autoedquota файл и изменяет значения для квот.

+ | W filesystem quota /Imp/file J Рис. 2.1. Изменение квот при помощи «ловкости рук» В действительности, это канал к программе edquota, которая передает потоки ввода и вывода запущенному Perl-сценарию.

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

$edquota = "/usr/etc/edquota";

it путь к edquota $autoedq = "/usr/adm/autoedquota";

tt полный путь к этому сценарию Я это первый или второй запуск?

# если присутствует более одного аргумента - это первый запуск if ($«ARGV > 0) { SParseArgs;

&CallEdquota;

} ft в противном случае это второй запуск, и мы должны выполнить ft редактирование else { &EdQuota();

} Рассмотрим код, вызываемый при первом запуске и используемый для анализа аргументов и вызова edquota через канал:

sub ParseArgs{ use Getopt: :Std;

tt для обработки параметров ft Устанавливаем переменную $opt_u равной идентификатору # пользователя, $opt_f - равной имени файловой системы, ft $opt_s - в значение для мягкого ограничения и $opt_h В в значение для жесткого ограничения getopt("u:f :s:h: ");

ft двоеточие говорит о том, что у этого ft ключа есть аргумент die "ИСПОЛЬЗОВАНИЕ: $0 -u uid -f -s -h \n" if (!$opt_u | !$opt_f | !$opt_s | !$opt_h);

| | | sub CallEdquotai $ENV{ "EDITOR"} = Sautoedq;

ft записываем в ft переменную окружения EDITOR ft путь к нашему сценарию open(EPROCESS, "|$edquota $opt_u") or die "Невозможно запустить edquota :$!\n";

58 Глава 2. Файловые системы П посылаем измененные строки во вторую копию сценария print EPROCESS "$opt_f |$opt_s|$opt_h\n";

close(EPROCESS);

} Вот вторая часть выполняемого действия:

sub EdQuota { $tfile = $ARGV[0];

# получаем имя временного файла edquota open(TEMPFILE, $tfile) or die "Невозможно открыть временный файл $tfile:$!\n";

# открываем файл-черновик, можно было бы и использовать и 10:: File — > new_tmpfile() open(NEWTEMP, ">$tfile.$$") or die " Невозможно открыть временный файл-черновик $tfile.$$:$!\n" ft получаем строку ввода из первого вызова и отсекаем символ \п chomp($change = );

my($fs,$soft,$hard) = split(/\|/,$change);

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

while (){ if (/"fs $fs\s+/){ s/(soft\s*=\s*)\d+(, hard\s*=\s*)\d+/$1$soft$2$hard/;

} print NEWTEMP;

> close(TEMPFILE);

close(NEWTEMP);

ft перезаписываем временный файл измененным черновиком, ft так что изменения передаются edquota rename("$tfile.$$",$tfile) or die "Невозможно переименовать $tfile.$$ в $tfile:$!\n";

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

работа с дисковыми квотами редактирование квот при помощи модуля Quota Когда-то очень давно предыдущий метод (или, если быть честным, предыдущий «хак») был единственным способом автоматизировать изменения квот, если, конечно, вас не радовала перспектива редакти рования системных вызовов из библиотеки С, чтобы встроить их в ин терпретатор Perl. Теперь, когда механизм расширений Perl сущест венно упростил встраивание библиотечных вызовов в Perl, создание модуля Quota для Perl стало только делом времени. Благодаря Тому Зорнеру (Tom Zoerner) и другим процесс установки квот средствами Perl теперь намного проще, если этот модуль поддерживает вашу вер сию Unix. Если нет, предыдущий метод все равно будет работать нор мально.

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

use Getopt::Std;

use Quota:;

getopt("u:f:s:h:");

die "USAGE: $0 -u uid -f -s -h \n" if (!$opt_u | !$opt_f | !$opt_s | !$opt_h);

| | $dev = Quota::getcarg($opt_f) or die "Невозможно преобразовать путь $opt_f:$!\n";

(Scurblock, Ssoft,Shard,Sbtimeout,Scurinode,Sisoft,$ihard,$itimeout)= Quota::query($dev,$uid) or die "Невозможно запросить квоту для $uid:$!\n";

Quota::setqlim($dev,$opt_u,$opt_s,$opt_h,Sisoft,Sihard,1) or die " Невозможно установить квоту:$!\п";

После анализа аргументов остаются три простых шага: во-первых, мы используем Quota: : g e t c a r g ( ) для получения идентификатора устройст ва, который передается другим подпрограммам. Затем мы передаем этот идентификатор и идентификатор пользователя функции Quo ta : : q u e ry (), чтобы получить текущие параметры квот. Нам нужны эти настройки, чтобы не нарушить ограничения, которые мы не будем из менять (например, число файлов). Наконец, мы устанавливаем квоту.

Вот и все, всего лишь три строчки кода на Perl.

Помните, что девиз Perl TMTOWTDI означает «существует более одно го способа сделать это», но это вовсе не значит «несколько одинаково хороших способов».

60 Глава 2. файловые системы Получение сведений об использовании файловой системы Располагая методами контроля над использованием файловой систе мы, которые мы только что рассмотрели, вполне естественно прове рить, как они работают. Чтобы закончить эту главу, давайте рассмот рим способ получения сведений об использовании файловой системы для каждой из операционных систем.

MacOS - операционная система, для которой эта задача наиболее сложна. В MacOS есть процедура PBHGetVInf о из Macintosh Toolbox для получения информации о томах, но в настоящее время не существует модулей MacPerl, которые сделали бы простым вызов этой функции.

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

Все используемые далее материалы основаны на работе Криса Нандо pa (Chris Nandor) и их можно найти на http://pudge.net или на CPAN.

Наберитесь терпения, пока мы будем рассматривать процесс настрой ки шаг за шагом:

1. Установите связку срап-тас. В срап-тас входит модуль CPAN. pm, на писанный Андреасом Кенигом (Andreas J. Kb'nig), и другие нужные методы, о которых говорилось в главе 1. Даже если вы не хотите по лучать сведения об использовании файловой системы в MacOS, эту связку лучше установить. После того как вы ее установите, обяза тельно выполните все инструкции из файла README.

2. Установите последнюю версию модуля Mac: :AppleEvents: :Simple, пе ретащив файл дистрибутива в installme.

3. Установите модуль Mac::Glue. «Крошка» installme распаковывав!

содержимое дистрибутива Mac: : G l u e в новый каталог в процессе ус тановки. Обязательно запустите сценарии установки gluedialect и gluescriptadds из подкаталога scripts того каталога, в который рас пакован дистрибутив.

4. Создайте файл связки для Finder. Откройте System Folder и перета щите файл Finder на вершину gluemac, чтобы создать необходимый файл (и, что очень приятно, документацию для него).

Этот сложный процесс установки позволяет нам написать такую прос' тенькую на вид программу:

use Mac::Glue qw(:all);

$fobj = new Mac::Glue 'Finder';

Svolumename = "Macintosh HD";

# имя одного из смонтированных дисков _. -уЧение сведений об использовании файловой системы Stotal = $fobj->get($fobj->prop('capacity', disk => Svolumename), as => 'doub');

$free = $fobj->get($fobj->prop('free_space', disk => $volumename), as => 'doub');

print "свободно $free байт из $total\n";

Перейдем к более простым темам. Для того чтобы получить ту же ин формацию на компьютере с Win32, мы могли бы использовать модуль Win32: : AdminMisc, написанный Дэйвом Ротом (Dave Roth):

use Win32::AdminMisc;

(Stotal,$fгее) = Win32::AdminMisc::GetDriveSpace("c:\\");

print "свободно $free байт из $total\n";

И, наконец, закончим эту главу рассмотрением эквивалентного вари анта для Unix. Существует несколько модулей для Unix, включая Fi lesys: :DiskSpace Фабьена Тассена (Fabien Tassin), Filesys: :Df Яна Гаф ри (Ian Guthrie) и Filesys: :DiskFree Алана Баркли (Alan R. Barclay). В первых двух из них используется системный вызов statvf s(), а послед ний анализирует вывод Unix-команды df на всех поддерживаемых системах. Выбор какого-либо из этих модулей зависит от ваших пред почтений и от того, что поддерживается вашей операционной систе мой. Я предпочитаю Filesys: : D f, поскольку он предлагает массу воз можностей и не запускает другой процесс (потенциальный риск, как уже говорилось в главе 1) во время запроса. Вот один из способов напи сания эквивалентного двум предыдущим примерам варианта:

use Filesys::Df;

Sfobj = df("/");

print $fobj->{su_bavail}*1024." байт в ".

$fobj->{su_blocks}*1024." байт свободно\п";

Нам необходимо выполнить некоторые расчеты (а именно: *1024), по скольку Filesys: : Df возвращает значения в блоках, а каждый блок ра вен 1024 байтам в нашей системе. Функции d f ( ) этого модуля может быть передан второй необязательный параметр, определяющий раз мер блока, если это необходимо. Следует также отметить в этом коде два запрошенных значения хэша. su_bavail и s u _ b l o c k s - это возвра щенные модулем значения размера диска и объема использованного пространства. В большинстве файловых систем Unix команда df выво дит информацию об использованном пространстве, скрывая 10% дис ка, зарезервированных для суперпользователя. При желании узнать размер доступного и свободного в настоящий момент дискового про 62 Глава 2. Файловые системы странства с точки зрения обычного пользователя мы должны исполь зовать user_blocks и user_bavail.

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

Информация о модулях из этой главы Идентифика- Версия Имя тор на CPAN File:: Find (входит в состав Perl) File:: Spec (входит в состав Perl) Cwd (входит в состав Perl) W i n 3 2 : : F i l e : : Get Attributes (входит в состав ActiveSta te Perl) W i n 3 2 : : FileSecurity (входит в состав ActiveState Perl) File:: Basename (входит в состав Perl) Getopt:: Std (входит в состав Perl) 1.2. Quota TOMZO CNANDOR 0. срап-тас (связка) 0. Mac::AppleEvents::Simple CNANDOR 0. CNANDOR Mac::Glue Источники подробной информации Страницы руководства по perlport - просто неоценимый источник ин формации для Perl-программистов о различиях платформ. Крис Нан дор (Chris Nandor) и Гурасами Сарати (Gurasamy Sarathy) дискутирова ли по поводу первых версий этого руководства на Perl Conference 2.0;

Нандор опубликовал некоторые выдержки из этой беседы на http:/l pudge.net/macperl/tpc/98.

Информация о пользователях в Unix Информация о пользователях в Windows NT/ Создание системы учетных записей дляработы с пользователями Информация о модулях из этой главы • Рекомендуемая дополнительная литература Учетные записи пользователей Попробуйте выбрать правильный ответ на следующий вопрос. Если бы не было пользователей, то системные администраторы:

a) Были бы добрее.

b) Исчезли бы с лица земли.

Независимо от того, что говорят по этому поводу системные админист раторы в «трудную минуту», Ь) - лучший ответ на этот вопрос. Как я уже говорил в главе 1, в конце концов, системное администрирование нужно для того, чтобы сделать возможным применение доступных технологий.

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

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

Но кто следит за всеми учетными записями в системе или в сети? Кто ответственен за их создание, защиту и распределение? Рискну предпо 64 Глава 3. Учетные записи пользователе ложить и скажу «вы, дорогой читатель». Ну а если не вы лично, то утилиты, которые вы создаете, и которые действуют от вашего имени в качестве посредников. Эта глава призвана помочь читателю спра виться с такой ответственностью.

Начнем разговор о пользователях с рассмотрения информации, кото рая формирует их индивидуальность, и способов хранения этой ин формации в системе. Начнем мы с пользователей операционной систе мы всех вариантов Unix, а затем рассмотрим те же проблемы в Win dows NT/2000. Для текущих версий MacOS такая проблема не акту альна, поэтому в данной главе MacOS упоминаться не будет. Познако мившись с этой информацией для обеих операционных систем, мы постараемся создать систему ведения учетных записей.

Информация о пользователях в Unix При обсуждении этой темы мы будем иметь дело лишь с несколькими •J^ ключевыми файлами, поскольку в них хранится постоянная информа ция о пользователе. Говоря «постоянная», я имею в виду атрибуты, которые существуют до тех пор, пока существует пользователь, сохра няясь даже тогда, когда пользователь не зарегистрирован в системе.

Иначе я буду называть это учетной записью. Если в системе у вас есть учетная запись, вы можете зарегистрироваться и стать пользователем данной системы.

Существование пользователя в системе начинается с того момента, когда информация о нем впервые заносится в файл паролей (или же служба каталогов обеспечивает аналогичную информацию). Пользова тель «уходит со сцены», когда эта запись удаляется. Рассмотрим под робнее, как хранится эта информация.

Классический файл паролей в Unix Начнем мы с «классического» формата файла паролей, а затем перей дем к более сложным вопросам. Я называю данный формат классичес ким, потому что на нем основаны все существующие в настоящее вре мя форматы файлов паролей в Unix. Более того, он и сейчас встречает ся во многих вариантах Unix, включая SunOS, Digital Unix и Linux.

Обычно это файл /etc/passwd, содержащий последовательность текс' товых ASCII-строк, причем каждая строка соответствует одной учет" ной записи или является ссылкой на другую службу каталогов. Любая строка файла состоит из нескольких полей, разделенных двоеточй' ями. Мы внимательно рассмотрим все эти поля, после того как на' учимся их получать.

Вот пример строки из файла /etc/passwd:

dnb:fMP.olmno4jGA6:6700:520:David N. Blank-Edelman:/home/dnb:/bin/zsh 66 Глава 3. Учетные записи пользователей онное имя пользователя, обладающего идентификатором 2397, с danielr на drinehart, то мгновенно владельцем всех его файлов ста нет пользователь drinehart. Для операционной системы идентифи катор пользователя - постоянная информация. При выделении ре сурсов и выяснении прав ядро и файловые системы следят за иден тификаторами, а не регистрационными именами. Регистрационное имя можно считать информацией, внешней для операционной сис темы;

эта информация существует, чтобы упростить жизнь пользо вателя.

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

Spasswd = "/etc/passwd";

open(PW,$passwd) or die "Невозможно открыть $passwd:$!\n";

while (){ @fields = split(/:/);

$highestuid = ($highestuid < $fields[2]) ? $fields[2] : Shlghestuid;

} close(PW);

print "Следующий доступный идентификатор: ". ++$highestuid. "\n";

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

Таблица 3.1. Переменные и функции, имеющие отношение к именам и идентификаторам пользователей Функция/ Использование Переменная getpwnam($name) В скалярном контексте возвращает идентификатор, соответст вующий этому регистрационному имени;

в списочном кон тексте возвращает все поля данной записи из файла паролей getpwuid($uid) В скалярном контексте возвращает регистрационное имя, со ответствующее данному идентификатору;

в списочном кон тексте возвращает все поля данной записи из файла паролей Соответствует эффективному идентификатору пользователя $> текущей выполняющейся программы на Perl Соответствует реальному идентификатору пользователя теку $< щей выполняющейся программы на Perl Идентификатор первичной группы (GID) В многопользовательских системах пользователи их группы работают с файлами и другими ресурсами совместно. В Unix сУ ществует механизм, позволяющий работать с группами пользовав лей. Учетная запись в системе может входить в несколько групп, при этом принадлежать она должна только одной главной труп ^формация о пользователях в Unix (primary group). Поле GID в файле паролей соответствует как раз первичной группе для данной учетной записи.

Имена групп, их идентификаторы и члены группы обычно перечис лены в файле /etc/group. Чтобы включить учетную запись в не сколько групп, необходимо просто указать ее в нескольких местах данного файла. В некоторых операционных системах существует жесткое ограничение на число групп, которым может принадле жать учетная запись (а значит, и пользователь). Чаще всего ограни чение равно 8. Вот пример пары строк из файла /etc/'group:

bin::2:root,bin,daemon sys::3:root,bin,sys,adm Первое поле — это имя группы, второе - пароль (в некоторых систе мах может употребляться пароль для присоединения к группе), третье - идентификатор группы и последнее поле - список пользо вателей в группе.

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

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

Таблица 3.2. Переменные и функции, имеющие отношение к именам и идентификаторам групп Функция/ Используется Переменная В скалярном контексте возвращает имя группы;

в списочном getgrent() контексте возвращает поля: $name, Spasswd, $gid, $members getgrnam($name) В скалярном контексте возвращает идентификатор группы;

в списочном контексте возвращает те же поля, что и функция getgrent() 9etgrgid($gid) В скалярном контексте возвращает имя группы;

в списочном контексте возвращает те же поля, что и функция g e t g r e n t ( ) $) Соответствует эффективному идентификатору группы теку щей выполняемой программы Соответствует реальному идентификатору группы текущей $( выполняемой программы 68 Глава 3. Учетные записи пользователей «Зашифрованный» пароль Мы уже рассмотрели три основных поля, в которых содержится ин формация о пользователе в Unix. Следующее поле не является частью хранимой информации, но оно подтверждает права, обязан ности и привилегии, присущие пользователю с конкретным идее тификатором. Именно так компьютер узнает, что тому, кто выдает себя за пользователя mguerre, позволено присвоить конкретный идентификатор. Существуют и другие, лучшие формы авторизации (например, использование криптографических методов с откры тым ключом), но этот способ унаследован от ранних версий Unix.

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

Работа с паролями пользователей - это отдельная тема. Ей будет посвящена глава 10 «Безопасность и наблюдение за сетью».

Поле GCOS Поле GCOS1 самое бесполезное (с точки зрения компьютера). Обыч но в этом поле записано полное имя пользователя (например «Рой Дж. Бив»), Часто люди добавляют туда должность и/или номер те лефона.

Системные администраторы, заботящиеся о приватности пользова телей (чему и следует быть), должны проверять содержимое данного поля. Это стандартный путь для определения соответствия между реальным именем пользователя и его регистрационным именем. Б большинстве Unix-систем такое поле находится в файле /etc/passwd, доступном всем для чтения, следовательно, эта информация может попасть в руки кого угодно в системе. Многие программы, почтовые клиенты и демоны finger-запросов обращаются к этому полю при добавлении регистрационного имени пользователя к какой-то ин формации. Если у вас есть необходимость скрыть реальные имени пользователей от других людей (например, если речь идет о политй' ческих диссидентах, федеральных свидетелях или известных пер' сонах), вы обязательно должны следить за этим полем.

В качестве дополнительной информации: если вы поддерживает сайт с менее развитой пользовательской базой, было бы неплох" запретить пользователям изменять их поле GCOS на случайны строки (по тем же причинам, по которым выбранные пользователя' ми регистрационные имена могут вызвать проблемы). Вряд ли ^ е придете в восторг, увидев в своем файле паролей бранные выраз# ния или иную непрофессиональную информацию.

Занятные подробности о происхождении названия этого поля можно найт' в словаре компьютерного жаргона http://www.jargon.org.

^формация о пользователях в Unix Домашний каталог Следующее поле содержит имя домашнего каталога пользователя.

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

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

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

use User::pwent;

use File::stat;

Pages:     || 2 | 3 | 4 | 5 |   ...   | 7 |



© 2011 www.dissers.ru - «Бесплатная электронная библиотека»

Материалы этого сайта размещены для ознакомления, все права принадлежат их авторам.
Если Вы не согласны с тем, что Ваш материал размещён на этом сайте, пожалуйста, напишите нам, мы в течении 1-2 рабочих дней удалим его.