upstart в Ubuntu

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

Несколько слов о классической схеме загрузки пользовательских процессов в Linux. На определенном этапе загрузки системы, запускается первый пользовательский процесс init, который читает конфигурационный файл /etc/inittab. В нем прописаны основные параметры запуска системы, в частности уровень запуска (runlevel) по умолчанию и представленные ниже строки:

1
2
3
4
5
6
7
l0:0:wait:/etc/init.d/rc 0
l1:1:wait:/etc/init.d/rc 1
l2:2:wait:/etc/init.d/rc 2
l3:3:wait:/etc/init.d/rc 3
l4:4:wait:/etc/init.d/rc 4
l5:5:wait:/etc/init.d/rc 5
l6:6:wait:/etc/init.d/rc 6

Каждый такой скрипт, которому в качестве параметра передается номер уровня запуска, начинает останавливать/запускать скрипты из каталога /etc/rcN.d/, где N - это номер уровня запуска. Подробнее об этом можно прочесть в в лекции по управлению демонами.

Основной недостаток этого подхода - это то, что запуск процессов (демонов), происходит последовательно, один за другим. В то же время загрузка многих демонов не зависит друг от друга, и их можно было бы запускать параллельно, ускоряя запуск операционной системы. Второй недостаток - необходимоcть самостоятельно писать управляющие скрипты, которые находятся в каталоге /etc/init.d/. Управляющие скрипты должны уметь как минимум запускать и останавливать демон, а также реализовать обработку возможных нестандартных ситуаций. Вероятно, существуют и другие недостатки, но эти два фигурируют как основные.

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

Как и в классическом варианте - upstart имеет главный процесс, который отвечает за загрузку и управление демонами. Называется он также как и в классическом варианте - init. Чтобы понять “кто есть кто” посмотрите отсутствует ли в системе файл /etc/inittab и присутствует ли каталог /etc/init/ или /etc/event.d/. Если это так, значит у вас установлен upstart. Сейчас в своей ubuntu 9.10 я вижу только каталог /etc/init, хотя в предыдущих версиях был и каталог /etc/event.d.

Далее по тексту, чтобы отличать классический процесс init от процесса init в upstart, я буду употреблять для последнего выражение upstart init.

В upstart ввели такое понятие как “задание” (jobs). Если во время запуска процесс init читает конфигурацию из файла /etc/inittab, то процесс upstart init читает конфигурацию из файлов каталога /etc/init/. Эти файлы и являются файлами-заданиями (jobs). Каждый файл в каталоге /etc/init/ отвечает за запуск отдельного демона или сервиса и должен заканчиваться на .conf. Также допускается, создавать подкаталоги в которых могут находится файлы-задания.

Синтаксис файлов-заданий несложный. Большую часть времени при дальнейшем изучении вопроса, займет разбор событий который понимает upstart init. Поэтому пока только в общих чертах. В файлах-заданиях обязательно содержится информация когда задание должно стартовать (определение start on), когда останавливаться (stop on) и, что запускать (ключевые слова exec или script).

Итак, когда же задание сработает? Вот здесь и есть первое основное отличие которое решает проблему последовательного запуска скриптов. upstart - это подсистема которая реагирует на события. Поэтому после ключевых слов start on или stop on, обязательно указывается событие (event), при наступлении которого начинает выполняться запуск или остановка задания. Например, задание failsafe-x.conf будет выполнено в том случае когда некорректно остановится менеджер gdm (start on stopped gdm EXIT_STATUS=[!0]).

Если рассматривать события наиболее часто употребляемые в файлах заданий, то это startup, runlevel, stopped и started. startup - это самое первое событие, которое распознается подсистемой upstart на самом раннем этапе загрузки операционной системы. Событие runlevel (с указанием целевого уровня), как следует из названия генерируется при смене уровня запуска. Событие stopped генерируется после остановки указанного задания, а started после завершения старта задания. Просмотрев файлы-задания в каталоге /etc/init/ можно найти и другие события.

Таким образом если необходимо создать задание которое будет запускать тестовый демон test на 2-м и 3-м уровне запуска и останавливать на остальных уровнях, достаточно создать файл test.conf в котором написать:

1
2
3
4
start on runlevel [23]
stop on runlevel [!23]

exec test

