Upstart в режиме простого пользователя
Всем, кто администрирует Ubuntu - уже давно известно, что Canonical продвигают свою альтернативу для init - upstart, и постепенно мигрирует все init.d скрипты в соответствующие сценарии upstart .
Многим, кто занимается разработкой серверных приложений под Linux, известно о множественных "демонах-контроллерах" вроде daemon-tools или supervisor, цель которых - следить за работой приложения, запустив как дочерний процесс; логгировать его stdout и stderr, перезапускать его в случае краха.
Но не все знают, что upstart предоставляет "из коробки" функционал, в том числе, минимальный для демонов-контроллеров, но в большинстве своём более чем достаточный - перезапуск в случае краха и логгирование выводов.
Собственно, данный функционал сам по себе достаточно неприметен, и используется upstart для реализации аналога древнего как мир функционала inittab "respawn", которым классически поддерживалась работа текстовых консолей.
Важно другое - что upstart позволяет непривилегированному пользователю иметь свои собственные сценарии upstart!
Работает это достаточно просто:
- в домашнем каталоге пользователя создаётся каталог
.init
, в котором и создаются сценарии - сценарии upstart пишутся полностью в том же виде, как и "системные"
Есть нюанс - по-умолчанию, в Ubuntu возможность выполнять сценарии от непривилегированного пользователя запрещена политиками D-Bus. Нужно добавить соответствующую политику в /etc/dbus-1/system.d/Upstart.conf
(пример для пользователя username):
<policy user="username">
<allow send_destination="com.ubuntu.Upstart"
send_interface="org.freedesktop.DBus.Introspectable" />
<allow send_destination="com.ubuntu.Upstart"
send_interface="org.freedesktop.DBus.Properties" />
<allow send_destination="com.ubuntu.Upstart"
send_interface="com.ubuntu.Upstart0_6" />
<allow send_destination="com.ubuntu.Upstart"
send_interface="com.ubuntu.Upstart0_6.Job" />
<allow send_destination="com.ubuntu.Upstart"
send_interface="com.ubuntu.Upstart0_6.Instance" />
</policy>
Конечно, можно просто сменить контекст default
(он по-умолчанию даёт read-only доступ всем), но изменить политику для одного пользователя мне показалось безопаснее.
Данное решение почти настолько же "админонезависимо" как, например, пользовательский crontab
- оно позволяет приложению, работающему с правами непривелегированного пользователя, иметь собственные сервисы и управлять ими, что иногда бывает очень полезно.
В моём случае я использую upstart для организации работы всяких обработчиков очередей в php-приложениях, без установки дополнительных демонов.
UPD: Есть ещё одна особенность, которую я обнаружил после рестарта сервера - сценарии upstart, созданные пользователем, не принимаются в учёт initctl
до тех пор, пока сам initctl
не будет вызван этим пользователем - пока не откроется сессия upstart. Для этого достаточно выполнить любую команду initctl
после перезагрузки от имени данного пользователя, и вызвать затем событие initctl emit EVENT
, а на данный EVENT повесить start on
пользовательского сценария upstart. В интернете есть примеры изящного решения это проблемы в виде скрипта upstart, например здесь
P.S. upstart может работать весь целиком от имени обычного пользователя (ключ --session
), но это скорее для отладки и экспериментов.