The good and bad of the System V init system
The good of System V init is that it gave us several big improvements
over what came before in V7 and BSD Unix. First
and largest, it modularized the boot process; instead of a monolithic
shell script (or two, if you counted
/etc/rc.local) you had a
collection of little ones, one for each separate service. This alone is
a massive win and enabled all sorts of things that we take for granted
today (for example, casually stopping or starting a service).
The other big change is that System V init turned the entire work of
init from a collection of hacks into a systematic and generalized
thing. It formally defined runlevels and runlevel transitions and
/etc/inittab a general mechanism for specifying all of the
work init did, from booting to running
gettys on serial lines (or
running anything) to how to reboot the system. System V init removed
the magic and hardcoding in favour of transparency. Things like
stopped killing processes and making special system calls and turned
into 'tell init to go into runlevel ...', and then
runlevel transitions said what to do so that this actually rebooted the
machine. In the process it added a way to specify how services shut
(Simply defining runlevels formally meant that other systems could now tell what state the system was in and behave differently between eg single user mode and multiuser mode.)
The very general and high level view of the bad of the System V init system is that fundamentally all it does is blindly run shell scripts (and that only when the runlevel changes). This creates all sorts of lower-level consequences:
- SysV init doesn't know what services are even theoretically running
right now, much less which ones of them might have failed since
they were started.
- It doesn't know what processes are associated with what services.
Even individual init scripts don't know this reliably, especially
for modern multi-process services.
- Even init scripts themselves can't be certain what the state of
their service is. They must resort to ad hoc approaches like PID
files, flag files for 'did someone run <script> start at some time
this boot', checking process listings, and so on. These can
- Services are restarted in a different environment than how they
are started on boot. Often
contamination leaks in to a restarted service (in the form of
stray environment variables and other things).
- Output from services being started is not logged or captured in any
systematic way. Many init scripts simply throw it away and there's
certainly no official proper place to put it.
- The ordering of service starts is entirely linear, by explicit
specification and guarantee. System V init explicitly says 'I
start things in the following order'. There is no parallelism.
- Services are only started and stopped when the runlevel changes.
There is no support for starting services on demand, on events,
or when their prerequisites become ready (or stopping them when
a prerequisite is being shut down).
- System V init has no idea of dependencies and thus no way for
services to declare 'if X is restarted I need to be restarted too'
or 'don't start me until X declares itself ready'.
- There is no provision for restarting services on failure.
Technically you can give your service a direct
/etc/inittabentry (if it doesn't background itself) but then you move it outside of what people consider 'the init system' and lose everything associated with a regular init script.
- Since init scripts are shell scripts, they're essentially
impossible for programs to analyse to determine various things about
- It's both hard and system-dependent to write a completely correct
init script (and many init scripts are mostly boilerplate). As a
result it's common for init scripts to not be completely correct.
- Init scripts are not lightweight things in general, either in reading them to understand them or in executing them to do things.
In theory you can try to fix many of these issues by adding workarounds in your standard init script functionality. Your 'standard' init script utilities would capture all daemon output in a documented place and way, start everything in cgroups (on Linux) or containers to track processes reliably, have support for restarting services on failure, carefully scrub every last bit of the environment on restarts, monitor things even after start, et cetera et cetera, and then you would insist that absolutely every init script use your utilities and only your utilities. In practice nothing like this has ever worked in practice (people always show up with init scripts that have bugs, take shortcuts, or do not even try to use your complex 'standard' init utilities) and the result would not particularly be a 'System V init system' except in a fairly loose sense.
(It would also make each init script do even more work and run even more slowly than they do now.)