Uyku durumunda tetiklemek için sistem kullanıcısı servisi nasıl çalıştırılır (askıya alma, hazırda bekletme)?


17

Çeşitli kaynaklara dayanarak birlikte Arnavut kaldırım ~/.config/systemd/user/screenlock.service:

[Unit]
Description=Lock X session
Before=sleep.target

[Service]
Environment=DISPLAY=:0
ExecStart=/usr/bin/xautolock -locknow

[Install]
WantedBy=sleep.target

Bunu kullanarak etkinleştirdim systemctl --user enable screenlock.service. Ancak yeniden başlattıktan, oturum açtıktan, askıya aldıktan ve devam ettirdikten sonra (hem systemctl suspendkapakla hem de kapağı kapatarak test edilmiştir ) ekran kilitlenmez ve hiçbir şey yokturjournalctl --user-unit screenlock.service . Neyi yanlış yapıyorum?

Koşu DISPLAY=:0 /usr/bin/xautolock -locknow, ekranı beklendiği gibi kilitler.

$ systemctl --version
systemd 215
+PAM -AUDIT -SELINUX -IMA -SYSVINIT +LIBCRYPTSETUP +GCRYPT +ACL +XZ +SECCOMP -APPARMOR
$ awesome --version
awesome v3.5.5 (Kansas City Shuffle)
 • Build: Apr 11 2014 09:36:33 for x86_64 by gcc version 4.8.2 (nobody@)
 • Compiled against Lua 5.2.3 (running with Lua 5.2)
 • D-Bus support: ✔
$ slim -v
slim version 1.3.6

systemctl --user start screenlock.serviceEkran kilitlerini hemen çalıştırırsam ve bir günlük mesajı alırsam journalctl --user-unit screenlock.service, bu yüzden ExecStartaçıkça doğrudur.

İlgili .xinitrcbölüm :

xautolock -locker slock &

Aynı dosya ile bir sistem hizmeti oluşturmak işe yarar (yani, slockdevam ederken etkindir):

# ln -s "${HOME}/.config/systemd/user/screenlock.service" /usr/lib/systemd/system/screenlock.service
# systemctl enable screenlock.service
$ systemctl suspend

Ancak $HOMEbirkaç nedenden ötürü kullanıcıya özel bir dosya eklemek istemiyorum :

  • Kullanıcı hizmetleri sistem hizmetlerinden açıkça ayrılmalıdır
  • Kullanıcı hizmetleri, süper kullanıcı ayrıcalıkları kullanılmadan kontrol edilmelidir
  • Yapılandırma kolayca sürüm kontrollü olmalıdır

Pencere yöneticisi olarak müthiş ve giriş yöneticisi olarak SLiM kullanıyorum . Arch tarafından tanımlanan tam bir masaüstü ortamı ve Wikipedia tarafından tanımlanan masaüstü ortamı olarak Linux / awesome kullanmıyorum . Linux için "masaüstü yöneticisi" gibi bir şey yok gibi görünüyor.
l0b0

Kullanıcı hizmetleri oturumun dışında çalıştırılır, bu nedenle oturum verileriniz onlar tarafından kullanılamaz; Bunun için standart bir servis dosyası kullanmak daha iyi olabilir: en azından yine de test etmek için ...
jasonwryan

@jasonwryan Hizmet tetiklenmiş olsaydı dergide bir tür hata mesajı görürdüm?
l0b0

Bilmiyorum: systemd-userhala çok lapa lapa; özetlediğim yaklaşımla oturumun bir parçası olarak çalışmasını sağlamak, konunun daraltılmasına yardımcı olacaktır; tüm önerebileceğim bu.
jasonwryan

Mükemmel bir çözüm (hala kök izinleriyle yönetilmesi gerekecektir) olmasa da, sadece kullanabilir /etc/systemd/system/veya $HOME/.local/systemd/systembir şey koyarak önlemek için /usrelle. @Jasonwryan'ın belirttiği gibi, kullanıcı oturumları hala üretim kalitesi olarak kabul edilmez; ama yaklaşıyorlar.
HalosGhost

Yanıtlar:


20

sleep.targetsistem hizmetlerine özgüdür. Bunun nedeni, sleep.targetuyurken otomatik olarak etkinleştirilen sihirli bir hedef değildir. O sıradan bir hedef olduğunu koyar elbette 'kullanıcı' örneklerini böylece eşdeğer olmaz - uykuya sistemi. (Ne yazık ki 'kullanıcı' örneklerinin şu anda sistem çapında hizmetlere bağımlı olma yolu yoktur.)

