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.