시스템 사용자 서비스를 실행하여 절전 모드 (일명 일시 중지, 최대 절전 모드)에서 트리거하는 방법은 무엇입니까?


17

나는 다양한 출처를 바탕으로 함께 모았습니다 ~/.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

를 사용하여 활성화했습니다 systemctl --user enable screenlock.service. 그러나 재부팅, 로그인, 일시 중단 및 재개 ( systemctl suspend뚜껑을 닫고 닫아 테스트 한 후 ) 화면이 잠기지 않고에 아무것도 없습니다journalctl --user-unit screenlock.service . 내가 도대체 ​​뭘 잘못하고있는 겁니까?

실행 DISPLAY=:0 /usr/bin/xautolock -locknow하면 화면이 예상대로 잠 깁니다.

$ 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.service화면 잠금을 즉시 실행 하고에 로그 메시지가 표시 journalctl --user-unit screenlock.service되면 ExecStart명확하게 맞습니다.

관련 .xinitrc섹션 :

xautolock -locker slock &

동일한 파일로 시스템 서비스를 작성하면 작동합니다 ( slock다시 시작할 때 활성화 됨).

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

그러나 $HOME여러 가지 이유로 사용자 특정 파일을 외부 에 추가하고 싶지 않습니다 .

  • 사용자 서비스는 시스템 서비스와 명확하게 분리되어야합니다
  • 수퍼 유저 권한을 사용하지 않고 사용자 서비스를 제어해야합니다.
  • 쉽게 버전을 제어 할 수있는 구성

나는 굉장 사용하고 윈도우 는 AS 관리자 및 슬림 로그인 관리자. Arch 에서 정의한 전체 데스크톱 환경 사용하지 않고 Wikipedia에서 정의한 데스크탑 환경 으로 Linux / awesome을 사용하고 있습니다 . Linux 용 "데스크톱 관리자"와 같은 것은 없습니다.
l0b0

사용자 서비스는 세션 외부에서 실행되므로 세션 데이터를 사용할 수 없습니다. 당신은 이것에 대한 표준 서비스 파일을 사용하는 것이 더 나을 것입니다 : 적어도 어쨌든 테스트하기 위해 ...
jasonwryan

@jasonwryan 서비스가 트리거 된 경우 저널에 일종의 오류 메시지가 표시됩니까?
l0b0

모르겠다 : systemd-user여전히 매우 벗겨져있다. 내가 설명한 접근 방식을 통해 세션의 일부로 작동하게하면 문제를 좁힐 수 있습니다. 그것이 내가 제안 할 수있는 전부입니다.
jasonwryan

완벽한 솔루션은 아니지만 (루트 권한으로 관리해야 할 경우도 있음) 단순히 사용 /etc/systemd/system/하거나 수동으로 입력 $HOME/.local/systemd/system하지 않도록 할 수 /usr있습니다. @jasonwryan이 언급했듯이 사용자 세션은 여전히 ​​프로덕션 품질로 간주되지 않습니다. 하지만 점점 가까워지고 있습니다.
HalosGhost

답변:


20

sleep.target시스템 서비스에 따라 다릅니다. 그 이유는 sleep.target잠들 때 자동으로 활성화되는 마법 대상이 아니기 때문입니다 . 이 것을 그냥 일반 대상의 물론 '사용자 인스턴스 그래서 해당이되지 않습니다 - 잠 시스템. 불행히도 '사용자'인스턴스는 현재 시스템 전체 서비스에 의존 할 방법이 없습니다.

(즉, 전체 "하드 코딩 $ DISPLAY"비즈니스가 있습니다. 많은 다중 사용자 / 다중 시트 Unix를 기반으로하는 OS에서 세션 매개 변수를 하드 코딩 할 때마다 루트가 새끼 고양이를 죽입니다.)

따라서이 작업을 수행하는 두 가지 좋은 방법이 있습니다 (두 번째 방법을 제안합니다).

방법 1

시스템이 휴면 상태가 될 때 systemd-logind 브로드 캐스트가 "모든 세션 잠금"신호를 보내는 시스템 서비스 (또는 systemd-sleep (8) 후크)를 만듭니다.

ExecStart=/usr/bin/loginctl lock-sessions

그런 다음 X11 세션 내에서 (예 : ~ / .xinitrc에서) 신호에 반응하는 것을 실행하십시오.

시스템 잠금 처리기 잠금
xss- lock-잠자기 잠금 무시 및

(GNOME, Cinnamon, KDE, Enlightenment는 이미이 기능을 기본적으로 지원합니다.)

방법 2

X11 세션 내에서 systemd-logind의 "inhibitors"에 연결하여 잠자기 시스템 을 직접 감시 하는 것을 실행하십시오 .

앞에서 언급 한 xss-lock은 명시적인 "모두 잠금"신호가 없어도 실제로 정확하게 수행하므로 실행하기에 충분합니다.

xss-lock 잠금

slocksystemd-logind가 컴퓨터를 일시 중단 할 준비를하는 즉시 실행 됩니다.


깨달음과 다른 사람들의 기본 지원에 대해 좀 더 자세히 설명해 주시겠습니까? 그들이 대답에서 정확히 무엇을 지원하는지 명확하지 않습니다.
Pavel Šimerda

@ PavelŠimerda : systemd-logind의 "세션 잠금"신호 (... 전체 섹션은 이것에 관한 것입니다 ...) 또한 틀 렸습니다. e19는 실제로 그것을 지원하지 않습니다.
user1686

E19에 대한 정보를 주셔서 감사합니다. 대답에는 여전히 그놈과 다른 사람들이 정확히 무엇을 지원하는지에 대한 설명이 부족합니다. systemd의 D-Bus 신호를 듣는 것은 (어떻게 작성되지 않더라도) 반응에서 수행되는 작업과 수행 할 작업 및 사용자가 수행 할 수있는 작업 중 하나입니다. 또한 systemd-lock-handler의 기능과 위치에 대한 정보가 없습니다.
Pavel Šimerda

xss-lockAUR에 있으므로 수동으로 빌드 할 필요가 없습니다.
l0b0

이것은 데비안 테스트에서 아름답게 작동합니다. 게시 해 주셔서 감사합니다. systemd는 사용자 서비스가 시스템 서비스에 의존하는 것을 허용하지 않는다는 것이 매우 실망 스럽다 ...
cgogolin

-1

systemd-lock-handlerhttps://github.com/grawity/code/blob/master/desktop/systemd-lock-handler를 수행 할 수있는 Python 스크립트입니다 .

#!/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()
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.