How can I make sure one Upstart job starts before other Upstart jobs?

34,732

Solution 1

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. ;)

Solution 2

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.

Share:
34,732
Mark Russell
Author by

Mark Russell

Updated on September 17, 2022

Comments

  • Mark Russell
    Mark Russell almost 2 years

    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?

  • ben w
    ben w over 11 years
    this seems totally backwards to me. why should the conf script for one service be modified when other things depend on it?
  • Paccc
    Paccc almost 11 years
    @benw So that you don't have to modify the existing settings of services you don't own.
  • ben w
    ben w almost 11 years
    @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.
  • Paccc
    Paccc almost 11 years
    @benw Why cant you use start on (started nginx) in your new script?
  • Chris Pacejo
    Chris Pacejo over 10 years
    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…)
  • sickill
    sickill over 9 years
    @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".
  • Siros Baghban
    Siros Baghban almost 9 years
    But it is the same as "start my service after nginx because my service needs nginx"
  • Cmag
    Cmag over 8 years
    I can not find any example syntax to this approach, can you please share?