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

Bug#727708: upstart and upgrading from sysvinit scripts



Resending this message, slightly edited, since Don pointed me in the right
direction to figure out the erroneous virus definition and work around it.

I've been continuing down the path of adding as complete of systemd and
upstart support as is feasible to one of my packages, and have started
working on upgrade scenarios from the existing package (which of course
has only an init script).

This has been a remarkably smooth process with systemd, far more than I
expected.  My compliments to the systemd maintainers and packagers.  All
the functionality that I needed was present, well-documented, and rather
intuitive.  The process with upstart has been a bit rockier.  Experiences
and some issues (also filed as bug reports) below.

This package has an existing /etc/default conffile which supports two
settings -- NO_START, which disables running the service, and DAEMON_OPTS,
which adds additional options to the executable command-line.  (Well,
right now it also contains a mandatory option, but since that option,
setting the PID file, is only required for the init script and not for
either systemd or upstart, I plan on adding it unconditionally in the init
script and documenting that it's no longer needed in a NEWS entry.)

NO_START was a bad idea and I regret ever adding it.  My intent is to fix
this during the upgrade by converting any existing setting into a proper
disabling of the init script.  So, in other words, in postinst:

    . /etc/default/lbcd
    if [ "$NO_START" = 1 ] ; then
        update-rc.d lbcd disable
    fi

(protected by a conditional to only happen on upgrades from the older
version).

With systemd, this does the right thing.  With upstart, this is ignored
entirely so far as I can tell (#733289).

Am I missing something?  I didn't actually reboot the test machine that
I'm working with to see if something somehow was reading the update-rc.d
status inside upstart, but Google turned up multiple people reporting the
same thing in Ubuntu: update-rc.d works for init scripts but not for
services converted to upstart.

I could work around this in the postinst with:

    . /etc/default/lbcd
    if [ "$NO_START" = 1 ] ; then
        update-rc.d lbcd disable
        echo manual > /etc/init/lbcd.override
    fi

but I'd need to add in more logic to be sure I'm not tromping on a user's
existing override file, and the user now has to track the fact that this
service is disabled in two different ways.  They can't just re-enable it
with update-rc.d lbcd enable, and behavior will not necessarily be
synchronized when they switch between init systems.

Given that I would like to be able to recommend this approach to anyone
who needs to get rid of the ill-advised /etc/default options to not start
services (something that doesn't work well with any of the new init
systems and was never a good idea in the first place), not having this
integration is frustrating.

The second supported option is DAEMON_OPTS, which sets additional flags to
add to the process.  For as long as we need to support multiple init
systems, this option needs to stay in /etc/default/lbcd and be read from
there by all supported init systems so that configuration is preserved as
the user moves between init systems.  With systemd, this is trivial.  Add
the following to lbcd.service:

    # Support for /etc/default/lbcd is here only for backward
    # compatibility with the lbcd init script shipped with Debian.  It and
    # the $DAEMON_OPTS reference can be dropped if this backward
    # compatibility is not needed.
    EnvironmentFile=-/etc/default/lbcd
    ExecStart=/usr/sbin/lbcd -f -l $DAEMON_OPTS

With upstart, it also turns out to be relatively simple, but the
documentation is not very good right now, and I had multiple dead ends.

First, I was using an exec line to run the daemon in my first draft of an
upstart script.  The documentation indicated that switching to a script
was the best way of handling this, so my first try was:

    expect stop
    script
        if [ -f /etc/default/lbcd ] ; then
            . /etc/default/lbcd
        fi
        /usr/sbin/lbcd -f -l -Z $DAEMON_OPTS
    end script

(well, my first try used

    [ -f /etc/default/lbcd ] && . /etc/default/lbcd

but upstart scripts use set -e, so this doesn't work, which is a standard
set -e pitfall that should probably be mentioned in the docs for the aid
of all the people who will be copying and pasting from init scripts).

Folks familiar with upstart probably already know that this fails.  The
last line needs an exec, or expect stop gets confused (#733287).  This is
obvious in retrospect.

After some more experimentation (the documentation doesn't say clearly
whether pre-start can expose environment variables to exec or not), it
looks like a better approach is:

    expect stop

    pre-start script
        test -x /usr/sbin/lbcd || { stop; exit 0; }
        if [ -f /etc/default/lbcd ] ; then 
            . /etc/default/lbcd
        fi
    end script

    # To change the default lbcd service, specify a command to run for the
    # weight and interval, or do round-robin (-R), set the desired flags
    # in DAEMON_OPTS in /etc/default/lbcd.
    exec /usr/sbin/lbcd -f -l -Z $DAEMON_OPTS

This seems to work and is what I will be uploading.

-- 
Russ Allbery (rra@debian.org)               <http://www.eyrie.org/~eagle/>


Reply to: