Upstart Scripts in Ubuntu

Upstart is an event based tool that handles starting of services during system booting and shut-down the services before system is shut down. It also monitors the services while they running. It was designed to overcome the limitations in system V and dependency based init systems.

Limitations in existing systems

  1. They are not dynamic in nature. That means when we plug in a new devise like a monitor after the system has booted up, the system cannot recognize it without user intervention.
  2. There is no parallelism. This means when we start certain services, like mysql which is dependent on some other services, they should start before mysql service has started. To start these dependent services, it requires manual configuration in /etc/rc.X directories and is prone to errors.
  3. In some systems, a brute force approach is used to ensure all dependent services has started. This bring load on the system and is sometimes in-efficient.

To get more limitations on existing systems, you can read more information here. Upstart overcomes these limitations by starting services only when all conditions are met. And there would be no kernel panic if init fails as it is designed in a very clean and sensible way.

Triggering Jobs

Upstart scripts are located in /etc/init/ directory with a .conf extension. The scripts are called ‘System Jobs’ and run using sudo privileges. Just like system jobs we also have ‘User Jobs’ that are located at $HOME/.init/ directory. (Note: Only Ubuntu versions above 11.10 support user jobs). After internal upstart initialization, it emits an event called ‘startup’ which triggers rest of system and user jobs.

Writing Upstart scripts

An Upstart script is a combination of states and events. On particular events the service state changes from one to another. Currently upstart supports 10 states. They are waiting, starting, pre-start, spawned, post-start, running, pre-stop, stopping, killed and post-stop. More details here. Here is a simple upstart script which starts node.js server whenever system boots.

# /etc/init/nodejs.conf

description "node.js server"
author      "Siva Gollapalli"

# used to be: start on startup
# until we found some mounts weren't ready yet while booting:
#start on started mountall
# If network interface is wireless
start on (local-filesystems and net-device-up IFACE=wlan0)
# If network interface is Ethernet uncomment below line and comment above line
#start on (local-filesystems and net-device-up IFACE=eth0)

stop on shutdown

# Automatically Respawn:
respawn limit 99 5

    # Not sure why $HOME is needed, but we found that it is:
    export HOME="/home/siva/work/myproject"

    exec /usr/local/bin/node $HOME/node/notify.js 13002 >> /var/log/node.log 2>&1
end script

post-start script
   # Optionally put a script here that will notify you node has (re)started
   # /root/bin/ "node.js has started!"
end script

Stanzas and Configuration

‘description’, ‘author’, ‘start on’, ‘stop on’, ‘respawn’, ‘script’ and ‘post-start’ are called as stanzas.

start on (local-filesystems and net-device-up IFACE=wlan0)

This tells Upstart to start node.js service when all local-filesystems and wireless network interface is up.

start on (local-filesystems and net-device-up IFACE=eth0)

This tells Upstart to start node.js service when all local-filesystems are up and Ethernet network interface is up.

Before starting node.js service Upstart executes the pre-start block if it exists. Later it executes the script block which is the actual code used to start a service. After service has been started, upstart executes post-start block.

In our current scenario with node.js service, there are no pre-start block and the post-start block is there with no code. So, upstart just start node.js service without any pre and post actions.

Monitoring services

You may not have noticed that I forgot to explain what is ‘respawn’ and when to use 🙂 ‘respawn’ is a stanza which executes when the service has exited for some reason and you want start the service again automatically then this will be used.

‘respawn limit’ defines the limit of re-tries for a service. In our current scenario it is 99 times after a time interval of 5 seconds. That means, try 99 times every 5 seconds to get our service started.

Note: It is preferred not to ‘respawn’ unless and until you are sure that the code you have written is correct. Otherwise it could leads to problems on CPU utilization and memory constraints.

After system has been started execute following command to know status of the service

sudo initctl nodejs status

Stopping services

Up till now we have seen how to start a service. When system is about shut down Upstart executes pre-stop block similar to pre-start block and then executes post-stop block after service has been shut down which is similar to post-start. In out current scenario node.js service stops when system is shut down. We do not need to do anything special to stop services on shutdown. Its guaranteed to cleanly shutdown processes in the correct order!

I hope everyone enjoys this article and let me know if you face any complex scenarios to write. I will give a shot. Feedback and suggestions are welcome.