Настройка и работа в Linux
adb5321d

Замуровали, демоны


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

Разрешение на выполнение нужного набора скриптов можно задавать интерактивно. Для этого достаточно обратить внимание на заголовочек, указывающий на то, что нажатие I можно использовать для управления процессом старта. Реально после нажатия появляется файл /var/run/confirm, который и служит флагом интерактивного режима загрузки. Для перхода на уровень выполняются все файлы в соответствующем подкаталоге rc$runlevel.d. Имена этих файлов, как правило, начинаются с большой (это существенно) буквы S или K. Если первая буква иная, то файл просто не участвует в процессе межуровневого перехода. Файлы на S отвечают за старт службы, а файлы на K - за остановку какой-либо службы. Обратите внимание, что при переходе на уровень 3 прямо со старта, мы никак не используем файлы из rc2.d - только rc3.d. Этот вариант отличается от того, который принят, например, в Unix System V. Там при старте, последовательно выполняются стартовые файлы всех промежуточных каталогов, в частности, rc1.d, rc2.d и т.п.

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

Посмотрим порядок выполнения командных файлов более подробно. Сначала выполняется останов служб (первая буква K) и только затем старт (соответственно S). Ясно, что одна и та же служба, как правило, нужна на нескольких уровнях. Было бы обидно при каждом переходе (например, с уровня 2 на уровень 3) останавливать и рестартовать ее. От этого надо как-то защищаться. Для System V это получается автоматически, так как старт и останов службы входят в набор конкретного уровня. В Linux же требуются специальные проверки. Роль флагов выполняют файлы в каталоге /var/lock/subsys/${subsys} или /var/lock/ subsys/${subsys}.init, где subsys - имя подсистемы. Если файлов нет, то данная подсистема считается не запущенной (и, соответственно, запуск S-файла имеет смысл), а если есть - запущенной (и, соответственно, запуск K-файла имеет смысл). Поэтому останов службы по команде kill не будет замечен этим механизмом. Если посмотреть подробнее, то окажется, что все файлы в каталогах rcn.d являются символьными ссылками на соответствующие файлы из /etc/rc.d/init.d. Более того, и стартовые файлы, и файлы остановки подсистемы ссылаются на один файл. Отличие обеспечивается за счет передачи параметра start или stop. В некоторых вариантах Unix можно явно использовать тот факт, что стартстопный файл запускается два раза, но лучше этого не делать и честно разбираться с параметрами. Иногда для выдачи красивого листинга старта/останова системы на экран в Unix используется большее количество опций, например, что-либо в стиле start_msg/stop_msg. Если у вас есть привычки, то отладка скриптов при переносе может отнять массу времени.


Для управления набором доступных служб можно использовать программу конфигурирования linuxconf. Что означает разрешить или запретить использование какой-либо службы с точки зрения всяких там файлов? Запрещение старта какого-либо сервиса просто приводит к удалению соответствующей ссылки из каталогов rcn.d, а разрешение - к появлению. А как же обеспечивается корректная установка номера у соответствующей ссылки? Мы же должны обеспечить правильный порядок выполнения старта для подсистем. Неужели linuxconf обязан знать про роль всех служб и что-то интеллектуально вычислять?

Все устроено гораздо проще. Обратите внимание на часть заголовка файла /etc/rc.d/init.d/atd:

# Запуск демона

# chkconfig: 345 40 60

# processname: atd


Что-то неуловимо знакомое мы видим в строке с chkconfig. 345 - явно похоже на список уровней. 40 и 60 смахивают на номера для S и K файлов. Сумма номеров 100 достаточно типична (но, естественно, не обязательна). Таким образом, проще добиться того, чтобы порядок останова подсистем был почти в точности обратен стартовому. Попробуйте поменять 40 на 41 и отменить (разрешить) какую-либо службу. Стартовый файл поменяет свое имя. Description в данном файле четко отвечает за комментарий, который linuxconf выдает вам на экран для объяснения роли данной службы.

Заглянем в сам файл /etc/rc.d/init.d/atd. Мы сразу видим, что реально возможных опций больше, чем стандартные start и stop. Имеются еще restart, reload и status. Такая ситуация тоже достаточно типична. Старт, останов и проверка состояния демона выполняется рядом функций типа daemon, killproc, status. Если все происходит по плану, то создается (удаляется) файл /var/lock/subsys/atd.

Рассмотрим теперь подробнее вышеуказанные процедуры daemon, killproc, status. Они определяются (вместе с рядом других) в /etc/rc.d/init.d/functions (а тот пользуется определениями из /etc/sysconfig/init). Уже по названию ясно для чего они предназначены - старт, останов и проверка статуса демона.

Функция daemon обеспечивает старт подсистемы (службы, демона и т.п.). При этом можно учесть особенности поведения демона (требуемые ресурсы процессора и т.п.) и заказать их в виде nice-значения (+/-nicevalue) и конкретного пользователя (-user).



Перед стартом демона всегда делается проверка наличия его в системе. Поскольку демон может вызываться из скрипта, то для проверки текущего состояния можно заказать точное имя (-check name). Так как появление dump-а демона может приводить к проблемам с security, то все демоны запускаются в режиме без core-dump. Сам старт выполняется командой initlog $INITLOG_ARGS -c , которая и стартует демона и записывает информацию об этом в лог.

Останов демона выполняется процедурой killproc. Данная функция предполагает один аргумент в виде имени демона и, возможно, еще один для указания сигнала, который и будет послан демону для окончания. SIGKILL очень часто может быть не желателен, так как могут возникнуть разнообразные проблемы типа блокирования ресурсов. Поэтому, если сигнал назначен, то используется только он, если не назначен, то сначала SIGTERM и, если данный сигнал не позволит упокоить демон за разумное время, то посылается SIGKILL. Последним действием удаляется флаговый файл /var/run/подсистема.pid.

Наконец status позволяет проверить текущее состояние работы подсистемы. Если процесс работает, то просто сообщается данный факт. Если не работает, то делается проверка на наличие флаговых файлов (/var/run/подсистема.pid и /var/lock/subsys/подсистема), которые должны блокировать повторный запуск. Естественно наличие их диагностируется как ошибка.

Кроме этого, в файле functions есть объявления action - просто выполнить действие (без каких-либо проверок) и зафиксировать его в логе; confirm - генерируемый запрос на подтверждение продолжения работы; другие макросы. Action необходимы в тех случаях, когда работа службы обеспечивается непосредственно ядром системы, т.е. демон для работы не нужен. Соответственно к этой группе можно отнести конфигурирование сетевой подсистемы (например, ifconfig не должен работать непрерывно), монтирование nfs-систем и т.п.

Попробуем теперь добавить новый демон или новое действие в систему. Для этого скопируем /etc/rc.d/init.d/atd в новый файл. Что можно (at/atd), заменим на sleep. Что будет, если в строчке с демоном поставить daemon sleep 120? Потребуем у linuxconf подцепить службу. Да, не долго готов конфигуратор ждать запуска демона. 15 секунд ожидания - уже побег. Другими словами, демон обязан завершиться за разумное время... Но как в таком случае он будет выполнять свои демонические функции? На самом деле, нам требуется ограниченность по времени старта демона. Демон стартует, что-то там проверяет и, выполнив fork-exit, уходит в тину. Если бы у нас имелся файл mysleep с содержимым наподобие sleep 120 &, то старт:

daemon -check sleep /etc/

rc.d/init.d/mysleep


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


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