Подсистема upstart решает и вторую проблему - она самостоятельно занимается запуском и завершением работы демонов. Строки start on runlevel [23] в одном только файле /etc/init/test.conf, достаточно для запуска демона test. Подсистема upstart освобождает нас от процедуры описания КАК запустить демон и позволяет сосредоточиться только на том ЧТО необходимо запустить.

Для ручного запуска или остановки заданий в upstart предусмотрены команды start и stop, расположенные, как правило, в каталоге /sbin. Чтобы в Ubuntu остановить демон cron достаточно ввести команду sudo stop cron:

1
2
igor@adm-ubuntu:/etc/event.d$ sudo stop cron
cron stop/waiting

Чтобы запустить cron набираем sudo start cron:

1
2
igor@adm-ubuntu:/etc/event.d$ sudo start cron
cron start/running, process 6874

Из других команд управления можно отметить команду status, которая показывает в каком состоянии (останова или работы) находится задание (а соответственно и демон):

1
2
igor@adm-ubuntu:/etc/event.d$ status cron
cron start/running, process 6874

Также следует отдельно упомянуть команду initctl. Эта команда как следует из ее названия (сокращенное от init control), позволяет управлять демоном upstart init. Команда initctl тоже умеет останавливать (initctl stop) и запускать (initctl start) задания, а также проверять их статусы (initctl status). Если нужно посмотреть статус всех заданий есть команда initctl list:

1
2
3
4
5
6
7
8
igor@adm-ubuntu:/etc/event.d$ initctl list
avahi-daemon start/running, process 836
mountall-net stop/waiting
...
...
dmesg stop/waiting
networking stop/waiting
tty6 stop/waiting

Узнать версию установленной подсистемы upstart можно по команде initctl version:

1
2
igor@adm-ubuntu:/etc/event.d$ initctl version
init (upstart 0.6.3)

В завершении пример запуска своего демона с помощью upstart. Вместо громоздкого скрипта timeconsole, достаточно создать файл /etc/init/showtime.conf следующего содержимого:

1
2
3
4
5
6
7
8
start on runlevel [2] #Запускать на втором уровне
stop on [!2] #Завершать на уровне запуска отличном от второго

post-stop script #секция позволяет задать дополнительные действия после остановки демона
clear > /dev/tty8 #очищаем консоль на которую выводилось время
end script

exec /usr/sbin/showtime #запуск демона

Для ручного управления используем команды start и stop:

1
2
3
4
5
6
igor@ubuntu:~$ sudo start showtime
showtime start/running, process 6214
igor@ubuntu:~$ sudo stop showtime
showtime stop/waiting
igor@ubuntu:~$ status showtime
showtime stop/waiting

Можно также проверить, что демон автоматически запускается при переходе на второй runlevel, набрав команду sudo telinit 2. Проверял - работает.

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

Статьи и новости схожей тематики:

