Thursday, April 26, 2012

Enabling Upstart user jobs to start at boot.

I've come across an issue with Upstart – user jobs' start on stanzas aren't honored at boot time.

The real issue is more general: user jobs aren't loaded into Upstart until the user creates an Upstart session. If a job isn't loaded into Upstart, it's basically invisible and hence its start on stanzas won't be honored.

Loading user jobs into Upstart is simple. It happens automatically when a user creates an Upstart session by connecting via D-Bus using initctl or one of the shortcuts (e.g. start or status). Until user jobs are loaded into Upstart, they're completely disabled.

So the problem at boot time is that user's don't have the opportunity to create an Upstart session prior to the rc-sysinit job emitting runlevel, this makes it impossible for user jobs with start on runlevel [2345] to be honored.

Perhaps this is by design – I'm not sure – but I wrote the following job to get around the issue by blocking rc-sysinit and creating an Upstart session for each user with an .init/ directory in their home:

The following job should be installed into /etc/init/load-user-jobs.conf:


  1. Tanks for the script!

    But unfortunately this doesn't work under Ubuntu Precise because initctl uses dbus and dbus isn't available pre rc-sysinit.

    dbus doesn't seem to get started until very late actually, so user jobs can't even hook into net-device-up or local-filesystem or whatever.

    I worked around this by changing your script to start after dbus and emit a user-jobs event that my user jobs can listen on instead, but that's not very flexible.

    I've opened a bug about this on Upstart's launchpad project:

  2. @johnleach, I am facing the same challenge. Would you care to provide more details about what your modified job looks like? Thanks!


  4. Has anyone tested this on Raring (13.04)?

  5. Has anyone tested this on Raring (13.04)?

  6. I'm using this on 12.04 (precise), and have found that it doesn't work reliably. I think what is happening is that the jobs aren't loaded in between the "initctl status" line to when the signal is emitted.

    I've "fixed" it by putting a sleep between the two lines (I've found 0.5 seconds to be sufficient), but I'm worried about how robust this solution is...