Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 26 Sep 1995 08:43:28 -0700
From:      patl@asimov.volant.org
To:        gryphon@healer.com, jmb@kryten.atinc.com, peter@taronga.com
Cc:        hackers@FreeBSD.ORG
Subject:   Re: ports startup scripts
Message-ID:  <9509261543.AA00716@asimov.volant.org>

next in thread | raw e-mail | index | archive | help
|>  > [SysV method] is the simplest mechanism that provides equivalent power.
|>  
|>  I can't see any more power from a directory listing proving control
|>  order vs. a control file providing that order.

Yep, same level of power.  But the directory technique is simpler.  It
doesn't require complex install-time file modifications, or run-time
control file parsing.

|>  They both have their plusses and minuses.

True.  So does the current mechanism.  I think we are agreed that both
proposals weigh in on the plus side compared to the current system.

|>  > I'll happily abandon it if I'm presented with a better solution.  But
|>  > loss of functionality simply to reduce the number of i-nodes used doesn't
|>  
|>  OK. Now we can actually cover some coherent points, that do not
|>  relate to personal preference in style.
|>  
|>  I say they have equivalent functionality. The only counter argument made so
|>  far is Terry's which talks about Union-FileSystem mounting to overlay files
|>  into the /etc/rc?.d directories (which makes me shudder at the thought).
|>  
|>  What functionality does the "rc?.d" sym-linked subdirs method gain over
|>  the control file model?

I can't think of any significant difference in functionality.  But the
rc?.d subdirs win on simplicity and (install time) safety.


|>  > |>  Each sub-system has it's own script. A control file determines what
|>  > |>  gets run when. Or each sub-system has it's own script, and directory
|>  > |>  ordering in a sym-linked tree determines which gets run when.
|>  
|>  > Right.  And it is orders-of-magnititude safer to add a file to a directory
|>  > than to automatically insert a line at the right place in a control file.
|>  
|>  Ok. Something that appears to have been lost in one of my mail messages.
|>  I am not talking about the package install script editing the file
|>  itself. I am talking about it calling a command utility (written
|>  as part of the setup mechanism) which will do the editing.
|>  
|>  That reduces the risk by an order of magnitude, since the util knows
|>  about the format, and know what is and is not safe to do. All it
|>  needs to be told are dependances to take into account.

Ok, you've reduced (but not entirely eliminated) the worry about whether
all of the package builders can get the edit right.  But at the cost of
introducing another complex sysadmin program.

|>  > |>  I don't care who invented it. I've looked at it, worked with it,
|>  > |>  and don't agree with it.  It's really that simple.
|>  
|>  > That's not the impression you leave from some of your other arguments.
|>  
|>  Then I'm sorry for not being clearer earlier. Everything in my life is build
|>  around a few simple concepts. First, that there are always more than one way
|>  to do something. Second, that just because you don't like  one part of
|>  something, don't let that affect your views on other parts. Corrallary,
|>  if you like something, be careful about assuming you'll like all of it.
|>  Third, if it works, then it is right.  Corallary, if it doesn't work,
|>  it's wrong, replace it.  Finally, re-evaluate everything constantly,
|>  you might have missed something the first few times.

Excellent rules.  Very similar to mine.  But I add a rul zero: Stay Out
Of The Way - you can't possibly imaging all of the ways people will want
to use your stuff, so don't try.  Just make it as general and flexible
as you can without sacrificing simplicity and robustness.  (One of the
things that SVr4, and various standards committies, did that really
pissed me off was to make the output of some commands more 'user friendly',
and script-hostile.  Apparently they've all forgotten about cut(1) and
think that scripts and aliases should contain inline awk scripts that
are as readable as line noise...)


|>  > I think we want an inittab in either case.  The difference is in how many
|>  > entries it is expected to have, and whether it is likely to be modified
|>  > at each site.
|>  
|>  OK. But doesn't the "inittab" and "rc?.d" provide the same redundant
|>  information that you diskliked in the control file method?
|>  
|>  What does the "inittab" your proposing gain over just the "rc?.d"
|>  directories with numbers dictating script order?