(Bu ve tüm "hardcoding $ DISPLAY" işi var. Çok kullanıcılı / çok koltuklu Unix'e dayanan bir işletim sistemindeki oturum parametrelerini her kodladığınızda, root bir yavru kedi öldürür.)

Yani bunu yapmanın iki iyi yolu var (ikincisini öneririm):

Yöntem 1

Sistem uyku moduna geçtiğinde, systemd-logind'in "tüm oturumları kilitle" sinyalini yayınlamasını sağlayan bir sistem hizmeti (veya systemd-sleep (8) kancası) oluşturun:

ExecStart=/usr/bin/loginctl lock-sessions

Ardından, X11 oturumunuzda (yani ~ / .xinitrc'den), sinyale tepki veren bir şey çalıştırın:

systemd-lock-handler slock ve
xss-lock --ignore-sleep slock ve

(GNOME, Tarçın, KDE, Aydınlanma bunu zaten yerel olarak destekliyor.)

Yöntem 2

X11 oturumunuzda, örneğin sistemd-logind'in "inhibitörlerine" bağlanmak suretiyle sistemin uykuya geçmesini doğrudan izleyen bir şey çalıştırın .

Yukarıda belirtilen xss-lock aslında tam olarak bunu yapar, açıkça "tümünü kilitle" sinyali olmadan bile, bu yüzden çalışmasını sağlamak yeterlidir:

xss-kilit slock &

Bu çalışacaktır slocko systemd-logind bilgisayarı askıya hazırlanıyor görür en kısa sürede.


Aydınlanma ve diğerlerinin yerel desteği hakkında biraz bilgi verebilir misiniz? Cevaptan doğal olarak neleri destekledikleri net değil.
Pavel Šimerda

@ PavelŠimerda: systemd-logind'den "kilit oturumu" sinyali (... tüm bölüm bununla ilgili ...) Ayrıca, yanılmışım, e19 aslında desteklemiyor.
user1686

E19 hakkında bilgi için teşekkürler. Cevap hala Gnome ve diğerlerinin tam olarak neyi desteklediğine dair açıklamalardan yoksundur. Systemd'ın D-Bus sinyalini dinlemek (orada yazılmamış olsa bile) bir şeydir, reaksiyonda hangi eylemlerin yapıldığı ve kullanıcının hangi eylemleri ve nasıl yapılacağını yapılandırabileceği başka bir şeydir. Ayrıca systemd-lock-handler'ın ne yaptığı ve nereden geldiği hakkında hiçbir bilgi yoktur.
Pavel Šimerda

xss-lockAUR'da olduğundan, manuel olarak oluşturmanıza gerek yoktur.
l0b0

Bu Debian testi altında güzel çalışıyor. Gönderdiğiniz için teşekkürler.
Systemd'in

-1

systemd-lock-handlerbunu başarabilen bir Python betiğidir: https://github.com/grawity/code/blob/master/desktop/systemd-lock-handler .

#!/usr/bin/env python
# systemd-lock-handler -- proxy between systemd-logind's "Lock" signal and your
#   favourite screen lock command

from __future__ import print_function
import os, sys, dbus, dbus.mainloop.glib
from gi.repository import GLib

def trace(*args):
    global arg0
    print("%s:" % arg0, *args)

def setup_signal(signal_handler):
    global session_id
    bus = dbus.SystemBus()
    manager = bus.get_object("org.freedesktop.login1", "/org/freedesktop/login1")
    # yecch
    manager = dbus.Interface(manager, "org.freedesktop.login1.Manager")
    session_path = manager.GetSession(session_id)
    session = bus.get_object("org.freedesktop.login1", session_path)
    session.connect_to_signal("Lock", signal_handler)

def handler_dbus_fdo():
    trace("locking session using DBus")
    bus = dbus.SessionBus()
    screensaver = bus.get_object("org.freedesktop.ScreenSaver", "/ScreenSaver")
    screensaver.Lock()

def handler_external():
    global lock_command
    trace("locking session using %r" % lock_command[0])
    os.spawnvp(os.P_NOWAIT, lock_command[0], lock_command)

def main():
    global arg0, lock_command, session_id
    arg0 = sys.argv[0].split("/")[-1]
    lock_command = sys.argv[1:] or ["--dbus"]
    try:
        session_id = os.environ["XDG_SESSION_ID"]
    except KeyError:
        print("error: $XDG_SESSION_ID not set; are you using pam_systemd?",
            file=sys.stderr)
        sys.exit(1)
    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
    if lock_command == ["--dbus"]:
        trace("using freedesktop.org DBus API")
        setup_signal(handler_dbus_fdo)
    else:
        trace("using external command %r" % lock_command[0])
        setup_signal(handler_external)
    trace("waiting for lock signals on session %s" % session_id)
    try:
        loop = GLib.MainLoop()
        loop.run()
    except KeyboardInterrupt:
        sys.exit(0)

main()
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.