[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

minimizing downtime of a daemon



One of the template NM questions is about "how to minimize the
downtime of a daemon during package upgrade (in maintainer scripts)".
ssh does an "/etc/init.d/ssh restart" in postinstall, which (with
luck) means that there will be *no* downtime.  This doesn't seem to be
necessary for allowing ssh upgrades, since running "/etc/init.d/ssh
stop" over an ssh connection doesn't disconnect existing ssh
connections, but only prevents establishing new connections until the
next "start".  This is different from how everybody else seems to do
it, but does accomplish the goal.

But, Debian doesn't seem to do actively persue this goal.  Of course,
apt-get install <daemon-package> should always work, and really
minimize the downtime, but doesn't solve the general problem for the
dist-upgrade case, or for apt-get install <many-packages>, where it
would be a small pain to have to figure out which packages are running
daemons.

The service isn't actually guaranteed to work during the upgrade
anyway, even if it isn't stopped, due to the potential for
inconsistencies between files on disk (eg. changed config file format,
reread at each connection by a daemon child process, or interrelated
files).

Packages using debhelper dh_installinit end up with an
"/etc/init.d/foo stop" in prerm and an "/etc/init.d/foo start" in
postinst .  During eg. a dist-upgrade, a maximal number of packages
are "dpkg --unpack"ed, and afterwards are "dpkg --configure"d.  This
decidedly does *not* minimize daemon downtime, since it allows an
arbitrarily large number of packages to be unpacked and configured
before the daemon is restarted.

debhelper intends to do what's needed with a simple interface.  If it
was acceptable to require more package-specific information, it would
be possible to only stop the service if it wasn't provided by the new
version of the package.  (Since binary packages with multiple daemons
are uncommon, it is more realistic to think of the same scenario with
info documents, which also get registered in postinst, and
deregistered in prerm).  debhelper would then need an interface to
specify that a daemon was included in certain previous versions of the
package, and removed at some critical versions.  Or, versions in which
a daemon is removed (and versions between that version and the next
stable release) could be required to have custom, not-generated
maintscripts.  This is an uncommon problem for daemons, but removal of
info documents is much more frequent, and presents the same trouble.

The implementation would involve the following in preinst (*not*
prerm, since it may not be known in advance that those files/daemons
would be removed):

ver_removed=1.2-3
( [ "$1" = "install" ] || [ "$1" = "upgrade" ] ) &&
        dpkg --compare-versions "$2" lt $ver_removed &&
        deregister_info && stop_server && ...
# postrm abort-[install|upgrade] should re-register them, and restart
# the server.

With this code, the info document and server will always be available
*during* upgrades of earlier versions, since dpkg uses an atomic
rename().  Upgrading to the critical version correctly stops the
server and deregisters the document *before* it is removed.

I'm particularly interested in this question since I'm writing a
document about dpkg, and, in particular, about use of maintainer
scripts.  I'm going through NM, and (so far) haven't been asked about
this.  If you don't want to spoil the fun for other NM's, you might
reply to me personally, or think of the same question phrased in terms
of info documents and dh_installdocs instead of daemon's and
dh_installinit.

Justin



Reply to: