Bagaimana menjalankan layanan pengguna systemd untuk memicu pada sleep (alias. Menangguhkan, hibernasi)?

17

Berdasarkan berbagai sumber saya telah dirakit ~/.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

Saya sudah mengaktifkannya menggunakan systemctl --user enable screenlock.service. Tetapi setelah reboot, masuk, menangguhkan dan melanjutkan (diuji dengan systemctl suspenddan dengan menutup tutupnya) layar tidak terkunci dan tidak ada apa-apa di dalamnyajournalctl --user-unit screenlock.service . Apa yang saya lakukan salah?

Menjalankan DISPLAY=:0 /usr/bin/xautolock -locknowmengunci layar seperti yang diharapkan.

$ 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

Jika saya menjalankan systemctl --user start screenlock.servicekunci layar segera dan saya mendapatkan pesan log journalctl --user-unit screenlock.service, jadi ExecStartjelas sudah benar.

.xinitrcBagian yang relevan :

xautolock -locker slock &

Membuat layanan sistem dengan file yang sama berfungsi (yaitu, slockaktif saat melanjutkan):

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

Tetapi saya tidak ingin menambahkan file khusus pengguna di luar $HOMEkarena beberapa alasan:

  • Layanan pengguna harus dipisahkan dengan jelas dari layanan sistem
  • Layanan pengguna harus dikontrol tanpa menggunakan hak pengguna super
  • Konfigurasi harus mudah dikendalikan versi
l0b0
sumber
Saya menggunakan yang luar biasa sebagai manajer jendela , dan SLIM sebagai manajer login . Saya tidak menggunakan lingkungan desktop penuh seperti yang didefinisikan oleh Arch , dan Linux / mengagumkan sebagai lingkungan desktop seperti yang didefinisikan oleh Wikipedia . Sepertinya tidak ada yang seperti "manajer desktop" untuk Linux.
l0b0
Layanan pengguna dijalankan di luar sesi, sehingga data sesi Anda tidak tersedia untuk mereka; Anda mungkin lebih baik menggunakan file layanan standar untuk ini: setidaknya untuk menguji tetap ...
jasonwryan
@jasonwryan Tentunya saya akan melihat semacam pesan kesalahan di jurnal jika layanan telah dipicu?
l0b0
Saya tidak tahu: systemd-usermasih sangat rapuh; membuatnya berfungsi sebagai bagian dari sesi melalui pendekatan yang saya uraikan akan membantu mempersempit masalah; hanya itu yang bisa saya sarankan.
jasonwryan
Meskipun ini bukan solusi yang sempurna (masih perlu dikelola dengan izin root), Anda bisa menggunakan /etc/systemd/system/atau $HOME/.local/systemd/systemmenghindari memasukkan apa pun ke dalam /usrmanual. Seperti @jasonwryan sebutkan, sesi pengguna masih belum dianggap berkualitas produksi; tapi mereka semakin dekat.
HalosGhost

Jawaban:

20

sleep.targetkhusus untuk layanan sistem. Alasannya, sleep.targetbukan target ajaib yang secara otomatis akan diaktifkan ketika akan tidur. Ini hanya target reguler yang membuat sistem tidur - jadi contoh 'pengguna' tentu saja tidak akan memiliki yang setara. (Dan sayangnya instans 'pengguna' saat ini tidak memiliki cara untuk bergantung pada layanan seluruh sistem.)

(Itu, dan ada seluruh bisnis "hardcoding $ DISPLAY". Setiap kali Anda melakukan hardcode pada parameter sesi di OS yang didasarkan pada Unix yang sangat multi-pengguna / multi-kursi, root membunuh anak kucing.)

Jadi ada dua cara yang baik untuk melakukan ini (saya sarankan yang ke-2):

Metode 1

Buat layanan sistem (atau kait systemd-sleep (8)) yang membuat systemd-logind menyiarkan sinyal "kunci semua sesi" ketika sistem tidur:

ExecStart=/usr/bin/loginctl lock-sessions

Kemudian, dalam sesi X11 Anda (yaitu dari ~ / .xinitrc), jalankan sesuatu yang bereaksi terhadap sinyal:

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

(GNOME, Cinnamon, KDE, Enlightenment sudah mendukung ini secara asli.)

Metode 2

Dalam sesi X11 Anda, jalankan sesuatu yang secara langsung mengawasi sistem akan tidur, misalnya dengan menghubungkan ke "inhibitor" systemd-logind.

Xss-lock yang disebutkan di atas sebenarnya melakukan hal itu, bahkan tanpa sinyal "kunci semua" yang eksplisit, sehingga cukup untuk menjalankannya:

xss-lock slock &

Ini akan berjalan slocksegera setelah melihat systemd-logind bersiap untuk menangguhkan komputer.

pengguna1686
sumber
Bisakah Anda menguraikan sedikit tentang Pencerahan dan dukungan asli orang lain? Tidak jelas apa sebenarnya yang mereka dukung secara asli dari jawabannya.
Pavel Šimerda
@ PavelŠimerda: Sinyal "kunci sesi" dari systemd-logind (... seluruh bagian tentang itu ...) Juga, saya salah, e19 sebenarnya tidak mendukungnya.
user1686
Terima kasih atas info tentang E19. Jawabannya masih kurang penjelasan tentang apa yang sebenarnya didukung Gnome dan lainnya. Mendengarkan sinyal D-Bus systemd (bahkan yang tidak tertulis di sana) adalah satu hal, tindakan apa yang dilakukan sebagai reaksi dan tindakan apa serta bagaimana pengguna dapat mengkonfigurasi yang harus dilakukan adalah hal lain. Juga tidak ada informasi tentang apa yang dilakukan systemd-lock-handler dan dari mana asalnya.
Pavel Šimerda
xss-lockada di AUR, jadi tidak perlu membuatnya secara manual.
l0b0
Ini berfungsi dengan baik di bawah pengujian Debian. Terima kasih telah memposting. Sangat mengecewakan bahwa systemd tidak memungkinkan layanan pengguna bergantung pada layanan sistem ...
cgogolin
-1

systemd-lock-handleradalah skrip Python yang dapat melakukan ini: 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()
yaerotugh
sumber