Iniscripts
Been trying out upstart today. It's a nice piece of code, but unfortunately it's totally useless today.
Not because its concepts suck; rather, because Debian packages today ship with SysV-style initscripts, and those do not integrate well with upstart: most of the features that make upstart so interesting require you to create an event.d script, which has a totally different syntax. The Debian Developer inside me couldn't help but start to think about a way to fix this, but that seems harder than what it initially would sound like to the uninitiated.
My first idea was to add some /sbin executable to upstart or one of its supporting packages, so that a SysV-style initscript could exit if that binary told it that upstart was running, before doing anything. That way, a package could ship both upstart event.d files and SysV-style initscripts during a migration period, and we could get rid of the SysV-style initscripts when and if Debian eventually decides to migrate to upstar.
But when I sent that past #debian-devel, someone mentioned initng, which is yet a different init implementation. If this would work for upstart, it could also work for initng, and I don't think many packages would want to ship initscripts for three different init implementations. So scratch that.
My next idea was to generate initscripts, rather than have packages ship them. The amount of common code in our initscripts is huge, anyway, and it's not as if it's all that hard to write an initscript. The things an initscript needs to do are limited, anyway: start a daemon when requested, stop it, restart it, perhaps send it a SIGHUP if or when configuration updates have been performed, and provide some useful output on all that. In most cases, that's about it. So, I thought, why not create an RFC822-style file (analogously to other files in the debian/ directory of a debian source package) containing all the metadata on an initscript, and generate the correct style of initscript out of that? That should work, I thought. So I started writing a specification, and had a look at the initscript of one of my own packages, nbd-server. Which does this at some point (nonrelevant content cut out):
i=0 while [ ! -z ${NBD_FILE[$i]} ] do start-stop-daemon --start --quiet --exec /bin/nbd-server (...) echo -n " ${NBD_FILE[$i]} ] i=$(( $i + 1 )) done
There's no way you'll be able to express that type of flexibility with an RFC822-style file containing all the metadata. So, scratch that too.
I still do think generating initscripts is the right thing to do, however; the question that remains is "how". One idea I had was to use m4 in an autoconf kind of way, since autoconf allows one to mix autoconf macros with "regular" shell snippets, which would be exactly the kind of flexibility that one would need. However, that totally ignores the fact that autoconf is only able to pull this off because its output is shellscript in every case. An m4 macro that has to produce output which are not, in fact, shellscripts (such as would be the case for this project) could not do that.
I think I'm kinda stuck now...
I was under the very clear impression that upstart was backwards compatible with SysV, and that this was actually the first part developed... then, Ubuntu was moved to upstart with no ill effect, and then the first scripts were rewritten...
From what I understand, upstart should work as well as before, and start to work better as soon as scripts are rewritten. I think it'd pay to look this up...? I mean, Ubuntu runs on it, and Ubuntu is basically Debian.
Or, I am missing something. Hope you succeed, though, it works really, really well in Ubuntu.
Hi Wouter,
You can use upstart-compat-sysv for sysvinit compatibility and then slowly migrate to upstart. Ubuntu is doing exactly this, although the mass migration will not start until after Ubuntu 7.04 is out. Currently only a few things use upstart natively.
Upstart in Debian is also rather out-of-date right now (afaik) because the most exciting and useful features have only just been written or are still being written (which is the reason that almost nobody uses it atm).
Hi Dennis,
you will be delighted to hear, that upstart in Debian is basically the same as the version in Ubuntu (you have to grab it from experimental though to get the latest revision. This is because it conflicts with sysvinit which is essential and the RMs didn't want to change that before etch is released).
So, the basic plan I have for Debian is:
1.) Hope etch is released in the foreseeable future and sort out the sysvinit-being-essential problem. 2.) If that is solved upload upstart to unstable. 3.) Write native upstart jobs which initialize the system. This basically means to write replacements for the sysv initscripts of the "initscripts" package. upstart-compat-sysv won't depend on initscripts anymore but rather add a conflicts to make sure, the initscripts package is uninstalled. 4.) Now comes the hardest part: All the packages that currently ship a sysv initscript have to be upstartified. My plan is to write upstart jobs for each of these packages (at least for the most important ones) and send it to the individual package maintainers which should include them directly into their packages. The packages would still ship both, the upstart job file and the sysv initscript. To avoid that the service is started twice, through the native upstart job file and upstart-compat-sysv, I will provide diversions for update-rc.d/invoke-rc.d which won't create symlinks in /etc/rc?.d/ if upstart is installed. This way upstart-compat-sysv won't start the service.
This allows for a gradual transition to upstart and gives the user the ability to switch back to sysvinit in case that should be necessary.
It is not possible to automatically convert a sysv initscript to an upstart job file. The underlying concepts (event based vs. static) are just to different.
Hope this clears things a bit. If you have more questions, feel free to ask them on the debian-devel m-l.
Cheers, Michael
Well, I think that even the RFC-2822-styled config files could work. Basically the point is, that no matter how the init system decides what to start and stop when, it ends up calling a shell snippet for that task. So you can do:
Start-command: i=0 while [ ! -z ${NBD_FILE[$i]} ] do start-stop-daemon --start --quiet --exec /bin/nbd-server (...) echo -n " ${NBD_FILE[$i]} ] i=$(( $i + 1 )) done
(it would deviate from RFC-2822 in that in such folded header the line breaks would be significant)
So this way there could be one header field with shell snippet for each of the start/stop/restart/reload/force-reload (with appropriate defaulting).
There would also have to be fields for deciding whether it should run, testing whether it is running and for common initialization (eg. reading /etc/defaults/), which would be prepended to all the others.
The start snippet (and the check-running probably as well) should be able to set some variable or output somewhere the list of things (PIDs, files, listening ports, ...) whose change indicates the serivce failed and needs restart.
Plus there would be some fields for the dependencies (I suggest Provides in addition to Depends, so the full flexibility of upstart can be used), which would not be shell snippets.