Xorg'a bağlı bir hizmet yazma


30

Ben için bir kullanıcı düzeyinde hizmet yazmaya çalışıyorum redshiftve Xorg çalışana kadar beklemek gerekiyor. Mevcut hizmet dosyam şöyle:

[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

Ancak, Xorg bitmeden önce başlatmaya çalışıyor gibi görünüyor ve daha sonra hizmeti manuel olarak başlatmam gerekiyor. Sanırım yanlış After=hedefi kullanıyorum . İpucu var mı?

Yanıtlar:


20

Bunu araştırıyordum ve grawity'nin cevabı güncel değil. Artık, kullanıcı oturumunun bir parçası olarak çalışan systemd ile kullanıcı hizmetlerini ayarlayabilirsiniz. DISPLAY ve XAUTHORITY ayarlarına sahip olabilirler (şu anda Arch ve Debian Stretch'te).

Bu, sistem düzeyinde bir uygulama (yeniden başlatma vb.) Yaptığınız gibi işlem yönetimini aldığınız için masaüstü otomatik başlatma dosyalarını kullanmanın önceki önerileri üzerinde anlamlıdır.

Şu anda en iyi dokümanlar Arch wiki; Systemd / Kullanıcı

TLDR sürümü;

  1. İstediğiniz * .service dosyasını oluşturun ~/.config/systemd/user/
  2. Çalıştır systemctl --user enable [service](.service son ekini hariç tut)
  3. İsteğe bağlı olarak systemctl --user start [service]şimdi başlamak için çalıştırın
  4. systemctl --user status [service]Nasıl çalıştığını kontrol etmek için kullanın

Birkaç yararlı komut daha.

  • systemctl --user list-unit-files - tüm kullanıcı birimlerini görüntüle
  • s ystemctl --user daemon-reload- bir .service dosyasını düzenlerseniz

-- Sonra...

Oturum artalanlarımın çoğunu systemd .service dosyalarına yükselttim ve dönüştürdüm. Birkaç ek not ekleyebilirim.

Hizmetleri girişte çalıştırmak için varsayılan bir kanca yoktu, bu yüzden kendiniz tetiklemelisiniz. Bunu ~ / .xsession dosyamdan yapıyorum.

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

İlk satır, bazı ortam değişkenlerini sistemd kullanıcı oturumuna alır ve ikinci satır hedefe başlar. Xsession.target dosyam;

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

Örnek olarak xbindkeys.service'im.

