Events as the key
Upstart's event-based design differs fundamentally from that used by SysV init, in which init scripts are stubbornly called in the lexical sequence in the relevant runlevel directory. This allows Upstart to be much more flexible. If, for example, there is no network connection present when the mail daemon (MTA) is launched, SysV init has to wait for the time-out before continuing to boot the system. In Upstart, the MTA is only started once the network connection has been established. The
network up event is set as the start event for the MTA job. This event is triggered by the service responsible for network set-up only after the network has been successfully configured – in the case of a laptop out on the road, for example, this means not at all.
Because jobs do not have a fixed start sequence, the system is able to boot faster with Upstart than with SysV init. In addition, it is possible to process multiple jobs simultaneously, so that initialisation tasks can be executed in parallel. This also represents a potential time saving.
A major change in Ubuntu 9.10 is that Upstart has finally been brought creaking to life now many system settings and calls to daemons have been converted to it. These include mounting drives and starting udev, cron and the GUI. However, Ubuntu is not yet quite at the point of being able to do away with the old init scripts altogether and there is still a wrapper job,
rc, which emulates the SysV init runlevels and calls the init scripts linked in /etc/init.d and /etc/rc?.d.
Shortly after the kernel has been started and the first pseudo-file system mounted, the /etc/init/rc-sysinit.conf job is started. The start event for this job is
filesystem and its role is to generate the
runlevel S event, thereby setting the equivalent of runlevel S. The /etc/init/rcS.conf job then starts; it processes the symbolic links in /etc/rcS.d, taking care of basic system configuration. The signal for runlevel 2, to which further Upstart jobs are coupled, is then generated and the init scripts linked in /etc/rc2.d are executed.
The /etc/inittab file – which on systems using SysV init deals with tasks such as starting the login console to complete initialisation – is replaced by a number of Upstart jobs, a illustrated by the following extract:
start on stopped rc RUNLEVEL=
stop on runlevel [!2345]
exec /sbin/getty -8 38400 tty1
rc job, which emulates the runlevels, terminates after calling the init script for the relevant runlevel and is not running during the emulated runlevel, the start signal for the
tty jobs is the termination of the
rc job, rather than for example, its start. In addition, the login console needs to be deactivated when shutting down the system (runlevels 0 and 6) and in single user mode. Getty itself runs in the foreground and, since it is called using the keyword
exec, is monitored by Upstart. The additional keyword
respawn tells Upstart to keep restarting the process if it terminates. This causes a new login prompt to be displayed after logging off.
To prevent the system from being overloaded by a process constantly restarting, the frequency with which Upstart tries to start a service over a particular period can be limited. Fedora 10 uses this feature in the prefdm job to launch the GUI.
start on stopped rc5
stop on runlevel [!5]
respawn limit 10 120
exec /etc/X11/prefdm --nodaemon
The limit for restarting is set to 10 attempts within 120 seconds, for which both the
respawn limit commands are required.
respawn limit on its own does not cause the service to restart.
When it comes to terminating a job, Upstart concerns itself only with the process started in the foreground using
exec. It sends the terminate signal (SIGTERM) and expects the process to quit. Upstart does not tolerate dissent – if the process fails to terminate, it is summarily terminated a few seconds later using the kill signal (SIGKILL). Once a stop event has been triggered, a service can neither block it, delay it or roll it back
post-stop can be used to specify commands which Upstart should execute before and after terminating the service. This is useful for any clean-up work, for example:
post-stop exec rm -f /var/run/tserv.pid
There are also
post-start keywords which can be used to specify commands to be executed immediately before and after starting a service, such as creating required directories or adjusting certain system settings, after starting the service. Since
exec expects the service to be started in the foreground, Upstart can't wait for the service to be terminated before executing
post-start. Upstart therefore executes
post-start in parallel with starting the service. The diagram on the right illustrates the sequence of events when starting and ending an Upstart job.
In the above examples, all our commands have been called using
exec. It is, however, also possible to use a block of commands book-ended by the keywords
if [ ! -e /var/run/tserv ]; then
mkdir -p /var/run/tserv
Where, instead of using
exec, a service application is started using a block of commands. It is worth bearing in mind that the commands following the command for calling the service will only be executed if the service terminates immediately after being called. If the service is subsequently terminated by means of a terminate signal from Upstart, these commands will not be executed.