help-guix
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Trying to add elogind sleep/shutdown hook support


From: 45mg.writes
Subject: Trying to add elogind sleep/shutdown hook support
Date: Wed, 11 Dec 2024 15:31:54 -0500

Hi Guix,

So I've been trying to patch `elogind-service-type` in order to add
support for the `system-sleep` and `system-shutdown` hook directories
[1]. This would give users a way to run scripts before/after
suspend/hibernate, a feature that is currently missing in Guix [2]. I've
run into a strange unbound-variable error that I'm not able to
troubleshoot further, and I would really appreciate any guidance.

The requirements are simple - put script files in
/etc/elogind/system-sleep/ or /etc/elogind/system-shutdown/ directories,
and they will be run pre/post suspend/hibernate/poweroff/whatever, with
arguments indicating what is happening.

I'm trying to do this by adding corresponding fields to
`elogind-configuration`
each taking a list of local (script) files, and then having
`elogind-service` extend `activation-service-type`. `elogind-activation`
then takes care of installing the files into the hook directories.
Here's a patch showing what I have so far:

diff --git a/gnu/services/desktop.scm b/gnu/services/desktop.scm
index 274aeeef9b..1237d53b6f 100644
--- a/gnu/services/desktop.scm
+++ b/gnu/services/desktop.scm
@@ -1084,7 +1084,10 @@ (define-record-type* <elogind-configuration>
elogind-configuration
   (hibernate-delay-seconds          elogind-hibernate-delay-seconds
                                     (default *unspecified*))
   (suspend-estimation-seconds       elogind-suspend-estimation-seconds
-                                    (default *unspecified*)))
+                                    (default *unspecified*))
+  (system-sleep-hook-files elogind-system-sleep-hook-files (default '()))
+  (system-shutdown-hook-files elogind-system-shutdown-hook-files (default
'())))
+; TODO  AllowPowerOffInterrupts, AllowSuspendInterrupts,
BroadcastPowerOffInterrupts, BroadcastSuspendInterrupts

 (define (elogind-configuration-file config)
   (define (yesno x)
@@ -1174,6 +1177,19 @@ (define (elogind-configuration-file config)
    ("HibernateDelaySec" (maybe-non-negative-integer
elogind-hibernate-delay-seconds))
    ("SuspendEstimationSec" (maybe-non-negative-integer
elogind-suspend-estimation-seconds))))

+(define (elogind-activation config)
+  "Return the activation GEXP for CONFIG."
+  (with-imported-modules (source-module-closure '((guix build utils) (srfi
srfi-26)))
+    #~(let ((sleep-dir "/etc/elogind/system-sleep")
+            (shutdown-dir "/etc/elogind/system-shutdown"))
+        (use-modules (guix build utils) (srfi srfi-26))
+        (for-each
+         (cut install-file <> sleep-dir)
+         '#$(elogind-system-sleep-hook-files config))
+        (for-each
+         (cut install-file <> shutdown-dir)
+         '#$(elogind-system-shutdown-hook-files config)))))
+
 (define (elogind-dbus-service config)
   "Return a @file{org.freedesktop.login1.service} file that tells D-Bus
how to
 \"start\" elogind.  In practice though, our elogind is started when
booting by
@@ -1294,6 +1310,10 @@ (define elogind-service-type
                        (service-extension pam-root-service-type
                                           pam-extension-procedure)

+                       ;; Install sleep/shutdown hook files.
+                       (service-extension activation-service-type
+                                          elogind-activation)
+
                        ;; We need /run/user, /run/systemd, etc.
                        (service-extension file-system-service-type
                                           (const %elogind-file-systems))))



And here is a test configuration file I'm running it with (a
stripped-down version of my own system config):

(use-modules (gnu))
(use-service-modules cups desktop networking ssh xorg)

(operating-system
  (locale "en_US.utf8")
  (timezone "America/New_York")
  (keyboard-layout (keyboard-layout "us"))
  (host-name "guixy")

  ;; The list of user accounts ('root' is implicit).
  (users (cons* (user-account
                  (name "me")
                  (comment "Me")
                  (group "users")
                  (home-directory "/home/me")
                  (supplementary-groups '("wheel" "netdev" "audio"
"video")))
                %base-user-accounts))

  (packages %base-packages)

  (services
         (append
          (list
           (service elogind-service-type
                    (elogind-configuration
                     (system-sleep-hook-files (list (local-file
"./test-sleep-script"))))
                    ))
        %base-services))

  (bootloader (bootloader-configuration
                (bootloader grub-bootloader)
                (targets (list "/dev/sda"))
                (keyboard-layout keyboard-layout)))
  (swap-devices (list (swap-space
                        (target (uuid
                                 "f04306ed-0fcb-44ab-b3fd-1921e03f8654")))))

  (file-systems (cons* (file-system
                         (mount-point "/")
                         (device (uuid
                                  "ddcfb0e2-7e45-4c44-86ce-ac81dd3e53ab"
                                  'btrfs))
                         (type "btrfs")) %base-file-systems)))



`test-sleep-script` is an executable in the same directory just
containing
#!/bin/sh
echo "$@" >> /home/me/elogind-test-log


I'm testing this by running the following in my Guix checkout (after
`guix shell -D guix --pure -- ./bootstrap`, and similarly for
`./configure --localstatedir=/var` and `make`):

sudo $(./pre-inst-env guix system container path/to/test-config.scm)


This is the output I see:

system container is running as PID 12670
WARNING: (guile-user): imported module (guix build utils) overrides core
binding `delete'
Run 'sudo guix container exec 12670 /run/current-system/profile/bin/bash
--login'
or run 'sudo nsenter -a -t 12670' to get a shell into it.

WARNING: (guile-user): imported module (guix build utils) overrides core
binding `delete'
making '/gnu/store/2jwl0mc296r71yf03q9ic75zmc39y3ni-system' the current
system...
populating /etc from /gnu/store/y89n82vyqlzcsn08bj34rgjjixkkfhla-etc...
WARNING: (guile-user): imported module (guix build utils) overrides core
binding `delete'
WARNING: (guile-user): imported module (guix build utils) overrides core
binding `delete'
setting up privileged programs in '/run/privileged/bin'...
WARNING: (guile-user): imported module (guix build utils) overrides core
binding `delete'
Please wait while gathering entropy to generate the key pair;
this may take time...
WARNING: (guile-user): imported module (guix build utils) overrides core
binding `delete'
Backtrace:
          13 (primitive-load "/gnu/store/9v4y45fcazxp8czkabawfqyc2bx…")
In gnu/build/linux-container.scm:
    300:8 12 (call-with-temporary-directory #<procedure 7f46a4c38d20…>)
   397:16 11 (_ "/tmp/guix-directory.RDCnGc")
     62:6 10 (call-with-clean-exit #<procedure 7f46a4c43100 at gnu/b…>)
In unknown file:
           9 (primitive-load "/gnu/store/2jwl0mc296r71yf03q9ic75zmc3…")
In ice-9/eval.scm:
    619:8  8 (_ #f)
In unknown file:
           7 (primitive-load "/gnu/store/yz4fklxd6qpcsv4x54m6a1dk4ck…")
In srfi/srfi-1.scm:
    634:9  6 (for-each #<procedure primitive-load (_)> _)
In unknown file:
           5 (primitive-load "/gnu/store/z8yvff5ni8w91ms4glmwhyczpsk…")
In ice-9/eval.scm:
    619:8  4 (_ #(#<directory (guile-user) 7f46a7f16c80> "/etc/el…" …))
    159:9  3 (_ #(#<directory (guile-user) 7f46a7f16c80> "/etc/el…" …))
    163:9  2 (_ #(#<directory (guile-user) 7f46a7f16c80> "/etc/el…" …))
   223:20  1 (proc #(#<directory (guile-user) 7f46a7f16c80> "/etc…" …))
In unknown file:
           0 (%resolve-variable (7 . <>) #<directory (guile-user) 7f…>)

ERROR: In procedure %resolve-variable:
Unbound variable: <>


Any ideas on where to go from here would be most appreciated.


[1]
https://manpages.debian.org/unstable/elogind/loginctl.1.en.html#Hook_directories
[2]
https://www.reddit.com/r/GUIX/comments/s3ab3f/running_scripts_commands_on_suspend_resume/?rdt=46057


reply via email to

[Prev in Thread] Current Thread [Next in Thread]