При работе с определёнными возможностями системы возникает несколько моделей поведения администратора относительно прав доступа пользователей к этим возможностям. Приведём два примера. Использование утилиты sudo (контролируемое получение прав другого пользователя) может быть разрешено всем пользователям (на усмотрение самой sudo), разрешено только членам группы wheel (традиционное именование группы пользователей, имеющих право управлять системой), или запрещено всем, кроме суперпользователя (из параноидальных соображений). Служба сетевой печати CUPS по умолчанию не может быть настроена через WWW-интерфейс, пока не будет перезапущена с административном режиме: service cups admrestart. В этом режиме её можно настраивать (зная пароль суперпользователя), но нельзя печатать... В другом варианте использования обе функции — и печати, и настройки — доступны одновременно, что безусловно, удобнее, но подозрительно с точки зрения безопасности.
В обоих случаях для получения нужного профиля использования необходимо выполнить ряд раз и навсегда установленных действий: соответственно, изменить права на запуск утилиты sudo и добавить в файл настройки CUPS /etc/cups/cupsd.conf две строки:
RunAsUser no NoIzvrat yes
Иногда последовательность действий довольно замысловата, но главное — она всегда одинакова. Пару раз выполнив её «руками», администратор непременно напишет командный сценарий, который будет делать всё то же самое за него.
Заимствованный ALT Linux из проекта Open Wall Linux пакет control — всего лишь набор функций для единообразного написания таких сценариев. Функций этих в файле /etc/control.d/functions меньше десятка, но с их помощью управление профилями использования и sudo, и CUPS, и некоторых других служб системы становится тривиальным. Например, первый вариант использования sudo (для всех) включается командой control sudo public, второй — control sudo wheelonly, а третий — control sudo restricted. Два варианта использования CUPS — control cups hardened и control cups public соответственно. Во многие пакеты ALT Linux добавлена поддержка control, это — своеобразная библиотека стандартных решений администраторских задач.
Самое примечательное, что и реализация многих задач при помощи control становится тривиальной. Тому пример control-сценарии для sudo и CUPS: сначала в них задаётся файл и то, какие права доступа он должен иметь или какую строку содержать в каждом из профилей, а затем вызывается функция, заданный профиль устанавливающая.
Список всех профилей, установленных в системе, их текущее значение и возможные варианты выдаёт команда control без параметров. Сами control-сценарии лежат в каталоге /etc/control.d/facilities. Список всех пакетов дистрибутива, использующих control, можно найти с помощью grep "/etc/control.d/facilities" каталог_дистрибутива/i586/base/contents_index. Прежде чем бросаться решать какую-нибудь задачу или исправлять «неполадки» в системе, посмотрите, а не управляется ли это control? Если не управляется, попробуйте оформить ваше решение в виде сценария для control — это сэкономит время. Если же вы поделитесь с окружающими результатами работы, и доведёте дело до включения в пакет ALT Linux, благодарность сообщества вам обеспечена!
В ALT Linux используется схема TCB, в которой при добавлении новой учётной записи добавляется новая строка в файл /etc/passwd, новый подкаталог /etc/tcb/входное_имя и файл shadow в нём. Для совместимости с другими схемами входное_имя может содержать только латинские буквы, цифры и символ подчёркивания. Для задания полного имени пользователя можно использовать ключ -c полное имя. Переключение между схемой хранения паролей TCB, классической схемой (с единым файлом /etc/shadow) и строгой схемой (классическая, при которой команду passwd имеет право запускать только суперпользователь) управляется командой control passwd с параметрами tcb, traditional и restricted соответственно.
Более того, изо всех схем создания невосстановимого ключа (hash) к паролю — DES, MD5, Blowfish — выбрана последняя, Blowfish, наиболее устойчивая к взлому. Эта схема поддерживается не всеми версиями glibc, и, как следствие, экспорт учётных записей в другие системы не всегда возможен. Руководство по функции crypt другой системы может дать ответ, поддерживается ли там Blowfish или нет. Импорт учётных записей из других систем, использующих shadow, не вызывает неприятностей, нужно только иметь в виду, что небезопасный ключ пребудет в shadow неизменным до тех пор, пока пользователь не сменит пароль (преобразование невосстановимого ключа из одного формата в другой, конечно, невозможно). При решении задач импорта-экспорта учётных записей стоит воспользоваться содержимым пакета tcb-utils.
Задача добавления пользователя в какую-нибудь группу или удаления его оттуда традиционно решается с помощью команды vigr — редактированием файла /etc/group (или /etc/gshadow). vigr заботится о том, чтобы на время работы доступ к этому файлу был закрыт, а специально созданный временный файл отдаёт на редактирование программе, указанной в переменной окружения $EDITOR, после чего заменяет старый файл новым. Если перемещение пользователей по группам — частая задача, на основе vigr несложно написать соответствующий сценарий.
Многие устройства системы могут быть доступны пользователю, если он включён в группу, которой это устройство принадлежит. К некоторым из них можно обращаться только из-под суперпользователя или будучи членом группы. Обращение к устройству чаще всего происходит неявно: например, при работе с модемом программа скорее всего будет обращаться к объекту /dev/modem, что есть ссылка, допустим, на устройство последовательного ввода-вывода /dev/ttyS1. Тогда пользователь должен входить в группу uucp, которой это устройство принадлежит.
Похожий эффект наблюдается у программ, работающих с таблицей процессов (w, ps или top): обычный пользователь увидит только процессы, принадлежащие ему. Для того, чтобы пользователь мог видеть и чужие процессы, ему необходимо быть членом группы proc, которой принадлежат все объекты виртуальной файловой системы /proc.
Некоторые системные службы ALT Linux 2.4 Master (в частности, Bind, DHCP и PostgreSQL) обладают достаточно высокими правами, но при этом в них часто обнаруживаются уязвимости, позволяющие стороннему злоумышленнику этими правами воспользоваться. Происходит ли это из-за лености разработчиков, сложности исходного кода или повышенного внимания со стороны хакеров — неважно, безопасность системы должна быть так или иначе обеспечена. Было бы неплохо иметь такой инструмент, который от всего системного наполнения оставлял в досягаемости этой службы только необходимые ей файлы, а всё остальное надёжно скрывал.
Такой инструмент есть. Он основан на системном вызове chroot() (и соответствующей ему утилите), выполнив который, программа теряет доступ ко всем каталогам, лежащим в дереве системных каталогов ниже заданного. При этом перестанут быть доступны и утилиты из /bin, и динамические библиотеки, лежавшие в /lib (используются утилитами), и /etc, и многое другое. Поэтому для организации окружения (chrooted environment) все необходимые файлы нужно копировать в chroot-каталог или его подкаталоги. В результате даже если злоумышленник сможет воспользоваться уязвимостью chroot-процесса, он получит доступ только к окружению, которое само является копией системных файлов.
Для того, чтобы запустить в таком окружении, допустим, командный интерпретатор, необходимо скопировать туда ещё три библиотеки:
# mkdir /tmp/chroot # { echo "/bin/sh"; ldd /bin/sh | awk '{print $3}'; } | cpio -pLdvm /tmp/chroot /tmp/chroot/bin/sh /tmp/chroot/lib/libdl.so.2 /tmp/chroot/lib/libc.so.6 /tmp/chroot/lib/ld-linux.so.2 3058 blocks # echo /tmp/chroot/* /tmp/chroot/bin /tmp/chroot/lib # chroot /tmp/chroot /bin/sh # echo * bin lib
Более сложные, чем ls программы и демоны требуют большего количества файлов в окружении. В частности, сервисы, которые держат настроечные файлы в /etc или обращаются к находящимся там общесистемным файлам, таким как /etc/passwd или /etc/hosts, должны копировать необходимое им содержимое /etc в своё окружение. Процедуры копирования окружения оформляются в виде командных сценариев и размещаются в каталоге /etc/chroot.d. Обновление окружений на основании содержимого этого каталога выполняет утилита update_chrooted.
Внося исправления в настройки сети, в файлы, отвечающие за механизм преобразования адресов (/etc/resolv.conf, /etc/nsswitch.conf и т. д.), в настроечные файлы служб, использующих chrooted environment, обязательно заканчивать работу командой update_chrooted conf.
По соображениям безопасности многие сетевые сервисы запускаются без возможности принимать соединения с других компьютеров. Например, супердемон xinetd, предназначенный ля обслуживания простых сетевых сервисов, таких как ftp или talk, по умолчанию имеет запись only_from = 127.0.0.1 в файле настройки /etc/xinetd.conf. Это означает, что без исправления этой записи xinetd будет принимать соединения только с локального компьютера. Кстати, все простые сетевые сервисы, устанавливающие дополнительные файлы настойки xinetd в каталог /etc/xinetd.d, по умолчанию используют настройку disable = yes, и не запускаются при старте системы.
Сходным образом модифицирован файл настроек почтового сервера postfix: строчка smtp inet n - - - - smtpd в файле /etc/postfix/main.cf закомментирована, отчего сервер не принимает соединений из сети. В такой конфигурации postfix вообще не использует сеть для обмена почтовыми сообщениями, ограничиваясь соединением посредством сокетов семейства UNIX (UNIX-domain socket). Такие же настройки имеет графическая среда XFree86 (команда startx приводит к запуску ║/usr/X11R6/bin/X -nolisten tcp) и сервер шрифтов xfs (он запускается с параметром -port -1).
Многие другие демоны (в частности, серверы БД PostgreSQL и MySQL) также по умолчанию не принимают внешних сетевых запросов. Администратору необходимо самостоятельно, под свою ответственность настроить эти сервисы.
Первое, что рассказывается про ядро в популярных книжках по Linux: как пересобрать его из исходных текстов с помощью специализированных утилит или даже непосредственно редактируя профиль. Первое, что стоит знать про ядра ALT Linux: их не надо пересобирать.
Дело в том, что технология пересборки ядра была весьма актуальна в прошлом, когда, с одной стороны, экономия нескольких килобайтов памяти могла повысить производительность системы, а, с другой стороны, многие функции ядра ещё не были окончательно от него отчуждены и вынесены в модули. Вдобавок драйверы некоторых устройств на шине ISA требовали, чтобы управляющие настройки этих устройств (порт, прерывание) задавались при компиляции. Поэтому приходилось заранее определять профиль ядра (подчас довольно сложный), после чего запускать процесс сборки (который требует наличия на компьютере средств разработки).
Ныне ситуация упростиласть. Потеря сотни килобайтов или даже пары мегабайтов памяти погоды не делает. Современные устройства настраиваются и анонсируют свои настройки сами — либо сразу после включения компьютера, либо в процессе начальной загрузки системы. Практически все устройства, наличие которых не требуется для загрузки ядра, в ядро не включены: они загружаются в виде модулей ядра во время начальной загрузки. Модуль ядра часто называют драйвером, хотя это может быть определённая способность системы (например, межсетевой экран), а не интерфейс к устройству. В отличие от демонов и прочих программ, модуль ядра прикомпоновывается непосредственно к ядру и процедуры, определённые в нём, работают в режиме ядра. В типовой системе загружается «чистое» ядро и дополнительные модули, либо подобранные программой установки системы, либо заранее заданные программой автоматической настройки kudzu, либо определённые в процессе загрузки программой hotplug.
Если особенности компьютера требую модификации внустренностей самого ядра (например, на многопроцессорных системах необходима поддержка архитектуры SMP, система Open Mosix внедряет свои исправления в ядро и т. п.), необходимо установить другое ядро командой apt-get install. Ядро устанавливается параллельно со старым, причём файлы настройки LILO и GRUB изменяются таким образом, чтобы при загрузке использовалось новое ядро, но было доступно также и старое. Ядра разных типов и версий используют разные модули, так что при обновлении ядра следует обновлять и модули. Некоторая неприятность заключается в том, что, если на вашей системе установлен виртуальный пакет kernel-complete-профиль-ядра (а это — результат установки системы), то в ней установлены все модули к этому ядру. Поэтому для полноценного обновления ядра необходимо либо обновлять все пакеты с модулями, либо для начала удалить все ненужные. Удаление модулей ядра требует познаний в архитектуре персонального компьютера. Возможно, вам поможет команда lsmod (выводящая список используемых модулей) и lspcidrake (выводящая список внешних устройств в системе), а возможно, и нет.
Следует помнить, что обновление ядра (например, по требованиям безопасности), не происходит в процессе автоматического обновления пакетов системы (apt-get update && apt-get dist-upgrade). Поэтому рекомендуется следующая процедура обновления (в нашем примере установлено обычное ядро для однопроцессорной архитектуры, kernel-image-std-up, и только один модуль, lm_sensors; версии пакетов соответствуют состоянию на июль-август 2004 года).
# apt-get install kernel-image-std-up Reading Package Lists... Done Building Dependency Tree... Done Package kernel-image-std-up is a virtual package provided by: kernel-image-std-up#2.4.26-alt5 2.4.26-alt5 [Installed] kernel-image-std-up#2.4.26-alt6 2.4.26-alt6 [Installed] You should explicitly select one to install. E: Package kernel-modules-std-up is a virtual package with multiple good providers. # apt-get install kernel-image-std-up#2.4.26-alt6 . . . # apt-get install kernel-modules-lm_sensors-std-up . . . (снова предупреждение о множественности) # apt-get install kernel-modules-lm_sensors-std-up#2.8.6-alt3.6 . . .
Обратите внимание, что APT уже знает о возможном обновлении ядра и модуля, но ничего не говорит до тех пор, пока вы его не попросите.
Если необходимо обновить модуль, который используется при загрузке ядра (то есть включается в initrd, например, для SCSI RAID), возникает неприятная ситуация. С одной стороны, модули ядра зависят от ядра, и поэтому устанавливаются в обязательном порядке после обновления своего ядра. С другой стороны, процесс обновления (установки) ядра завершается пересозданием initrd, и ещё не поставленные модули туда не попадают. Решением будет по окончании процедур обновления ещё раз запустить послеустановочный сценарий (post-install script):
# rpmquery --qf '%{POSTIN}\n' kernel-image-std-up-2.4.26-alt6 /sbin/installkernel 2.4.26-std-up-alt6 # /sbin/installkernel 2.4.26-std-up-alt6
После этого следует перезагрузить систему (по умолчанию — с новым ядром и модулями). Если ядро и модули работают нормально, можно, наконец, удалить старое ядро и зависящие от него модули (модули удалятся автоматически, поскольку зависят от удаляемого ядра). Пакет с ядром занимает около 20 мегабайтов, так что удаление имеет смысл.
# apt-get remove kernel-image-std-up#2.4.26-alt5
Загрузка модулей управляется с помощью пакета modutils. В частности, посмотреть список загруженных модулей можно командой lsmod. Загрузить новый модуль — командой insmod имя_модуля, а выгрузить — командой rmmod имя_модуля. В процессе начальной загрузки обрабатывается файл /etc/modules.conf и файлы в каталоге /etc/modutils.d/, и по результатам обработки загружаются модули. При острой необходимости modules.conf можно изменять вручную. Перед этим рекомендуется изучить документацию, входящую в пакет modutils.
Пример. Дистрибутив ALT Linux 2.4 Master поддерживает два различных семейства звуковых драйверов — Open Sound System (OSS) и ALSA (Advanced Linux Sound Architecture). Оба семейства весьма обширны, но списки поддерживаемого ими оборудования различаются (хотя во многом пересекаются). Поэтому, если звук на вашем (видимо, не совсем стандартном) компьютере работает неудовлетворительно, вы можете попытаться переключиться на другое семейство. Допустим, используется драйвер OSS для звуковой карты ES1978 Maestro 2E:
root# lspcidrake . . . maestro : ESS Technology|ES1978 Maestro 2E . . . root# cat /etc/modules.conf alias sound-slot-0 maestro
Чтобы переключиться на ALSA, необходимо установить пакет kernel-modules-alsa и поправить modules.conf сообразно информации на сайте ALSA (там следует выбрать разработчика, ESS Technology, и тип карты, maestro-2e). Нсстройки для каждого типа карт разные, но зависят только от структуры ALSA, и поэтому не различаются от версии к версии.
root# apt-get install kernel-modules-alsa-std-up root# $EDITOR /etc/modules.conf root# cat /etc/modules.conf . . . # alias sound-slot-0 maestro # ALSA portion, got from http://www.alsa-project.org/alsa-doc/doc-php/template.php?company=ESS+Technology&card=maestro-2e&chip=maestro-2e&module=es1968 alias char-major-116 snd alias snd-card-0 snd-es1968 # module options should go here # OSS/Free portion alias char-major-14 soundcore alias sound-slot-0 snd-card-0 # card #1 alias sound-service-0-0 snd-mixer-oss alias sound-service-0-1 snd-seq-oss alias sound-service-0-3 snd-pcm-oss alias sound-service-0-8 snd-seq-oss alias sound-service-0-12 snd-pcm-oss . . .
Альтернативы позволяют иметь в системе несколько программ со сходной функциональностью, вызываемых по одному и тому же имени. Формально их можно считать определённым расширением файловой системы. Например, в системе может стоять несколько версий компилятора C 2.95, 2.96, 3.2, 3.3 ,пользователь пишет хорошо переносимую программы и ему удобнее в Makefile один раз прописать cc, а потом проверять компиляцию по очереди разными версиями.
Кроме того пользователь или программа могут не заботиться о текущем используемом эмуляторе терминала, а просто вызывать его по имени xvt.
Если есть несколько альтернатив, то надо как-то организовать выбор. Выбор той или иной альтернативы определяется или в ручную администратором системы или автоматически согласно выставленным весам. Веса задаются при упаковке пакета и не подлежат дальнейшему изменению, иначе будет хаос.
Пример 6.1. разные веса
Например kconsole может иметь вес 11, а xterm 12. Cоответственно если в системе установлены обе эти программы одновременно, то предпочтение будет отдано xterm. Программа желающая запустить xvt реально запустит xterm.
В принципе возможно в будущем пользователь тоже сможет определить собственные альтернативы, но это требует тщательного обдумывания ибо связано с потенциальными проблемами безопасности: пользователя смогут «заставить» выполнить совсем не ту программу которую он хотел
Ниже приводится список формальных требований к альтернативам. Сначала основные определения:
Есть список альтернатив
Для каждой альтернативы (alternative) определён список возможных кандидатов (candidate)
Альтернатива является или главной(master), или подчинённой (slave)
Альтернатива находится или в ручном режиме(manual), или автоматическом(auto)
Каждый кандидат главной альтернативы имеет вес - неотрицательное целое число. Вес кандидатa подчинённой альтернативы считается неопределённым.
Выбор кандидата происходит по следующим принципам:
Если альтернатива находится в ручном режиме, то выбирается указанный кандидат
Если альтернатива находится в автоматическом режиме и главная, то выбирается кандидат с наибольшим весом
Если есть несколько кандидатов с одним весом, то среди них выбирается лексикографически старший
Если альтернатива находится в автоматическом режиме и подчинённая, то выбор определяет главная для неё альтернатива
В голосовании участвуют только кандидаты соответствующие реально существующим файлам. Если у данной альтернативы нет кандидатов на голосование, то она выбывает из рассмотрения. Если альтернатива находится в ручном режиме и указанный кандидат не соответствует никакому реальному файлу, то альтернатива переводится в автоматический режим.
В любой момент система альтернатив должна находиться в целостном состоянии. Требования к целостности приведены ниже:
Альтернатива в ручном режиме может указывать только на своих кандидатов.
Во избежание проблем не должно быть двух и более одинаковых кандидатов
Не должно быть циклов в зависимостях между альтернативами (под зависимостью понимается отношение: главная-подчинённая)
Каждый кандидат обязан указывать тех и только тех подчинённых кандидатов, которые указаны в описании альтернативы,не могут существовать кандидаты одной и той альтернативы с разным набором подчинённых (slaves)
При изменении конфигурации, система должна провести проверку целостности и если проверка не прошла откатить изменения.
Одновременно работать с базой может только одна программа (блокировка)
Перечисленных требований должно быть достаточно чтобы любая их реализация работала корректно и без сбоев.
Ниже изложен один из возможных подходов к реализации системы альтернатив
Файлы альтернатив реализуются с помощью символических ссылок следующим образом: Общее имя , по которому пользователи вызывают программу /path/common-name указывает на служебную ссылку /etc/alternatives/internal-name, которая в свою очередь указывает на определённого кандидата /path/candidate. Такое размещение позволяет перенастраивать альтернативы даже если каталог с бинарными файлами /usr) находится в режиме «только чтение». Кроме того, для программе работающей с альтернативами это, пожалуй, самый удобный способ удалять символические ссылки на уже несуществующие альтернативы (например в результате удаления пакета из системы).
Есть два возможных подхода организации базы данных кандидатов. Первый подход [20]: пакет при установке добавляет сведения в базу с помощью специальной утилиты, а при удалении - удаляет за собой данные из базы . В этом случае надо хорошо продумывать формат хранения из базы, а также корректное добавление/удаление данных. Существует большая опасность порушить базу, а вместе с ней и все альтернативы. Второй [21] - не создавать отдельного хранилища, каждый пакет носит с собой конфигурационный файл. При добавлении/удалении пакета данные «автоматически» добавляются/удаляются. Корректность процедуры гарантирует rpm. Во втором подходе пакету после установки достаточно только дать запрос на обновление. Система альтернатив проанализирует все альтернативы и произведёт все изменения, которые необходимы.
Второй подход лучше в плане хранения данных, облегчает восстановление в сбойных ситуациях, но тоже не без проблем. Скрипты обновления статуса альтернатив логично размещать в %post и %postun. Если просто проводить обновление, например, вызывая макрос %update_alternatives, то возможна ситуация, что в небольшой промежуток времени символические ссылки будут в подвешенном состоянии. Такое случается, например, когда удаляется пакет с большим весом - возникает промежуток времени между удалением файлов и запуском скрипта %postun (и соответственно восстановлением ситуации).
Истина как всегда где-то посередине. В нашей реализации используется смешанный подход: При установке пакета происходит активизация кандидата (%register_alternative), а перед началом удаления - деактивизация (%unregister_alternative). Поэтому несмотря на то что файлы ещё присутствуют в системе система альтернатив считает, что их уже нет и переключает альтернативу на новые файлы. Активизация/деактивизация реализована через создание/удалении символической ссылки на файл-описание кандидата (/etc/alternatives/packages.d/some-name) в рабочий каталог (/etc/alternatives/auto/).
Конфигурационный файл альтернатив находится по адресу /etc/alternatives/alternatives.xml. Формат конфигурационного файла общий для всех программ, использующих класс Config из libing. Настраиваемые параметры:
Каталог куда кладут свои файлы описания кандидатов пакеты, по-умолчанию это /etc/alternatives/packages.d/
Каталог, где размещаются символические ссылки на активных кандидатов, по-умолчанию это /etc/alternatives/auto/
Каталог, где размещаются служебные ссылки, по-умолчанию - /etc/alternatives
Файл-описание также имеет стандартный формат со следующими параметрами. Внутри файла может присутствовать несколько групп candidate. Каждая группа есть описание одного кандидата альтернативы. Внутри группы candidate могут дополнительно присутствовать несколько групп slave - описание соответствующего предоставляемого кандидата подчинённой альтернативы
общее имя файла, разделяемое между несколькими альтернативами
реальное имя файла кандидата
вес кандидата, может отсутствовать у альтернатив находящихся в ручном режиме
текущий кандидат альтернативы, присутствует только если альтернатива находится в ручном режиме
общее, разделяемое имя подчинённой альтернативы
реальное имя файла кандидата подчинённой альтернативы
В этом разделе на простом примере будет продемонстрировано как добавить поддержку альтернатив в пакет. Одновременно будут даны разъяснения по миграции со старой схемы на новую.
Пакет colorifer занимается расцветкой вывода приложений изначально не приспособленных для этого. В частности, он может быть использован для расцвечивания ошибок компиляции gcc. Действует он следующим образом: пользователь запускает как обычно gcc, вместо него стартует colorifer, который запускает уже настоящий gcc и расцвечивает его вывод на экран. Не всем пользователям нравится «цветной» компилятор, поэтому надо создать альтернативу /usr/bin/gcc.
В старой версии альтернатив у каждого кандидата было три атрибута: общее имя, имя альтернативы, имя кандидата. В данном случае это: /usr/bin/gcc, gcc и /usr/bin/colorifer соответственно.
В новой версии альтернатив у каждого кандидата только два атрибута: общее имя и имя кандидата. Имя альтернативы признано избыточным и автоматически вычисляется для внутренних нужд. Если вы переходите со старой схемы на новую и желаете удалить служебные ссылки от старой версии не забудьте указать это имя.
Основные используемые макросы:
Каталог куда кладут свои файлы описания кандидатов пакеты, /etc/alternatives/packages.d/
Произвести регистрацию (сделать активными) файлы-описания name1 и name2, удалить старые служебные ссылки oldname1 и oldname2. Если нет необходимости в удалении старых ссылок, то формат сокращается до «%register_alternatives name». Обновить состояние альтернатив. Помещается в скрипт %post.
Отменить регистрацию файла-описания name и обновить состояние альтернатив. Помещается в скрипт %preun.
Итак пусть старый spec-файл colorifer выглядел следующим образом [22]
PreReq: /usr/sbin/update-alternatives .... %post /usr/sbin/update-alternatives \ --install %_bindir/gcc gcc %_bindir/colorifer 50 \ --slave %_bindir/g++ g++ %_bindir/colorifer \ --slave %_bindir/g77 g77 %_bindir/colorifer \ --slave %_bindir/gcj gcj %_bindir/colorifer %preun [ $1 = 0 ] || exit 0 /usr/sbin/update-alternatives --remove gcc %_bindir/colorifer ....
Первым делом создадим файл описания альтернативы colorifer.xml со следующим содержанием:
<group name="candidate"> <option name="link">/usr/bin/gcc</option> <option name="real">/usr/bin/colorifer</option> <option name="weight" type="number">50</option> <group name="slave"> <option name="link">/usr/bin/g++</option> <option name="real">/usr/bin/colorifer</option> </group> <group name="slave"> <option name="link">/usr/bin/g77</option> <option name="real">/usr/bin/colorifer</option> </group> <group name="slave"> <option name="link">/usr/bin/gcj</option> <option name="real">/usr/bin/colorifer</option> </group> </group>
Добавим его в секцию %files, изменим %post и %preun скрипты, не забудем удалить cтарые ссылки (gcc,g++,g77,gcj). Поменяем зависимость пакета на пакет alternatives. После этого spec-файл примет следующий вид: [23]
.. Source100: colorifer.xml .. PreReq: alternatives >= 0.0.6 .. %install install -d $RPM_BUILD_ROOT%_altdir install %SOURCE100 $RPM_BUILD_ROOT%_altdir/%name.xml ... %post %register_alternative colorifer.xml -- gcc g++ g77 gcj %preun %unregister_alternative colorifer.xml ... %files %_altdir/colorifer.xml ...
Пакет готов.
Стартовые сценарии ALT Linux устроены примерно так же, как в RedHat Linux, по простой «.d»-схеме. Суть её в следующем. Любое атомарное действие по изменению способностей системы — запуск и останов определённой службы, автоматическое изменение или сохранение настроек и т. п. — оформляется в виде командного сценария в каталоге /etc/rc.d/init.d. К такому сценарию предъявляются определённые требования: как минимум, он должен распознавать в качестве первого параметра слова start и stop. Будучи запущен с параметром start этот сценарий выполняет действия по запуску службы или активации настроек, а с параметром stop он останавливает службу или записывает активные настройки в файл.
Когда система загружается, init — выполняет сначала сценарий /etc/rc.d/rc.sysinit, а затем — /etc/rc.d/rcномер, где номер соответствует уровню выполнения (профилю использования системы, обычно он равен 3, многопользовательский с сетью или 5, многопользовательский с сетью и графической средой). Всё это сводится к выполнению в лексикографическом (грубо говоря, алфавитном) порядке всех сценариев из каталога /etc/rc.d/rcномер.d/, начинающихся на букву K (Kill) с параметром stop и всех сценариев, начинающихся на S (Start) с параметром start. Принято после буквы K или S вставлять двузначное число, а затем — имя службы, а сами файлы в rcномер.d/ делать символьными ссылками на сценарии в /etc/rc.d/init.d/ (точнее, на файлы в ../init.d/, так достигается совместимость с системами, в которых init.d и rc*.d лежат не в /etc/rc.d, а в /etc или вообще где угодно). Останов системы рассматривается как переход на уровень выполнения 0, а перезагрузка — на уровень выполнения 6, так что имена файлов в каталогах rc0.d и rc6.d начинаются сплошь на K, кроме S00killall, S01reboot или S01halt. Таким образом достигается строгий порядок выполнения действий без создания единого стартового сценария, как в ранних версиях BSD.
В ALT Linux 2.4 Master эти рекомендации носят обязательный характер, потому что размещение сценариев в каталогах rc*.d происходит не вручную, а автоматически. Для этого в начало каждого сценария вносятся комментарии особого вида: # description:, после которого следует краткое описание, и chkconfig:, после которого следует три числа. Первое — набор цифр (без пробелов), соответствующих уровням выполнения, на которых сценарий будет использоваться (т. е. создаваться ссылка, начинающаяся на S). Второе — двузначное число, которое будет добавляться в имя ссылки после S, а третье — двузначное число, которое будет добавляться в имя ссылки после K. Команда chkconfig имя_службы on автоматически создаёт ссылки типа S для всех уровней выполнения, указанных в первом числе поля chkconfig:, а для остальных уровней выполнения — ссылки типа K. Команда chkconfig имя_службы off заводит во всех каталогах rc*.d ссылки типа K. Стоит заметить, что другие поля похожего формата остались в стартовых сценариях от других, более сложных систем автоматической загрузки и в ALT Linux 2.4 Master не используются. В приведённом примере сценарий netfs (монтирование сетевых файловых систем) запускается на уровнях 3, 4, и 5, причём при запуске служба имеет номер 25, а при останове — 75.
$ grep chkconfig: /etc/rc.d/init.d/netfs # chkconfig: 345 25 75 $ chkconfig —list netfs netfs 0:выкл 1:выкл 2:выкл 3:вкл 4:вкл 5:вкл 6:выкл $ ls -l /etc/rc.d/rc*.d/*netfs* lrwxrwxrwx 1 root root 15 Авг 15 19:06 /etc/rc.d/rc0.d/K75netfs -> ../init.d/netfs lrwxrwxrwx 1 root root 15 Авг 15 19:06 /etc/rc.d/rc1.d/K75netfs -> ../init.d/netfs lrwxrwxrwx 1 root root 15 Авг 15 19:06 /etc/rc.d/rc2.d/K75netfs -> ../init.d/netfs lrwxrwxrwx 1 root root 15 Авг 15 19:06 /etc/rc.d/rc3.d/S25netfs -> ../init.d/netfs lrwxrwxrwx 1 root root 15 Авг 15 19:06 /etc/rc.d/rc4.d/S25netfs -> ../init.d/netfs lrwxrwxrwx 1 root root 15 Авг 15 19:06 /etc/rc.d/rc5.d/S25netfs -> ../init.d/netfs lrwxrwxrwx 1 root root 15 Авг 15 19:06 /etc/rc.d/rc6.d/K75netfs -> ../init.d/netfs
Кроме того, правила оформления стартовых сценариев ALT Linux рекомендуют, чтобы они распознавали ещё один параметр — status, позволяющий определить состояние службы (по крайней мере, узнать, запущена ли она или нет). Честный стартовый сценарий всё равно должен уметь это определять, иначе попытка запуска K-сценария при остановленной службе будет выдавать сообщение об ошибке, даже если спецификой службы это предусмотрено. Например, супердемон xinetd при запуске проверяет, зарегистрирована ли в нём хотя бы одна сетевая служба, а не найдя таковых, завершает работу. Для отражения того, что запуск службы прошёл успешно, в ALT Linux заведён специальный каталог, /var/lock/subsys, в котором стартовые сценарии создают т. н. lock-файлы. Если lock-файл службы есть в этом каталоге, значит, она запущена, и K-сценарий действительно должен её останавливать. Поэтому рекомендуется запускать и останавливать системные службы не напрямую, запуском демонов, и даже не путём запуска сценария из init.d, а с помощью утилиты service. Впрочем, вызов service имя_службы команда" эквивалентен /etc/rc.d/init.d/имя_службы команда", просто командная строка выходит короче.
При написании стартового сценария рекомендуется пользоваться файлом /etc/init.d/functions, в котором определены основные функции для работы с /var/lock/subsys и унифицированным выводом сообщений на экран. Обратите внимание, что по соображениям совместимости обычно используется имя каталога /etc/init.d, а не /etc/rc.d/init.d, при этом первое имя — всего лишь символьная ссылка на второе.