systemd (Русский)/User (Русский)

From ArchWiki

Состояние перевода: На этой странице представлен перевод статьи systemd/User. Дата последней синхронизации: 12 июля 2021. Вы можете помочь синхронизировать перевод, если в английской версии произошли изменения.

systemd позволяет пользователю управлять службами в личном, отдельном экземпляре systemd. Благодаря этому пользователь может запускать, останавливать, включать и отключать свои собственные юниты. Это очень удобно в случае демонов и служб, которые обычно запускаются для отдельного пользователя (mpd), или выполнения автоматизированных задач (например, скачивание почты).

Как это работает

В соответствии с конфигурацией по умолчанию в /etc/pam.d/system-login, модуль pam_systemd автоматически запускает systemd --user в случае, когда пользователь в первый раз входит в систему . Этот процесс будет работать до тех пор, пока существует сессия этого пользователя, и будет убит, как только последний сеанс для пользователя будет закрыт. Когда включен #Автоматический запуск systemd от имени пользователя, то процесс запускается при загрузке и убит не будет. Пользовательский процесс systemd отвечает за управление службами пользователей, которые могут быть использованы для запуска демонов или автоматизированных задач, со всеми преимуществами systemd, таких как активация сокета, таймеры, системы зависимостей или строгий контроль процесса через контрольные группы.

Аналогично системным службам, пользовательские службы расположены в следующих каталогах (отсортированы по возрастанию приоритета):

  • /usr/lib/systemd/user/ где находятся службы, относящиеся к установленным пакетам.
  • ~/.local/share/systemd/user/ где находятся службы, относящиеся к пакетам, установленным в домашний каталог.
  • /etc/systemd/user/ где находятся общесистемные пользовательские службы, созданные системным администратором.
  • ~/.config/systemd/user/ где пользователь размещает свои собственные службы.

При запуске пользовательского процесса systemd он привязывается к пользовательской же (то есть отдельной для каждого пользователя) цели default.target. Другие службы могут управляться вручную с помощью команды systemctl --user. См. systemd.special(7) § UNITS MANAGED BY THE USER SERVICE MANAGER.

Примечание:
  • Имейте в виду, что systemd --user представляет собой процесс для каждого пользователя, а не для сессии. Смысл заключается в том, что большая часть ресурсов, обрабатываемых пользовательскими службами, такие как сокеты или файлы состояния будут создаваться отдельно для каждого пользователя (в его домашнем каталоге), и не за один сеанс. Это означает, что все пользовательские службы работают вне сеанса. Как следствие, программы, которые должны быть запущены внутри сессии, вероятно, прервут выполнение пользовательских служб. С помощью systemd в пользовательском сеансе обрабатывается довольно много данных. См [1] и [2] для получения подсказок о том, как идут дела.
  • systemd --user выполняется как процесс, отдельный от родительского процесса systemd --system. Службы пользователей не могут ссылаться или зависеть от системных юнитов или юнитов других пользователей.

Основные настройки

Все пользовательские службы размещаются в ~/.config/systemd/user/. Если вы хотите запускать службы при первом входе в систему, выполните systemctl --user enable service для любой службы, которую вы хотите сделать автозагрузочной.

Совет: Если вы хотите включить службу для всех пользователей, а не для пользователя, выполняющего команду systemctl , запустите systemctl --user --global enable service от имени суперпользователя.

Переменные окружения

