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>