The inittab has little more than a single line per run state.  For each
state there will normally be an rc? script that actually runs the rc?.d
scripts.  There will be no need for a site to ever modify the inittab
unless they are adding site-specific runstates.  The major gain here
is that if the model changes a bit, we don't have to change init, we
can just change the rc? scripts.  (The theory being that if you break
init, there is no way to bring the system up by hand; but if you break
an rc? script, you can probably fix it in single user.)

Actually, if we go with something resembling the Solaris2 model, the
inittab entries control the actions that init takes to any condition
it can recognize.  The runstate transitions are the most commonly used,
but there are also things like handling impending power failure via
SIGPWR.  Each inittab line is of the form 'id:states:action:process',
where id is a unique one or two character identifier, states is a
list of the target runstates that the line applies to, action is a
keyword telling init how to treat the process [respawn, wait, once,
boot, bootwait, powerfail, powerwait, off, ondemand, initdefault,
sysinit], and process is a command line to execute.  It sounds
complicated, but reading the man page makes it more obvious why
it's all necessary and useful.


|>  > |>  Each mechanism will have to have a means to automatically add config
|>  > |>  information. These two will become subroutines of some overall tool
|>  > |>  (called "pkg_init_setup" or whatever).
|>  
|>  > More complication for people doing ports; but probably not
|>  > outrageously so.
|>  
|>  Actually, I see it as simpler :-)
|>  
|>  With this common tool, all they have to do is execute the utility and give
|>  it the relevant dependancy info (if any). It knows about everything else.
|>  Thus the packages and ports only need to know how to call it, and we
|>  can implement any later install/startup mechanism and only need to change
|>  this one utility.

But it assumes that the dependancy info is easily codified in a form
that can be automatically handled.  That makes it a bit harder to handle
arbitrary abstractions.  (Like "this has to be after all remote file
system clients have been started but before any user-level information
servers [HTTP, gopher, etc.]".)  If the package developer can figure
out how to codify the dependancies, they can pick a sequence number
for each standard runstate that should include the service.

Don't get me wrong - I love automation.  I firmly believe that Computers
Were Invented to Make Our Lives Easier.  It's just that I seem to frequently
find myself needing to do something slightly different then the norm, and
often discover that the standard mechanisms won't allow me to do it.  That's
why I rate generality and flexability so high.

|>  > |>  Anything which can figure out the correct number to use for the script
|>  > |>  name can figure out where to place itself in a file. If it can't, then
|>  > |>  it can't and the argument become moot.
|>  
|>  > The sequence number can be static - built in when
|>  > the package was built.  It is the same for all systems.  The file editing
|>  > must be done dynamically at installation time, by examining and modifying
|>  > a file that is likely to be different at each site.
|>  
|>  Urk. OK, I misunderstood where the numbers are coming from. I assumed
|>  that the package would determine the numbers at the local system.
|>  
|>  That adds a lot to the shoulder of the ports/packages coordinator,
|>  but does solve all the problems with numbering sequences.

It isn't really adding much.  Most of the work is in identifying the
dependancies in the first place.  This actually allows some of them
to remain abstract.

|>  Ok. We have another basic question here: I am hanging onto less information
|>  than you are, in that I am only keeping track of relative ordering, while
|>  you are keeping track of specific numbers. I can't see anything I'm loosing
|>  in not having the explicit numbers, aside from ease of translation back to
|>  your system. Am I missing something?

The explicit numbers make it easier to insert new packages in the middle
of the sequence.  (No need to renumber.)  And easier to define fixed abstract
sequence points.  These aren't issues if the order is automatically generated
from a dependancy tree.  (But I still think that manual sequencing at
package creation time is easier and more robust.)

|>  |>  So the numbers also become run levels (being how much we've started 
|>  |>  running).  Great.  Back to argument #1. :-)
|>  
|>  > I suppose you might think of them that way; but you'd probably be in the
|>  > minority.  They are significant points within the sequence for a given
|>  > state.  Points that other services are likely to be dependant upon.  You
|>  
|>  That's what I consider run-levels: plateaus where a certain amount
|>  if system functionality is enabled.

The difference is subtle, perhaps an example from the Solaris2.4 rc2.d
README would help:

        After the S20 scripts have executed, local file systems are
        mounted and temporary directories have been cleaned as
        appropriate.
 
        After the S80 scripts have executed, the machine is a fully
        configured NFS client.  NFS file systems have been mounted.
        The name service (if any) is running.  syslogd and cron are
        running.

Here S80 could clearly be considered a run level, but S20 has that
extra notation about 'temporary directories have been cleaned...'.
This doesn't really correspond to a run level, but is one of the
operations of the startup sequence.  (Which also points out that
the [SK]* scripts don't necessarily each start a service daemon;
some of them will do once-per-state-transition operations.)

|>  Anything else is what sets of additional things (mounted filesystems,
|>  daemons, subsystems) are run after that point. But the discrete points
|>  I don't think are likely to change.

Certainly not frequently.  Additions are more likely than actual changes.
(Where an addition is most likely to be nailing down some intermediate
step that was already occurring.)


|>  > You're thinking in a box again.  Do it this way, and I guarantee that
|>  > somebody will curse the makers of that decision for getting in the way
|>  
|>  Ok. I don't see how.

My point is that you don't have to see how.  In fact you probably can't
see all of the ways somebody will want to use this.  Don't try - just
aim for the most flexable, powerful, system you can without sacrificing
simplicity or robustness.  (Rule number one: Stay Out Of The Way.  If
I appear to be repeating this frequently, it is because I also remind
myself of it frequently...)

|>  Either it depends upon nothing (thus no problem),
|>  depends upon something with nothing depending upon it (again, simple),
|>  replaces something directly (still simple), or goes into the middle
|>  of a dependency chain. (which case requires most of the design sweat)
|>  
|>  I can't see any other case in an ordered system.

Right.  But I prefer to leave the decision to the human who was building
the package in the first place.  Humans are good at that sort of decision,
when they have all the relevant information; and the package builder
should have all that info.  (If they don't, how are they going to specify
the dependancies for the tool to do it?)


|>  > lose if the lines to be recognized have been hand-editted for any reason.)
|>  
|>  Granted. But a person with an editor will always be able to screw up
|>  an working configuration. What we have to do is make it such that
|>  they have no reason to hand-edit any files.

