I was the maintainer of minit for some time, and spent some time adding some runit-like functionality to minit I then called “enitdir”. It worked similar to runit (IIRC, maybe it was a different init).

Basically you had a directory for each runlevel, which contained symlinks to all services supposed to be running. There is a symlink called “current” or something pointing to the current runlevel. enitdir monitored this symlink and the directories contents via dnotify, so it supposedly was both very fast and efficient at noticing changes there.

Switching runlevels was as easy as “ln -snf current foobar”; starting and stopping services worked by removing the symlinks in the current runlevel or manually calling minit (for non-persistent changes, restarts, etc.)

(I think I never uploaded a package with any of this, the minit packages remained really close to upstream. I intended to do a fork/rewrite named enit, but never got around to it. Many of my ideas are addressed by upstart.)

However this didn’t solve some integration issues.

First of all, not all packages back then were using invoke-rc.d; this should be a lot better nowadays.

But the major issues lie within handling multiple inits on one system.

There is a hook that applications could use to prevent init scripts from running (which might be the answer to Wouters iniscripts post). It’s called “policy-rc.d”.

However there are some things wrong with this approach: it doesn’t really support the installation of multiple inits or handles the problems of switching between inits in any way.

Basically, the moment we need to switch inits (and thus service startup/stopping behaviour!) is during reboot. While the old init is still running, any start/stop operations MUST still use the method appropriate for the current init system. Otherwise, major bugs can occur, especially with smarter init systems that respawn services.

E.g. the user runs “apt-get install sysvinit mysql-server”. Lets assume sysvinit has a debconf prompt ‘make me the default init’ and the user says yes. Next mysql-server is upgraded, during which it calls the sysvinit way of stopping the service (i.e. /etc/init.d/mysql-sever stop), then does some dangerous things to the database, then restarts the server. However, a smart init such as minit (when equipped with appropriate service files) will notice the mysql-server process dying and immediately restart it (notified by kernel, efficient and fast) while the upgrade script is still messing with the database files. Boom, there goes your database.

I guess you got the point.

So we probably need a smarter invoke-rc.d script. It should support

  • init detection - figure out which init is running, e.g. by comparing the inode of /proc/1/exe to the inode of /sbin/init.* (current init doesn’t need to be named /sbin/init, but note that this magic might break on upgrades. Fallback to readlink(/proc/1/exe) maybe?)
  • different init behaviours. The current policy-rc.d hook is pretty much a yes/no hook. Instead it should call the appropriate init-specific invoke tool.

Such an invoke tool could then for example look like this:

if [ -e "/etc/enit/service/$1" ]; then
    enitctl start $1
else
    /etc/init.d/$1 start
fi

You get the idea, having the policy script figure handle compability for services that don’t have an appropriate service description for this init system yet. (Yes, s/start/$2/ or something, above is pretty dumb, but helps bringing my idea over).