Написання послуги, що залежить від Xorg


30

Я намагаюся написати службу на рівні користувача redshift, і їй потрібно почекати, поки Xorg буде запущений і запущений. Мій поточний файл служби виглядає так:

[Unit]
Description=Redshift
After=graphical.target

[Service]
Environment=DISPLAY=:0
ExecStart=/bin/redshift -l 28:-13 -t 5300:3300 -b 0.80:0.91 -m randr
Restart=always

[Install]
WantedBy=default.target

Однак, схоже, він намагається запуститись до запуску Xorg, і мені доведеться згодом вручну запускати службу. Я думаю, я використовую неправильну After=ціль. Якісь підказки?

Відповіді:


20

Я досліджував це, і відповідь grawity здається застарілою. Тепер ви можете налаштувати служби користувачів за допомогою systemd, які запускаються в рамках сеансу користувача. У них можуть бути встановлені DISPLAY та XAUTHORITY (зараз в Arch і Debian Stretch).

Це має сенс у порівнянні з попередніми рекомендаціями щодо використання файлів автозапуску на робочому столі, оскільки ви отримуєте управління процесом так само, як у програмі на системному рівні (перезапуск тощо).

Найкращі документи на даний момент - вікі Arch; Systemd / Користувач

Версія TLDR;

  1. Створіть потрібний * .service файл у ~/.config/systemd/user/
  2. Запустити systemctl --user enable [service](виключити сервісний суфікс)
  3. Необов’язково запустіть, systemctl --user start [service]щоб почати зараз
  4. Використовуйте, systemctl --user status [service]щоб перевірити, як це робиться

Кілька інших корисних команд.

  • systemctl --user list-unit-files - переглянути всі одиниці користувача
  • s ystemctl --user daemon-reload- якщо ви редагуєте файл .service

- Пізніше ...

Я оновив і перетворив більшість демонів сеансу в системні файли .service. Тож я можу додати пару додаткових заміток.

Для запуску служб при вході в систему не було жодної гачки за замовчуванням, тому її потрібно запустити самостійно. Я роблю це з мого файлу ~ / .xsession.

systemctl --user import-environment PATH DBUS_SESSION_BUS_ADDRESS
systemctl --no-block --user start xsession.target

Перший рядок імпортує деякі змінні середовища в сеанс користувача systemd, а другий відбиває ціль. Мій файл xsession.target;

[Unit]
Description=Xsession running
BindsTo=graphical-session.target

Мій приклад xbindkeys.service як приклад.

[Unit]
Description=xbindkeys
PartOf=graphical-session.target

[Service]
ExecStart=/usr/bin/xbindkeys -n -f ${HOME}/projects/dotfiles/.xbindkeysrc
Restart=always

[Install]
WantedBy=xsession.target

2
Якщо ви можете надати приклад файлу одиниці та пояснити, як дозволити пристрою використовувати DISPLAY та XAUTHORITY, я буду радий переключити прийняту відповідь.
mkaito

@mkaito Я вивчу це, коли Debian випустить Stretch. Я запускаю Debian стабільно і чекав до цього, щоб більше грати з ним.
Джон Ейкенберрі

@mkaito На github.com/systemd/systemd/blob/v219/NEWS#L194 написано, що "тепер передається сценарій сеансу X11, який завантажує $ DISPLAY та $ XAUTHORITY у середовище демонстратора systemd --user, якщо сеанс розпочнеться. Це повинно покращити сумісність із програмами, що підтримуються X11, які запускаються як системи системних користувачів ".
Джош

Я все ще хотів би побачити приклад файлу блоку, просто щоб зрозуміти, чи потрібно щось особливе.
mkaito

11

Звичайний натяк - "не робити". redshiftНЕ загальносистемний сервіс - це буде мати окремий екземпляр для кожної сесії , і він повинен знати про те , як підключитися до Xorg цієї конкретної сесії.