There are people who will hand-edit because they don't like the tool,
or don't like automated setup modification tools in general; and there
will probably be somebody who needs to hand edit because their particular
situation is outside the design parameters of the tool.  And there are
people who will hand-edit because they somehow miss the very existance of
the tool.  There are people who will hand edit because the Hand of Murphy
is Upon Them.  Don't try to imagine why, just accept that it will happen.

|>  |>  If we automate things, we either do it right or we screw up a lot
|>  |>  of things.  That holds regardless of the automation procedure, or
|>  |>  how the underlying layers are implemented.
|>  
|>  > No, it can work right -almost- all of the time.  Which makes it all the
|>  > worse when it fails.
|>  
|>  Granted. The dangers come in two places - ports/packages that do not
|>  follow the setup requirements, and sysadmins editing things by hand.

Both will happen in either scheme.  The goal is to reduce the occurrances
of either, and the potential severity of both problems.  In the first
case, our best armor is simplicity.  I happen to think the rc?.d system
is slightly simpler for the package builder than invoking a tool with
explicit dependancies; but the win is very small.

I also think the rc?.d system reduces the potential for hand-editing
by reducing the amount of editing at all.  They can change the sequence
number on a script; but that should be a very easy potential modification
to deal with.  A more severe one would be if they change the service
name itself.  ("I don't like 'httpd', let's call it 'WebServer'.")  A
re-install would miss the renamed file and fail to remove it.  But an
equivalent problem exists with a control file; and there is a level of
idiocy that we just can't protect against.  (Heinlein was fond of writing
"Stupidity is nature's only capitol crime."  Unfortunately, far to many
natural felons avoid punishment...)


|>  Or very complex packages, that require lots of system modifications
|>  to work. And finding ways to do that automatically. But those other
|>  modifications don't change regardless of which startup method we use.
|>  
|>  The question is: is there any fool-proof method, anywhere?
|>  Or do we just do the best we can, design to eliminate as many
|>  problems as we can forsee, and fix the others when they come up?

"You can't make anything foolproof, because fools are so ingenious."
(Sorry, forgot who that's attributed to.)  So we design to cover as
much foolishness as we easily and safely can.  But we also recognize
the point of diminishing returns and move on to something with a
higher payback.



-Pat



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?9509261543.AA00716>