Комментариев: 16

  1. IgorKa - Информационный ресурс » Отключить загрузку графического режима в Ubuntu 9.10:

    [...] файл /etc/inittab, так как управление загрузкой занимается подсистема upstart. Вторая причина - в Ubuntu уже нет такого разделения на [...]

  2. Сергей:

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

    start on (net-device-up
    and local-filesystems)

    на

    start on runlevel [2345]
    stop on runlevel [016]

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

    Ответить

    Igorka Reply:

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

    Ответить

  3. Анатолий Вугман:

    Спасибо за статью! Вот только я так и не смог запустить мою Kubuntu 10.04 в single user mode. Никак не могу понять, как при этой новой системе вручную из консоли запустить свой комп в Runlevel 1? init S не срабатывает…
    Не разъясните?
    Заранее очень признателен.

    Ответить

    Igorka Reply:

    Спасибо за комментарий.
    В справке написано, что “The RUNLEVEL argument should be one of the multi-user runlevels 2-5, 0 to halt the system, 6 to reboot the system or 1 to bring the system down into single-user mode.”
    Соответственно переходить нужно по команде sudo init 1 или sudo telinit 1. У меня Ubuntu 9.10 по этим командам переходит в single user mode.

    Ответить

  4. Анатолий Вугман:

    Самое любопытное, что даже в режиме single user (команда runlevel возвращает S), раздел root примонтирован к системе и отмонтировать его не удаётся. Всё это делает невозможной проверку файловой системы при помощи fsck. Может быть это повод написать bugreport?

    Ответить

  5. Сергей:

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

    В продолжение темы, другую более близкую не могу
    найти среди лекций, поэтому пишу здесь.
    Проблема касается остановки процессов.
    Как то я задумал выключить все лишние процессы, которые для
    моей задачи не нужны в Ububtu 9.04 (еще не обновился)
    может после этого, а может я раньше не замечал, но в процессе
    выключения компьютера за долю секунды до выключения на экран выскакивает надпись
    halt:unable to iterate IDE devices:no such files or directory

    на компе установлено два винчестера SATA и только CD-ROM -IDEшный
    какой ИДЕ девайс он не может “iterate” не понятно.
    Тем не менее, если он не может корректно остановить винчестер, это уже неприятно. Об этой проблемме довольно много написано в интернете.
    Но откуда источник ее не вполне понятно. И я не хотел, бы не разобравшись в сути, пользоваться советами из интернета типа,- уберите из скрипта то то, и надпись исчезнет…, а проблема? проблема то может остаться!

    PS. с помощью программы sysv-rc-conf я отключил запуск kvm (так как виртуализация у меня не поддерживается процессором) и libvirt, которая нужна как вспомогательная вещь для первой, насколько я понял. libvirt кроме всего прочего как я прочитал организует дополнительный сетевой интерфейс virbr0 (пропал из списка ifconfig) и, возможно, виртуальный диск какой нибудь???? который не может теперь “iterate” служба halt ???

    PPS.Эту тему обсуждали здесь
    https://bugs.launchpad.net/ubuntu/+bug/193125

    Думаю вам будет интересна эта тема.

    Ответить

    Сергей Reply:

    обновился до 10.10
    теперь при выключении shutdown -HP now слышно как сначала паркуется винчестер, а потом выключается питание. Винт сигейт 1,5 терабайта.
    надпись не возникает.
    зато другие проблемы появились.

    Ответить

    Igorka Reply:

    Добрый день.
    Спасибо большое за поздравление!
    О проблеме ничего сказать не могу - не сталкивался. Но тему постараюсь почитать.

    Ответить

  6. Илья:

    Здравствуйте, Игорь.
    Ваша статья очень интересная.
    У меня такая ситуация: при вводе команды runlevel, получаю unknown.
    Не запускаются скрипты из /etc/rc*.d, даже при выполнении команд telinit * или init *.
    Не могли бы Вы поподробнее расказать о совместимость upstart и старого способа запуска.
    Много демонов запускается из /etc/rc*.d и писать для каждого скрипт запуска в /etc/init нехочется (хотя для некоторых и написал стартовать по событию local-filesystems).

    Ответить

    Igorka Reply:

    Добрый день, Илья
    Спасибо за отзыв. По поводу совместимости upstart и классического init написал небольшое дополнение http://igorka.com.ua/2010-11-27/upstart-i-sovmestimost-s-tradicionnym-init/ . Попробуйте проверить файл /etc/init/rc.conf - он отвечает за запуск скриптов из /etc/rc*.d

    Ответить

  7. Igorka: Upstart и совместимость с традиционным init:

    [...] статье upstart в Ubuntu я постарался разложить для себя по полочкам работу [...]

  8. Илья:

    Все замечательно, только вот runlevel откуда берется?
    Например у меня при запуске системы он unknown.
    А событие “start on runlevel [0123456]” из файлика rc.conf естественно при таком раскладе не происходит.

    Ответить

    Igorka Reply:

    Если подразумевается значение выдаваемое программой runlevel, то в man runlevel четко написано: runlevel reads the system UTMP file, which defaults to /var/run/utmp , а также: If no runlevel record can be found, runlevel outputs the word unknown and exits with an error. Если интересно как запись попадает в /var/run/utmp, то там это тоже написано.

    Ответить

  9. Илья:

    Спасибо за ответ, буду разбираться.

    Ответить

  10. MCE:

    Спасибо, статья старая, а польза большая)) почти до всего сам докопался, упёрся в то что убунта упорно перекидывала меня на 7ю консольку…
    начиная с версии 11 системе на файлик gdm.conf до фонаря.. там появилась такая штука как ligthdm. Для запуска без иксов надо удалить конфиг с соответствующим именем.

    Ответить

Оставьте свой отзыв