(Xorg також не є системною службою - лише диспетчер дисплеїв , і він також запускає окремий Xorg для кожного сеансу. // graphical.targetпідкаже, коли менеджер дисплеїв буде готовий, але він нічого не говорить про те, коли DM фактично запускає спочатку - або всі - відображає.)

DISPLAY=:0Не достатньо лише запустити його під час завантаження , оскільки немає гарантії того, що в даний момент існує точно один дисплей, і що це завжди :0(наприклад, якщо Xorg виходить з ладу, залишаючи застарілий lockfile, наступний запускається :1як міг би подумати :0, що все ще зайнятий); вам також потрібно встановити шлях до XAUTHORITYфайлу, оскільки для X11 потрібна автентифікація; і переконайтеся, що redshiftвін перезапущений, якщо ви коли-небудь виходитимете та входите знову.

Отже, як це почати? Майже завжди в середовищі робочого столу є кілька методів запуску власних служб сеансу . Дивіться старішу публікацію, яка вже описує два звичайних; ~/.xprofileсценарій і ~/.config/autostart/*.desktopмісце.

Якщо ви використовуєте startx , ви можете використовувати ~/.xinitrcдля запуску таких речей. Автономні менеджери вікон часто мають власні сценарії запуску / запуску; наприклад ~/.config/openbox/autostartдля Openbox.

Що є загальним для всіх цих методів, це те, що програма запускається зсередини сеансу - уникаючи всіх перерахованих вище проблем.


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

5

Ось що я тільки що створив як вирішення ще не доступної graphical-session.target(У моїй системі Kubuntu 16.04):

  1. Створіть псевдосистемний користувальницький блок, який приводить графічний графік-session.target вгору та вниз.

Створіть ~/.config/systemd/user/xsession.targetіз наступним вмістом:

[Одиниця]
Опис = запущена Xsession
BindsTo = graphical-session.target

Розкажіть systemd про цей новий блок:

$> systemctl --user daemon-reload
  1. Створіть сценарії автоматичного запуску та відключення, які керують за xsession.targetдопомогою наявної в даний час механіки робочого столу Ubuntu 16.04.

Створіть ~/.config/autostart-scripts/xsession.target-login.shіз наступним вмістом:

#! / бін / баш

якщо! systemctl --користувач є активним xsession.target &> / dev / null
потім
  / bin / systemctl - середовище імпорту -користувача DISPLAY XAUTHORITY
  / bin / systemctl - запуск користувача xsession.target
фі

Створіть ~/.config/plasma-workspace/shutdown/xsession.target-logout.shіз наступним вмістом:

#! / бін / баш

якщо systemctl --user активний xsession.target &> / dev / null
потім
  / bin / systemctl - ціль зупинки xsession.target
фі

Зробіть сценарії виконуваними:

$> chmod + x ~ / .config / autostart-script / xsession.target-login.sh
$> chmod + x ~ / .config / плазма-робоча область / вимкнення / xsession.target-logout.sh

Примітка: ці два файли розміщуються там, де KDE підбере їх для автоматичного запуску та вимкнення. Файли, можливо, розміщені десь в інших робочих середовищах (наприклад, Gnome), але я не знаю про ці середовища.

Примітка. У цьому вирішенні бракує підтримки декількох сесій на робочому столі. Він обробляє лише graphical-session.targetправильно, поки на машині працює лише один активний сеанс X11 (але це стосується більшості з нас користувачів Linux).

  1. Створіть власні системні одиниці користувачів, які залежать від graphical-session.targetних та примусово вони працюватимуть під час входу на робочий стіл.

Наприклад, блок @ mkaito повинен виглядати так:

[Одиниця]
Опис = Зміна
PartOf = graphical-session.target

[Сервіс]
ExecStart = / bin / redshift -l 28: -13 -t 5300: 3300 -b 0,80: 0,91 -м randr
Перезапуск = завжди

(Не забувайте робити daemon-reloadпісля редагування своїх підрозділів!)

  1. Перезавантажте свою машину, увійдіть в систему і підтвердіть, що ваші одиниці запускаються, як очікувалося
$> systemctl - ціль статусукористувача
● graphical-session.target - Поточний графічний сеанс користувача
   Завантажено: завантажено (/usr/lib/systemd/user/graphical-session.target; статичний; попередньо встановлений постачальник: увімкнено)
   Активний: активний з Дон 2017-01-05 15:08:42 CET; 47 хв тому
     Документи: людина: systemd.special (7)
$> systemctl - користувацький статус вашої одиниці ...

У якийсь майбутній день (це буде Ubuntu 17.04?) Моє вирішення застаріло, оскільки система graphical-session.targetсама поправить себе. У цей день просто видаліть сценарій автоматичного запуску та відключення, а також xsession.target- ваші користувацькі одиниці користувача можуть залишитися недоторканими та просто працювати.


Я знаю, що це старий коментар, але ви також можете додати сценарії запуску / входу через додаток "Налаштування системи" в розділі Робоча область> Запуск і вимкнення> Автозапуск, якщо ви хочете розмістити ці сценарії в тому місці, яке ви їх запам’ятаєте.
AmbientCyan

2

Це рішення робить саме те, що запитує автор запитання:

йому потрібно почекати, поки Xorg буде запущений і запущений

Хоча можуть бути кращі способи зробити це, як уже відповіли інші користувачі, це ще один підхід до цієї проблеми.

Це схоже на systemd- systemd-networkd-wait-online.service, який блокує, поки не будуть виконані певні критерії. Інші послуги, які залежать від нього, будуть запущені, як тільки ця послуга запуститься успішно або вичерпається.

Згідно з посібником (розділ "Файли"), X-сервер створить UNIX-розетку /tmp/.X11-unix/Xn(де nномер відображення).

Відстежуючи наявність цього сокета, ми можемо визначити, що сервер для конкретного дисплея запущений.

confirm_x_started.sh:

#!/bin/bash
COUNTER=0

while [ 1 ]
do
  # Check whether or not socket exists
  if [ -S /tmp/.X11-unix/X0 ]
  then
    exit 0
  fi

  ((++COUNTER))

  if [ $COUNTER -gt 20 ]
  then
    exit 1
  fi

  sleep 0.5
done

x_server_started.service:

[Unit]
Description=Monitor X server start

[Service]
Type=oneshot
ExecStart=/path/to/confirm_x_started.sh

[Install]
WantedBy=example.target

Тепер увімкніть x_server_started.serviceдля запуску одночасно з сервером X.

Зробіть інші сервіси (для яких потрібно запустити X-сервер) залежно від x_server_started.service

залежна одиниця:

[Unit]
Description=Service that needs to have the X server started
Requires=x_server_started.service
After=x_server_started.service

[Service]
ExecStart=/path/to/binary

[Install]
WantedBy=example.target

Якщо X-сервер запускається без проблем, x_server_started.serviceзапуск буде запущений майже негайно, а systemd приступить до запуску всіх блоків, від яких залежить x_server_started.service.


Це прекрасно працює. Додатковий сервіс - приємний штрих. Ви також можете просто використовувати ExecStartPre у своїй цільовій службі. Мені довелося додати додатковий "сон 1" перед "виходом 0", хоча, здається, це було занадто швидко, щоб просто спробувати зловити X одразу.
TTimo
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.