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.