[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
Örnek bir birim dosyası sağlayabilir ve birimin DISPLAY ve XAUTHORITY'yi nasıl kullanabileceğini açıklayabilirseniz, kabul edilen cevabı değiştirmekten memnuniyet duyarız.
mkaito

Debian Stretch'i serbest bıraktıktan sonra bunu inceleyeceğim. Debian istikrarlı çalışıyorum ve o zamana kadar daha fazla oynamak için bekliyordu.
John Eikenberry

@mkaito github.com/systemd/systemd/blob/v219/NEWS#L194 adresinde "Bir oturum başlarsa, $ DISPLAY ve $ XAUTHORITY ortamına sistemd - user daemon yükleyen bir X11 oturum komut dosyası gönderilir. Bu, systemd kullanıcı hizmetleri olarak çalışan X11 özellikli uygulamalarla uyumluluğu geliştirmelidir. "
josch

Özel bir şey olup olmadığını netleştirmek için hala örnek bir birim dosyası görmek istiyorum.
mkaito

11

Her zamanki ipucu "yapma" dır. redshiftsistem çapında bir hizmet değildir - her oturum için ayrı bir örneği olur ve söz konusu oturumun Xorg'una nasıl bağlanacağını bilmesi gerekir.

(Xorg da bir sistem hizmeti değildir - yalnızca ekran yöneticisi ve aynı zamanda her oturum için ayrı bir Xorg başlatır. // graphical.targetekran yöneticisinin ne zaman hazır olduğunu size söyleyecektir, ancak DM'nin ilk veya tümü görüntülenir.)

İle Sadece açılışta üzerine başlayan DISPLAY=:0orada herhangi bir zamanda tam olarak bir ekran var ki hiçbir garantisi, ne de her zaman bunun için yeterli değildir :0Xorg bayat kilit dosyası ayrılan çökerse (örneğin, bir sonraki en aday olacağını :1o kadar :0hala meşgul olduğunu düşünür ); XAUTHORITYX11 kimlik doğrulaması gerektirdiğinden dosyanızın yolunu da ayarlamanız gerekir; ve redshifttekrar çıkış yaparsanız ve tekrar giriş yaparsanız yeniden başlatıldığından emin olun .

Peki nasıl başlamalı? Neredeyse her zaman, masaüstü ortamının kendi oturum hizmetlerini başlatmak için çeşitli yöntemleri vardır . Her zamanki iki tanesini açıklayan eski bir gönderiye bakın ; ~/.xprofilesenaryo ve ~/.config/autostart/*.desktopkonumu.

Eğer kullanırsanız startx , kullanabileceğiniz ~/.xinitrcgibi şeyler başlatın. Bağımsız pencere yöneticilerinin genellikle kendi başlatma / başlatma komut dosyaları vardır; ör ~/.config/openbox/autostart. Openbox için.

Tüm bu yöntemler için ortak olan, programın oturum içinde başlatılmasıdır - yukarıda listelenen tüm sorunlardan kaçınılması.


Redshift, çoğu durumda sistem çapında bir hizmet olmasa da, OP'nin tam olarak yapmaya çalıştığı şey olan bir kullanıcı hizmeti olmak mantıklıdır.
simotek

5

Henüz mevcut olmayanlar için geçici çözüm olarak oluşturduğum şey graphical-session.target(Kubuntu 16.04 sistemimde):

  1. Bir oluşturma sözde systemd kullanıcı ünitesini aşağı graphical-session.target yukarı ve getiriyor.

~/.config/systemd/user/xsession.targetAşağıdaki içeriklerle oluşturun :

[Birim]
Description = Xsession çalışıyor ve çalışıyor
BindsTo = graphical-session.target

Systemd'e bu yeni birim hakkında bilgi verin:

$> systemctl --user daemon-reload
  1. Oluşturmak autostart ve kapatma komut dosyalarını kontrol xsession.targetUbuntu 16.04 masaüstü mevcut mekaniği aracılığıyla.

~/.config/autostart-scripts/xsession.target-login.shAşağıdaki içeriklerle oluşturun :

#! / Bin / bash

Eğer ! systemctl --kullanıcı etkin xsession.target &> / dev / null
sonra
  / bin / systemctl --kullanıcı içe aktarma ortamı EKRAN XAUTHORITY
  / bin / systemctl --kullanıcı başlat xsession.target
fi

~/.config/plasma-workspace/shutdown/xsession.target-logout.shAşağıdaki içeriklerle oluşturun :

#! / Bin / bash

systemctl --user etkinse xsession.target &> / dev / null
sonra
  / bin / systemctl --kullanıcı durdurma xsession.target
fi

Komut dosyalarını yürütülebilir yapın:

$> chmod + x ~ / .config / autostart-scriptler / xsession.target-login.sh
$> chmod + x ~ / .config / plasma-workspace / shutdown / xsession.target-logout.sh

Not: bu iki dosya otomatik başlatma ve kapatma için KDE tarafından alınacak şekilde yerleştirilir. Dosyalar diğer masaüstü ortamları için başka bir yere yerleştirilebilir (örneğin Gnome) - ancak bu ortamları bilmiyorum.

Not: Bu geçici çözüm, çoklu masaüstü oturumlarının desteğinden yoksundur. graphical-session.targetBir makinede yalnızca bir etkin X11 oturumu çalıştırıldığı sürece yalnızca doğru şekilde işler (ancak çoğu linux kullanıcısı için geçerlidir).

  1. Oluşturun Kendi systemd kullanıcı birimleri bağlıdır graphical-session.targetve masaüstünüzde oturum olurken onları temiz bir şekilde yayınlanmasını sağlamak.

Örnek olarak @ mkaito'nun birimi şöyle görünmelidir:

[Birim]
Açıklama kırmızıya kayma =
PartOf = graphical-session.target

[Hizmet]
ExecStart = / bin / redshift -l 28: -13 -t 5300: 3300 -b 0.80: 0.91 -m randr
Yeniden her zaman =

( daemon-reloadBirimlerinizi düzenledikten sonra yapmayı unutmayın !)

  1. Makinenizi yeniden başlatın, giriş yapın ve ünitelerinizin beklendiği gibi başlatıldığını doğrulayın
$> systemctl --kullanıcı durumu graphical-session.target
● graphical-session.target - Geçerli grafik kullanıcı oturumu
   Yüklendi: yüklendi (/usr/lib/systemd/user/graphical-session.target; statik; tedarikçi ön ayarı: etkin)
   Aktif: Don'dan beri aktif 2017-01-05 15:08:42 CET; 47 dakika önce
     Dokümanlar: adam: systemd.special (7)
$> systemctl - birim durumu üniteniz ...

Gelecek günlerde (Ubuntu 17.04 olacak mı?) Geçici çözümüm, sistem graphical-session.targetdoğru şekilde çalışacağı için geçersiz hale geliyor . O gün sadece otomatik başlatma ve kapatma komut dosyasını kaldırın ve ayrıca xsession.target- özel kullanıcı birimleriniz dokunulmadan kalabilir ve işe yarayabilir.


Bunun eski bir yorum olduğunu biliyorum, ancak Çalışma Alanı> Başlangıç ​​ve Kapatma> Otomatik Başlat altındaki Sistem ayarları uygulaması aracılığıyla başlatma / giriş komut dosyaları da ekleyebilirsiniz, bu komut dosyalarını hatırlayacağınız bir yere koymak istiyorsanız.
AmbientCyan

2

Bu çözüm, sorunun yazarının sorduğunu tam olarak yapar:

Xorg çalışana kadar beklemesi gerekiyor

Diğer kullanıcılar tarafından zaten yanıtlandığı gibi, bunu yapmanın daha iyi yolları olabilir, ancak bu, bu soruna başka bir yaklaşımdır.

Bu, belirli ölçütler karşılanıncaya kadar engelleyen systemd'nin systemd-networkd-wait-online.service hizmetine benzer . Buna bağlı olan diğer hizmetler, bu hizmet başarılı bir şekilde başlar başlamaz veya zaman aşımına uğrarsa başlatılacaktır.

Başına manuel (bölüm "Dosyalar"), X sunucusu UNIX soket yaratacaktır /tmp/.X11-unix/Xn( nbir görüntüleme sayı).

Bu soketin varlığını izleyerek belirli bir ekran için sunucunun başlatıldığını belirleyebiliriz.

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

Şimdi, x_server_started.serviceX sunucusuyla aynı anda başlamayı etkinleştirin .

Bağlanmak için diğer hizmetleri (X sunucusunun başlatılması gerekir) yapın x_server_started.service

bağımlı birim:

[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 sunucusu sorunsuz bir x_server_started.serviceşekilde başlarsa, hemen başlar ve systemd bağımlı tüm birimleri başlatmaya devam eder x_server_started.service.


Bu güzel çalışıyor. Ekstra hizmet hoş bir dokunuş olduğunu. Hedef hizmetinizde ExecStartPre öğesini de kullanabilirsiniz. Ben 'çıkış 0' önce ekstra bir 'uyku 1' eklemek zorunda kaldı, sadece denemek ve hemen X yakalamak için biraz çok hızlı gibi görünüyor.
TTimo
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.