33

This is a general Upstart question, but let me use a specific case:

Centrify is a NIS to ActiveDirectory gateway. It needs to load before any service that will depend the authentication service that it provides, e.g. autofs, cron, nis, et al.

This has proven to be quite challenging to achieve, even when trying to change the dependencies of the other services (which I don't think we should be doing anyway, I don't want to touch the other Upstart jobs if at all possible).

Suggestions?

2 Answers 2

29

The solution is to approach the problem from the other direction: to satisfy the start criteria for Centrify, it is not necessary to make existing services depend on the new Centrify service, rather make the new Centrify service depend on existing services.

For example, an Upstart configuration file /etc/init/centrify.conf could say:

start on (starting cron or starting autofs or starting nis)

Converting this into English, this would translate as:

start the Centrify service just before either cron, autofs or nis start (whichever starts first).

The order in which cron, autofs or nis start is irrelevant: Upstart will ensure that Centrify will start before whichever service starts first, thus ensuring that Centrify is running before any one of those services start.

Note too that Upstart will block the start of the first service that wants to start until Centrify has started running.

Very elegant and simple once you get used to thinking in this manner.

7
  • 4
    this seems totally backwards to me. why should the conf script for one service be modified when other things depend on it?
    – ben w
    Commented Mar 12, 2013 at 21:42
  • 3
    @benw So that you don't have to modify the existing settings of services you don't own.
    – Paccc
    Commented Jul 31, 2013 at 16:22
  • 1
    @Paccc when I write a new script that depends on nginx, I have to modify the conf script for nginx ... which I don't own.
    – ben w
    Commented Jul 31, 2013 at 16:59
  • 2
    @benw Why cant you use start on (started nginx) in your new script?
    – Paccc
    Commented Jul 31, 2013 at 17:46
  • 2
    @Paccc not really. start on (started nginx) means "start my service after nginx". Which is not the same as "start nginx before my service because it needs it".
    – ku1ik
    Commented Oct 16, 2014 at 9:41
12

James's answer works for a 1 to 1 dependency. For a 1 to many, i.e., to make sure service A starts before services B, C, and D, you need to take another approach. You can look at the current portmap scripts for reference but here is the general approach: create a wait script.

Scenario: you want your Service A to always run before service-b, service-c, and service-d.

Solution: create a wait script for Service A. Call it "/etc/init/service-a-wait.conf"

# service-a-wait

start on (starting service-b 
    or starting service-c
    or starting service-d)
stop on (started service-a or stopped service-a)

# We know that we have more than one job that needs to wait for service-a and
# will make use of this service, so we need to instantiate.
instance $JOB

# Needed to make starting the job successful despite being killed
normal exit 2
task

script

    status service-a | grep -q "start/running" && exit 0
    start service-a || true

    # Waiting forever is ok.. upstart will kill this job when
    # the service-a we tried to start above either starts or stops
    while sleep 3600 ; do :; done

end script

What this means in plain English is: when service b, c, or d signals that they want to start, they must wait to start until service-a is running. The service-a-wait job is designed to run until service-a has started. Once service-a-wait exits, now services b, c, and d are free to carry on and run.

This will assure service-a is up and running before any of its reverse dependencies attempts to start.

Note: the "instance $JOB" line is important in this "start on... or.. or.." scenario. Otherwise you will only really block for whichever of B, C, or D fires off first.

(instantiation deserves a better explanation honestly. for now, just do it. ;)

2
  • 3
    I don't get this… what prevents a race condition between starting service A and service B continuing to start? I don't see how upstart will know that the script has completed "start service-a"… (blame this on Upstart's shoddy documentation maybe…) Commented Oct 15, 2013 at 15:34
  • @Mark Russell: Shouldn't that normal exit 2 line be normal exit 0 2 instead? The first line in the script section quite clearly can exit 0.
    – froage
    Commented Oct 11, 2014 at 20:45

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .