Поиск по сайту:

Система событий Upstart: что это такое и как ее использовать


Введение

Инициализация — это важнейшая процедура, которая лежит в основе любой операционной системы на основе Unix и позволяет контролировать работу каждого скрипта и службы. Это важно в серверной среде, где проблемы могут возникать в критических точках запуска и завершения работы и где приоритетом является обеспечение оптимальной производительности.

По сути, инициализация следует такому процессу:

  1. Сервер загружается
  2. Выполняется процесс инициализации (обычно как PID 1)
  3. Заданный набор задач запуска активируется последовательно

Инициализация отвечает за обеспечение корректной загрузки и завершения работы облачного сервера.

Некоторые дистрибутивы на базе Unix используют для инициализации стандартный процесс инициализации. В этой статье мы рассмотрим Upstart — практичную и мощную замену, которая может ускорить работу вашего сервера.

Что не так с классическим init?

Традиционная инициализация следует линейному процессу: отдельные задачи загружаются в предопределенной последовательности при загрузке системы. Это не очень полезно, особенно в быстро меняющихся ситуациях. Чтобы понять почему, представьте, что вы, например, изменили среду сервера, добавив дополнительное устройство хранения.

Процесс инициализации не может учитывать внезапные изменения в среде, а это означает, что ваш облачный сервер должен быть повторно инициализирован, прежде чем он сможет распознать дополнительное хранилище. Обнаружение «на лету» — это то, что необходимо, хотя это и не возможность классической процедуры инициализации.

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

Вы также можете быть обеспокоены состоянием ваших задач после загрузки системы. К сожалению, init работает с последовательностью только при загрузке или выключении.

Синхронные последовательности загрузки больше не нужны. Жесткая система могла поддерживать системы вчерашнего дня, но сегодня она динамична.

Вот тут-то и появляется Upstart — решение этих проблем с расширенными возможностями.

Основываясь на событиях в реальном времени, а не на заданном списке последовательных задач, этот заменяющий демон инициализации обрабатывает запуск и остановку задач и отслеживает эти процессы во время работы системы. – «полный охват» – лучший способ описать это.

Эта новая асинхронная обработка устраняет необходимость в жесткой последовательности загрузки. Обработка в реальном времени может быть сложной для понимания, но Upstart может поддерживать самые сложные системы и держать все под контролем, используя структуру заданий.

Обзор Upstart

С самого начала разработанная с учетом гибкости, система событий Upstart использует множество концепций, которые отличаются от традиционных систем инициализации. Решение установлено по умолчанию в Red Hat Enterprise Linux (RHEL) 6, а также в Google Chrome OS и Ubuntu, хотя недавние дебаты вызвали недоумение относительно того, будет ли это продолжаться.

Работа

В мире Upstart задания — это рабочие процессы, разделенные на задания-задачи (с определенной целью) и задания-службы (которые могут выполняться в фоновом режиме). Существуют также абстрактные задания — процессы, которые выполняются вечно, пока их не остановит пользователь с правами администратора.

События

События, однако, представляют собой сигналы или «вызовы», используемые для запуска определенного действия с заданием или другим событием. Общие формы событий относятся к мониторингу процесса: starting, запущено, остановлено и остановлено.

Отправка событий

Процесс трансляции события называется «излучением». Обычно это вызвано состоянием процесса или задания, хотя администратор также может создать событие вручную, введя команду initctl emit . Вы заметите, что элемент управления инициализацией становится невероятно полезной при навигации по множеству операций, связанных с Upstart.

Написание вашей первой конфигурации задания

Известно, что Upstart хорошо работает на Ubuntu, поэтому перед началом работы запустите каплю Ubuntu 14.04.

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

  • Он не должен быть пустым (файл без содержимого)
  • Он не должен содержать синтаксических ошибок.
  • Он должен содержать хотя бы один командный блок, известный как строфа.

Давайте оставим это базовым на данный момент. Через мгновение мы создадим файл с именем testjob.conf в каталоге /etc/init. В этом случае \инициализация просто используется как сокращенная версия \инициализация.

Обратите внимание на ассоциацию файлов .conf — это указывает на то, что вы будете писать файл конфигурации задания.

Для целей этого руководства рекомендуется использовать текстовый редактор командной строки nano. Для некоторых из этих команд могут потребоваться права администратора с помощью sudo, поэтому ознакомьтесь с этой статьей, чтобы создать соответствующего пользователя.

Чтобы создать новый файл конфигурации для нашего тестового задания, запустите:

sudo nano /etc/init/testjob.conf

Давайте теперь наметим цель. Мы хотим, чтобы это задание записывало сообщение и текущую метку времени в файл журнала.

Есть две основные строфы, которые могут помочь вам определить цель сценария задания и его создателя: описание и автор. Запишите их в качестве первых строк в файле.

description "A test job file for experimenting with Upstart"
author "Your Name"

Теперь мы хотим, чтобы это задание выполнялось после того, как системные службы и процессы уже загружены (чтобы предотвратить любой конфликт), поэтому ваша следующая строка будет включать следующее событие:

start on runlevel [2345]

Вам может быть интересно, что такое уровень выполнения. По сути, это одно значение, которое представляет текущую конфигурацию системы. [2345] относится ко всем состояниям конфигурации с общим доступом к Linux и сетью, что идеально подходит для базового тестового примера.

Затем мы добавим код выполнения. Эта строка начинается с exec, чтобы указать, что следующие команды должны выполняться через оболочку Bash:

exec echo Test Job ran at  `date` >> /var/log/testjob.log

Обратите внимание, что эта команда echo использует обратные кавычки для запуска date как команды, а затем записывает все сообщение в файл журнала. Если вы напишете слово date без обратных кавычек, вместо вывода команды будет напечатано само слово.

Сохраните и закройте этот файл.

Вы можете убедиться, что это работает, запустив задание вручную, но давайте сначала проверим синтаксис файла конфигурации:

init-checkconf /etc/init/testjob.conf

Если обнаружены какие-либо проблемы, эта команда укажет конкретный номер строки и проблему. Однако с тестовым заданием вы должны увидеть такой вывод:

File /etc/init/testjob.conf: syntax ok

Эту команду можно использовать для управления заданиями Upstart и другими фоновыми службами, такими как веб-сервер.

Основной синтаксис команды:

sudo service <servicename> <control>

Этот синтаксис работает со следующими основными элементами управления:

  • перезапустить: это остановит, затем запустит службу
  • start: запустит службу, если она не запущена
  • stop: остановит службу, если она запущена
  • статус: отображает статус службы

Мы хотим вручную запустить наше тестовое задание, поэтому команда должна выглядеть так:

sudo service testjob start

Теперь проверьте файл testjob.log, выполнив следующую команду:

cat /var/log/testjob.log

Эта команда прочитает файл в оболочку; вы должны увидеть одну строку, похожую на приведенную ниже:

Test Job ran at Fri Aug 1 08:43:05 BST 2014

Это показывает, что ваше тестовое задание настроено и готово к работе.

Перезагрузите дроплет, затем войдите в систему и снова прочитайте файл журнала:

cat /var/log/testjob.log

Вы должны увидеть вторую строку в журнале, отображающую более позднюю отметку времени, чтобы подтвердить, что она выполнялась как задание Upstart.

Test Job ran at Fri Aug 1 08:44:23 BST 2014

Это лишь малая часть того, что вы можете делать с Upstart. Мы рассмотрим подробный пример позже, а пока давайте перейдем к объяснению состояний и событий заданий.

Состояния работы и события

Системные задания находятся в каталоге /etc/init/, а пользовательские задания — в собственном каталоге инициализации пользователя, ~/.init/.

Пользовательские задания выполняются в собственном сеансе пользователя, поэтому они также называются сеансовыми заданиями. Они не работают в масштабах всей системы и не имеют обозначения PID 1. Для целей нашего тестового задания мы использовали /etc/init, чтобы он мог загружаться при загрузке системы.

Независимо от типа задание всегда определяется в файле конфигурации (.conf), где его имя файла должно представлять задействованную службу или задачу.

У каждого из этих заданий есть цель — начать или остановить. Между этими двумя целями находится набор состояний задачи, которые определяют текущие действия задания по отношению к цели. Важными состояниями являются следующие:

  • ожидание: начальное состояние обработки
  • начало: начало задания
  • pre-start: где загружается предстартовый раздел
  • порождено: место, где собирается запуститься раздел скрипта
  • post-start: где происходят операции после запуска
  • выполняется: когда задание работает в полном объеме.
  • pre-stop: где выполняются операции pre-stop
  • остановка: место, где задание останавливается
  • убито: задание остановлено
  • post-stop: место, где выполняются операции post-stop — для очистки

После состояния после запуска задание определяется как работающее. Он продолжает работать до тех пор, пока не будет запущена предварительная остановка, когда задание готовится к остановке, затем задание уничтожается и выполняются процедуры очистки после остановки, если они определены.

Вы можете просмотреть, как задание переходит между состояниями, установив приоритет системного журнала Upstart (расположенного в каталоге /var/log/upstart/) на debug с помощью этой команды. :

sudo initctl log-priority debug

Помните, что состояния — это не события, а события — это не состояния. Четыре события (запуск, запуск, остановка и останов) генерируются Upstart, но состояния задачи определяют переход между этапами жизненного цикла задания.

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

Углубленный пример: сервисное задание

Кратко рассмотренное во введении, задание службы включает в себя сценарии файлов конфигурации, которые позволяют процессам работать в фоновом режиме. Мы настроим базовый сервер Node.js с нуля.

Если вы не знакомы с Node, по сути это «кроссплатформенная среда для серверных и сетевых приложений» (Википедия).

Node.js — очень легкий пакет, хотя он не установлен по умолчанию в Ubuntu 14.04. Для начала установите его на свой облачный сервер.

sudo apt-get install nodejs

Теперь давайте начнем с работы службы. Создайте новый файл конфигурации задания в /etc/init с именем nodetest.conf. Очень важно назвать файл в соответствии с его назначением, чтобы вы могли понять, что это задание службы предназначено для теста Node.js.

sudo nano /etc/init/nodetest.conf

Мы рассмотрим само приложение Node позже в этом примере, так как важно заранее понять конфигурацию Upstart.

Перво-наперво. Начните с ввода описания задания и строк автора, чтобы определить конфигурацию.

description "Service for a test node.js server"
author      "Your Name"

Мы хотим, чтобы это серверное приложение на основе Node запускалось, когда сервер запущен и работает, и останавливалось, когда он корректно завершал работу. Поэтому обязательно укажите оба условия:

start on filesystem or runlevel [2345]
stop on shutdown

Помните критерий уровня запуска, который мы использовали ранее? В сочетании с событием filesystem это гарантирует загрузку задания при нормальном запуске сервера.

Это основы, но теперь все становится сложнее; мы собираемся использовать строфы, которые мы упоминали ранее.

Поскольку это серверное приложение, мы собираемся включить элемент ведения журнала в конфигурацию задания. Поскольку мы хотим регистрировать запуск и остановку приложения Node, мы будем использовать три разных строфы для разделения действий службы — script, pre-start script и скрипт предварительной остановки.

Если вы думаете, что это звучит знакомо, вы абсолютно правы. Pre-start и pre-stop — это состояния работы, но они также работают в строфах. Это означает, что разные команды могут выполняться в зависимости от состояния, в котором находится задание.

Однако первая строфа, которую нужно написать, — это сам сценарий задания. Это позволит получить идентификатор процесса для фонового сервера Node, а затем запустить сценарий приложения. Обратите внимание на отступ команд внутри строфы — это важно для синтаксически правильного форматирования.

script

	export HOME="/srv"
	echo $$ > /var/run/nodetest.pid
	exec /usr/bin/nodejs /srv/nodetest.js

end script

