- Systemd за пять минут
- systemd/User
- Contents
- How it works
- Basic setup
- Environment variables
- Service example
- DISPLAY and XAUTHORITY
- pam_environment
- Automatic start-up of systemd user instances
- Writing user units
- Example
- Example with variables
- Reading the journal
- Temporary files
- Xorg and systemd
- Automatic login into Xorg without display manager
- Xorg as a systemd user service
- X clients as a user service
- Some use cases
- Persistent terminal multiplexer
- Window manager
- Kill user processes on logout
- Troubleshooting
- Runtime directory ‘/run/user/1000’ is not owned by UID 1000, as it should
Systemd за пять минут
Наша компания занимается администрированием веб-серверов на базе CentOS. Довольно часто наши клиенты используют веб-приложения на базе python, ruby или java. Для автозапуска подобных приложений есть готовые шаблоны для написания стартап-скриптов. Но прогресс не стоит на месте, вышел уже второй релиз CentOS 7 и, следуя старой традиции «не ставить dot-zero релизы на продакшен», мы начинаем предлагать клиентам сервера на базе CentOS 7.1 (1503).
В CentOS7, так же как и в его родителе RHEL7, используется systemd — менеджер системы и служб для Linux, совместимый со скриптами инициализации SysV и LSB. systemd обеспечивает возможности агрессивной параллелизации и много всего прочего.
Огромный монстр с множеством возможностей, гибкими настройками и мегабайтами документации…
Но что делать, если стоит задача быстро-быстро, вот прямо вчера, сделать автозапуск некоего сервиса?
Давайте выжмем из документации минимально необходимый набор информации для создания простых старт-стоп скриптов.
Systemd запускает сервисы описанные в его конфигурации.
Конфигурация состоит из множества файлов, которые по-модному называют юнитами.
Все эти юниты разложены в трех каталогах:
/usr/lib/systemd/system/ – юниты из установленных пакетов RPM — всякие nginx, apache, mysql и прочее
/run/systemd/system/ — юниты, созданные в рантайме — тоже, наверное, нужная штука
/etc/systemd/system/ — юниты, созданные системным администратором — а вот сюда мы и положим свой юнит.
Юнит представляет из себя текстовый файл с форматом, похожим на файлы .ini Microsoft Windows.
[Название секции в квадратных скобках]
имя_переменной = значение
Для создания простейшего юнита надо описать три секции: [Unit], [Service], [Install]
В секции Unit описываем, что это за юнит:
Названия переменных достаточно говорящие:
Далее следует блок переменных, которые влияют на порядок загрузки сервисов:
Запускать юнит после какого-либо сервиса или группы сервисов (например network.target):
After=syslog.target
After=network.target
After=nginx.service
After=mysql.service
В итоге переменная Wants получается чисто описательной.
Если сервис есть в Requires, но нет в After, то наш сервис будет запущен параллельно с требуемым сервисом, а не после успешной загрузки требуемого сервиса
В секции Service указываем какими командами и под каким пользователем надо запускать сервис:
(по умолчанию): systemd предполагает, что служба будет запущена незамедлительно. Процесс при этом не должен разветвляться. Не используйте этот тип, если другие службы зависят от очередности при запуске данной службы.
systemd предполагает, что служба запускается однократно и процесс разветвляется с завершением родительского процесса. Данный тип используется для запуска классических демонов.
Также следует определить PIDFile=, чтобы systemd могла отслеживать основной процесс:
Команды на старт/стоп и релоад сервиса
ExecStart=/usr/local/bin/bundle exec service -C /work/www/myunit/shared/config/service.rb —daemon
ExecStop=/usr/local/bin/bundle exec service -S /work/www/myunit/shared/tmp/pids/service.state stop
ExecReload=/usr/local/bin/bundle exec service -S /work/www/myunit/shared/tmp/pids/service.state restart
Тут есть тонкость — systemd настаивает, чтобы команда указывала на конкретный исполняемый файл. Надо указывать полный путь.
Таймаут в секундах, сколько ждать system отработки старт/стоп команд.
Попросим systemd автоматически рестартовать наш сервис, если он вдруг перестанет работать.
Контроль ведется по наличию процесса из PID файла
В секции [Install] опишем, в каком уровне запуска должен стартовать сервис
multi-user.target или runlevel3.target соответствует нашему привычному runlevel=3 «Многопользовательский режим без графики. Пользователи, как правило, входят в систему при помощи множества консолей или через сеть»
Вот и готов простейший стартап скрипт, он же unit для systemd:
myunit.service
Кладем этот файл в каталог /etc/systemd/system/
Смотрим его статус systemctl status myunit
Видим, что он disabled — разрешаем его
systemctl enable myunit
systemctl -l status myunit
Если нет никаких ошибок в юните — то вывод будет вот такой:
Запускаем сервис
systemctl start myunit
Смотрим красивый статус:
systemctl -l status myunit
Если есть ошибки — читаем вывод в статусе, исправляем, не забываем после исправлений в юните перегружать демон systemd
Источник
systemd/User
systemd offers users the ability to manage services under the user’s control with a per-user systemd instance, enabling users to start, stop, enable, and disable their own user units. This is convenient for daemons and other services that are commonly run for a single user, such as mpd, or to perform automated tasks like fetching mail.
Contents
How it works
As per default configuration in /etc/pam.d/system-login , the pam_systemd module automatically launches a systemd —user instance when the user logs in for the first time. This process will survive as long as there is some session for that user, and will be killed as soon as the last session for the user is closed. When #Automatic start-up of systemd user instances is enabled, the instance is started on boot and will not be killed. The systemd user instance is responsible for managing user services, which can be used to run daemons or automated tasks, with all the benefits of systemd, such as socket activation, timers, dependency system or strict process control via cgroups.
Similarly to system units, user units are located in the following directories (ordered by ascending precedence):
- /usr/lib/systemd/user/ where units provided by installed packages belong.
/.local/share/systemd/user/ where units of packages that have been installed in the home directory belong.
/etc/systemd/user/ where system-wide user units are placed by the system administrator.
/.config/systemd/user/ where the user puts their own units.
When a systemd user instance starts, it brings up the per user target default.target . Other units can be controlled manually with systemctl —user . See systemd.special(7) § UNITS MANAGED BY THE USER SERVICE MANAGER .
Basic setup
All the user units will be placed in
/.config/systemd/user/ . If you want to start units on first login, execute systemctl —user enable unit for any unit you want to be autostarted.
Environment variables
The user instance of systemd does not inherit any of the environment variables set in places like .bashrc etc. There are several ways to set environment variables for the systemd user instance:
- For users with a $HOME directory, create a .conf file in the
/.config/environment.d/ directory with lines of the form NAME=VAL . Affects only that user’s user unit. See environment.d(5) for more information.
One variable you may want to set is PATH .
After configuration, the command systemctl —user show-environment can be used to verify that the values are correct.
Service example
Create the drop-in directory /etc/systemd/system/user@.service.d/ and inside create a file that has the extension .conf (e.g. local.conf ):
DISPLAY and XAUTHORITY
DISPLAY is used by any X application to know which display to use and XAUTHORITY to provide a path to the user’s .Xauthority file and thus the cookie needed to access the X server. If you plan on launching X applications from systemd units, these variables need to be set. Systemd provides a script in /etc/X11/xinit/xinitrc.d/50-systemd-user.sh to import those variables into the systemd user session on X launch. [3] So unless you start X in a nonstandard way, user services should be aware of the DISPLAY and XAUTHORITY .
If you customize your PATH and plan on launching applications that make use of it from systemd units, you should make sure the modified PATH is set on the systemd environment. Assuming you set your PATH in .bash_profile , the best way to make systemd aware of your modified PATH is by adding the following to .bash_profile after the PATH variable is set:
Note that this will not affect systemd services started before PATH is imported.
pam_environment
Environment variables can be made available through use of the pam_env.so module. See Environment variables#Using pam_env for configuration details.
Automatic start-up of systemd user instances
The systemd user instance is started after the first login of a user and killed after the last session of the user is closed. Sometimes it may be useful to start it right after boot, and keep the systemd user instance running after the last session closes, for instance to have some user process running without any open session. Lingering is used to that effect. Use the following command to enable lingering for specific user:
Writing user units
See systemd#Writing unit files for general information about writing systemd unit files.
Example
The following is an example of a user version of the mpd service:
Example with variables
The following is an example of a user version of sickbeard.service , which takes into account variable home directories where SickBeard can find certain files:
As detailed in systemd.unit(5) , the %h variable is replaced by the home directory of the user running the service. There are other variables that can be taken into account in the systemd manpages.
Reading the journal
The journal for the user can be read using the analogous command:
To specify a unit, one can use
Note that journald will not write user journals for users with UIDs below 1000, instead directing everything to the system journal.
Temporary files
systemd-tmpfiles allows users to manage custom volatile and temporary files and directories just like in the system-wide way (see systemd#systemd-tmpfiles — temporary files). User-specific configuration files are read from
/.local/share/user-tmpfiles.d/ , in that order. For this functionality to be used, it is needed to enable the necessary systemd user units for your user:
The syntax of the configuration files is the same than those used system-wide. See the systemd-tmpfiles(8) and tmpfiles.d(5) man pages for details.
Xorg and systemd
This article or section needs expansion.
There are several ways to run xorg within systemd units. Below there are two options, either by starting a new user session with an xorg process, or by launching xorg from a systemd user service.
Automatic login into Xorg without display manager
The factual accuracy of this article or section is disputed.
This option will launch a system unit that will start a user session with an xorg server and then run the usual
/.xinitrc to launch the window manager, etc. You need to have xlogin-git AUR installed. Set up your xinitrc as specified in the Xinit#xinitrc section.
The session will use its own dbus daemon, but various systemd utilities will automatically connect to the dbus.service instance. Finally, enable the xlogin@username service for automatic login at boot. The user session lives entirely inside a systemd scope and everything in the user session should work just fine.
Xorg as a systemd user service
Alternatively, xorg can be run from within a systemd user service. This is nice since other X-related units can be made to depend on xorg, etc, but on the other hand, it has some drawbacks explained below.
xorg-server provides integration with systemd in two ways:
- Can be run unprivileged, delegating device management to logind (see Hans de Goede commits around this commit).
- Can be made into a socket activated service (see this commit). This removes the need for systemd-xorg-launch-helper-gitAUR .
Unfortunately, to be able to run xorg in unprivileged mode, it needs to run inside a session. So, right now the handicap of running xorg as user service is that it must be run with root privileges (like before 1.16), and cannot take advantage of the unprivileged mode introduced in 1.16.
This is how to launch xorg from a user service:
1. Make xorg run with root privileges for any user, by editing /etc/X11/Xwrapper.config
2. Add the following units to
where $
3. Make sure to configure the DISPLAY environment variable as explained above.
4. Then, to enable socket activation for xorg on display 0 and tty 2 one would do:
Now running any X application will launch xorg on virtual terminal 2 automatically.
The environment variable XDG_VTNR can be set in the systemd environment from .bash_profile , and then one could start any X application, including a window manager, as a systemd unit that depends on xorg@0.socket .
X clients as a user service
This section is being considered for removal.
With an adapted version of sx , one can easily have all the X clients running as a user service while leaving Xorg, the server, running in a session unprivileged.
First, put a copy of /usr/bin/sx under /usr/local/bin/ . The copy can be named e.g. sdsx so that the original sx can remain accessible.
The caveat of this approach is that, if for some reason not a single X client succeeded in reaching the server, the server will need to be killed from another tty manually. Also, if e.g. xrdb needs to be run in sxrc , it will now need to be run with the option -retain . See Xserver(1) and xrdb(1) for details.
One of the use cases and/or advantages of this approach is that the X clients will now be running under the user manager ( user@$uid.service ) and snippet (i.e. systemctl edit ) applied to it (e.g. NetworkNamespacePath= ) will also be applied to the programs running in the graphical environment (including but not limited to the command-line shells running in an terminal emulator).
Some use cases
Persistent terminal multiplexer
This article or section is out of date.
You may wish your user session to default to running a terminal multiplexer, such as GNU Screen or Tmux, in the background rather than logging you into a window manager session. Separating login from X login is most likely only useful for those who boot to a TTY instead of to a display manager (in which case you can simply bundle everything you start in with myStuff.target).
To create this type of user session, procede as above, but instead of creating wm.target, create multiplexer.target:
cruft.target , like mystuff.target above, should start anything you think should run before tmux or screen starts (or which you want started at boot regardless of timing), such as a GnuPG daemon session.
You then need to create a service for your multiplexer session. Here is a sample service, using tmux as an example and sourcing a gpg-agent session which wrote its information to /tmp/gpg-agent-info . This sample session, when you start X, will also be able to run X programs, since DISPLAY is set.
Once this is done, systemctl —user enable tmux.service , multiplexer.target and any services you created to be run by cruft.target and you should be set to go! Activated user-session@.service as described above, but be sure to remove the Conflicts=getty@tty1.service from user-session@.service , since your user session will not be taking over a TTY. Congratulations! You have a running terminal multiplexer and some other useful programs ready to start at boot!
Window manager
To run a window manager as a systemd service, you first need to run #Xorg as a systemd user service. In the following we will use awesome as an example:
/.config/systemd/user/wm.target.wants/window_manager.service , allowing it to be started at login. Is recommended to enable this service, not to link it manually.
Kill user processes on logout
Arch Linux builds the systemd package with —without-kill-user-processes , setting KillUserProcesses to no by default. This setting causes user processes not to be killed when the user logs out. To change this behavior in order to have all user processes killed on the user’s logout, set KillUserProcesses=yes in /etc/systemd/logind.conf .
Note that changing this setting breaks terminal multiplexers such as tmux and GNU Screen. If you change this setting, you can still use a terminal multiplexer by using systemd-run as follows:
For example, to run screen you would do:
Using systemd-run will keep the process running after logout only while the user is logged in at least once somewhere else in the system and user@.service is still running.
After the user logs out of all sessions, user@.service will be terminated too, by default, unless the user has «lingering» enabled [8]. To effectively allow users to run long-term tasks even if they are completely logged out, lingering must be enabled for them. See #Automatic start-up of systemd user instances and loginctl(1) for details.
Troubleshooting
Runtime directory ‘/run/user/1000’ is not owned by UID 1000, as it should
If you see errors such as this and your login session is broken, it is possible that another system (non-user) service on your system is creating this folder. This can happen for example if you use a docker container that has a bind mount to /run/user/1000 . To fix this, you can either fix the container by removing the mount, or disable/delay the docker service.
Источник