Invalid configurations
- upstart
Refuses to start a job if it contains invalid syntax.
- systemd
Ignores invalid directives and starts the service. Note that you must test your configuration carefully since a typo will not be detected! Use systemd-analyze verify file to get warnings on typos and badly formatted options.
Override Files
- upstart
-
Upstart allows part or all of a Job Configuration («/etc/init/$job.conf«) file to be overridden. To create an override file:
-
Create file «/etc/init/$job.override» containing one or more stanzas which take priority over their counterparts from the original «$job.conf» file.
-
- systemd
- Systemd allows a similar facility via «drop-ins»: a drop-in allows a directive to be modified without changing the original unit file. To create a drop-in:
-
Create a subdirectory below either «/etc/systemd/system/» or «/lib/systemd/system/» called «${unit}.d/«.
-
Create files called <something>.conf in the «${unit}.d/» directory containing the directives that you wish to override.
Behavioral differences (aka Gotchas)
-
systemd will refuse to run a binary (via ExecStart, ExecStartPre, etc) unless the full path to the binary is specified:
BAD (systemd will not search for sleep in $PATH):
ExecStart=sleep 20
GOOD (absolute path specified):
ExecStart=/bin/sleep 20
Commands
Note that these are commands for interactive human usage. Package maintainer scripts, ifupdown hooks and similar must always use the init system agnostic abstractions like invoke-rc.d.
Operation |
Upstart Command |
Systemd equivalent |
Notes |
Start service |
start $job |
systemctl start $unit |
|
Stop service |
stop $job |
systemctl stop $unit |
|
Restart service |
restart $job |
systemctl restart $unit |
|
See status of services |
initctl list |
systemctl status |
|
Check configuration is valid |
init-checkconf /tmp/foo.conf |
systemd-analyze verify <unit_file> |
|
Show job environment |
initctl list-env |
systemctl show-environment |
|
Set job environment variable |
initctl set-env foo=bar |
systemctl set-environment foo=bar |
|
Remove job environment variable |
initctl unset-env foo |
systemctl unset-environment foo |
|
View job log |
cat /var/log/upstart/$job.log |
sudo journalctl -u $unit |
|
tail -f job log |
tail -f /var/log/upstart/$job.log |
sudo journalctl -u $unit -f |
|
Show relationship between services |
initctl2dot |
systemctl list-dependencies --all |
Shows pstree-style output. |
Спор вокруг систем инициализации в Linux
System V init (или просто «SysV») — это система инициализации, которая существует со времен операционной системы System V, которая была выпущена в 1983 году. SysV оставалась системой инициализации в течение почти трех десятилетий (за некоторыми исключениями). Многие IT-специалисты и программисты в силу своей привычки не хотели отказываться от SysV, да и к тому же она была очень простой для понимания.
Проблема с SysV заключалась в том, что в её основе лежали концепции, существовавшие много лет назад. SysV не хватало возможности нативно обрабатывать многие вещи, такие как: обнаружение съемных носителей, корректное обнаружение аппаратного обеспечения и загрузка встроенного ПО, загрузка различных модулей и пр. Кроме того, при использовании данной системы, инициализация процессов происходит последовательно, т.е. одна задача запускается только после успешного завершения предыдущей. Часто это приводило к задержке и длительному времени загрузки. Задачи, подобные монтированию файловых систем, выполняются один раз во время загрузки, после чего «забываются». Но такого подхода недостаточно для автоматизированного управления сервисами, требующими к себе постоянного внимания.
В попытке привнести больше возможностей в процесс инициализации Linux-систем, компания Canonical в 2006 году вместе с релизом Ubuntu 6.10 (Edgy Eft) выпускает систему инициализации Upstart, которая с самого начала разрабатывалась с учетом обратной совместимости. Она может запускать демоны без каких-либо изменений в их скриптах запуска.
Другой системой инициализации, восходящей своими корнями к операционной системе 4.4BSD, является rc.init. Она применяется в таких дистрибутивах, как: FreeBSD, NetBSD и Slackware. В 2007 году разработчики Gentoo выпустили улучшенный вариант данной системы инициализации, сделав её модульной и назвав OpenRC. Большинство других дистрибутивов Linux исторически продолжало использовать SysV.
В 2010 году инженеры компании Red Hat Леннарт Пёттеринг и Кей Сиверс приступили к разработке новой системы инициализации — systemd, которая разрабатывалась с учетом недостатков, имеющихся в SysV. В состав systemd, помимо прочего, также входят и различные пакеты, утилиты и библиотеки, позволяющие производить параллельный запуск процессов, сокращая тем самым время загрузки системы и количество необходимых вычислений. Весной того же года Fedora 15 стала первым дистрибутивом, в котором по умолчанию использовалась система инициализации systemd. После чего, на протяжении следующих трех лет, большинство дистрибутивов массово перешли на systemd.
Но, если все остальные дистрибутивы отдают предпочтение systemd и считают её лучшей системой инициализации, как для предприятий, так и для любителей, почему так много споров вокруг нее?
systemd, по сравнению с SysV и Upstart, содержит большое количество различных улучшений, а также предлагает и другие компоненты, имеющие более тесную интеграцию с системой, с помощью которых разработчики могут уменьшить объем выполняемой работы. Что в этом плохого? Ну, поскольку разработчики создают программное обеспечение, которое зависит от systemd и/или от любой из её многочисленных служб (journald, udevd, consoled, logind или networkd), то такое ПО становится менее совместимым с системами, в которых systemd не применяется. По мере того, как количество служб, предоставляемых проектом systemd, продолжает расти, systemd сама становится все более зависимой от них.
В результате systemd становится самостоятельной платформой, и её повсеместное распространение непреднамеренно препятствует разработке программного обеспечения, которое является переносимым и совместимым с операционными системами, не поддерживающими systemd. Но действительно ли всё так печально? Конечно, нет. Прежде всего, это проект с открытым исходным кодом, и у людей есть выбор: использовать его или нет. Пользователи и разработчики могут извлечь выгоду из наличия нескольких конкурирующих систем инициализации, и нет вины systemd в том, что основные дистрибутивы переключились на нее из-за её плюсов.
/etc/default files which enable/disable jobs
enable=1|0 type settings in /etc/default files should generally be avoided. The canonical way to enable/disable a service in an init system agnostic way is update-rc.d <service> enable|disable, which will translate to init system specific actions such as adding/removing symlinks (SysV and systemd) or creating/removing job override files (upstart). For systemd in particular, admins also often call systemctl enable|disable <service> directly. Thus these settings are redundant in /etc/default.
There is no clean way to evaluate these in a systemd unit. You can check them in ExecStartPre=, but that would mean that the unit will be in «failed» state if the service gets disabled that way, and so, is not desirable.
For these reasons (confusing/duplication/cannot be modelled in systemd), these settings should be removed. This was done in whoopsie 0.2.42, you can check its diff for a transition which respects the old default setting and removes it on upgrade.
Example Systemd service
/lib/systemd/system/foo.service:
Description=Job that runs the foo daemon Documentation=man:foo(1) Type=forking Environment=statedir=/var/cache/foo ExecStartPre=/usr/bin/mkdir -p ${statedir} ExecStart=/usr/bin/foo-daemon --arg1 "hello world" --statedir ${statedir} WantedBy=multi-user.target
Outstanding Work
If you’d like to help out with the migration, take a look at …
- Outstanding packages to convert:
-
http://people.canonical.com/~jhunt/systemd/packages-to-convert/
Note that the priority are the packages in «main».
-
-
blueprint: https://blueprints.launchpad.net/ubuntu/+spec/core-1411-systemd-migration
… and then come and chat to us on #ubuntu-devel.
Unit
Unit – это описание сервиса (в широком смысле этого слова). Unit-файл описывает все настройки сервиса, как его запускать, когда (очередность, зависимости) и что делать, если запуск не удался. Unit-ы, которые пишет пользователь руками – должны находится в и иметь окончание в названии. Юниты, которые устанавливают пакеты – находятся в ином месте. Если в нескольких папках лежит юнит с одним и тем же именем – применяется тот, что лежит в . Пример юнита:
Я специально взял юнит посложнее, чтобы пример был наглядным
На что обратить внимание:
- Description – человеко-читаемое описание. Показывается по команде
- After – начать загрузку после того, как начнется загрузка сервиса (или цели)
- Wants – опциональная зависимость. Подробнее ниже, в разделе про зависимости
- Environment – создать переменную окружения при запуске этого сервиса
- WorkingDir – демон запускается из этой папки. Аналогично перед запуском
- Type – тип сервиса. Подробнее ниже
- User – имя пользователя, от которого будет запущен сервис
- PermissionsStartOnly – используется, если перед стартом нужна какая-то специальная подготовка – создание папок, изменение прав и так далее. При эти действия будут выполнятся от root. Без – от имени User
- ExecStart – что, собственно, запускать. Обязательно полный путь
- RestartOn – при каких условиях перезапускать
- WantedBy – в какой target должен быть установлен сервис. Подробнее – в разделе про target-ы
Виды Unit-ов
Systemd может обслуживать процессы с разным поведением. Тип описывает, как systemd будет с ним взаимодействовать. Есть следующие варианты:
- – самый стандартный тип. Процесс остается в foreground, stdout перехватывается systemd. Это тип по умолчанию.
- – прямая противоположность. Процесс должен форкнуться и отсоединится от foreground. Для этого типа юнитов должен быть указан pid через директиву .
- – процесс, который успешно выполняется (не делая fork) и завершается. Пример – монтирование файловых систем. Рекомендуется добавить в юнит, чтобы результаты работы процесса остался в статусе юнита.
- – аналог simple, но в этом случае сам процесс сообщит systemd о том, что он закончил загрузку и готов к работе.
Взаимодействие с unit-ами
После каждого изменения файла юнита (создание/изменение/удаление) – нужно перечитывать изменения, так как состояния юнитов systemd кеширует:
Запус, состояние, остановка:
Systemd имеет свою собственную реализацию логирования (хотя по умолчанию в syslog копию сообщения он тоже отправляет). Чтение сообщений от сервисов – командой journalctl. Команда очень мощная, умеет много. Ниже примеры
Управление зависимостями, очередность загрузки юнитов
Для управления зависимостями в unit есть ключевые слова , и :
- – сервис начнет загрузку после того, как начнет загружаться сервис, указанный в .
- – сервис начнет загрузку после того, как закончит загружаться сервис, указанный в . Статус загрузки этого сервиса не важен – даже если он упал и загрузится не смог – юнит попытается стартовать. То есть зависимость эта опциональная, и нужна она только для того, чтобы наш сервис начал загружаться не раньше, чем другой – закончит.
- – сервис начнет загрузку после того, как сервис, указанный в закончит загрузку успешно. Если сервис-зависимость загрузится не смог – наш сервис так же упадет с ошибкой (точнее – он даже не будет стартовать).
Написание файлов юнитов
- /usr/lib/systemd/system/: юниты, предоставляемые пакетами при их установке
- /etc/systemd/system/: юниты, устанавливаемые системным администратором
Обработка зависимостей
В случае использования systemd зависимости могут быть указаны правильным построением файлов юнитов. Наиболее частый случай — юниту A требуется, чтобы юнит B был запущен перед тем, как запустится сам юнит A. В этом случае добавьте строки Requires=B и After=B в секцию файла службы A. Если подобная зависимость не является обязательной, взамен указанных выше добавьте, соответственно, строки Wants=B и After=B
Обратите внимание, что Wants= и Requires= не подразумевают After=, что означает, что если After= не определено, два юнита будут запущены параллельно друг другу.
Обычно зависимости указываются в файлах служб, а не в целевых юнитах. Например, network.target потребуется любой службе, которая связана с настройкой ваших сетевых интерфейсов, поэтому в любом случае определите загрузку вашего пользовательского юнита после запуска network.target.
Типы служб
Существует несколько различных типов запуска служб, которые надо иметь в виду при написании пользовательского файла службы. Тип определяется параметром Type= в секции :
- Type=simple (по умолчанию): systemd предполагает, что служба будет запущена незамедлительно. Процесс при этом не должен разветвляться. Не используйте этот тип, если другие службы зависят от очередности при запуске данной службы. Исключение — активация сокета
- Type=forking: systemd предполагает, что служба запускается однократно и процесс разветвляется с завершением родительского процесса. Используйте данный тип для запуска классических демонов за исключением тех случаев, когда, как вам известно, в таком поведении процесса нет необходимости. Вам следует также определить PIDFile=, чтобы systemd могла отслеживать основной процесс
- Type=oneshot: полезен для скриптов, которые выполняют одно задание и завершаются. Вам может понадобиться также установить параметр RemainAfterExit=yes, чтобы systemd по-прежнему считала процесс активным, даже после его завершения
- Type=notify: идентичен параметру Type=simple, но с той оговоркой, что демон пошлет systemd сигнал о своей готовности. Эталонная реализация данного уведомления представлена в libsystemd-daemon.so
- Type=dbus: сервис считается находящимся в состоянии готовности, когда определенное BusName появляется в системной шине DBus
- Type=idle: systemd задержит выполнение двоичного файла службы до тех пор, пока все задания отправляются. Кроме того, поведение очень похоже на Type=simple.
Редактирование предоставленных пакетами файлов юнитов
Есть два способа редактирования файлов юнита, предоставленного пакетом: заменить весь блок файла на новый или создать фрагмент кода, который применяется в верхней части существующего блока файла. В обоих методах, чтобы применить изменения, нужно перезагрузить юнит. Это может быть сделано либо путем редактирования блока с помощью Шаблон:Ic (которая автоматически загружает модуль) либо при перезагрузке всех юнитов:
# systemctl daemon-reload
Замена файлов юнита
Чтобы заменить файл юнита /usr/lib/systemd/system/юнит, создайте файл /etc/systemd/system/юнит и перезапустите юнит для обновления символьных ссылок:
# systemctl reenable юнит
В качестве альтернативы, можно выполнить:
# systemctl edit --full юнит
Эта команда откроет /etc/systemd/system/юнит в вашем текстовом редакторе (копирует установленную версию, если она еще не существует) и автоматически загружает её, когда вы закончите редактирование.
Drop-in snippets
Чтобы создать drop-in snippets для файла юнита /usr/lib/systemd/system/юнит, создайте каталог /etc/systemd/system/юнит.d/ и поместите файлы .conf там, чтобы отменять или добавлять новые опции. systemd будет анализировать эти файлы .conf и применять их поверх оригинального юнита.
Самый простой способ чтобы выполнить это, сделайте:
# systemctl edit юнит
Эта команда откроет /etc/systemd/system/юнит.d/override.conf (создаст его если это потребуется) в вашем текстовом редакторе и автоматически перезапустит юнит, когда вы закончите редактирование.
Обнаружение системы 5 init
Как это ни парадоксально, как описано в https://unix.stackexchange.com/a/196197/5132 , один из способов в Debian Linux по крайней мере для обнаружения отсутствия System 5 — это отсутствие . Однако:
- Это побочный эффектСпособ Debian для упаковки таких вещей, как .
- Одна часть общей проблемы заключается в том, что используется, если в качестве параметра использовалась System 5 в любой момент прошлого , поскольку удаление пакета не удаляет его конфигурационный файл. (Это была значительная проблема для работы Debian 8, так как в Debian 7 есть несколько пакетов, которые устанавливают себя, добавляя записи в .)
- Это инвертированный тест.
Полезные команды
Следующая команда загружает конфигурационный файл демона, а не файл его сервиса systemd. Используйте ее, когда вы делаете изменения конфигурации и хотите активировать ее, например, так, как в следующем примере для Apache:
# systemctl reload httpd.service
Перезагрузите файл сервиса — полностью остановите сервис, а затем перезапустите сервис. Если он не заработает, то начните со следующего:
# systemctl restart httpd.service
Вы можете перезапустить все сервисы с помощью одной команды. Она перезагружает все юнит файлы и пересоздает все дерево зависимостей systemd:
# systemctl daemon-reload
Вы можете в роли обычного непривилегированного пользователя выполнять операции reboot (перезагрузка), suspend (приостановка) и poweroff (отключение):
$ systemctl reboot $ systemctl suspend $ systemctl poweroff
Как всегда, есть много другого, что можно узнать о systemd. Хорошими введениями в systemd,
причем со ссылками на более подробные ресурсы являются статьи
Проходим еще раз, еще один Linux
Init: Введение в systemd и Изучаем и
используем Systemd.
Targets
Target – целевое состояние системы. Именно Target определяет, какие сервисы будут загружены и в каком порядке. Аналог из мира sysV init – runlevel. Основные виды таргетов:
- – отключение системы
- – режим восстановления, однопользовательский (init 1)
- – сетевой режим без графической оболочки, (init 3)
- – сетевой режим с графической оболочкой (init 5)
- – перезагрузка
- – аварийная командная строка, минимальный функционал
Цели могут наследоваться друг от друга. Например, graphical включает в себя загрузку всего, что есть multiuser + после этого – подгрузку графической оболочки.
Взаимодействие с целями:
10.3.6. Переход в аварийный режим
Аварийный режим предоставляет минимально возможную среду и позволяет восстановить систему даже тогда, когда она не может загрузиться в режим восстановления. Система монтирует root file system только для чтения и запускает только несколько основных сервисов, не пытается подключить другие файловые системы и не активирует сеть. В RHEL 7 аварийный режим требует ввода пароля root’а.
Чтобы сменить текущий таргет на аварийный режим, введите от root’а:
systemctl emergency |
Эта команда похожа на , но она дополнительно отправляет сообщение всем пользователям, которые в настоящее время вошли в систему. Чтобы система не отправляла сообщение, запустите команду с опцией :
systemctl --no-wall emergency |
Пример 10.15. Переход в аварийный режим
Чтобы перейти в аварийный режим с отправкой сообщения всем пользователям, запустите от root’а:
~# systemctl --no-wall emergency |
Permanent switch back to upstart
Install the upstart-sysv package, which will remove ubuntu-standard and systemd-sysv (but should not remove anything else — if it does, yell!), and run sudo update-initramfs -u. After that, grub’s «Advanced options» menu will have a corresponding «Ubuntu, with Linux … (systemd)» entry where you can do an one-time boot with systemd.
If you want to switch back to systemd, install the systemd-sysv and ubuntu-standard packages.
High-level startup concept
Upstart’s model for starting processes (jobs) is «greedy event-based», i. e. all available jobs whose startup events happen are started as early as possible. During boot, upstart synthesizes some initial events like startup or rcS as the «tree root», the early services start on those, and later services start when the former are running. A new job merely needs to install its configuration file into /etc/init/ to become active.
systemd’s model for starting processes (units) is «lazy dependency-based», i. e. a unit will only start if and when some other starting unit depends on it. During boot, systemd starts a «root unit» (default.target, can be overridden in grub), which then transitively expands and starts its dependencies. A new unit needs to add itself as a dependency of a unit of the boot sequence (commonly multi-user.target) in order to become active.
Job vs. unit keywords
This maps the keywords that can occur in an upstart job to the corresponding ones in a systemd unit. Keywords which don’t have a direct equivalent are marked with «-«.
Upstart stanza |
systemd unit file directive |
systemd unit file section |
Notes |
apparmor load |
AppArmorProfile |
Available in systemd version 210 and later |
|
apparmor switch |
— |
||
author |
— |
||
chdir |
WorkingDirectory |
Service |
|
chroot |
RootDirectory |
||
console output |
StandardOutput=tty, StandardError=tty |
||
console owner |
StandardOutput=tty, StandardError=tty |
No real equivalent? |
|
console none |
StandardOutput=null, StandardError=null |
||
description |
Description |
Unit |
|
env |
Environment, EnvironmentFile |
Service |
|
exec |
ExecStart |
Service |
|
expect fork |
Type=forking |
Unit |
|
expect daemon |
Type=forking |
Unit |
|
expect stop |
Type=notify |
Unit |
Similar, not equivalent. Requires daemon to link to libsystemd-daemon and call sd_notify(). |
instance |
Use «%I» and «%i» in ExecStart, etc to specify an instance |
See /lib/systemd/system/getty@.service for an example |
|
kill signal |
KillSignal |
||
kill timeout |
TimeoutStopSec |
||
limit as |
LimitAS |
||
limit core |
LimitCORE |
||
limit cpu |
LimitCPU |
||
limit data |
LimitDATA |
||
limit fsize |
LimitFSIZE |
||
limit memlock |
LimitMEMLOCK |
||
limit msgqueue |
LimitMSGQUEUE |
||
limit nice |
LimitNICE |
||
limit nofile |
LimitNOFILE |
||
limit nproc |
LimitNPROC |
||
limit rss |
LimitRSS |
||
limit rtprio |
LimitRTPRIO |
||
limit sigpending |
LimitSIGPENDING |
||
limit stack |
LimitSTACK |
||
manual |
No directive(?) — use systemctl disable foo.service |
||
nice |
Nice |
Unit |
|
normal exit |
SuccessExitStatus |
||
oom score |
OOMScoreAdjust |
||
post-start exec/script |
ExecStartPost |
Service |
|
post-stop exec/script |
ExecStopPost |
Service |
|
pre-start exec/script |
ExecStartPre |
Service |
|
pre-stop |
— |
||
reload signal |
ExecReload=/bin/kill -SIGFOO $MAINPID |
Service |
|
respawn |
Restart=on-failure |
Service |
|
respawn limit |
RestartSec |
||
script/end script |
See shell scripts below |
||
setgid |
Group |
Service |
|
setuid |
User |
Service |
|
start on |
Wants, Requires, Before, After |
Unit |
|
stop on |
Conflicts, BindsTo (but not commonly used) |
Unit |
|
task |
Type=oneshot |
Unit |
|
umask |
UMask |
Unit |
|
usage |
Documentation |
Unit |
no direct equivalent |
version |
— |
Shell scripts
systemd does not provide special support for shell scripts (by design). For short shell commands you can use something like
ExecStart=/bin/sh -ec 'echo hello'
Longer scripts are usually program logic and should not be directly in a conffile and duplicated between upstart and systemd; factor it out in a proper script in e. g. /usr/share/myapp/ and call it from both the upstart job and the systemd unit.
Automatic starting
As described above, services which want to start during boot (i. e. are not activated through sockets, D-BUS, or similar) need to become a dependency of an existing boot target. Those need an section with a WantedBy= that specifies the unit which that new service wants to become a dependency of (see man systemd.unit). Very commonly this is multi-user.target, which is roughly equivalent to start on runlevel in upstart; see man systemd.special for other common targets.
Xorg и systemd
Есть несколько способов запустить xorg в системных модулях. Ниже представлены два варианта: либо запустить новый пользовательский сеанс с процессом xorg, либо запустить xorg из пользовательской службы systemd.
Автоматический логин в Xorg без экранного менеджера
The factual accuracy of this article or section is disputed.
Эта опция запускает системный блок, который запускает сеанс пользователя с сервером xorg, а затем запускает обычный для запуска оконного менеджера и т.д.
Вам необходим установленный AUR. Настройте свой xinitrc, как указано в разделе .
Сеанс будет использовать собственный dbus демон, но различные утилиты systemd будут автоматически подключаться к экземпляру . Наконец, enable службу для автоматического входа при загрузке.Сеанс пользователя полностью находится в области видимости systemd, и все в сеансе пользователя должно работать нормально.
Xorg как пользовательская служба systemd
Кроме того, Xorg можно запустить из службы пользователя systemd. Это хорошо, поскольку другие связанные с X юниты могут зависеть от xorg и т. д. Но с другой стороны, у этого есть некоторые недостатки, объясненные ниже.
обеспечивает интеграцию с systemd двумя способами:
К сожалению, чтобы иметь возможность запускать xorg в непривилегированном режиме, он должен запускаться внутри сеанса. Итак, в данный момент недостаток запуска xorg в качестве пользовательской службы заключается в том, что он должен запускаться с привилегиями суперпользователя (как до 1.16) и не может использовать преимущества непривилегированного режима, представленного в 1.16.
Вот как запустить xorg из пользовательского сервиса:
1. Заставить xorg работать с правами суперпользователя и для любого пользователя путем редактирования
/etc/X11/Xwrapper.config
allowed_users=anybody needs_root_rights=yes
2. Добавить следующие юниты в
~/.config/systemd/user/xorg@.socket
Description=Socket for xorg at display %i ListenStream=/tmp/.X11-unix/X%i
~/.config/systemd/user/xorg@.service
Description=Xorg server at display %i Requires=xorg@%i.socket After=xorg@%i.socket Type=simple SuccessExitStatus=0 1 ExecStart=/usr/bin/Xorg :%i -nolisten tcp -noreset -verbose 2 "vt${XDG_VTNR}"
где } — виртуальный терминал, на котором будет запущен xorg, либо прописанный в сервисном модуле, либо установленный в среде systemd с помощью
$ systemctl --user set-environment XDG_VTNR=1
Примечание: xorg должен быть запущен на том же виртуальном терминале, где пользователь вошел в систему. В противном случае logind будет считать сеанс неактивным.
3. Обязательно настройте переменную среды , как описано .
4. Затем, чтобы активировать сокет для xorg на дисплее 0 и tty 2, следует выполнить:
$ systemctl --user set-environment XDG_VTNR=2 # Так что xorg@.service знает, какой vt использовать $ systemctl --user start xorg@0.socket # начинает слушать на сокете для дисплея 0
Теперь запуск любого X приложения автоматически запустит xorg на виртуальном терминале 2.
Переменная среды может быть установлена в среде systemd из , а затем можно запустить любое приложение X, включая диспетчер окон, как системный модуль, зависящий от .