Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 17 Jan 2016 02:23:02 +0000
From:      Jonathan de Boyne Pollard <J.deBoynePollard-newsgroups@NTLWorld.com>
To:        debian-devel@lists.debian.org
Cc:        FreeBSD Hackers <freebsd-hackers@freebsd.org>
Subject:   Re: Removing sysV init files
Message-ID:  <569AFB06.8070201@NTLWorld.com>
In-Reply-To: <5698EBCD.6050603@gmail.com>
References:  <5698EBCD.6050603@gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
Michael Biebl:

> I wonder if nosh could be an option for non-linux. According to its 
> website it supports native systemd service files. I have to admit 
> though, I never looked at nosh myself, so I have no idea how far that 
> "systemd support" goes.

This caught my eye, so I thought that I'd demonstrate.  Before getting 
to what I did, let's clear up some tangential points.

Alec Leamas:

> The systemd setup [for lirc] is three different services, the sysV 
> [setup] one. There is no systemd service directly corresponding to the 
> sysV one.

The Debian revision log says that that's not in fact true.

    http://anonscm.debian.org/viewvc/pkg-lirc?view=revision&revision=521

There have been three System 5 rc scripts since May 2014; precisely so 
that there *is* a correspondence between service names, according to the 
commentary.

 From a Debian point of view, I suspect that the answer that you'll get 
