On Tue, Mar 28, 2023 at 01:10:36AM +0200, Lorenzo wrote:

Hi,

> Please follow up and let me know if my idea would solve this issue or at 
> least improve the situation from your point of view:
> > 
> > Checking for /etc/sv/$name and skipping initscripts if those directories 
> > exist is wrong for two reasons:
> > 
> >  1. /etc/sv/$name may not be symlinked into /etc/service (false positive);
> > 
> >  2. /etc/service may contain a symlink to a service directory for this 
> > service that is elsewhere in the filesystem, not in /etc/sv (false 
> > negative).
> > 
> > As a minimum, I suggest the following: instead of /etc/sv/$name, check for 
> > /etc/service/$name (and $name-daemon if necessary), and not with "-d" but 
> > "-L" (because when running rcS.d, the target of the symlink may only appear 
> > later, for example when a new filesystem is mounted).
> 
> I propose the following:
> 
> * patch runit-helper, update-service and /lib/runit/trigger_sv so that every 
> (package provided) runit service is always represented in /etc/service/, 
> either with a foo symlink (enabled) or with a .foo symlink (disabled).

OK, this works (although I don't see why it's necessary), as long as nothing 
gets confused by the existence of both symlinks. For example, under this 
scheme, I may have:

/service/ssh -> /some/dir/where/I/keep/my/services/ssh  # created "manually"
/service/.ssh -> /etc/sv/ssh                            # created during 
container provisioning to prevent the ssh package from installing its version 
of the service (otherwise it creates /etc/service/ssh/ssh)

If there is potential for confusion, then a mechanism to delete the .ssh 
symlink if/when the plain ssh symlink is present would also be needed.

>   This way I (as a packager) can test /etc/service/ to know if a runscript 
> exists in /etc/sv/.

You can, but I'm not sure I see why you have to. The /etc/sv location is not 
special per se; why does it matter whether there is anything there in 
particular?

>   For users that have their own runscripts collection somewhere in the 
> filesystem: they will enable their services by creating the foo symlink, and 
> they can have the sysv emulation skip certain services (let's say a bar 
> service) by creating a /etc/service/.bar symlink.

That's a needless extra hoop to jump through. When deciding whether to skip 
invoking /etc/init.d/bar, why is it better to check for the existence of 
"/etc/service/.bar" than "/etc/service/bar"? The latter needs to exist anyway, 
because that's what will cause runit to start the service.

>   This would also prevent runit package (and runit-helper) to enable the bar 
> service, if any /etc/sv/bar exists, because the logic in runit-helper and 
> sv_trigger only test if the symlink (or dot-symlink) exists, but it doesn't 
> care where it points.

Again, to me it seems that the existence of /etc/service/bar should be 
sufficient. If it exists, the service is enabled. If it needs to be disabled in 
a way that it can be re-enabled later, you can rename the existing bar symlink 
to ".bar", regardless of where it points.

>   In any case runit/runit-helper only creates and remove links in the 
> /etc/runit/runsvdir/default directory, so if you point runsvdir to another 
> directory runit package doesn't enable or disable anything for you.

Perhaps it should be called debian-default; but it's good to know that using a 
differently-named runsvdir is a way of opting out of much of the 
nanny-automation I find so annoying. :)

> * turn the run_sysv_scripts into a runit service that test for 
> /etc/service/$name. Two main reason for this:

This needs to be thought through carefully (it would need to only run once, but 
finish before other services are started -- for example, it could do a 
runsvchdir in ./finish).

>   1. users can disable it, or change it at their will, while any change into 
> /lib/runit/run_sysv_scripts is overwritten by the package, so users are 
> forced to change stage 2 and create their own version of the script

You could also achieve this by preferring /etc/runit/lib/run_sysv_scripts if it 
is executable, and only running /lib/runit/run_sysv_scripts if not. Even more 
complex setups would also be possible, with /lib/runit/run_sysv_scripts relying 
on shell functions that a user-supplied sourced file could override, but I 
think that would go too far.

>   2. when runit services are mixed with sysv scripts in the start sequence, 
> the run_sysv_scripts can be RC-buggy, see #1024969 [1] for an example

Yeah, that's a hard problem to solve cleanly.

Maybe you just shouldn't ship (or enable by default) runit services that 
initscript-based stuff frequently depends on. I'm not sure how much else there 
is, other than dbus.

Alternatively, you could ship a one-shot runit service that depends on the dbus 
service and that invokes all initscripts that declare a dependency on dbus... 
Far from my idea of clean.

I also have another idea but it's so complex that I won't even write it down. :)

I'd be perfectly fine with manual setup being required to run dbus from runit. 
The <15 users worldwide who want to do so can do it.

> > This is still imperfect during boot because /etc/service may point to some 
> > directory that is not the one we'll switch to with runsvdir in stage 2. I 
> > don't know what the best way of handling this (likely rare) case is, but 
> > the following solutions come to mind:
> 
> I think with the above solution this should be no longer a problem as we run 
> the sysv emulation from within runsvdir.
>
> Hopefully this will make your "runit" life easier (?)

I'm not sure the added complexity is worth it.

One alternative would be to just have people who actively use runsvchdir 
provide their own solution to avoid starting initscripts that don't need to be 
started (giving them some hooks to make this easier).

I suspect that for most users, the "/etc/runit/runsvdir/current" symlink never 
changes, and thus relying on seeing whether /etc/service/foo exists before 
starting /etc/init.d/foo is sufficient. People who want more complexity should 
have the option to implement it, but I don't think it's necessary to push 
complexity on everyone.

Whatever you do is just going to be an imperfect heuristic anyway; for example, 
maybe the user has /etc/service/apache2-{foo,bar,baz} and doesn't want 
/etc/init.d/apache2 started. Such cases will need manual configuration, and we 
should accept that.

AndrĂ¡s

-- 
     True love is okay but a series of false loves gives you more variety.

Reply via email to