- Подписка на печатную версию:
- Подписка на электронную версию:
- Подшивки старых номеров журнала (печатные версии)
LXF109:DRBruan3
Материал из Linuxformat.
Содержание |
Юный выскочка
- init малость устарел; пришло время нового демона запуска системы.
Много лет в Linux использовалась схема управления запуском сервисов во время загрузки, которая появилась в System V Unix еще в 1983 году. За эти годы системные администраторы подружились со структурой System V и уровнями выполнения. Они знают и о скриптах запуска сервисов в /etc/init.d, и обо всех этих символических ссылках с названиями на ‘S’ и ‘K’, и о процессе init с его файлом конфигурации /etc/inittab.
Поэтому исчезновение inittab в некоторых последних дистрибутивах Linux немного шокирует, как и замена почтенного init на upstart. Первым дистрибутивом, выполнившим ее, был Ubuntu (еще в Edgy Eft более полутора лет назад). В Fedora 9 также используется upstart (это позволяет предположить, что за ним со временем последует Red Hat Enterprise Linux), а разработчики OpenSUSE 11.0 предпочли остаться со старым добрым init.
Upstart – это основанная на событиях замена init; управляет запуском задач и сервисов во время загрузки и их остановкой во время выключения системы и наблюдает за ними во время работы. Демон upstart, для обратной совместимости (и для вящей путаницы) названный init, управляется «событиями», формируемыми D-BUS. У события есть простое текстовое имя, например, ‘startup’, ‘control-alt-delete’ или ‘runlevel’.
При запуске демон читает все файлы в /etc/event.d/. Каждый из них определяет задание, которым будет управлять upstart. Имя задания совпадает с именем файла. Эти файлы устанавливают, какие события вызовут запуск (или останов) задания и что делать, когда происходит событие. Вот простой пример – файл события Ctrl+Alt+Delete из Fedora 9 (обе его строки!):
start on control-alt-delete exec /sbin/shutdown -r now “Control-Alt-Delete pressed”
Когда задание активизируется, оно проходит через серию состояний: ожидание, запуск, выполнение, остановка и т.д. Эти изменения состояний сами порождают события: «запускается», «запущено», «останавливается» и «остановлен». Поэтому можно определить задание, запускаемое по окончании другого. Вот файл события prefdm – он отвечает за запуск графического экрана входа в систему сразу после перехода на уровень выполнения 5 (т.е. после завершения задания ‘rc5’):
start on stopped rc5 stop on runlevel [!5] console output respawn respawn limit 10 120 exec /etc/X11/prefdm -nodaemon
Директивы respawn в этом файле говорят, что upstart должен перезапустить программу после ее завершения, но не более 10 раз каждые 120 секунд. Механизм обработки событий upstart предоставляет большую гибкость в определении того, что должно произойти при выполнении заданных условий; можно, например, потребовать «смонтировать USB-брелок, когда он обнаружен». Впрочем, ни в Ubuntu, ни в Fedora я не увидел подтверждения тому, что upstart настроен на такие штуки.
Upstart поставляется с утилитой initctl, позволяющей получить список заданий, показать все сгенерированные события и переходы и даже вызвать собственные события вручную. Есть и утилита telinit, предоставленная для обратной совместимости, хотя, насколько я могу судить, она просто вызывает событие подходящего уровня выполнения.
Поэкспериментируем
Понять, как работает upstart, поможет простой эксперимент. (Я проводил его на Fedora 9, но все должно работать точно так же на Ubuntu.) Начнем с создания файла sayhello в каталоге /etc/event.d с таким содержимым:
start on greet console output script echo “hello $1” at $(date) > /tmp/upstart-test end script
Затем просигнализируем upstart перечитать файлы событий. Как и у старины init, у демона upstart идентификатор процесса равен 1:
# kill -HUP 1
Теперь проверим, что upstart знает о нашем задании, с помощью команды:
# initctl list control-alt-delete (stop) waiting logd (stop) waiting prefdm (start) running, process 2119 rc0 (stop) waiting ... кое-что опущено ... sayhello (stop) waiting ... опущено еще больше ... tty5 (start) running, process 2123 tty6 (start) running, process 2127
Вызовем событие ‘greet’ с помощью initctl таким образом:
# initctl emit greet ellie greet ellie sayhello (start) waiting sayhello (start) starting sayhello (start) pre-start sayhello (start) spawned, process 9333 sayhello (start) post-start, (main) process 9333 sayhello (start) running, process 9333 sayhello (stop) running sayhello (stop) stopping sayhello (stop) killed sayhello (stop) post-stop sayhello (stop) waiting
Вывод команды ясно показывает изменения состояний, порождаемые нашим заданием ‘sayhello’. А проверка содержимого файла /tmp/upstart-test должна дать соответственно:
# cat /tmp/upstart-test hello ellie at Mon Jun 2 06:45:36 BST 2008
Чтобы продвинуться на этап вперед, определим второе задание ‘saygoodbye’ в файле /etc/event.d. Оно будет запускаться после завершения ‘sayhello’:
start on stopped sayhello console output script echo “goodbye world” >> /tmp/upstart-test end script
Конечно, будет нужно велеть upstart перечитать файлы. Теперь откройте второе окно терминала. Выполните в нем следующую команду:
# initctl events
Она останется работать в фоне и сообщит обо всех событиях.
Вернитесь в первое окно и сгенерируйте другое событие ‘greet’:
# initctl emit greet taylor
потом вернитесь во второе, чтобы посмотреть, какие события были сгенерированы:
greet taylor starting sayhello started sayhello stopping sayhello ok stopped sayhello ok starting saygoodbye started saygoodbye stopping saygoodbye ok stopped saygoodbye ok
и в завершение эксперимента снова проверьте содержимое файла /tmp/upstart-test, чтобы убедиться в том, что задание ‘saygoodbye’ запускалось:
# cat /tmp/upstart-test hello taylor at Mon Jun 2 07:01:45 BST 2008 goodbye world
Ну да, пример игрушечный. Но я надеюсь, что он помогает почувствовать, как работает механизм обработки событий upstart, и показывает некоторые его возможности. Он мог бы заменить, например, запуск задач по расписанию, который сейчас выполняется Cron. Однако его главная цель на данный момент – просто заместить init как средство запуска сервисов во время загрузки. В самом upstart нет уровней выполнения, но просмотрев файлы событий в /etc/event.d, можно увидеть, что конфигурация эмулирует прежнее поведение. Все начинается с события startup, активизирующего задание rcS, которое выполняет традиционный низкоуровневый скрипт инициализации /etc/init.d/rcS (в Ubuntu) или /etc/rc.d/rc.sysinit (в Fedora). Что произойдет дальше, зависит от конкретного дистрибутива.
Потенциал
В Fedora 9 задание rcS запускает скрипт ‘post-stop’ – он вытаскивает уровень выполнения по умолчанию из /etc/inittab и вызывает telinit с этим уровнем выполнения как аргументом. Версия telinit в upstart нужна только для обратной совместимости, она просто генерирует событие ‘runlevel 3’, которое в свою очередь активизирует задание rc3, запускающее традиционный скрипт /etc/rc.d/rc3 для перехода на желаемый уровень выполнения.
Чтобы разобраться с Ubuntu, потребовалось чуть больше времени, но я в конце концов заметил файл rc-default, запускаемый по завершению задания rcS (он содержит строку ‘start on stopped rcS’). Этот файл также пытается получить уровень выполнения по умолчанию из /etc/inittab, а если такого файла нет (кстати, в установке по умолчанию его и нет), то переходит на уровень выполнения 2 путем вызова telinit. Но и в Ubuntu, и в Fedora все заканчивается вызовом обычного стартового сценария, который запускает скрипты S* из каталога с соответствующим уровнем выполнения. Другими словами, методы взаимодействия с сервисами времени загрузки не изменились. (Например, для управления ссылками S* и K* все еще используется chkconfig.) В обоих случаях ссылка на /etc/inittab – это лишь мимолетный кивок в сторону обратной совместимости; в этом файле всего одна строка ‘initdefault’, она задает начальный уровень выполнения. В самом upstart нет уровней выполнения, они лишь результат настройки upstart, заботящейся об обратной совместимости.
Вообще-то в Ubuntu от идеи уровней выполнения почти отказались, так как их всего два: single-user и 2. Кажется, мы возвращаемся ко временам BSD Unix, где были только уровни выполнения single-user и multi-user, и даже я смог понять, что происходит.
Документация по upstart довольно скупа. В частности, в Ubuntu даже нет раздела man, где описывался бы формат файлов событий, хотя такой раздел имеется в Fedora. Неплохое обсуждение есть в блоге Скотта Джеймса Ремнанта [Scott James Remnant] (http://www.netsplit.com), но как-то странно искать документацию по фундаментальным вопросам в подобных местах. LXF
Не цитируйте меня…
Мой коллега, преподаватель по Linux, как-то спросил меня: «Чем различаются теория и практика?» Как, наверное, требует профессиональная этика в такие моменты, я ответил: «Не знаю, а чем?» «Ну, – сказал он, – в теории разницы нет, а на практике есть».
Компьютерщики привыкли присваивать слова: ремешок ботинка (начальная загрузка – bootstrap), семафор, сигнал, молотить (thrash), мышь, печенье (cookie – куки), пламя (flame – флейм), мясные консервы (spam – спам), вилка (fork) и т.д. – и это напоминает мне наблюдение Шалтая-Болтая из «Алисы в Зазеркалье» Льюиса Кэрролла. Он сказал: «Когда я употребляю слово, оно означает только то, что я хочу, чтобы оно означало – ни больше, ни меньше». Вот моя любимая цитата из Ларри Уолла [Larry Wall]: «Скажем, вы вернулись в прошлое к Аде Лавлейс [Ada Lovelace, дочь поэта Байрона; считается самым первым программистом, – прим. ред.] и спросили бы ее, в чем разница между скриптом [сценарием] и программой. Она бы, наверное, улыбнулась и сказала что-то типа: “Ну, сценарий дают актерам, а программку – публике”».
И моя самая любимая, из Роберта Ферта [Robert Firth]: «Одной из главных причин падения Римской Империи было отсутствие нуля в нумерации: не было способа узнать, что их программы на C успешно завершились».
Это терминал
Заметили, как трудно стало встретить добрую старую командную строку? Раньше вы просто загрузили бы компьютер и сразу ее увидели, но в современных дистрибутивах, чтобы до нее добраться, нужно пройти через три уровня меню. В Vista – четыре. В поисках этой подсказки я теперь начинаю чувствовать себя изгоем, вынужденным мокнуть под дождем на заднем дворе, чтобы выкурить сигарету. Итак, вот мое «впечатление художника» о том, как найти командную строку в Intrepid Ibex.