help-guix
[Top][All Lists]
Advanced

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

Re: Environment of a shepherd service


From: Jonathan McHugh
Subject: Re: Environment of a shepherd service
Date: Tue, 13 Apr 2021 22:47:58 +0200

Did you read this blog post?:
https://guix.gnu.org/en/blog/2020/gnu-shepherd-user-services/

====== START ========
The GNU Shepherd manual suggests putting all the services inside a monolithic 
init.scm file, located by default at $XDG_CONFIG_DIR/shepherd/init.scm. While 
this does make it easy to keep everything in one place, it does create one 
glaring issue: any changes to the file mean that all the services need to be 
stopped and restarted in order for any changes to take place.

Luckily there's a nice function called scandir hiding in ice-9 ftw which 
returns a list of all files in a specified directory (with options for 
narrowing down the list or sorting it). This means that our init.scm can 
contain a minimum of code and all actual services can be loaded from individual 
files.

First the minimal init.scm:

(use-modules (shepherd service)
             ((ice-9 ftw) #:select (scandir)))

;; Load all the files in the directory 'init.d' with a suffix '.scm'.
(for-each
  (lambda (file)
    (load (string-append "init.d/" file)))
  (scandir (string-append (dirname (current-filename)) "/init.d")
           (lambda (file)
             (string-suffix? ".scm" file))))

;; Send shepherd into the background
(action 'shepherd 'daemonize)

Let's take a sample service for running syncthing, as defined in 
$XDG_CONFIG_DIR/shepherd/init.d/syncthing.scm:

(define syncthing
  (make <service>
    #:provides '(syncthing)
    #:docstring "Run `syncthing' without calling the browser"
    #:start (make-forkexec-constructor
              '("syncthing" "-no-browser")
              #:log-file (string-append (getenv "HOME")
                                        "/log/syncthing.log"))
    #:stop (make-kill-destructor)
    #:respawn? #t))
(register-services syncthing)

(start syncthing)

As with any other shepherd service it is defined and registered, and in
this case it will start automatically. When the file is loaded by
shepherd after being discovered by scandir everything works exactly as
though the service definition were located directly inside the init.scm.

======== END =======


HTH


Edouard Klein <edou@rdklein.fr> writes:

> Hi,
>
> So I looked at the source and I understand that there's no way around
> having only PATH=/run/current-system/profile/bin as the sole environment
> of a service (which makes me wonder how anyone is running any service in
> GuixSD, don't you need any env variables ?).
>
> I tried to define a trivial package that would use wrap-program to
> create a script that would set the environment variables to all the
> search-paths of my requisomatic package, but I don't know how to access
> those !
>
> In the code that is executed by the daemon, all references to the
> package are lost, it is not in the same strata as the package.
>
> I can get the store path to the package but that does not help me.
>
> I really could use some guidance here.
>
> Cheers,
>
> Edouard.
> edk@beaver-labs.com writes:
>
>> Dear fellow Guixers,
>>
>> I'm trying to create an operating system declaration, so that I can run
>> a piece of software of mine in a container with =guix system container=.
>>
>> I wrote a package for the software. The package works: the tests pass
>> and when the package is installed I can run the software.
>>
>> I wrote a shepherd service for the software (it's called requisomatic).
>> I copied the relevant part at the end of the email.
>>
>> When I run the container script created by =guix system container=, and
>> get a shell in the container, I can run the software (I added the software's
>> package to the globally installed packages in the operating-system 
>> definition).
>>
>> But, when I try to run it with shepherd, it fails because it can't find
>> flask (a dependency of the software, which I've put as a
>> propagated-input, and is indeed installed in the container).
>>
>> I replaced the software invocation in the shepherd service with just
>> "env", and saw that the whole env in the service is:
>>
>> PATH=/run/current-system/profile/bin
>>
>> whereas in the shell I get when I connect to the container, the env
>> contains many other variables, including a correctly set PYTHONPATH,
>> which allows the finding of flask.
>>
>> So I now know why my software is not starting, but my question is:
>>
>> Why is the PYTHONPATH (and the other env vars, for that matter) not
>> propagated from the package to the shepherd service by default ? And how
>> can I make it so ? I would have expected the shepherd service to run
>> with the global profile active.
>>
>> Follow up question, can shepherd services be specified to run in a
>> specific profile ? So that I can have two services with incompatible
>> dependencies running at the same time in the same operating-system ?
>>
>> Thanks in advance,
>>
>> Cheers,
>>
>> Edouard.
>>
>>
>>
>> -----extract from my operating-system declaration file-------
>> (define requisomatic-shepherd-service
>>   (match-lambda
>>     (($ <requisomatic-configuration> user group db-file)
>>      (list (shepherd-service
>>             (provision '(requisomatic))
>>             (requirement '(user-processes networking))
>>             (documentation "Run the requisomatic server")
>>             (start #~((make-forkexec-constructor
>>                     ;;   (append
>>                     ;;    (if db-file
>>                     ;;      `("env"
>>                     ;;        ,(string-append "REQUISOMATIC_DB_FILE=" 
>> db-file))
>>                     ;;      '())
>>                                         '("gunicorn" "requisomatic:app")
>>                    ;;   '("env")
>>                        ;;)
>>                        #:directory (string-append #$requisomatic 
>> "/bin/requisomatic/")
>>                        #:log-file "/var/log/requisomatic.log")))
>>             (stop #~(make-kill-destructor)))))))


-- 
Jonathan McHugh
indieterminacy@libre.brussels



reply via email to

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