Upstart 0.5: Job Environment
In my previous post on Upstart 0.5, I talked about the ways you can define a service for Upstart to manage and introduced the different processes in a job’s lifecyle. In this post, I’ll look into the detail of those processes and their environment.
Upstart ensures that each process it runs has a sane, safe and predictable environment. By default each process is run in a new process group and session, but not as a leader of that process group or session (otherwise the process would have to be careful on all open() calls to make sure it didn’t suddenly own any ttys it opened); the standard input, output and error file descriptors are bound to /dev/null; the PATH environment variable is set to a sensible default, and the TERM variable inherited from the kernel, otherwise no other variables are set; and all resource limits and the like are inherited from init itself.
There are, of course, many ways to customise this environment from the job definition:
- Jobs may run as a process group and session leader (normally getty likes this).
- Jobs may have standard file descriptors sent to
/dev/consoleand may be the owner of/dev/console(so they receive Ctrl-C). - Jobs may specify custom resource limits, umask, “nice” level, working directory and chroot directory.
Environment Variables
To say that jobs only have the PATH and TERM environment variables set is quite a fallacy, these are just the two variables that all jobs always have set. In fact, the additional environment variables for a job are very important to Upstart since they are the primary method of communicating with that job how it should behave.
To illustrate this, take an instance of the getty service; it needs to know which tty it should use. We could invent some kind of common configuration or parameter database (or D-Bus service) for this kind of thing, with the job being able to run commands to interrogate it, etc. but that’s entirely unnecessary. UNIX already gives us the functionality we need in environment variables, which you’ve probably noticed your shell documentation calls parameters anyway.
In our getty example, we would store the tty in the TTY environment variable, and then the job definition is nice and simple to understand:
exec /sbin/getty 38400 $TTY
So environment variables can be set from a number of sources: the built-in PATH and TERM variables will always be set; others can be set from the job definition (which can specify to inherit the value from init’s environment); and finally environment can come from the start request for the job. I’ll explain more on the latter in later posts, but for now, it suffices to demonstrate that we’d start our getty example with:
# start getty TTY=tty1
So Upstart allows you to define the job’s true life cycle, including any setup and cleanup it needs to perform before and after the daemon is running; and it allows you to define the environment that daemon runs in, so you don’t have to worry about unexpected situations. In the next post, I’ll talk about how you can manage the lifetime of a job, looking at things such as singletons and respawning.






As well as CPU-nice, will IO-nice be a configurable setting?
@kees: Yes, I was going to add ionice the other day but realised nobody’s included linux/ioprio.h in linux-libc-dev yet … and wasn’t going to try and push that one past slangasek
We also support “oom -16 thru +15″ or “oom never” to adjust OOM-killer priority.
I should probably look at rt priority stuff, and the new cgroups settings that Bill Nottingham pointed me at.