upstart: Explanation & Insights

Ubuntu's event-driven init from the late 2000s — the bridge between sequential scripts and systemd, now retired.

What It Is

upstart is an init system — the first userspace process, PID 1, parent of everything else on the box — that Ubuntu created in 2006 to fix the thing everyone hated about sysvinit: slow, rigid, sequential boots. Its big idea was to make booting event-driven and parallel. Instead of marching down a numbered list of shell scripts one at a time, upstart treated the boot as a cascade of events — "a filesystem mounted," "the network came up," "another job started" — and let any job fire the moment its triggering events occurred. Many jobs could therefore start at once, and the boot finished as fast as the slowest chain of dependencies rather than the sum of every script.

For a few years this was the future. upstart shipped as the default init in Ubuntu from 2006, in Red Hat Enterprise Linux 6 (2010), in Google's Chrome OS, and elsewhere. It genuinely sped up boots and brought real supervision — if a job's process crashed, upstart could respawn it automatically, something sysvinit never did.

And then it lost. systemd arrived with a more complete answer to the same problems, distributions adopted it one by one, and Ubuntu — upstart's own home — switched to systemd in 2015. Today upstart is effectively dead software: unmaintained, removed from current releases, encountered only on legacy boxes. This page exists so that when you meet one of those boxes, or read a tutorial from upstart's heyday, you know exactly what you're looking at.

How It Worked

The mental model that separates upstart from its predecessor is the event. In sysvinit, a script ran because a number in its filename said it was that script's turn. In upstart, a job ran because an event it was waiting for fired. The two phrasings sound similar but they're profoundly different: the first is a fixed schedule, the second is a reactive web.

Jobs were defined in plain-text config files in /etc/init, one .conf per job. A real-ish one for a database might read:

description "Example database server"

start on filesystem and net-device-up IFACE!=lo
stop on runlevel [!2345]

respawn
respawn limit 10 5

exec /usr/sbin/exampledb

Read it top to bottom and the model reveals itself:

  • start on filesystem and net-device-up IFACE!=lo — the trigger. Don't start at position 20 in a list; start when the filesystem is ready and a real network interface (anything but loopback) has come up. upstart watches for those events and launches the job the instant both have happened — which might be early, might be late, and might be simultaneously with five other jobs. That's the parallelism: nobody's waiting in line, everyone's waiting for their conditions.
  • stop on runlevel [!2345] — when to shut it down: on entering any runlevel that isn't 2, 3, 4, or 5 (i.e. on halt or reboot). upstart kept runlevels around as compatibility events, so old habits still half-worked.
  • respawn — supervision. If the process dies, restart it. respawn limit 10 5 caps that at 10 restarts in 5 seconds so a hopeless crash-loop doesn't spin forever — a genuinely thoughtful touch, and a feature sysvinit lacked entirely.
  • exec /usr/sbin/exampledb — the actual program to run.

You managed jobs with initctl, upstart's control tool:

initctl list                     # every job and its current state
initctl start exampledb          # start a job now
initctl stop exampledb           # stop it
initctl status exampledb         # is it running?

The service command also worked here, the same way it worked on sysvinit and later systemd — it detected upstart underneath and called initctl for you. That cross-era consistency is why service is the safest command to reach for on any unfamiliar box.

Why It Existed, and Why It Lost

It's worth being clear-eyed about both halves, because the rise-and-fall is the whole lesson.

Why it existed: sysvinit booted slowly (everything serial) and couldn't supervise (start a script, walk away). On the laptops and desktops Ubuntu cared about most, slow boots were the visible pain, and hot-pluggable hardware — plug in a USB drive, a network cable, a dock — fit the event model beautifully: an event fires, the right job reacts. upstart was a sharp, well-aimed answer to a real problem, and for its moment it was the best init Linux had.

Why it lost comes down to one architectural choice. upstart asked you to describe the world as events: "start when X happens." systemd asked you to describe it as dependencies: "this needs that." It turns out dependencies are the more natural way for a human to think about services — you know that your web app needs the database, but expressing that as a chain of start-on events ("start the app on the event that the database emitted the started event") is roundabout and easy to get subtly wrong. As systems grew more interconnected, the event web got tangled, and reasoning about why a job did or didn't start became genuinely hard.

systemd also did more: socket activation, parallelization that didn't even need the dependency to be running yet (just its socket), a unified log via journalctl, device and mount management, and a consistent control surface in systemctl. It wasn't only faster; it was more complete. One by one the distributions agreed — and when Ubuntu, the project that invented upstart, switched to systemd for 15.04 in 2015, the verdict was unanimous. There's a particular kind of finality to being abandoned by your own parents.

Backstory

upstart wasn't a failure — it was the proof of concept the whole field needed. It demonstrated, in shipping distributions used by millions, that init could be parallel, event-aware, and supervising, and that the world wouldn't end if you retired the thirty-year-old shell-script model. systemd took that proof and built the more durable version. Some of the best engineering in history is the kind that makes its own successor inevitable; upstart is a tidy example of an idea that won the argument and then handed the trophy to whoever argued it better.

Where You'll Meet It Today

On a current server: nowhere. Don't install it, don't choose it, don't write new .conf jobs for it — the project is unmaintained and every distribution that once shipped it has moved on. Reaching for upstart now would be choosing a dead end on purpose.

Where it still lurks is the museum wing of the internet:

  • Old Ubuntu LTS releases (roughly 9.10 through 14.10, and 14.04 LTS in particular) booted with upstart. A long-running 14.04 box that nobody dared upgrade is the single most likely place you'll meet it in the wild.
  • RHEL/CentOS 6 used upstart underneath, though it kept a sysvinit-style /etc/init.d veneer on top, so it often looked like classic System V.
  • Old tutorials that tell you to drop a .conf in /etc/init and run initctl reload-configuration. If you're on a modern box, that advice simply won't apply — translate it to a systemd unit instead.

The recognition trick: if ps -p 1 -o comm= reports init and there's a populated /etc/init directory full of .conf files (note: /etc/init, not /etc/init.d), you're on upstart. The directory names are almost identical and trip people up constantly — /etc/init.d is sysvinit's script folder; /etc/init is upstart's job folder. One letter of difference, two different eras.

Cheat Sheet

# --- Identify it ---
ps -p 1 -o comm=                 # 'init' (shared with sysvinit — check the dirs)
ls /etc/init/*.conf              # upstart jobs live here (.conf files)
initctl version                  # prints the upstart version if present

# --- Manage jobs ---
initctl list                     # all jobs and states
initctl start  <job>
initctl stop   <job>
initctl restart <job>
initctl status <job>
initctl reload-configuration     # re-read /etc/init after editing a .conf

# --- The portable command (works here, on sysvinit, and on systemd) ---
service <job> start|stop|status|restart

See Also

  • init system — the concept, PID 1, and the full family tree
  • sysvinit — the sequential, script-based init upstart aimed to replace
  • systemd — the dependency-based init that replaced upstart
  • runlevel — the older mode concept upstart kept for compatibility
  • process — what PID 1 is the root of
  • daemon — the long-running services an init supervises
  • service — the unit of "something that should be running"
  • service — the command that works across all three init eras
  • systemctl — what you'll actually use on a modern box

Inherited a server old enough to still run upstart?

CleverUptime reads /proc to tell you which services are actually up right now and which one has gone quiet — without caring whether initctl, service, or systemctl started it.

Want to see your own server's health right now? One command, no signup, no install.

Check your server →