Пользовательский процесс systemd не наследует какую-либо из переменных окружения, установленных в .bashrc или других. Существует несколько способов установить переменные окружения для systemd:

  1. Для переменной $HOME пользовательского каталога, создайте файл .conf в каталоге ~/.config/environment.d/ со строками вида {{ic | 1 = NAME = VAL}. Применяется только к части пользовательских служб.

Смотрите environment.d(5) для получения дополнительной информации.

  1. Используйте опцию DefaultEnvironment в /etc/systemd/user.conf. Применяется ко всем пользовательским службам.
  2. Добавление конфигурационного файла в /etc/systemd/system/[email protected]/. Применяется ко всем пользовательским процессам; см #Пример службы
  3. Для временного изменения используйте systemctl --user set-environment или systemctl --user import-environment. Применяется ко всем пользовательским службам, созданным после установки переменных окружения, но не к службам, которые уже были запущены.
  4. Используйте dbus-update-activation-environment --systemd --all — команду, которую предоставляет D-Bus. Имеет тот же эффект, что и systemctl --user import-environment, но также влияет на сессию D-Bus. Вы можете добавить это в конец вашего файла инициализации оболочки.
  5. Для "глобальных" переменных пользовательского окружения вы можете использовать каталоги environment.d, которые анализируются генераторами systemd. Подробнее см. environment.d(5) и systemd.generator(7).
  6. Вы также можете написать скрипт генератора среды, который может создавать переменные среды, которые варьируются от пользователя к пользователю. Это, вероятно, лучший способ, если вам нужны индивидуальные среды (это относится к XDG_RUNTIME_DIR, DBUS_SESSION_BUS_ADDRESS и т.д.). Смотрите systemd.environment-generator(7).

Одну переменную Вы можете установить в PATH.

После настройки можно использовать команду systemctl --user show-environment для проверки правильности значений.

Пример службы

Создайте drop-in каталог /etc/systemd/system/[email protected]/ и внутри создайте файл с расширением .conf (например, local.conf):

/etc/systemd/system/[email protected]/local.conf
[Service]
Environment="PATH=/usr/lib/ccache/bin:/usr/local/bin:/usr/bin:/bin"
Environment="EDITOR=nano -c"
Environment="BROWSER=firefox"
Environment="NO_AT_BRIDGE=1"

DISPLAY и XAUTHORITY

Переменная DISPLAY используется любым графическим приложением, чтобы знать, какой дисплей использовать, XAUTHORITY, чтобы указать путь к пользовательскому файлу .Xauthority, а также куки, необходимые для запуска Х-сервера. Если Вы планируете запускать графические приложения из процесса systemd, то эти переменные обязательно должны быть установлены. Systemd предоставляет скрипт в /etc/X11/xinit/xinitrc.d/50-systemd-user.sh для импорта этих переменных в пользовательскую сессию systemd на запуск X. [3] Так что если Вы не запускаете Х нестандартным образом, пользовательские службы должны знать переменные DISPLAY и XAUTHORITY.

PATH

Если изменить PATH и запланированный запуск приложений, которые используют службу systemd, Вы должны убедиться, что модифицированный PATH установлен и в среде systemd. Если предположить, что Вы установили переменную PATH в .bash_profile, то лучшим способом сделать systemd осведомленным о модификации PATH будет добавление в .bash_profile после PATH заданной переменной:

~/.bash_profile
systemctl --user import-environment PATH

Обратите внимание, что это не повлияет на службы systemd, запущенные до импортирования PATH.

pam_env

Переменные среды можно сделать доступными с помощью модуля pam_env.so. Смотрите Environment variables#Using pam_env для деталей конфигурации.

Автоматический запуск systemd от имени пользователя

Пользовательский процесс systemd запускается сразу после первого входа пользователя в систему, и будет убит после завершения последнего сеанса пользователя. Иногда может быть полезно запустить службу сразу после загрузки, и поддерживать процесс systemd запущенным даже после завершения последнего сеанса пользователя, например, чтобы некоторый пользовательский процесс работал без какой-либо открытой сессии. Для этой цели используются долговременные службы. Используйте следующую команду, чтобы включить долговременную службу для конкретного пользователя:

# loginctl enable-linger username
Важно: Служба systemd находится вне сессии, она запускается за пределами logind. Не используйте долговременные службы для включения автоматического входа в систему, иначе будет перерыв в работе сессии.

Написание пользовательских юнитов

Смотрите systemd#Writing unit files для получения общей информации о написании юнитов модулей systemd.

Пример

Ниже приведен пример варианта пользовательской службы mpd.

~/.config/systemd/user/mpd.service
[Unit]
Description=Music Player Daemon

[Service]
ExecStart=/usr/bin/mpd --no-daemon

[Install]
WantedBy=default.target

Пример с переменными

Ниже приведен пример пользовательской версии sickbeard.service, которая учитывает все переменные окружения пользовательских каталогов, где SickBeard может найти некоторые файлы:

~/.config/systemd/user/sickbeard.service
[Unit]
Description=SickBeard Daemon

[Service]
ExecStart=/usr/bin/env python2 /opt/sickbeard/SickBeard.py --config %h/.sickbeard/config.ini --datadir %h/.sickbeard

[Install]
WantedBy=default.target

Как указано в systemd.unit(5), переменная %h заменяется домашней директорией пользователя, запускающего службу. Есть и другие переменные, которые учитываются на странице руководства systemd.

Чтение журнала

Журнал для пользователя может быть прочитан с помощью аналогичной команды:

$ journalctl --user

Чтобы указать юнит, можно использовать

$ journalctl --user -u myunit.service

Эквивалентная команда

$ journalctl --user --user-unit myunit.service

Обратите внимание, что journald не будет писать пользовательские журналы для пользователей с UID ниже 1000, вместо этого перенаправляя всё в системный журнал.

Временные файлы

systemd-tmpfiles позволяет пользователям управлять нестабильными и временными файлами и каталогами так же, как общесистемным способом (см. systemd#systemd-tmpfiles — временные файлы). Пользовательские файлы конфигурации считываются из ~/.config/user-tmpfiles.d/ и ~/.local/share/user-tmpfiles.d/ в указанном порядке. Для использования этой функциональности требуется включить необходимые пользовательские юниты systemd для вашего пользователя:

$ systemctl --user enable systemd-tmpfiles-setup.service systemd-tmpfiles-clean.timer

Синтаксис конфигурационных файлов такой же, как и для всей системы. Для получения дополнительной информации смотрите справочные страницы systemd-tmpfiles(8) и tmpfiles.d(5).

Xorg и systemd

Есть несколько способов запустить xorg в системных модулях. Ниже представлены два варианта: либо запустить новый пользовательский сеанс с процессом xorg, либо запустить xorg из пользовательской службы systemd.

Автоматический логин в Xorg без экранного менеджера

Tango-inaccurate.pngThe factual accuracy of this article or section is disputed.Tango-inaccurate.png

Reason: Спорная информация в оригинале: This setup ends up with two user D-Bus buses, one for the desktop, and an other for systemd. Why can't we use the systemd one alone? (Discuss in Talk:Systemd (Русский)/User (Русский))

Эта опция запускает системный блок, который запускает сеанс пользователя с сервером xorg, а затем запускает обычный ~/.xinitrc для запуска оконного менеджера и т.д.

Вам необходим установленный xlogin-gitAUR. Настройте свой xinitrc, как указано в разделе Xinit#xinitrc.

Сеанс будет использовать собственный dbus демон, но различные утилиты systemd будут автоматически подключаться к экземпляру dbus.service. Наконец, enable службу xlogin@username для автоматического входа при загрузке.Сеанс пользователя полностью находится в области видимости systemd, и все в сеансе пользователя должно работать нормально.

Xorg как пользовательская служба systemd

Кроме того, Xorg можно запустить из службы пользователя systemd. Это хорошо, поскольку другие связанные с X юниты могут зависеть от xorg и т. д. Но с другой стороны, у этого есть некоторые недостатки, объясненные ниже.

xorg-server обеспечивает интеграцию с systemd двумя способами:

  • Может быть запущен непривилегированным, делегируя управление устройствами logind (смотрите коммиты Hans de Goede коммит).
  • Может быть превращен в сервис, активируемый сокетом (смотрите этот коммит). Это устраняет необходимость в systemd-xorg-launch-helper-gitAUR.

К сожалению, чтобы иметь возможность запускать xorg в непривилегированном режиме, он должен запускаться внутри сеанса. Итак, в данный момент недостаток запуска xorg в качестве пользовательской службы заключается в том, что он должен запускаться с привилегиями суперпользователя (как до 1.16) и не может использовать преимущества непривилегированного режима, представленного в 1.16.

Примечание: Это не является фундаментальным ограничением, налагаемым logind, но причина, по-видимому, заключается в том, что xorg нужно знать, какой сеанс взять на себя, и сейчас он получает эту информацию, вызывая logind's GetSessionByPID используя свой собственный pid в качестве аргумента. Смотрите this thread и xorg sources. Кажется вероятным, что xorg можно изменить, чтобы получить сеанс от tty, к которому он подключен, и затем он мог бы работать непривилегированным из пользовательской службы вне сеанса.
Важно: В xorg 1.18 активация сокета, кажется, сломана. Клиент, вызывающий активацию, зависает. Смотрите вышестоящий отчет об ошибках [4]. В качестве временного обходного пути вы можете запустить сервер xorg без активации сокета, убедившись, что клиенты подключаются после задержки, поэтому сервер полностью запускается. Кажется, нет никакого удобного механизма, чтобы получить уведомление о запуске для X сервера.

Вот как запустить xorg из пользовательского сервиса:

1. Заставить xorg работать с правами суперпользователя и для любого пользователя путем редактирования /etc/X11/Xwrapper.config

/etc/X11/Xwrapper.config
allowed_users=anybody
needs_root_rights=yes

2. Добавить следующие юниты в ~/.config/systemd/user

~/.config/systemd/user/[email protected]
[Unit]
Description=Socket for xorg at display %i

[Socket]
ListenStream=/tmp/.X11-unix/X%i
~/.config/systemd/user/[email protected]
[Unit]
Description=Xorg server at display %i

Requires=xorg@%i.socket
After=xorg@%i.socket

[Service]
Type=simple
SuccessExitStatus=0 1

ExecStart=/usr/bin/Xorg :%i -nolisten tcp -noreset -verbose 2 "vt${XDG_VTNR}"

где ${XDG_VTNR} - виртуальный терминал, на котором будет запущен xorg, либо прописанный в сервисном модуле, либо установленный в среде systemd с помощью

$ systemctl --user set-environment XDG_VTNR=1
Примечание: xorg должен быть запущен на том же виртуальном терминале, где пользователь вошел в систему. В противном случае logind будет считать сеанс неактивным.

3. Обязательно настройте переменную среды DISPLAY, как описано выше.

4. Затем, чтобы активировать сокет для xorg на дисплее 0 и tty 2, следует выполнить:

$ systemctl --user set-environment XDG_VTNR=2     # Так что [email protected] знает, какой vt использовать
$ systemctl --user start [email protected]            # начинает слушать на сокете для дисплея 0

Теперь запуск любого X приложения автоматически запустит xorg на виртуальном терминале 2.

Переменная среды XDG_VTNR может быть установлена в среде systemd из .bash_profile, а затем можно запустить любое приложение X, включая диспетчер окон, как системный модуль, зависящий от [email protected].

Важно: В настоящее время запуск оконного менеджера в качестве пользовательской службы означает, что он работает работает за пределами сеанса, с проблемами, которые могут возникнуть: break the session. Однако, похоже, что разработчики systemd намерены сделать что-то подобное возможным. Смотрите [5] и [6]

Некоторые случаи использования

Постоянный терминальный мультиплексор

Tango-view-refresh-red.pngThis article or section is out of date.Tango-view-refresh-red.png

Reason: Устаревшая информация в оригинале: Ссылается на [email protected] вместо [email protected]; последний не содержит [email protected]. (Discuss in Talk:Systemd (Русский)/User (Русский))

Возможно, вы захотите, чтобы в сеансе пользователя по умолчанию использовался терминальный мультиплексор, например GNU Screen или Tmux, в фоновом режиме, а не для входа в сеанс оконного менеджера. Разделение входа в систему от входа в систему X, скорее всего, полезно только для тех, кто загружается с TTY, а не с экранным менеджером (в этом случае вы можете просто связать все, что вы запускаете, с myStuff.target).

Чтобы создать пользовательский сеанс такого типа, действуйте, как указано выше, но вместо создания wm.target создайте multiplexer.target:

[Unit]
Description=Terminal multiplexer
Documentation=info:screen man:screen(1) man:tmux(1)
After=cruft.target
Wants=cruft.target

[Install]
Alias=default.target

cruft.target, как mystuff.target выше, должен запускать все, что, по вашему мнению, должно запускаться до запуска tmux или экрана (или что вы хотите запустить при загрузке независимо от времени), например сеанс демона GnuPG.

Затем вам нужно создать сервис для сеанса мультиплексора. Вот пример службы, использующей tmux в качестве примера и использующей сеанс gpg-agent, который записал свою информацию в /tmp/gpg-agent-info. Этот пример сеанса при запуске X также сможет запускать программы X, так как установлен DISPLAY.

[Unit]
Description=tmux: A terminal multiplixer 
Documentation=man:tmux(1)
After=gpg-agent.service
Wants=gpg-agent.service

[Service]
Type=forking
ExecStart=/usr/bin/tmux start
ExecStop=/usr/bin/tmux kill-server
Environment=DISPLAY=:0
EnvironmentFile=/tmp/gpg-agent-info

[Install]
WantedBy=multiplexer.target

Как только это будет сделано, systemctl --user enable tmux.service, multiplexer.target и любые сервисы, которые вы создали для запуска cruft.target, и вы должны быть готовы к работе! Активирован [email protected], как описано выше, но обязательно удалите [email protected] из {{ic|[email protected]} }, поскольку ваш пользовательский сеанс не будет принимать TTY. Поздравляем! У вас есть работающий терминальный мультиплексор и некоторые другие полезные программы, готовые к запуску при загрузке!

Оконный менеджер

Чтобы запустить оконный менеджер в качестве службы systemd, сначала необходимо запустить Xorg как пользовательскую службу systemd. В следующем примере мы будем использовать awesome (Русский):

~/.config/systemd/user/awesome.service
[Unit]
Description=Awesome window manager
After=xorg.target
Requires=xorg.target

[Service]
ExecStart=/usr/bin/awesome
Restart=always
RestartSec=10
 
[Install]
WantedBy=wm.target
Примечание: Раздел [Install] содержит часть WantedBy. При использовании systemctl --user enable он будет связывать это как ~/.config/systemd/user/wm.target.wants /window_manager.service, позволяя ему стартовать при входе в систему. Рекомендуется включить этот сервис, а не связывать его вручную.

Завершение процессов пользователя при выходе из системы

Arch Linux создает пакет systemd с помощью --without-kill-user-process, устанавливая KillUserProcesses равным no по умолчанию. Этот параметр предотвращает уничтожение пользовательских процессов, когда пользователь полностью выходит из системы. Чтобы изменить это поведение и убить все пользовательские процессы при выходе из системы, установите KillUserProcesses=yes в /etc/systemd/logind.conf.

Обратите внимание, что изменение этого параметра нарушает работу мультиплексоров терминала, таких как tmux и GNU Screen (Русский). Если вы измените этот параметр, вы все равно сможете использовать терминальный мультиплексор, используя systemd-run следующим образом:

$ systemd-run --scope --user command args

Например, чтобы запустить screen, вы должны сделать:

$ systemd-run --scope --user screen -S foo

Запущенные с помощью systemd-run процессы продолжат работу даже после выхода пользователя, если он залогинен в системе где-то ещё и служба [email protected] всё ещё работает.

После завершения всех активных сеансов [email protected] прекращает работу, если для этого пользователя не был включён lingering [7]. Поэтому для запуска и работы долгосрочных процессов после полного выхода пользователя из системы необходимо включить lingering. Подробнее см. #Автоматический запуск systemd от имени пользователя и loginctl(1).

Решение проблем

Runtime directory '/run/user/1000' is not owned by UID 1000, as it should

systemd[1867]: pam_systemd(systemd-user:session): Runtime directory '/run/user/1000' is not owned by UID 1000, as it should.
systemd[1867]: Trying to run as user instance, but $XDG_RUNTIME_DIR is not set

Если вы видите такую ошибку и ваш сеанс в порядке, то возможно, что другая системная (не пользовательская) служба создала этот каталог. Например, такое могло произойти при использовании контейнера docker, который выполнил bind-монтирование в каталог /run/user/1000. Чтобы это исправить, либо отредактируйте контейнер, удалив монтирование, либо отключите/отложите службу docker.

Смотрите также