A lot of people get this wrong. Some of the answers here are even getting it wrong.
First, let's clear up some misnomers:
- The distinction between a program named
init
that runs as process #1 and a program named rc
that runs as another process goes back all the way to First Edition Unix. Most of what you are discussing isn't done by process #1 in the overwhelming majority of service/system management softwares, Upstart and systemd being exceptions rather than the rule.
- "sysvinit" isn't AT&T Unix System 5
init
+rc
. It's a clone init
and rc
system written originally for Minix by Miquel van Smoorenburg, ironically some years after AT&T Unix System 5 itself largely did away with that system, replacing it with something called the Service Access Facility.
What you are asking about is service management, the task of the aforementioned Service Access Facility (SAF) on AT&T Unix, the AIX System Resource Controller (SRC), the Solaris Service Management Facility (SMF), systemd, Upstart, daemontools, daemontools-encore, runit, nosh toolset service management, s6, and a whole bunch of other toolsets.
The original AT&T Unix System 5 rc
, before the SAF and SRC came along, had just forked off the service processes directly and didn't really manage them thereafter.
The van Smoorenburg rc
on Linux (from Minix) still did this.
Moreover, it originally relied upon manual and rather ad hoc ordering of service startups/shutdowns with respect to one another.
The original giant single rc
script, which went through several mutations in the 1970s and early 1980s that one can still find fossilized here and there (in the likes of rc.local
), by the time of the van Smoorenburg rc
clone in the 1990s had become a set of drop-in scripts in a subdirectory of /etc/
and some symbolic link farms (in other subdirectories of /etc/
) that represented the order that those scripts were run in in order to do the overall rc
task.
The symbolic link farms were based around a priority scheme, where the different rc
scripts were assigned priorities from 0 to 99.
(There was an alternative mechanism to the symbolic link farm in the late 1990s, file-rc, but it too used a priority system.)
This was a pain to administer, because there were no universal conventions on choices of priority, and because of the "two softwares both want to be first" problem.
(Ironically, you can see someone who is using a fossil way of doing things asking about one of the related problems on this very WWW site just yesterday.)
Dependency-based service management tries to do better.
Service definitions, in whatever form they come in, list what services each service depends from and should be ordered relative to when starting up and shutting down.
There is no "first" and "last", but there are before and after, as well as needs and conflicts with.
It has been in the old rc
-style systems on Linux and the BSDs for most of the 21st century.
- Mewburn
rc
and OpenRC (both 21st century inventions) learned from the systems that came before them, and incorporated a means of expressing interdependencies between the different rc
scripts from the start. In Mewburn rc
, a system of comments in the various rc
scripts (e.g. REQUIRE
, PROVIDE
, and BEFORE
) expresses the interdependencies amongst services, and a program named rcorder
calculates from them the order to run things in at the start of every bootstrap/shutdown.
- van Smoorenburg
rc
gained a program called insserv
from Debian people. Interdependencies were expressed among services by a system of conventional "LSB headers" included as comments in the various rc
scripts, and the priorities were rewritten in the symbolic links by insserv
at software installation/deinstallation time, to reflect the dependencies. This was fairly heavily adopted by Debian and some of its derivatives in the latter part of the first decade of the 21st century. See the Debian wiki for more.
It moreover existed as a first-class mechanism in many of the non-rc
service managers, from Solaris SMF to systemd, from the outset.
Notable exceptions were Upstart, daemontools (and daemontools-encore, perp, and runit), and (years ago) s6.
daemontools, runit, et al. all originally took the "giant thundering herd" approach to the problem, starting and restarting services over and over until they all stayed up.
Some tweaked this slightly with tricks, such as programs that made services pause and not invoke their main service programs until something else happened, but the basic idea remained that everything in an entire "scan" directory got started all at once.
I long maintained that one could do better than this, with some layering on top of the base service management, and eventually demonstrated this with a concrete toolset that did so, taking the startup "scan" logic out of the actual service manager, moving it into a separate program, and building a system of service bundle interdependencies around the base daemontools service/supervise directory structures.
Laurent Bercot also demonstrated the same with additions to s6 named s6-rc.
Even OpenRC demonstrates this, as its rc
scripts express interdependencies and can be made to employ an external service manager (such as s6).
Upstart, ironically for what some people thought in the 2010s, was actually envisioned (back around 2005) as the new way of doing service management, to replace dependency-based service management with event-based service management, where services were started in response to events happening rather than as the result of calculating an ordered set of dependencies.
It's beyond the scope of this answer to discuss why that concept was eventually rejected, and people went back to dependency-based service management, but it is important to realize that by the start of the 2010s dependency-based service management was the norm.
Upstart developers had regarded it as old hat.
van Smoorenburg rc
had it via the Debian work, albeit that Fedora and SUSE didn't really pick that up from Debian.
Mewburn rc
and OpenRC had it from the outset.
systemd was just about to be invented with it.
Solaris, Illumos, et al. had it with the SMF.
And so forth.
This isn't a distinguishing feature, except from the likes of runit and Upstart.
It was and is the norm.
This is something that other people had already done, or were doing, even at the inception of GNU Shepherd.
GNU dmd, now known as GNU Shepherd, was invented in 2003.
Debian had begun the move to insserv
in 2002; Richard Gooch had written about need
in 2002; Mewburn rc
was invented in 2000, and Luke Mewburn's original paper on the subject explains how expressing dependencies with something better than a priority system encoded in filenames was a design feature.
Further reading