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.

Личные инструменты
  • Купить электронную версию
  • Подписаться на бумажную версию