from all of the Debian people who actually look into the situation is 
that if Debian Maintainer Stefan Lippers-Hollmann is willing to continue 
doing this work to maintain System 5 rc scripts for your software, you 
should let xem.  (-:

I suggest that you should probably pay more attention to the System 5 rc 
scripts, because your systemd units aren't up to scratch and don't do as 
good a job.  I discovered this by running your |lircd.socket| and 
|lircd.service| unit files through the nosh conversion process and 
seeing what resulted.  Your "bad gut feeling" about your System 5 rc 
files is, ironically, misplaced and should be about your systemd mechanisms.

Yes the nosh package can take this sort of thing and convert it to 
native form.  There's a detailed worked example of doing so on the nosh 
WWW pages.

    http://homepage.ntlworld.com./jonathan.deboynepollard/Softwares/nosh/worked-example.html

For lirc it was almost as easy as:

    JdeBP /tmp $ fetch 'http://sourceforge.net/p/lirc/git/ci/master/tree/systemd/lircd.socket?format=raw' -o lircd.socket
    JdeBP /tmp $ fetch 'http://sourceforge.net/p/lirc/git/ci/master/tree/systemd/lircd.service?format=raw' -o lircd.service
    JdeBP /tmp $ convert-systemd-units ./lircd.socket
    JdeBP /tmp $ sudo system-control start /tmp/lircd

What resulted was a service that didn't start.  Hence "almost".

    JdeBP /tmp $ svstat /tmp/lircd
    /tmp/lircd: stopped since 2016-01-16 23:06:12 +0000; 2m 1s ago. , initially started
    JdeBP /tmp $

It didn't start because the service unit was wrong.

A quick check of the log revealed that the service was trying to create 
a local-domain socket at |/run/lirc/lircd| . But there was no 
|/run/lirc/| directory on my system to contain that.  Your systemd units 
didn't make one; and one doesn't appear by telepathy.  (-:  Stefan 
Lippers-Hollmann's System 5 rc scripts *do* make this directory, 
however.  They have this near the start:

    [ -d "/run/lirc" ] || mkdir -p "/run/lirc"

The systemd service unit file way of doing the same thing is:

    [Service]
    RuntimeDirectory=lirc

So I edited that into your |lircd.service| and had another go.  This 
time I was hit by a problem with "quirks mode" conversion (which I don't 
use all that often).  Since your |lircd| program doesn't actually rely 
upon any systemd quirks as far as I can see, I simply switched to "ideal 
mode" conversion and converted a third time:

    JdeBP /tmp $ convert-systemd-units --no-systemd-quirks ./lircd.socket
    JdeBP /tmp $ sudo system-control start /tmp/lircd

Now I was hit by the fact that you'd hardwired the pathname 
|/usr/sbin/lircd| into your service unit.  This isn't wrong from a Linux 
systemd operating system perspective.  But I'm doing this on FreeBSD 
(PC-BSD 10.2, in fact) to demonstrate that the nosh toolset very much 
does provide the tools for non-Linux operating systems.  The 
FreeBSD-supplied lircd installs into |/usr/local/sbin |not |/usr/sbin|, 
because that's the rule for non-operating-system stuff.  Fortunately, 
there are at least two ways around this.  I took the one that uses 
|$PATH|. The conversion tool can be told |ExecStart=lircd| and that will 
make a service bundle that will just work for either |/usr/sbin/lircd| 
or |/usr/local/sbin/lircd| .  So I edited that into your |lircd.service| 
and had another go.

    JdeBP /tmp $ convert-systemd-units --no-systemd-quirks ./lircd.socket
    JdeBP /tmp $ sudo system-control start /tmp/lircd

And it's up and running, converted from your socket and service units 
into native service bundles, on nosh-managed PC-BSD 10.2.

    JdeBP /tmp $ svstat /tmp/lircd
    /tmp/lircd: running (pid 50174) since 2016-01-16 23:39:56 +0000; 6s ago.
    JdeBP /tmp $

There are several things that you probably should take note of here.

The converted service bundle uses UCSPI-TCP tools from the toolset to 
set up the listening socket for lircd to inherit. Unfortunately, even 
though this is lirc version 0.9.0, built straight from the FreeBSD port 
today, it doesn't have the code that takes the socket as an already open 
file descriptor at program startup.  So process 50174 actually has two 
open file descriptors for the |/run/lirc/lircd| socket, one that was set 
up for it with UCSPI-TCP and one that it opened itself because the 
FreeBSD port doesn't actually contain any |HAVE_SYSTEMD| code.

Your |HAVE_SYSTEMD| approach isn't ideal, from your perspective of 
having lircd work on other operating systems like it does with systemd, 
anyway.  This is because it doesn't cope with non-Linux operating 
systems where you might still get the listening socket passed in, 
already open.  This is in turn because you are using the systemd 
developers' library.  Their library doesn't do anything on non-Linux 
operating systems.  I recommend instead looking to one of the many 
alternatives now available and floating around on the likes of GitHub.  
The alternatives don't conditionally compile out everything on non-Linux 
targets.

Both the System 5 rc scripts and the port-supplied NetBSD rc script (in 
|/usr/local/etc/rc.d/lircd|) are parameterized.  Your systemd unit files 
are not.  In particular, note that the NetBSD rc script has this:

    command_args="-d ${lircd_device} ${lircd_config}"

This means that FreeBSD/PC-BSD users can use their conventional 
|/etc/rc.conf.local| system to configure how the lircd daemon is 
invoked, by setting |lircd_device| and |lircd_config| variables.  (See 
the rc.conf(5) manual page for details of this system.)  There's even a 
handy |rcctl| tool in OpenBSD designed for working with these settings.  
This mechanism can be made to work with the nosh toolset.  I adjusted 
your |lircd.service| yet again to now read:

    EnvironmentDirectory=env
    ExecStart=lircd --nodaemon ${device:+-d "${device}"} ${config}

(To make this unit work with systemd too, note that you would have to 
explicitly state the invocation of the shell.)

Running that through the conversion tool yielded a slightly more complex 
service bundle:

    JdeBP /tmp $ convert-systemd-units --no-systemd-quirks ./lircd.socket
    JdeBP /tmp $ mkdir /tmp/lircd/service/env
    JdeBP /tmp $ cat /tmp/lircd/service/service
    #!/bin/nosh
    #Service file generated from ./lircd.service
    #LIRC Infrared Signal Decoder
    sh -c "exec lircd --nodaemon ${device:+-d \"${device}\"} ${config}"
    JdeBP /tmp $

This can be manipulated with the |rcctl| shim provided in the nosh toolset:

    JdeBP /tmp $ rcctl get /tmp/lircd
    JdeBP /tmp $ rcctl set /tmp/lircd device "/run/lirc/lirc0"
    JdeBP /tmp $ rcctl get /tmp/lircd
    device=/run/lirc/lirc0
    JdeBP /tmp $ sudo rcctl stop /tmp/lircd
    JdeBP /tmp $ sudo rcctl start /tmp/lircd
    JdeBP /tmp $ ps -o command -p 50260
    COMMAND
    lircd --nodaemon -d /run/lirc/lirc0
    JdeBP /tmp $

It's not necessary to use a full pathname such as |/tmp/lircd| .  That's 
only because I chose to operate in |/tmp| which isn't a place that is 
searched for service bundles.  I could have chosen instead to work in 
|/var/local/sv/|, in which case all of the commands above that have 
|/tmp/lircd| would have just read unadorned |lircd|.  As a bonus, this 
would have also enabled the system configuration autoconversion feature 
of the nosh toolset, which would have taken any |lircd_device| setting 
from |/etc/rc.conf{,.local}| and applied it to the |lircd| service as 
its |device| setting without my having to run |rcctl| manually.

All of this (apart from using the Debian equivalent of FreeBSD's |fetch| 
command) is pretty much exactly the same on Debian, when nosh-managed.  
I went through much the same steps.




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?569AFB06.8070201>