unofficial mirror of help-guix@gnu.org 
 help / color / mirror / Atom feed
* Staging Scheme code to run as one-shot service
@ 2024-03-02  6:28 Owen T. Heisler
  2024-03-04  8:18 ` pelzflorian (Florian Pelz)
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Owen T. Heisler @ 2024-03-02  6:28 UTC (permalink / raw)
  To: help-guix

service where the entire service functionality is in a procedure. =====
Hi! I am trying to declare a simple one-shot operating-system service
where the entire service functionality is in a procedure. Following is
a minimal reproducible example. The error is `In procedure fport_write:
Broken pipe` (see end of message). What is wrong here? I'm new to
Scheme and Guix, and it's not very clear to me yet how code staging and
g-expressions work, so it's probably something quite obvious. Thanks
for looking!

```scm
;; operating-system declaration
(use-modules (gnu)
              (gnu services shepherd)
              (ice-9 popen))
(use-service-modules networking)
(use-package-modules bootloaders)
(define (say-hello)
   #~(let ((port (open-pipe* OPEN_WRITE "logger" "-plocal0.alert")))
       (display "========say-hello========\n" port)
       (close-pipe port)))
(define say-hello-service
   (simple-service 'say-hello-service shepherd-root-service-type
                   (list (shepherd-service (auto-start? #f)
                                           (documentation "Say hello.")
                                           (one-shot? #t)
                                           (provision '(say-hello-service))
                                           (respawn? #f)
                                           (start #~(lambda ()
                                                      #$(say-hello)))))))
(operating-system
   (bootloader (bootloader-configuration
                 (bootloader grub-bootloader)
                 (targets '("/dev/vda"))
                 (terminal-inputs '(console serial))
                 (terminal-outputs '(console serial))
                 (timeout 1)))
   (file-systems (cons (file-system
                         (mount-point "/")
                         (device "/dev/vda1")
                         (type "ext4")) %base-file-systems))
   (host-name "test-guix-vm")
   (kernel-arguments (cons "console=ttyS0" %default-kernel-arguments))
   (services
    (append (list say-hello-service) %base-services)))
```

```sh
# Build system image and run with qemu
cp $(guix system image --image-type=qcow2 in.scm) image.qcow2
chmod u+w image.qcow2
qemu-system-x86_64 -enable-kvm -m 2048 -device virtio-blk,drive=myhd \
     -nographic -drive if=none,file=image.qcow2,id=myhd
```

```console
## Log in as root and attempt to start service
# herd start say-hello-service
Starting service say-hello-service...
Service say-hello-service failed to start.
herd: error: exception caught while executing 'start' on service 'say-hello-service':
In procedure fport_write: Broken pipe
```


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Staging Scheme code to run as one-shot service
  2024-03-02  6:28 Staging Scheme code to run as one-shot service Owen T. Heisler
@ 2024-03-04  8:18 ` pelzflorian (Florian Pelz)
  2024-03-04  8:31 ` pelzflorian (Florian Pelz)
  2024-03-04 16:08 ` Felix Lechner via
  2 siblings, 0 replies; 8+ messages in thread
From: pelzflorian (Florian Pelz) @ 2024-03-04  8:18 UTC (permalink / raw)
  To: Owen T. Heisler; +Cc: help-guix

Hi Owen.

"Owen T. Heisler" <writer@owenh.net> writes:
> (shepherd-service (auto-start? #f)
>                   (documentation "Say hello.")
>                   (one-shot? #t)
>                   (provision '(say-hello-service))
>                   (respawn? #f)
>                   (start #~(lambda ()
>                              #$(say-hello)))))))

According to

info "(shepherd)Service De- and Constructors"

the procedure in the start field normally forks, like with
make-forkexec-constructor.  Maybe this is a way forward?

Regards,
Florian




^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Staging Scheme code to run as one-shot service
  2024-03-02  6:28 Staging Scheme code to run as one-shot service Owen T. Heisler
  2024-03-04  8:18 ` pelzflorian (Florian Pelz)
@ 2024-03-04  8:31 ` pelzflorian (Florian Pelz)
  2024-03-05  4:01   ` Owen T. Heisler
  2024-03-04 16:08 ` Felix Lechner via
  2 siblings, 1 reply; 8+ messages in thread
From: pelzflorian (Florian Pelz) @ 2024-03-04  8:31 UTC (permalink / raw)
  To: Owen T. Heisler; +Cc: help-guix

P.S. There also is the code for

https://issues.guix.gnu.org/62584#0

which is not using a Shepherd service.

Regards,
Florian


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Staging Scheme code to run as one-shot service
  2024-03-02  6:28 Staging Scheme code to run as one-shot service Owen T. Heisler
  2024-03-04  8:18 ` pelzflorian (Florian Pelz)
  2024-03-04  8:31 ` pelzflorian (Florian Pelz)
@ 2024-03-04 16:08 ` Felix Lechner via
  2024-03-05  3:07   ` Owen T. Heisler
  2 siblings, 1 reply; 8+ messages in thread
From: Felix Lechner via @ 2024-03-04 16:08 UTC (permalink / raw)
  To: Owen T. Heisler, help-guix

Hi Owen,

On Sat, Mar 02 2024, Owen T. Heisler wrote:

>    (start #~(lambda ()
>               #$(say-hello)))

My code works when I place it directly into the 'start' G-exp. [1]

By comparison, I think you have two lambdas (with quoting and
unquoting). I would try something like this:

    (start #~(let ((port (open-pipe* OPEN_WRITE "logger" "-plocal0.alert")))
               (display "========say-hello========\n" port)
               (close-pipe port)))

Kind regards
Felix

[1] https://codeberg.org/lechner/juix/src/commit/fe8cac5165bfbe290413cedd36a492109e29e38b/juix/deploy/cachefilesd.scm#L158


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Staging Scheme code to run as one-shot service
  2024-03-04 16:08 ` Felix Lechner via
@ 2024-03-05  3:07   ` Owen T. Heisler
  2024-03-06  1:32     ` Owen T. Heisler
  0 siblings, 1 reply; 8+ messages in thread
From: Owen T. Heisler @ 2024-03-05  3:07 UTC (permalink / raw)
  To: Felix Lechner, help-guix

Hi Felix,

On 3/4/24 10:08, Felix Lechner wrote:
> On Sat, Mar 02 2024, Owen T. Heisler wrote:
> 
>>     (start #~(lambda ()
>>                #$(say-hello)))
> 
> My code works when I place it directly into the 'start' G-exp. [1]
> 
> By comparison, I think you have two lambdas (with quoting and
> unquoting). I would try something like this:
> 
>      (start #~(let ((port (open-pipe* OPEN_WRITE "logger" "-plocal0.alert")))
>                 (display "========say-hello========\n" port)
>                 (close-pipe port)))

> [1] https://codeberg.org/lechner/juix/src/commit/fe8cac5165bfbe290413cedd36a492109e29e38b/juix/deploy/cachefilesd.scm#L158

Thanks for the suggestion. I tried that, but it doesn't work either. 
Instead I now get this error during boot before the login prompt (note, 
auto-start is false):

/run/current-system/profile/bin/logger: cannot connect: No such file or 
directory

It appears to me that the code isn't adequately staged. I assume the 
code in #~(begin) is being executed (rather than staged) when Shepherd 
starts. That's why I added the other lambda. (Perhaps the linked service 
declaration your link [1] above would create the cache directory even if 
auto-start was set to false; that's just a guess though.)

This is what I tried:

```scm
;; Run with `$(guix system vm input.scm --no-graphic)`
(use-modules (gnu)
              (gnu services shepherd)
              (ice-9 popen))
(use-service-modules networking)
(use-package-modules bootloaders)
(define say-hello-service
   (simple-service 'say-hello-service shepherd-root-service-type
                   (list (shepherd-service (auto-start? #f)
                                         (documentation "Say hello.")
                                         (one-shot? #t)
                                         (provision '(say-hello-service))
                                         (respawn? #f)
                                         (start
                #~(begin
                    (let ((port (open-pipe*
                                 OPEN_WRITE
                                 "/run/current-system/profile/bin/logger"
                                 "-plocal0.alert")))
                      (display "========say-hello========\n" port)
                      (close-pipe port))))))))
(operating-system
   (bootloader (bootloader-configuration
                 (bootloader grub-bootloader)
                 (targets '("/dev/vda"))
                 (terminal-inputs '(console serial))
                 (terminal-outputs '(console serial))
                 (timeout 1)))
   (file-systems (cons (file-system
                         (mount-point "/")
                         (device "/dev/vda1")
                         (type "ext4")) %base-file-systems))
   (host-name "test-guix-vm")
   (kernel-arguments (cons "console=ttyS0" %default-kernel-arguments))
   (services
    (append (list say-hello-service) %base-services)))
```

Thanks,
Owen


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Staging Scheme code to run as one-shot service
  2024-03-04  8:31 ` pelzflorian (Florian Pelz)
@ 2024-03-05  4:01   ` Owen T. Heisler
  0 siblings, 0 replies; 8+ messages in thread
From: Owen T. Heisler @ 2024-03-05  4:01 UTC (permalink / raw)
  To: pelzflorian (Florian Pelz); +Cc: help-guix

Hi Florian,

On 3/4/24 02:31, pelzflorian (Florian Pelz) wrote:
> P.S. There also is the code for
> 
> https://issues.guix.gnu.org/62584#0
> 
> which is not using a Shepherd service.

At first I was confused by the link to an April-1 joke. :-) But that did 
work, thanks!

Here is a working example (I'm not sure why default-value is required):

```scm
;; $(guix system vm input.scm --no-graphic)
(use-modules (gnu bootloader)
              (gnu bootloader grub)
              (gnu services base)
              (gnu system file-systems)
              (guix gexp))
(define (say-hello-gexp _)
   #~(begin
       (display "====say-hello====\n"
                (current-error-port))))
(define say-hello-service-type
   (service-type (name 'say-hello)
                 (extensions (list (service-extension boot-service-type
                                                      say-hello-gexp)))
                 ;; without default-value, error:
                 ;; no value specified for service of type 'say-hello'
                 (default-value 0)
                 (description "Print say-hello during boot.")))
(operating-system
   (bootloader (bootloader-configuration
                 (bootloader grub-bootloader)
                 (targets '("/dev/vda"))
                 (terminal-inputs '(console serial))
                 (terminal-outputs '(console serial))
                 (timeout 1)))
   (file-systems (cons (file-system
                         (mount-point "/")
                         (device "/dev/vda1")
                         (type "ext4")) %base-file-systems))
   (host-name "test-guix-vm")
   (kernel-arguments (cons "console=ttyS0" %default-kernel-arguments))
   (services
    (append (list (service say-hello-service-type)) %base-services)))
```

Thanks,
Owen


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Staging Scheme code to run as one-shot service
  2024-03-05  3:07   ` Owen T. Heisler
@ 2024-03-06  1:32     ` Owen T. Heisler
  2024-03-07 18:31       ` Owen T. Heisler
  0 siblings, 1 reply; 8+ messages in thread
From: Owen T. Heisler @ 2024-03-06  1:32 UTC (permalink / raw)
  To: Felix Lechner, help-guix

On 3/4/24 21:07, Owen T. Heisler wrote:
> On 3/4/24 10:08, Felix Lechner wrote:
>> try something like this:
>>
>>      (start #~(let ((port (open-pipe* OPEN_WRITE "logger" 
>> "-plocal0.alert")))
>>                 (display "========say-hello========\n" port)
>>                 (close-pipe port)))
> 
>> [1] 
>> https://codeberg.org/lechner/juix/src/commit/fe8cac5165bfbe290413cedd36a492109e29e38b/juix/deploy/cachefilesd.scm#L158
> 
> Thanks for the suggestion. I tried that, but it doesn't work either.

Apparently I failed to follow your example properly and had an extra 
`#~(begin` in there. I have a minimal example now that does work, 
including with the G-expression defined separately.

As I wrote in another message, I also got a boot script 
(non-Shepherd) service working (with the help of a hint from Florian) 
but I need to use a regular Shepherd service so I can declare a 
dependency on another service (in this case, syslogd).

Here is the working example:

```scm
;; $(guix system vm input.scm --no-graphic)
(use-modules (gnu)
             (gnu services shepherd)
             (ice-9 popen))
(use-service-modules networking)
(use-package-modules admin bootloaders)
(define say-hello-gexp
  #~(begin
      (let ((port (open-pipe* OPEN_WRITE
                              #$(file-append inetutils "/bin/logger")
                              "-plocal0.alert"))
            ;; Use random string to counter syslog deduplication
            (rand_str (number->string (random 100))))
        (display (string-append "====say-hello" rand_str "====\n") port)
        (close-pipe port))))
(define say-hello-service
  (simple-service 'say-hello-service shepherd-root-service-type
                  (list (shepherd-service (auto-start? #t)
                                          (documentation "Say hello.")
                                          (one-shot? #t)
                                          (provision '(say-hello-service))
                                          (requirement '(syslogd))
                                          (respawn? #f)
                                          (start #~(lambda _
                                                     #$say-hello-gexp))))))
(operating-system
  (bootloader (bootloader-configuration
                (bootloader grub-bootloader)
                (targets '("/dev/vda"))
                (terminal-inputs '(console serial))
                (terminal-outputs '(console serial))
                (timeout 1)))
  (file-systems (cons (file-system
                        (mount-point "/")
                        (device "/dev/vda1")
                        (type "ext4")) %base-file-systems))
  (host-name "test-guix-vm")
  (kernel-arguments (cons "console=ttyS0" %default-kernel-arguments))
  (services
   (append (list say-hello-service) %base-services)))
;; # herd start say-hello-service
```

Thanks,
Owen


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Staging Scheme code to run as one-shot service
  2024-03-06  1:32     ` Owen T. Heisler
@ 2024-03-07 18:31       ` Owen T. Heisler
  0 siblings, 0 replies; 8+ messages in thread
From: Owen T. Heisler @ 2024-03-07 18:31 UTC (permalink / raw)
  To: Felix Lechner, help-guix

On 3/5/24 19:32, Owen T. Heisler wrote:
> I have a minimal example now that does work,
> including with the G-expression defined separately.

And thanks, Felix, for your help!

Owen


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2024-03-07 18:32 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-03-02  6:28 Staging Scheme code to run as one-shot service Owen T. Heisler
2024-03-04  8:18 ` pelzflorian (Florian Pelz)
2024-03-04  8:31 ` pelzflorian (Florian Pelz)
2024-03-05  4:01   ` Owen T. Heisler
2024-03-04 16:08 ` Felix Lechner via
2024-03-05  3:07   ` Owen T. Heisler
2024-03-06  1:32     ` Owen T. Heisler
2024-03-07 18:31       ` Owen T. Heisler

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).