Wie starte ich den systemd-Benutzerdienst, um den Ruhezustand auszulösen (alias Suspend, Hibernate)?

17

Basierend auf verschiedenen Quellen habe ich zusammengeschustert ~/.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

Ich habe es mit aktiviert systemctl --user enable screenlock.service. Aber nach dem Neustart, Einloggen, Anhalten und Wiederaufnehmen (getestet mit systemctl suspendund durch Schließen des Deckels) ist der Bildschirm nicht gesperrt und es ist nichts drinjournalctl --user-unit screenlock.service . Was mache ich falsch?

Beim Ausführen wird DISPLAY=:0 /usr/bin/xautolock -locknowder Bildschirm wie erwartet gesperrt.

$ 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

Wenn ich systemctl --user start screenlock.serviceden Bildschirm sofort sperre und eine Logmeldung bekomme journalctl --user-unit screenlock.service, ist das ExecStarteindeutig richtig.

Relevanter .xinitrcAbschnitt :

xautolock -locker slock &

Das Erstellen eines Systemdienstes mit derselben Datei funktioniert (dh, er slockist aktiv, wenn der Vorgang fortgesetzt wird):

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

Ich möchte jedoch $HOMEaus mehreren Gründen keine benutzerspezifische Datei außerhalb hinzufügen :

  • Benutzerdienste sollten klar von Systemdiensten getrennt sein
  • Benutzerdienste sollten ohne Verwendung von Superuser-Berechtigungen gesteuert werden
  • Die Konfiguration sollte leicht versionskontrollierbar sein
l0b0
quelle
Ich benutze awesome als Fenstermanager und SLiM als Login- Manager. Ich verwende keine vollständige Desktop-Umgebung, wie sie von Arch definiert wurde , und Linux / awesome nicht als Desktop-Umgebung, wie sie von Wikipedia definiert wurde . Es scheint keinen "Desktop Manager" für Linux zu geben.
l0b0
Benutzerdienste werden außerhalb der Sitzung ausgeführt, sodass Ihre Sitzungsdaten für sie nicht verfügbar sind. Sie könnten besser dran sein, eine Standard-Service-Datei dafür zu verwenden: Zumindest, um es trotzdem zu testen ...
jasonwryan
@ jasonwryan Sicherlich würde ich eine Art Fehlermeldung im Journal sehen, wenn der Dienst ausgelöst worden wäre?
14.
Ich weiß nicht: systemd-userist immer noch sehr schuppig; Es würde helfen, das Problem einzugrenzen, indem man es im Rahmen der Sitzung über den von mir beschriebenen Ansatz zum Laufen bringt. Das ist alles, was ich vorschlagen kann.
Jasonwryan
Obwohl es keine perfekte Lösung ist (es müsste immer noch mit Root-Berechtigungen verwaltet werden), können Sie es einfach verwenden /etc/systemd/system/oder $HOME/.local/systemd/systemvermeiden, etwas /usrmanuell einzugeben. Wie @jasonwryan bereits erwähnt hat, werden Benutzersitzungen immer noch nicht als Produktionsqualität angesehen. aber sie kommen näher.
HalosGhost

Antworten:

20

sleep.targetist spezifisch für Systemdienste. Der Grund dafür ist, dass sleep.targetes sich nicht um ein magisches Ziel handelt, das beim Einschlafen automatisch aktiviert wird. Es ist nur ein reguläres Ziel, das das System in den Energiesparmodus versetzt. Die "Benutzer" -Instanzen verfügen also natürlich nicht über ein Äquivalent. (Leider können sich die Benutzerinstanzen derzeit nicht auf systemweite Dienste verlassen.)

(Das und das ganze "hardcoding $ DISPLAY" -Geschäft. Jedes Mal, wenn Sie Sitzungsparameter in einem Betriebssystem fest codieren, das auf dem Unix mit vielen Benutzern und mehreren Sitzen basiert, tötet root ein Kätzchen.)

Dafür gibt es zwei gute Möglichkeiten (ich schlage die zweite vor):

Methode 1

Erstellen Sie einen Systemdienst (oder einen systemd-sleep (8) -Hook), mit dem systemd-logind das Signal "Alle Sitzungen sperren" sendet, wenn das System in den Ruhezustand wechselt:

ExecStart=/usr/bin/loginctl lock-sessions

Führen Sie dann in Ihrer X11-Sitzung (dh von ~ / .xinitrc) etwas aus, das auf das Signal reagiert:

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

(GNOME, Cinnamon, KDE, Enlightenment unterstützen dies bereits von Haus aus.)

Methode 2

Führen Sie in Ihrer X11-Sitzung etwas aus, das direkt darauf wartet , dass das System in den Ruhezustand versetzt wird, z. B. indem Sie sich in die "Inhibitoren" von systemd-logind einhängen.

Das oben erwähnte xss-lock macht eigentlich genau das, auch ohne das explizite "lock all" Signal, es reicht also aus, es laufen zu lassen:

xss-lock slock &

Es wird ausgeführt slock, sobald systemd-logind sich darauf vorbereitet, den Computer anzuhalten.

Grawity
quelle
Könnten Sie bitte ein wenig über die Unterstützung der Aufklärung und der Einheimischen anderer sprechen? Es ist nicht klar, was genau sie aus der Antwort nativ unterstützen.
Pavel Šimerda
@ PavelŠimerda: Das "lock session" Signal von systemd-logind (... der gesamte Abschnitt handelt davon ...) Auch ich habe mich geirrt, e19 unterstützt es eigentlich nicht.
Grawity
Danke für die Infos zu E19. Der Antwort fehlt noch eine Erklärung, was Gnome und andere genau unterstützen. Das Abhören des D-Bus-Signals von systemd (auch wenn es dort nicht geschrieben ist) ist eine Sache, welche Aktionen als Reaktion ausgeführt werden und welche Aktionen und wie der Benutzer die Ausführung konfigurieren kann. Außerdem gibt es keine Informationen darüber, was systemd-lock-handler macht und woher es kommt.
Pavel Šimerda
xss-lockist in der AUR enthalten, daher muss sie nicht manuell erstellt werden.
l0b0
Dies funktioniert wunderbar unter Debian-Tests. Danke fürs Schreiben. Es ist ziemlich enttäuschend, dass systemd nicht zulässt, dass Benutzerdienste von
Systemdiensten
-1

systemd-lock-handlerist ein Python-Skript, das dies ausführen kann: 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
quelle