6 comments

[ 6.7 ms ] story [ 19.1 ms ] thread
Mmh, binary configuration blobs. No, thanks.
Text configuration in individual small files, described at length in the doco, merely compiled into a database for runtime use; just like /etc/pwd.db and /etc/spwd.db (compiled with pwd_mkdb from /etc/master.passwd) /usr/share/misc/termcap.db (compiled with cap_mkdb from /usr/share/misc/termcap) /usr/share/terminfo/?/* (compiled with tic) data.cdb (compiled with tinydns-data from data) nsd.db (compiled with zonec) /etc/postfix/virtual.db (compiled from /etc/postfix/virtual with postmap) and so on and so forth.
To add to that, I think the definitive reason for a persistent dependency graph would be enabling a deterministic boot order.
I'd have to check to see whether M. Bercot explained the design decision, but I wouldn't discount simple efficiency as a reason. Calculate things once, store the result, recalculate when the inputs change rather than again and again whenever one wants the result. It's the principle that has tinydns-data run via a makefile. It's the principle that has vipw run pwd_mkdb. It's a design principle that gave nosh

  cd /etc/system-control/convert/ && redo all
which is another system that takes files (/etc/fstab, /etc/passwd, /etc/ttys, /etc/rc.conf, and others) and builds a structure of services. The principle prompts the question "I know that my /var volume is /dev/label/var and it stays that way across reboots. Why should I regenerate the service for mounting it over and over, instead of only when /etc/fstab actually changes?".
passwd is accessed by multiple programs and fast lookups are a reason to implement binary formats. Same for termcap, timezones, etc (though I wouldn't call those configuration files...). Postfix might also need fast lookups and doesn't keep in-memory state.

For a service manager however these reasons do not apply. Having it use a binary configuration database makes no sense as there is only a single program accessing the configuration that doesn't need fast access to these. And no, I don't think claiming that it's just "compiled for runtime use" makes this much better[1]: it doesn't help with having the proprietary binary format and its source go out of sync, requires special tools to debug (rescue systems might not have s6-rc's compiler installed[2]) and so on.

  [1] That's like saying the Windows registry is just "compiled for runtime use" from *.reg files ;)
  [2] Yes, one might be able to use the compiler via a chroot, but why should I have to spend more effort?
As Jonathan said: the reason for the compilation phase is efficiency. The information in the compiled database is organized for fast loading and immediate access to the complete dependency tree.

And yes, efficiency is important. The point of s6-rc is to provide a dependency-based system manager with minimal overhead. Time a s6-rc run against an equivalent openrc run, and you will see a notable difference. strace both runs and you will understand why: OpenRC performs all its dependency analysis at run time, every time you run a script, and it has to read the whole database of scripts to do so. s6-rc performs the "read a zillion scripts, do the dependency analysis" part only once, and offline.

There are also other benefits: for instance, simple checking - when you write an invalid set of services, the error is detected at compile-time, not at run-time when it could prevent your machine from properly booting.

The database format is not proprietary. It's undocumented, which is not the same thing; and if people insist, I may document it. In the meantime, the code that reads it is in src/libs6rc/s6rc_db_read.c, a function that you can use in your own code, or that you can analyze to understand the format. It's not a complex one.

Going out of sync is not specific to s6-rc. It's a risk as soon as you compile something. It may happen with OpenRC too, if you forget to rc-update. It may happen with your binaries, if you forget to make install. "Things may go out of sync" is not an argument against compiled designs, it's an argument in favour of paying a little attention.