This document describes a proposal for an implementation of
/etc/init.d/* scripts for NetBSD. It is based on work and ideas
by Luke Mewburn, Matthew Green, and others.
It has been felt by many people that NetBSD needs a more flexible
method of system startup scripts. Exactly what model is used to
improve flexibility is a contentious issue, but we feel that this
proposal has the benefits of many other systems without the warts,
whilst retaining backward compatibility for those that require it.
The current methodology of startup scripts that NetBSD uses is a
variant on the `traditional' BSD ``/etc/rc'': a single monolithic
script with behaviour controlled by variables set in /etc/rc.conf.
Some other scripts are called (netstart, rc.lkm, rc.local, rc.wscons),
but you get the general idea.
A `traditional' SYSV ``/etc/init.d/'' directory has been suggested,
but there a various `warts' in that system that can be rectified
in a new design.
Scope
=====
A new system should have the following attributes:
* Separate scripts for each function, which support
`start' and `stop' type functionality.
* Ordering with more control than numeric prefixes on
scripts (c.f. rcorder(8)).
* Control over a function via /etc/rc.conf (rather than
via the existance of a file/link in /etc/rc*.d).
* The ability to generate /etc/rc and /etc/rc.shutdown
from `/etc/init.d/*'.
* Implementers should be able to add extra actions to a
script (e.g, `reload', `debugon', etc) fairly easily.
* Optional checks that a process isn't running before
starting, is running before stopping, etc...
The solution
============
a) Extra functions in /etc/rc.subr
check_pidfile pidfile procname
Parses the first line of pidfile for a process id,
and checks that the pid matches procname.
Prints the pid.
check_process procname
Ensures that a process (or processes) named procname
is running. Prints a list of matching pids.
run_rc_command arg [supported_args]
Scan supported_args (which has "start stop restart status"
prepended) for arg. If there's a match, run ${arg}_cmd
or the default command.
run_rc_command is the `meat' of the system. You set a few variables
and call it and things `just work'.
b) /etc/init.d/
This contains files - one for each function to execute on
startup - which can either be invoked directly or used to
generate /etc/rc (via mkrc).
Currently there are 75 scripts in /etc/init.d.
NOTE: During development this directory was called `/etc/rc.d'.
It was changed to `/etc/init.d' because:
a) prior art (cf. SYSV), and people are used to running
/etc/init.d/foo start
b) `completion-conflict-with-rc[03].d' asthetics :-)
If there's a strong argument for /etc/rc.d over
/etc/init.d, we could rename it to /etc/rc.d.
c) /etc/rc.sh
A script which effectively does:
for i in `rcorder /etc/init.d/*`; do
$i faststart
done
(`faststart' is like start but without the check for
running processes).
If a user wants to use this method (instead of having to
rebuild /etc/rc when necessary), just symlink /etc/rc.sh
to /etc/rc.
d) /etc/rc.shutdown.sh
Similar to /etc/rc.sh, but reverses the order of the output
of `rcorder /etc/init.d/*`, and calls each script with `stop'.
e) /etc/rc.sysv.sh
A script which effectively does:
for i in /etc/rc3./S*; do
$i start
done
This is provided for users who like the `Sxx' and `Kxx' style
names.
f) /sbin/mkrc
Depending upon the options, mkrc generates /etc/rc, /etc/rc.shutdown,
/etc/rc0.d and /etc/rc3.d from /etc/init.d/*.
The generated /etc/rc{,.shutdown} is rather readable sh script
(especially for machine generated scripts!)
/etc/rc0.d will contain symlinks from KxxFOO -> ../init.d/FOO.
/etc/rc3.d will contain symlinks from SxxFOO -> ../init.d/FOO.
g) /etc/netstart
A wrapper for /etc/init.d/network and /etc/init.d/ppp
An example script - /etc/init.d/mountd - is as follows (indented for
readability):
====
# PROVIDE: mountd
# REQUIRE: beforemountlkm network portmap
. /etc/rc.subr
name="mountd"
rcvar="nfs_server"
command="/usr/sbin/${name}"
required_files="/etc/exports"
start_precmd=\
'rm -f /var/db/mountdtab
echo -n > /var/db/mountdtab
:'
run_rc_command "$1" "reload"
====
This is one of the more complicated startup scripts. It uses a
different rc.conf variable than the daemon name, it depends upon
/etc/exports, a `pre command' operation is run before the actual
daemon if all the startup conditions are met. `reload' is added
to the list of commands which are supported; this defaults to
sending a SIGHUP but that can be changed with sig_reload=SIGfoo.
A simpler one - /etc/init.d/rwho - is:
====
# PROVIDE: rwho
# REQUIRE: daemon
. /etc/rc.subr
name="rwhod"
command="/usr/sbin/${name}"
run_rc_command "$1"
====
The functionality provided by this proposed system should cater
for the majority of needs.
Availability
============
A tar file containing a snapshot of the work in progress is available from:
ftp://ftp.netbsd.org/pub/NetBSD/misc/lukem/rc-19991201.tar.gz
Implementation timeframe
========================
Once I've tested this stuff a bit more, parts of this start appearing
in the standard distribution. The existing /etc/rc scripts won't be
modified (except for /etc/netstart; but the functionality should
remain).
After that, /etc/rc could be replaced by the output of /sbin/mkrc.
Feedback
========
Thoughts/comments?
(snip)
>Implementation timeframe
>========================
>Once I've tested this stuff a bit more, parts of this start appearing
>in the standard distribution. The existing /etc/rc scripts won't be
>modified (except for /etc/netstart; but the functionality should
>remain).
>After that, /etc/rc could be replaced by the output of /sbin/mkrc.
>Feedback
>========
>Thoughts/comments?
correct me if I misunderstand something.
dependency list in /etc/init.d/foo looks good to me at a first glance,
but when i've done reading it i'm a bit worried about problem tracking
issues and support issues.
it will become harder to track problems in rc script as rc script
will be tailor-made to the installation site. if random user says
that she has some problem with start up script, we basically have
to get her script, read it through, to track the problem.
since there's little manpower to handle PRs, I would vote to stick
with simple-and-static rc and rc.conf...
itojun
There should be some way of disabling daemons other than deleting
potentially hard-to-recreate files from /etc/init.d ...
- Bill
Luke> f) /sbin/mkrc
Luke> Depending upon the options, mkrc generates /etc/rc, /etc/rc.shutdown,
Luke> /etc/rc0.d and /etc/rc3.d from /etc/init.d/*.
Luke> The generated /etc/rc{,.shutdown} is rather readable sh script
Luke> (especially for machine generated scripts!)
Luke> /etc/rc0.d will contain symlinks from KxxFOO -> ../init.d/FOO.
Luke> /etc/rc3.d will contain symlinks from SxxFOO -> ../init.d/FOO.
Was there a reason for /etc/rcX.d instead of /etc/rc.d/rcX.d which maybe
more familiar to Penguin people who decide to upgrade?
] Out and about in Ottawa. hmmm... beer. | firewalls [
] Michael Richardson, Sandelman Software Works, Ottawa, ON |net architect[
] m...@sandelman.ottawa.on.ca http://www.sandelman.ottawa.on.ca/ |device driver[
] panic("Just another NetBSD/notebook using, kernel hacking, security guy"); [
This reads to me like a requirement on the design, not a specification
of how this system implements the requirement. i'm looking for the
latter...
- Bill
itojun> since there's little manpower to handle PRs, I would vote to stick
itojun> with simple-and-static rc and rc.conf...
I suggest that we distribute an /etc/rc generated by mkrc by default.
That solves the typical user problem. If our /etc/rc.d/* is empty, then
users can install packages, etc. easily without disturbing /etc/rc too much.
- It's nice that you support both generating SysV (rc?.d) and BSD (rc)
environments, but I think we should decide for one system to use.
- I wouldn't mind see the rc.sh replace the /etc/rc we have now
- I feel uneasy with the idea that there is a possibility to get my
system in a non-booting state by touching /etc/rc
- Most important: what does it need to drop in a "classical" SysV script,
as distributed with various pkgs? The examples you show use a lot of
variables which usual SysV scripts don't use. They're usually just
shell scripts that know what to do with 'start' and 'stop', are the
lacking options (or the errors caused by using them) caught?
- Is there a way to drop in init-scripts in some other place than
/etc/init.d (e.g. /usr/pkg/etc/init.d, /usr/local/etc/init.d, ...), and
get them picked up?
Thanks,
Hubert
--
NetBSD - Better for your uptime than Viagra
So instead of the old
fiddle with /etc/rc(.local)
to get something added it's
drop a file somewhere and
fiddle with /etc/rc.conf
now. Um... didn't we want to avoid this?
- Hubert
ok. :-)
> dependency list in /etc/init.d/foo looks good to me at a first glance,
> but when i've done reading it i'm a bit worried about problem tracking
> issues and support issues.
> it will become harder to track problems in rc script as rc script
> will be tailor-made to the installation site. if random user says
> that she has some problem with start up script, we basically have
> to get her script, read it through, to track the problem.
we're going to ship with /etc/rc as the `static' file by default.
it's much easier, and boots in about 1/2 the time that /etc/rc.sh does
(on my ss10 anyway)
> since there's little manpower to handle PRs, I would vote to stick
> with simple-and-static rc and rc.conf...
(i don't buy that as a justification; if we used that we wouldn't add
any new features to the tree, incase they may cause a PR to be raised :)
Given that the new scheme isn't really compatible with System V (or
Linux, FreeBSD etc.) (no runlevels, no S/K semantics and so forth),
I think we should lose the rc.d/init.d name. Apart from the appalling
uglyness of the .d notation, it might confuse people into assuming real
compatibility.
Other than that, I think the new scheme looks good. I honestly would
prefer the extremely robust static rc + rc.conf setup we have now,
because there are so few things that can break, and it's not like we
have gobs of commercial packages that demand being able to install a
startup script by dropping a file anyway, but I realise that a lot of
people want this. If we switch, and it looks that way to me, I think we
should do it whole-heartedly and not maintain old-rc compatibility as
the old simplicity won't really be there anymore and that sort of dual
system-ness tends to lead to confusion in general.
--
Soren
I would like to see "reload" and/or "restart", too.
Kind regards
--
Matthias Scheler http://www.sighardstrasse.de/~tron/
Please do NOT do /etc/rc.d/init.d -- that's a nasty hackery; if you
must use init.d, put it directly in /etc.
Maybe more on this later, but a plea from an old-timer: PLEASE
don't make the sys-V-ish thing the default.
--*greywolf;
--
A _Real_ Operating System for _Real_ Hackers.
____ __ _ ____ __ __ ___ ___ ___
___ / | / /__ _/ /_ / |/ __\ / _ |
__ / |/ // _\/_ _/ / ' / _ \ / / /
_ / /| // __/ / /_ / , | __/ // / ,/
/_/ |__/___/____//___/____//___'
With many thanks to the core team and UCB CSRG.
How about `status' too ?
0 = started successfully
1 = failed to start
2 = starting (not completed)
3 = not configured to be started (/etc/rc.conf turned this script off
but it's still in /etc/rc3.d because mkrc hasn't been rerun)
"reload/restart" would be another useful one.
I'd consider both of those as "must have" before adding this to
NetBSD, based on what's in the marketplace today.
> * The ability to generate /etc/rc and /etc/rc.shutdown
> from `/etc/init.d/*'.
Good.
> * Implementers should be able to add extra actions to a
> script (e.g, `reload', `debugon', etc) fairly easily.
Any `additions' should be standard across all scripts which are
NetBSD derived (vs 3rd party) - even if they're null ops so that
invalid actions always return errors.
[...]
> NOTE: During development this directory was called `/etc/rc.d'.
> It was changed to `/etc/init.d' because:
> a) prior art (cf. SYSV), and people are used to running
> /etc/init.d/foo start
Or /etc/rc2.d/foo start
And what about /etc/rcS.d ?
> c) /etc/rc.sh
>
> A script which effectively does:
> for i in `rcorder /etc/init.d/*`; do
> $i faststart
> done
> (`faststart' is like start but without the check for
> running processes).
>
> If a user wants to use this method (instead of having to
> rebuild /etc/rc when necessary), just symlink /etc/rc.sh
> to /etc/rc.
"faststart" seems like a bad idea to me. It seems to me something
like what you'd use in testing, but that's about it. Or maybe you'd
use it when booting a vax so that it boots `today' ;) Granted this
is pretty much what we do today, but who's to say that's something
to brag about ? :->
[...]
> ====
> # PROVIDE: mountd
> # REQUIRE: beforemountlkm network portmap
Is that meant to mean "before mountlkm" or "before mount lkm" ? Or is
"beforemountlkm" really the name of a single script ? If it's the latter
then the name just sucks. If either of the former, split it up.
On the whole good, but I've got one major criticism:
in an effort to not piss anyone off (too much) there's too much fence
sitting being done. I don't mind the /etc/rc still being supported
(the everything in one script version) but the rest is of concern.
There's an /etc/rcX.d which gets used sometimes and an /etc/init.d
which also gets used sometimes. It's possible to have a /etc/rcX.d
populated but then ignored by a script which independantly interrogates
scripts in /etc/init.d. From a featurism point of view, sure, it's
great that we've got all these features, but I think these two are
competing with each other and offer no real long term benefit. We
need to pick one and go with it. I think this is trying to be everything
to everyone and ultimately we'll lose.
Darren
`restart' is built in by default (does `stop' then `start', unless
otherwise specified). `reload' is only supported if asked for, because
it doesn't make sense in all contexts.
> > * Implementers should be able to add extra actions to a
> > script (e.g, `reload', `debugon', etc) fairly easily.
>
> Any `additions' should be standard across all scripts which are
> NetBSD derived (vs 3rd party) - even if they're null ops so that
> invalid actions always return errors.
???. if you do /etc/init.d/foo blah and foo doesn't support blah,
you'll get an error; this is what i'd expect. do you want every
script to support every option that another script needs (e.g,
`named' might support querylog, debug, etc)?
> > a) prior art (cf. SYSV), and people are used to running
> > /etc/init.d/foo start
>
> Or /etc/rc2.d/foo start
> And what about /etc/rcS.d ?
`prior art' to me is solaris/irix; deal with it ;-). if you want rc2.d
or rcS.d because that's what you're used to, then MAKE A SYMLINK!
> > for i in `rcorder /etc/init.d/*`; do
> > $i faststart
> > done
> > (`faststart' is like start but without the check for
> > running processes).
>
> "faststart" seems like a bad idea to me. It seems to me something
> like what you'd use in testing, but that's about it. Or maybe you'd
> use it when booting a vax so that it boots `today' ;) Granted this
> is pretty much what we do today, but who's to say that's something
> to brag about ? :->
faststart is a `backdoor' just for the startup scripts, because we
`know' that the process won't be running so we don't waste time doing
the `ps' check. if a user does `/etc/init.d/foo faststart' when foo
is already running and then they get screwed, THATS THEIR FAULT, because
it's not supported `clueful' behaviour post-boot.
> > # PROVIDE: mountd
> > # REQUIRE: beforemountlkm network portmap
>
> Is that meant to mean "before mountlkm" or "before mount lkm" ? Or is
> "beforemountlkm" really the name of a single script ? If it's the latter
> then the name just sucks. If either of the former, split it up.
[beats head against wall.] this project is not going to be held up
because someone has a hangup about what the name of a script/variable/
whatever is...
> On the whole good, but I've got one major criticism:
>
> in an effort to not piss anyone off (too much) there's too much fence
> sitting being done. I don't mind the /etc/rc still being supported
> (the everything in one script version) but the rest is of concern.
> There's an /etc/rcX.d which gets used sometimes and an /etc/init.d
> which also gets used sometimes. It's possible to have a /etc/rcX.d
> populated but then ignored by a script which independantly interrogates
> scripts in /etc/init.d. From a featurism point of view, sure, it's
> great that we've got all these features, but I think these two are
> competing with each other and offer no real long term benefit. We
> need to pick one and go with it. I think this is trying to be everything
> to everyone and ultimately we'll lose.
but you're asking for stuff that's effectively fence sitting as well!
.
netbsd will ship with *one* method of running rc, but provide the
system administrator with the flexibility to choose from a couple of
others if they so desire. saying that we shouldn't support this
flexibility is like saying we shouldn't support anything other than
sendmail (vs postfix/qmail) , /bin/mail (vs 100s of MUAs), /bin/sh
(vs csh/zsh/tcsh/bash), etc. it doesn't cost us that much, and gives
us the `win' that system administrators think our system is flexible.
imho, the only real valid point i've seen in this thread so far is
hubert's regarding how to support packages; i genuinely forgot to
mention some thoughts on how to address that (and will do so RSN). the
rest of the discussion appears to be hair splitting about personal
preferences, or other `problems' that were already solved but i forgot
to document them in my initial post; if you read the source you'd see
it wasn't an issue...
(slightly grumpy) luke.
Agreed.
> > > * Implementers should be able to add extra actions to a
> > > script (e.g, `reload', `debugon', etc) fairly easily.
> >
> > Any `additions' should be standard across all scripts which are
> > NetBSD derived (vs 3rd party) - even if they're null ops so that
> > invalid actions always return errors.
>
> ???. if you do /etc/init.d/foo blah and foo doesn't support blah,
> you'll get an error; this is what i'd expect. do you want every
> script to support every option that another script needs (e.g,
> `named' might support querylog, debug, etc)?
Yes. The actions should be supported by all scripts. They may do
nothing or they may do something. At least that way when you want
to do something like "for i in /etc/init.d/*; do $i querylog; done"
you don't get a bunch of crap from scripts which don't support that
particular switch. I think things like the cachefs.daemon script
on Solaris7 are bad examples (that particular script has been written
in such a way that it does start but not stop). The S99dtlogin is
another bad example because it supports a bunch of switches which
are otherwise unused elsewhere (reset/update_printers/get_server_pid).
There should be some semblance of orthogonal design across all the
scripts.
> > > a) prior art (cf. SYSV), and people are used to running
> > > /etc/init.d/foo start
> >
> > Or /etc/rc2.d/foo start
> > And what about /etc/rcS.d ?
>
> `prior art' to me is solaris/irix; deal with it ;-). if you want rc2.d
> or rcS.d because that's what you're used to, then MAKE A SYMLINK!
Well, Solaris has /etc/rc[012356S].d so nerh. Each of the run levels
is also different in terms of what is started, etc. You don't want to
go the extra step and create a "RUNLEVEL" tag in your scripts, do you ?
*poke*
[...]
> faststart is a `backdoor' just for the startup scripts, because we
> `know' that the process won't be running so we don't waste time doing
> the `ps' check. if a user does `/etc/init.d/foo faststart' when foo
> is already running and then they get screwed, THATS THEIR FAULT, because
> it's not supported `clueful' behaviour post-boot.
To me it sounds like you're saying "faststart" should be our default startup
method, here, which I think is wrong.
[...]
> > On the whole good, but I've got one major criticism:
> >
> > in an effort to not piss anyone off (too much) there's too much fence
> > sitting being done. I don't mind the /etc/rc still being supported
> > (the everything in one script version) but the rest is of concern.
> > There's an /etc/rcX.d which gets used sometimes and an /etc/init.d
> > which also gets used sometimes. It's possible to have a /etc/rcX.d
> > populated but then ignored by a script which independantly interrogates
> > scripts in /etc/init.d. From a featurism point of view, sure, it's
> > great that we've got all these features, but I think these two are
> > competing with each other and offer no real long term benefit. We
> > need to pick one and go with it. I think this is trying to be everything
> > to everyone and ultimately we'll lose.
>
> but you're asking for stuff that's effectively fence sitting as well!
Well, I'd go for sitting on less fences, if that makes sense :) Personally,
I like the idea of supporting /etc/rc as well as the init directory thing,
but do we need to have multiple init directory based things ? I mean, it's
not like we're trying to turn NetBSD into Linux, is it ?
Darren
i don't think it's fence sitting...so i'll have to pop in here.
for a netbsd system, "kill 1" will always return the sysadmin to a
single user system with *nothing* else running. for a solaris system
"shutdown -iS -g0 -y" will possibly return you to a single user system
with nothing running. you'll certainly be at the single user run
level, but there might be tons of stuff running because the moron
administering the stupid operating system as adding scripts to the rc
directories where they needed to be started without a mind for
shutting them down at a later point.
linux (redhat, at least) attempts to gloss over this problem by
providing a nice gui "run level editor" so that one can pick and
choose from the six run levels easily enough and make sure that what's
started is stopped in the right places, but with *no regard for
attempting to enforce any sanity on the situation*. it just makes it
easier to screw up your machine by using your mouse.
since we don't have "runlevels" (and neither do we need them, imho),
what assurance do i have that this can't (or won't be able to) happen
to netbsd systems now, with this new scheme?
--
|-----< "CODE WARRIOR" >-----|
codew...@daemon.org * "ah! i see you have the internet
twof...@graffiti.com (Andrew Brown) that goes *ping*!"
and...@crossbar.com * "information is power -- share the wealth."
I have been using rc.local files for a long time now and my
previous experiences with /{etc,sbin}/init.d stuff had been
devastating. In fact, I only tried to use them a few times on
Solaris and this scheme was very frustrating (the number stuff
and especially the fact that making a new startup script was a
pain in the ass).
I now use at work Tru64 UNIX (previously known as DIGITAL UNIX,
or even OSF1 before), by the way one of the best commercial
UNICes, that has a startup sequence based on /sbin/init.d files.
Though I found this awkward at the beginning, as time passed, I
started to like the ability to use /sbin/init.d/foo start and
/sbin/init.d/foo stop, which gives much more flexibility than the
rc.local scheme on a much cleaner way.
I really like the way /etc/init.d is implemented in your proposal
because all the complexity (recognizing if the script is invoked
with start or stop...) is hidden in the run_rc_command function.
The local file also provides rc.local functionnality for people
no liking the /etc/init.d stuff (I understand people can dislike
this, as that's been my case before).
I have a request to make tough. Please include an fully
commented EXAMPLE script so that people can easily make their own
scripts from the ground up. A README file in /etc/init.d would
also be appreciated. Not providing such files is one of the
biggest criticisms I can make to systems using such a scheme.
Anyway, I like this system and it would be a good thing to
provided it with the next major release of NetBSD.
--
Marc Baudoin -=- <bab...@babafou.eu.org>
> Feedback
> ========
>
> Thoughts/comments?
Hello Luke,
I guess I wouldn't change a thing... I think the current method of
using /etc/rc to start programs based on information from /etc/rc.conf
works fine. By adding extra config files and directories I think the
administration process for the startup scripts becomes more complex.
At work I use machines running AIX and I find that having to deal with
/etc/inittab, all of the /etc/rc.* scripts and contents of the /etc/rc2.d
directory to be a real pain at times. I really like the simplicity of
NetBSD's startup process.
Brian
-------------------------------------------------------------------------
| Brian Stark | Internet : bst...@siemens-psc.com |
| Siemens PT&D, Inc. | Voice : +1 612 536-4697 |
| Power Systems Control Division | Fax : +1 612 536-4919 |
| 7225 Northland Drive, Brooklyn Park, Minnesota 55428 USA |
-------------------------------------------------------------------------
> b) /etc/init.d/
>
> This contains files - one for each function to execute on
> startup - which can either be invoked directly or used to
> generate /etc/rc (via mkrc).
>
> Currently there are 75 scripts in /etc/init.d.
>
> NOTE: During development this directory was called `/etc/rc.d'.
> It was changed to `/etc/init.d' because:
> a) prior art (cf. SYSV), and people are used to running
> /etc/init.d/foo start
> b) `completion-conflict-with-rc[03].d' asthetics :-)
>
> If there's a strong argument for /etc/rc.d over
> /etc/init.d, we could rename it to /etc/rc.d.
Can the scripts in `/etc/init.d' be invoked directly, as in
`/etc/init.d/nfs stop'? This is not clear as the example scripts do
not seem to be directly executable.
If not, i.e. you need to run some interpreter on them explicitly, I
would not use the `/etc/init.d' name as that will add confusion.
=========================================================================
Eduardo Horvath e...@netbsd.org
"I need to find a pithy new quote." -- me
>
> This reads to me like a requirement on the design, not a specification
> of how this system implements the requirement. i'm looking for the
> latter...
>
> it implements it using exactly the same methods that /etc/rc does,
> right now (ie, 'checkyesno'). this work is 100% fully backwards
> compatible with the current rc.conf -- anything else would be
> completely unacceptable.
So how does this jive with supporting SysV usage? I must be missing
something.
Yes, you can invoke them directly. The scripts are installed executable.
first of all, thanx for working on this issue, which has
been discussed many times in heated discussions on various
NetBSD-mailing lists!
> A new system should have the following attributes:
> * Separate scripts for each function, which support
> `start' and `stop' type functionality.
> * Ordering with more control than numeric prefixes on
> scripts (c.f. rcorder(8)).
> * Control over a function via /etc/rc.conf (rather than
> via the existance of a file/link in /etc/rc*.d).
> * The ability to generate /etc/rc and /etc/rc.shutdown
> from `/etc/init.d/*'.
> * Implementers should be able to add extra actions to a
> script (e.g, `reload', `debugon', etc) fairly easily.
> * Optional checks that a process isn't running before
> starting, is running before stopping, etc...
IMHO, the new system should also be compatible to System V init
mechanism.
I think it has been mentioned before but your scheme is missing
the ability to have real run levels. I know this could be implemented
using your scheme, but you do not seem to provide this. Is this
something that is left as an excercise to the user or do you
plan implementing this?
The init.d scripts you provide (they are still in rc.d in
your tar-file :-) have a proposed structure. Is there anything
that forces me (or any software vendor, for that matter) to
follow this scheme? Let's say I want to have the least differences
between my Solaris edition and my NetBSD edition. Can I just
drop in/use the "normal" Solaris scripts, i.e. without
setting any variables/using the /etc/rc.subr commands?
I think the sysV Sxx/Kxx version will still work, but
will the creation of /etc/rc still work?
Besides that, great work! It is not exactly what I would
have implemented. I tend to agree with others that we
should drop support for the old rc scheme completely, but
if there are enough people who still "need" the rc-way... :-)
Maybe we should simply do a poll to find out. On the
other hand, I didn't step up to do the implementation,
so I have to and do accept what you have come up with.
It looks like a good compromise. The only thing left
for discussion is now, what will be the default settings
used when NetBSD is shipped :-) What are your plans on
this?
Thanx again, and don't get grumpy on users complaining
about your proposal. This seems to be a very sensible
area for BSD-people.
Guenther
> It has been felt by many people that NetBSD needs a more flexible
> method of system startup scripts. Exactly what model is used to
> improve flexibility is a contentious issue, but we feel that this
> proposal has the benefits of many other systems without the warts,
> whilst retaining backward compatibility for those that require it.
Yay.
> A `traditional' SYSV ``/etc/init.d/'' directory has been suggested,
> but there a various `warts' in that system that can be rectified
> in a new design.
Probably worth expounding on the perceived warts a bit more (such as
the utter lack of compatibility in the various modern SysV
implementations)
> Scope
> =====
>
> A new system should have the following attributes:
> * The ability to generate /etc/rc and /etc/rc.shutdown
> from `/etc/init.d/*'.
An interesting choice. Is it intended that the generated scripts will
be editable, or should editing be through the original scripts and
re-generation? If the latter, it's probably worth adding some "#
GENERATED BY ... - DO NOT EDIT" lines to the resulting files.
I also see accidental failure to regenerate rc/rc.shutdown as a pretty
annoying misfeature, so a comment or even echo command that says
"Generated at Wed Dec 1 16:49:25 EST 1999" could be useful.
> a) Extra functions in /etc/rc.subr
> check_process procname
> Ensures that a process (or processes) named procname
> is running. Prints a list of matching pids.
This is nigh-impossible to get totally right. It should probably deal
with paged-out processes that show up as (process), and the
documentation should mention problems with setproctitle()-happy
daemons (sendmail, for example) and user-named processes unrelated to
the actual service (it'd be an annoying DoS attack if I could just run
some programs that happened to be named "portmap" and "mountd" that
kept the sysadmin from restarting those).
Checking the uid might be a win here.
> d) /etc/rc.shutdown.sh
>
> Similar to /etc/rc.sh, but reverses the order of the output
> of `rcorder /etc/init.d/*`, and calls each script with `stop'.
This makes me nervous on a few levels. First, I'm not sure that
backwards order is really right, although a counterexample does not
immediately leap to mind. Second, some of the shutdown steps, while
the opposite of the startup steps, are far from necessary (cf. quota).
Finally, it depends (even more than the startup stuff does) on "foo
stop" actually stopping the service and not continuing until it's
dead. I guess for cases like the classic "Shut down the database
before unmounting the disks" case, the stop script should be smart
enough to wait until it's really gone, not just exiting after sending
the TERM signal.
> e) /etc/rc.sysv.sh
>
> A script which effectively does:
> for i in /etc/rc3./S*; do
> $i start
> done
>
> This is provided for users who like the `Sxx' and `Kxx' style
> names.
Ew. Can we get a quick show of hands from people who actually want
this? I don't object, generally, to having tools to do things in
different ways, but I don't want us to really support this, either.
> f) /sbin/mkrc
>
> Depending upon the options, mkrc generates /etc/rc, /etc/rc.shutdown,
> /etc/rc0.d and /etc/rc3.d from /etc/init.d/*.
>
> The generated /etc/rc{,.shutdown} is rather readable sh script
> (especially for machine generated scripts!)
>
> /etc/rc0.d will contain symlinks from KxxFOO -> ../init.d/FOO.
> /etc/rc3.d will contain symlinks from SxxFOO -> ../init.d/FOO.
>
> g) /etc/netstart
>
> A wrapper for /etc/init.d/network and /etc/init.d/ppp
Purely for historical compatibility for people who ran it directly? It
doesn't seem to be generated; would it make more sense for it to run
network and ppp, rather than including them? More potential
consistency problems otherwise.
> This is one of the more complicated startup scripts. It uses a
> different rc.conf variable than the daemon name, it depends upon
> /etc/exports, a `pre command' operation is run before the actual
> daemon if all the startup conditions are met.
This highlights a weakness in our current setup that the proposed
scheme does not improve on (not that it necessarily should, especially
in an early pass), which is handling failures. Execution based on
rcorder output, without preserving the dependencies and keeping track
of what has been provided and is required, does not give us the
ability to, for example, avoid starting nfsd if mountd failed (perhaps
/etc/exports was toasted in an unclean crash).
This is much more an area for future exploration than a deficiency of
the proposed scheme.
> Feedback
> ========
>
> Thoughts/comments?
* There should be well-documented names that scripts should REQUIRE
(network, daemon, and login are the obvious candidates) for reasonable
operation that does not depend on the exact set of services
run. Perhaps those documented points should always be dummies......
> * Optional checks that a process isn't running before
> starting, is running before stopping, etc...
> * Separate scripts for each function, which support
> `start' and `stop' type functionality.
> a) prior art (cf. SYSV), and people are used to running
> /etc/init.d/foo start
* It's not clear whether the purpose of each of the /etc/init.d
scripts for a service is "perform boot time/shutdown time operation"
or "start and stop". The implementation looks like the former, since
all invocations of /etc/init.d/foo {start,stop} call checkyesno();
but those two bits of the description cover both cases (and it seems
that the check-before-starting is the default, rather than an
option).
* Minor bug in rc.subr's check_process() function:
check_process()
{
_procname=$1
if [ -z "$_procname" ]; then
err 3 'USAGE: check_process procname'
fi
_procnamept=`basename $_procname`:
That trailing : gets stuck to _procnamept and hence the process
doesn't get found.
* rcorder-related stuff:
I note that the dependency of foo on bar can be expressed by
"# REQUIRES: bar" in foo or "# BEFORE: foo" in bar. I see the impulse of
generality that led here, but it's not clear which is appropriate for
what cases, and there is one place in the sample where both are used:
local is "# BEFORE: login" and login is "# REQUIRES: local"
Oh, and rcorder(8) mentions but doesn't actually describe BEFORE.
* Documentation is key (but you knew that). If you like I can do some
writing.
Thanks for working on this!
- Nathan
This is losing.
There are lots of programs which already ship with scripts to properly
start and stop their daemons. The one which pops into minde
immediately is ndc, though there are plenty of others out there for
third-party software.
Further, sysadmins everywhere have created many scripts to start local
daemons over the years.
Basically, what a scheme like this -- which requires additional
script commands -- does is either:
* force these scripts to be specially hacked for NetBSD (to add those
special commands), or
* force people to reimplement them with the happy shell-command
meta-language which seems to have been implemented.
From the point of view of maintainability, compatiblity with existing
systems (i.e. what people know about and understand), and getting
third party vendors to produce startup scripts which are useful with
NetBSD, I think this is less than optimal.
(we're still waiting on the description of how third-party scripts get
integrated into your world, unless i'm mistaken.)
In my perfect world, each there'd be a nice template init.d script
which showed the basic skeleton of what to implement (i.e. the
standard targets), then each individual init.d script would implement
those bits, plus whatever else you wanted to. And, for instance, you
could just think of ndc or other similar scripts as things to symlink
into the init.d directory. This is nice: every script shows you the
right thing to do, you don't need to read a twisty little maze of
shell functions to do it, and you've got literally dozens of good
examples of what to do.
The right way to create an /etc/rc isn't to magically put together all
of the commands from these files, it's to generate a list of commands
like:
set -e
/etc/init.d/foo start
/etc/init.d/bar start
/etc/init.d/baz start
In fact, i'd go so far as to say that a hard-coded /etc/rc should be
for die-hards only, and that the default would be something that
figured out what to run and ran it dynamically.
A couple of other points:
* i'm generally in favor of something like this... but I think this
method includes _way_ too much magic.
* part of the business of being OS developers is that we figure out
the right technical solution for the customers' needs is. It's not at
all obvious to me that there's a real need to support all of the
features you have here. (for instance: while static startup
configuration is nice, being able to generate the perfect /etc/rc from
that static startup configuration seems ... over the top.)
* it's not obvious to me how you can support fine grained ordering
_except_ by resorting to sysv S* and K* numbering. how would you do
that useing the requires/provides features? what happens to things
which generally depend on one set of features, e.g. networking being
up, but nothing else? (i.e. how are they ordered, w.r.t other
things that also require just networking, and those which require
networking and more, but for which there are no actual dependencies.)
The nice thing about the sysv S* and K* numbering is that it's all
very explicit what's going on and when...
cgd
--
Chris Demetriou - c...@netbsd.org - http://www.netbsd.org/People/Pages/cgd.html
Disclaimer: Not speaking for NetBSD, just expressing my own opinion.
> Yes. The actions should be supported by all scripts. They may do
> nothing or they may do something. At least that way when you want
> to do something like "for i in /etc/init.d/*; do $i querylog; done"
> you don't get a bunch of crap from scripts which don't support that
> particular switch. I think things like the cachefs.daemon script
> on Solaris7 are bad examples (that particular script has been written
> in such a way that it does start but not stop). The S99dtlogin is
> another bad example because it supports a bunch of switches which
> are otherwise unused elsewhere (reset/update_printers/get_server_pid).
> There should be some semblance of orthogonal design across all the
> scripts.
>
> this is ludicrous! these scripts are modular *individual* beings.
> if you attempt to force a defined set of `operations' on them, you
> will cripple them. it does not allow for expansion. personally,
> if i call a script with an unsupported argument, i *want* it to fail
> for me!
What about a rc.conf option that allows silent failures for unsupported
arguments? Obviously not all 3rd party rc scripts would know about this
(and we can "fix" this with pkgsrc), but it would seem to keep both
camps happy.
Then Nathan Williams wrote:
> Luke Mewburn <lu...@cs.rmit.edu.au> writes:
>
> > a) Extra functions in /etc/rc.subr
>
> > check_process procname
> > Ensures that a process (or processes) named procname
> > is running. Prints a list of matching pids.
>
> This is nigh-impossible to get totally right. It should probably deal
> with paged-out processes that show up as (process), and the
> documentation should mention problems with setproctitle()-happy
> daemons (sendmail, for example) and user-named processes unrelated to
> the actual service (it'd be an annoying DoS attack if I could just run
> some programs that happened to be named "portmap" and "mountd" that
> kept the sysadmin from restarting those).
>
> Checking the uid might be a win here.
Note: I haven't looked at the examples, just followed the discussion.
It seems that you may be able to:
check for /var/run/<process>.pid
else check for ps -c if <process> < MAXCOMLEN chars long
else check for ps
This should be relatively resiliant to setproctitle() changers as I'd
say most process names are less than MAXCOMLEN characters long - on a
smattering of different boxes here "rpc.frameusersd" is the longest at
exactly MAXCOMLEN...
Simon.
I've been working on a new startup scheme in Darwin/Mac OS X, and
have run into some similar problems. This may not be interesting to
you, but it might be, so I thought I'd tell you what I've done in
case it's useful.
Our old system was a series of scripts in /etc/startup. /etc/rc
would call each in order (filenames were 0100_LocalMounts,
0200_Devices, etc). Some of my goals:
- Want the ability to drop in a new script without having to give it
a number, since we could renumber the scripts between system
releases, and this is therefore fragile.
- Want to be able to launch the window system very early so we can
show boot progress graphically (eg. a progress bar), as well as
optionally booting in verbose Unix-style.
- Need to be able to extend it eventually to load in application
libraries, so we can put up a dialog and ask users for input about
something (eg. another machine is using your IP address. Start
without network? Pick a new address? etc.)
- Have start/stop functionality in each script.
I've only met some of these goals so far, but the current scheme
uses a program called SystemStarter, which is currently launched by
/etc/rc, though it will probably eventually replace /etc/rc.
"Startup Items" are directories in /System/Library/StartupItems
(in BSD that would probably be /etc/startup). Each directory
contains a program (currently all are scripts, but could be a
binary), a config file, and any resources needed by the program.
SystemStarter runs each script in an order that is affected by the
config files.
Below are my notes on how that works. You can get the source code
from the Darwin read-only CVS server. See
http://www.publicsource.apple.com/tools/cvs/ for info on that. The
module name is "Startup". Note that is uses the Apple's
CoreFoundation (CF) library for C objects like strings and whatnot,
so you won't be able to build it on BSD, but you can see what it
does. It's not much code.
-Fred
Logistics of Startup Items:
Startup items are directory bundles which contain, at a minimum,
an excecutable file and a property list text file. For a startup
item named "Foo", the bundle will be a directory named "Foo"
containing (at a minimum) an executable "Foo" and a plist file
"StartupParameters.plist".
Item Launch Ordering:
The plist file contains parameters which tell SystemStarter some
information about the executable, such as what services is provides,
which services are prerequisites to its use, and so on. The plist
contains the following attributes:
{
Description = "blah blah";
Provides = ("service", ...);
Requires = ("service", ...);
Uses = ("service", ...);
OrderPreference = "time";
Messages =
{
start = "Starting blah.";
stop = "Stoping blah.";
}
}
Note that while the above example is writting in the old
NeXT-style property list format for compactness, the new XML property
lists are also handled. You may prefer using PropertyListEditor.app
to editing the property list files manually.
Provides is an array that declares the services are provided by
this bundle. A typical bundle provides a single service. Two
bundles may not provide the same service; should multiple bundles
which provide the same service be installed on a system, the first
one encountered will be run, while the others will be disabled. It
is therefore undesireable to provide multiple services in a single
bundle unless they are codependant, as the overriding of one will
effectively override all services in a given bundle (see also "Search
Paths for Startup Items").
Requires and Uses comprise the primary method for sorting bundles
into the startup order. Requires is an array of services, provided
by other bundles, that must be successfully started before the bundle
can be run. If no such service is provided by any other bundle, the
requiring bundle will not run. Uses is similar to Requires in that
the bundle will attempt wait for the listed services before running,
but it will still launch even if no such service can be provided by
another bundle.
OrderPreference provides a hint as to the ordering used when a set
of bundles are all ready to load. Bundles which have their
prerequisites met (that is, all Requires services are launched and
all Uses services are either launched or deemed unavailable) are
prioritized in this order, based on OrderPreference:
First
Early
None (default)
Late
Last
Note that other than the above ordering rules, there are no
guarantees about the startup order of items. That is, if multiple
items are prioritized equally given the above contraints, there is no
rule for while starts first. In particular, we may be starting
multiple items in parallel at some point, and this will change the
ordering behaviour for equal-priority items. You must use the above
mechanism to ensure the correct dependancies have been met.
Description is a general-use string describing the item, for use
by Admin tools. The Messages property provides strings which are
displayed by SystemStarter during startup and shutdown.
Search Paths for Startup Items:
Startup items may be placed in the "Library" subdirectory of the
primary file domains ("System", "Local", and "Network"). The search
order is defined by routines defined in NSSystemDirectories.h: Local,
then Network, then System. However, because the Network mounts have
not been established at the beginning of system startup, bundles in
/Network is currently not searched; this may be fixed later such that
/Network is searched when ti becomes available. This search order
does not define the startup order, but it does effect the handling of
conflicts between bundles which provide the same services.
Executables and Bundles:
Presently, SystemStarter looks for an executable file with the
name of the bundle (eg. Foo/Foo), and runs that file with the single
argument "start" during startup. The argument "stop" is reserved for
shutdown time.
The plan is to also allow for loadable dyld bundles which get
loaded, run, and unloaded by SystemStarter. This will provide some
opportunity for SystemStarter to present a UI during startup during
special events, such as failure conditions (eg. NetInfo isn't
available), and user configuration panels (eg. Location Manager).
Shutdown:
The intent is to add a shutdown sequence in the future so that the
computer can be brought down more cleanly. The mechanism for this
is still in the design stage.
--
Wilfredo Sanchez, wsan...@apple.com
Apple Computer, Inc., Core Operating Systems / BSD
Technical Lead, Darwin Project
1 Infinite Loop, 302-4K, Cupertino, CA 95014
> while i'll never use, the sysv option, i can not see any harm in
> supporting its existence as non-default.
I can. It will introduce constraints and maintenence demands that
may require later abandonment.
If you execute one of these scripts in `/etc/init.d' does it just
execute that script or do a dependency check and properly invoke other
dependent scripts? Or to word it another way, is there a provision to
bring the system to an arbitrary boot configuration level without
resorting to pattern matches on `/etc/rc?.d'?
> Luke Mewburn <lu...@goanna.cs.rmit.edu.au> writes:
> > this is a tricky issue. for the `autogeneration' to work the script
> > has to support argument `dumpstart' and `dumpstop', which output
> > a series of commands which do what `start' and `stop' do
> > (respectively).
>
> This is losing.
I'm not completely convinced that's true. If a script doesn't
implement `dumpstart' or `dumpstop', mkrc could simply add the
`/etc/init.d/foo st{art,op}' command instead. Actually, I wonder why
it doesn't do this anyway; the speed issue just can't be that large.
> The nice thing about the sysv S* and K* numbering is that it's all
> very explicit what's going on and when...
Except that (at least) Solararis doesn't promise that there is any ordering!
-is
I hadn't considered doing that (adding /etc/init.d/foo st{art,op} if
dumpstart returning nothing or a non-zero exit code). It sounds
reasonable; I'll take a look.
Just FYI: there was a speed issue in booting; my SS10/50 took about
twice the time to boot by running "/etc/init.d/* start" than running
the generated rc. I can't recall if the former was using the
`faststart' hack at the time. Further investigation should be be done.
Marc Baudoin <bab...@babafou.eu.org> wrote:
> Luke Mewburn <lu...@cs.rmit.edu.au> wrote:
> > This document describes a proposal for an implementation of
> > /etc/init.d/* scripts for NetBSD. It is based on work and ideas
> > by Luke Mewburn, Matthew Green, and others.
>
> I have been using rc.local files for a long time now and my
...
> I have a request to make tough. Please include an fully
> commented EXAMPLE script so that people can easily make their own
> scripts from the ground up. A README file in /etc/init.d would
> also be appreciated. Not providing such files is one of the
> biggest criticisms I can make to systems using such a scheme.
A man page, which describes, what and how things should be implemented
in the scripts, would be a good idea. One of the best things in UNIX
is the "central" point of documentation, with the man pages. I think
section 5 file formats are the right place.
...
> Anyway, I like this system and it would be a good thing to
> provided it with the next major release of NetBSD.
I also like it.
...
++ itojun wrote that it will be harder to track problems on startup.
I think with proper logging, maybe enforced by the framework, it shouldn't
be a problem.
++ Darren Reed wrote:
> Any `additions' should be standard across all scripts which are
> NetBSD derived (vs 3rd party) - even if they're null ops so that
> invalid actions always return errors.
And some want to the scripts to fail and some not. I would follow
"Simon Burge" to have a way to allow silent failures for unsupported
commands. Maybe the scripts should have an additional line "# OPERATIONS"
with a list of all supported commands.
There where also some discussion about a "# BEFORE" line, which I really
think it's required. i.e. I use exchangeable hard disks and will need
different "fstab" to get all automaticly mounted. I can simply write a
script, that checks the disk labels and switch between the set of "fstab"
files, but this must be done before the not critical file systems are
mounted.
++ Nathan J. Williams wrote:
> > Similar to /etc/rc.sh, but reverses the order of the output
> > of `rcorder /etc/init.d/*`, and calls each script with `stop'.
>
> This makes me nervous on a few levels. First, I'm not sure that
> backwards order is really right, although a counterexample does not
> immediately leap to mind. Second, some of the shutdown steps, while
> the opposite of the startup steps, are far from necessary (cf. quota).
See above and empty operation or not implemented and silently ignored.
> Finally, it depends (even more than the startup stuff does) on "foo
> stop" actually stopping the service and not continuing until it's
> dead. I guess for cases like the classic "Shut down the database
> before unmounting the disks" case, the stop script should be smart
> enough to wait until it's really gone, not just exiting after sending
> the TERM signal.
Be careful, the shutdown should always work, there must be a way to
continue, if a part fails to shutdown. For this timeouts are need, an
other line '# TIMEOUT' or a central value? Should the stop be split into
a graceful stop and a force stop?
BTW. I have not found the rcorder command, is this part of 1.4.1?
have a nice day
Bernd Salbrechter
Huh? Maybe look at /etc/rc? and sh(1) ...
No, it has just been added to -current.