Node требует установки переменной домашнего каталога, поэтому /srv экспортируется в первую строку строфы. Затем $$ используется для получения доступного идентификатора процесса и создания PID-файла для нашего задания. После этого загружается приложение Node.js, которое мы напишем позже.

Теперь пришло время сосредоточиться на pre-start и pre-stop, которые будут использоваться для нашего простого ведения журнала приложения. Дата вместе с сообщением о запуске или остановке будет добавлена в файл журнала для нашей работы:

pre-start script
	echo "[`date`] Node Test Starting" >> /var/log/nodetest.log
end script

Обратите внимание, что раздел предварительной остановки содержит еще одну строку: удаление файла PID как часть процедуры выключения сервера (что делает предварительная остановка).

pre-stop script
	rm /var/run/nodetest.pid
	echo "[`date`] Node Test Stopping" >> /var/log/nodetest.log
end script

Это вся конфигурация задания Upstart; вот еще раз все для справки:

description "Test node.js server"
author      "Your Name"

start on filesystem or runlevel [2345]
stop on shutdown

script

	export HOME="/srv"
	echo $$ > /var/run/nodetest.pid
	exec /usr/bin/nodejs /srv/nodetest.js

end script

pre-start script
	echo "[`date`] Node Test Starting" >> /var/log/nodetest.log
end script

pre-stop script
	rm /var/run/nodetest.pid
	echo "[`date`] Node Test Stopping" >> /var/log/nodetest.log
end script

Сохраните и закройте файл.

Как указано в строке exec, сценарий Node.js запускается с сервера, поэтому создайте файл nodetest.js в нужном месте (/srv/ используется для этого примера):

sudo nano /srv/nodetest.js

Поскольку это учебное пособие по Upstart, мы не будем слишком долго рассматривать код Node.js, хотя вот краткое изложение того, что делает этот скрипт:

  • Запрашивать и загружать HTTP-модуль Node.
  • Создать веб-сервер HTTP
  • Укажите ответ со статусом 200 (ОК) в заголовке.
  • Напишите \Hello World” в качестве вывода
  • Прослушивание на порту 8888

Вот код, необходимый для запуска приложения Node, который можно скопировать напрямую, чтобы сэкономить время:

var http = require("http");

http.createServer(function(request, response) {
	response.writeHead(200, {"Content-Type": "text/plain"});
	response.write("Hello World");
	response.end();
}).listen(8888);

После сохранения файла Node.js последнее, что нужно проверить, — это правильность синтаксиса задания Upstart. Как обычно, запустите команду проверки конфигурации, и вы должны получить подтверждение в виде вывода:

init-checkconf /etc/init/nodetest.conf 

File nodetest.conf: syntax ok

Вы получили конфигурацию своего задания, проверили его синтаксис и сохранили свой код Node.js — все готово к работе, поэтому перезагрузите свою каплю и затем посетите http://IP:8888 или связанный домен.

Если вы встретились со словом «Hello World» в верхнем левом углу окна, то задание службы Upstart сработало!

Для подтверждения ведения журнала на основе состояния прочитайте предопределенный файл журнала, и вы должны увидеть строку Starting с отметкой времени. Выключение сервера или ручная остановка задания службы запишет в журнал строку Stopping, которую вы также можете проверить, если хотите.

cat /var/log/nodetest.log

[Sun Aug 17 08:08:34 EDT 2014] Node Test Starting
[Sun Aug 17 08:13:03 EDT 2014] Node Test Stopping

Вы можете запускать стандартные команды запуска, остановки, перезапуска и т. д. для этой службы и любых других подобных заданий Upstart с синтаксисом, подобным следующему:

sudo service nodetest restart

Заключение

Этот туториал только поверхностно описывает систему событий Upstart. Вы прочитали предысторию традиционной инициализации, узнали, почему решение Upstart с открытым исходным кодом является более мощным выбором, и начали писать свои собственные задания. Теперь, когда вы знаете основы, возможности безграничны.

Логотип с официального сайта Upstart, авторские права принадлежат оригинальным дизайнерам/Canonical Ltd.