[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Initscripts management proposal



On Wed, Feb 16, 2000 at 11:35:28AM -0500, Theodore Y. Ts'o wrote:
> Initiscripts management proposal for the LSB
> ============================================
> 
> XXX The idea is to put together a scheme which can provide much faster
> (parallel) boot startups, but not require distributions should use it.
> It should be compatible with with the old rc.d/init.d scheme.

FWIW, I coded up something like this a while ago (well, I took some
stuff that Richard Woodcock and Richard Braakman had started, and made
it actually do stuff). It didn't actually go noticably faster on my
machine (it's uni-processor, and doesn't have any particular problems
with waiting for DNS lookups etc), so we basically just dropped it. The
headers were required to include:
	# Name: <foo>
	# Needs: <bar> <baz>
	# Provides: <quux>
or similar. Lots of fun, didn't actually do much good. [0]

> Packages that need to execute a script at bootup and/or shutdown will
> provide an init.d file.  This file is either installed in some
> standard directory (i.e. /etc/init.d --- which may be a symbolic link
> to some other location), or we specify the use of an installation
> shell script which copies the file to the correct.  This is more
                                                  ^^^ location
> complicated; I would prefer a standard installation directory, which
> may be a symlink if necessary.

Agreed. /etc/init.d/ for everyone's much more convenient.

> In the init.d file, information about the shell script is delimited by
> the strings "### BEGIN INIT INFO" and "### END INIT INFO".  Inside
> this block declarations shall take the form of "# <keyword>: [arg1]
> [arg2] ..."  The following keywords, with their arguments are defined
> in this specification:
> 
> 	# Provides: <boot facility 1> [<boot facility 2> ...]
> 	# Required-Start: <boot facility 1> [<boot facility 2> ...]
> 	# Required-Stop: <boot facility 1> [<boot facility 2> ...]
> 	# Default-Start: <run level 1> [<run level 2> ...]
> 	# Default-Stop: <run level 1> [<run level 2> ...]
> 	# Description: <multiline description>

The description probably has i18n issues. (i18n of comments in a script
is probably less convenient than i18n of the script itself, eg, and
introducing new things which need to be translated using different
techniques seems unnecessary)

What's the point of `Default-start' and `Default-stop'? For one,
run-levels on different distributions mean different things. For another,
run-levels on different systems mean different things. I wonder if this
wouldn't be better being just a system-wide default (all new packages
go into run levels 2, 3, 4, 5), and/or depedant on the `Required-Start'
tag (if it depends on X, only start it in runlevel 5)

What's `Required-Stop' header for? Other services that should be stopped
before this service? That might be cumbersome. For example, the portmapper
ought to be stopped after the NFS server, but you probably don't want to
have:
	/etc/init.d/nfs-server
		# Required-Start: portmap
	/etc/init.d/portmap
		# Required-Stop: nfs-server

Is there any reason the `Required-Start' headers can't just be reversed
for stopping? IIRC, that's what I did in run-scripts, and it seemed
sensible at the time.

> Additional keywords may be defined in future LSB specifications.
> Distributions may define local extensions by using the prefix
> "X-<distribution name>" --- for example, "X-RedHat-foobardecl", or
> "X-Debian-xyzzydecl".  

What's with the "decl"s?

> An init.d shell script may declare using the "Requires: " header that
                                                ^^^^^^^^^^
Presumably required-start: now?

> it must not be run until certain boot facilities are provided.  This
> information is used by the installation tool or the boot-time
> boot-script execution facility to assure that init scripts are run in
> the correct order.  

This seems like it could be a nuisance to achieve with existing SysVinits;
there's only so much room for dependencies between S30foo and S40bar.
Perhaps adding a rider strongly discouraging their use wherever possible
would be good? (/usr being mounted is an obvious requirement, having
/etc/init.d/exim already running doesn't matter so much as long as
/usr/{sbin,lib}/sendmail still queues mail, eg)

Also, what should happen if a dependency *can't* be met? For run-scripts
I just treated the `provides/needs' clauses as advisories, and ignored
any circularities or missing scripts. Anything more complicated at boot
time seemed unreasonable.

> In a multiline description, each continuation line must begin with a
> '#' followed by a tab character.  The multiline description is
> terminated by the first line that does not match the '#','Tab'
> continuation specification.

I'm inclined to think an optional `/etc/init.d/foo about' would make
more sense here. Easier to get at, and (as I understand it) easy to i18n.

> Installation of init.d files
> ============================
> 
> An init.d file is installed by copying it into /etc/init.d (which may
> be a symlink to another location).  This can be done by the package
> installer.  During the package's postinstall script, the program
> "/usr/lib/lsb/install_initd" to configure the distribution's boot
> script system to call the package's init.d file at the appropriate
> time.
> 
> The install_initd program takes a single argument, the pathanme to the
> /etc/init.d file.  For example:
> 
> 	/usr/lib/lsb/install_initd /etc/init.d/inet

(FWIW, `install-initd' with a hyphen rather than an underscore would look
much less kludgy to me, but anyway.)

Isn't the /etc/init.d/ redundant?

I'd be a lot more comfortable, too, if there was a proof of concept
implementation of this that worked with the existing SysVinit startups
Debian (and RH? and everyone else?) use and the `requires/provides'
stuff discussed above. ie, one that somehow translates the dependencies
into Sxx and Kyy numbers.

> There should be a tool available to the user (ala RedHat's chkconfig)
> which can be used by the system administrator to easily manipulate at
> which init levels a particular init.d script is started or stopped.
> This specification currently does not specify such an interface,
> however.  (XXX should it?)

XXX, possibly. Possibly it should do so separately. I think distinguishing
the goals of `make it so ISVs can distribute packages installable on
Debian, RedHat and SuSE', and `make it so admins can copes with SuSE,
RedHat and Debian with minimal retraining'. I think the former's much
more important.

(IMAO, this area (updating rcX.d/* links) is a place where Debian's
severely lacking)

> Facility names
> ==============
> 
> Facility names that begin with a dollar sign ('$') are system facility
> names, defined by the LSB, and MUST be provided by distributions.  LSB
> applications should not provide system facilities.  This document
> defines the following system facility names:
> 
> 	$local_fs	all remote filesystems are mounted
> 	$remote_fs	all remote filesystems are mounted (note
> 				in some cases /usr may be remote.

Is there any reason these are separate? `$usr_mounted' or something
would make more sense to me. What, if any, certainty does depending
on `$local_fs' alone buy you?

> 	$network	low level networking (ethernet card; may
> 				imply PCMCIA running)

This interests me, and I plan on doing some more toying with it later.

I've written a tool `ifupdown' [1] which provides two binaries `ifup',
`ifdown', modelled somewhat after the way RedHat does it. (With the
provisos that RH didn't supply manpages when I looked, and I don't use
RH enough to really grok how they're meant to behave) This uses a single
config file, /etc/network/interfaces, and calls ifconfig, or pump, or
whatever as appropriate. It has some support for PCMCIA style devices,
but pcmcia-cs currently doesn't have support for it.

FWIW, my /etc/network/interfaces on my laptop looks like:

	iface lo inet loopback
	iface eth0 inet dhcp
		noauto	# PCMCIA cards don't come up at bootup

In future, I expect it to look more like:

	iface lo inet loopback

	scheme home
		iface eth0 inet dhcp
			noauto

	scheme humbug # local LUG
		iface eth0 inet static
			noauto
			address 192.168.105.26
			netmask 255.255.255.0
			gateway 192.168.105.1
			var name-server 192.168.105.1 130.102.2.15

With the `name-server' variable being passed to an external script that
modifies /etc/resolv.conf appropriately (as pump already does for dhcp).

What's my point?

My point is, this'll mean I'll need an ip-up.d directory to collect
all the scripts that find the various `var's that my configuration file
contains or the, eg, DHCP picks up from its server.

This seems very similar to having an /etc/rcNET.d/ directory, but with
a couple of extra things: they don't all start services, exactly; and
they read from some sort of variables to get the exact configuration.

There's an extra problem here. Consider a home network connected at times
(but not 24/7) to the Internet via PPP. It might want, eg, to have a name
server to resolve the local (reserved) IPs, but need to be restarted
to cope with the fact that a new route's been made, and some upstream
servers are now available. So the same script needs to be executed a
couple of times, without actually changing runlevels (we've always been
multiuser, network, just that the network's expanded a bit).

So that's just a note. For machines with changing network situations,
network services can be weird. They can need to be told stuff about
their particular environment, and can need to be restarted. They're
kinda special.

Or, at least, that's how it seems to me today. I haven't worked this
all through yet, and I haven't implemented it, and so on. So take it
with a grain of salt.

> 	$named		named is operational

Hmmm. I wonder if this shouldn't be almost implicit in $network. Before
the $network is up, you should have everything you need in
/etc/hosts. Immediately afterwards, you should have bind running.

That said, what about $portmap, needed for NFS, and presumably other
things.

> 	$netdaemons	all network daemons are running

What's this for?

> Script names
> =============
> 	1) Assigned namespace.  This namespace consists of names which
> 		only use the character set [a-z0-9].  This space is
> 		desireable for scripts which system administrators may
> 		often wish to run manually: e.g., "/etc/init.d/named
> restart"

This is /etc/init.d/bind restart in Debian. /etc/init.d/ names in Debian
are taken after the program providing the service, not the service itself;
so if you want to restart the SMTP daemon, you need to know which one
you're actually running (/etc/init.d/sendmail, exim, smail, postfix, etc).

It might be worth considering /etc/init.d/smtpd being a link to the
approrpiate one of these, via, eg, the alternatives mechanism from
Debian's POV. Similarly, it might be worth recommending that the mail
server be available to be stopped and started by admins as that name.

> 		In order to avoid conflicts these names must be reserved
> 		through the LANA (Linux Assigned Names/Numbers
> Authority).

LANA doesn't actually exist at this time, right?

> 	2) Hierarchical namespace.  This namespace consists of scripts
> 		names which look like this: <hier1>-<hier2>-...-<name>,
> 		where name is again taken from [a-z0-9], and where
> 		there may be one or more <hier-n> components.  <hier1>
> 		may either be a [a-z0-9] name assigned by the LANA, or
> 		it may be owners' DNS name in lower case, with at
> 		least one '.'.  I.e., "debian.org",
> "staroffice.sun.com", etc.

I can't imagine Debian using this, fwiw. Registering a LANA name
for the package, and using that would be much more likely. (As such,
corel.com-wordperfect, or similar might be a better example)

It may be a good idea to reserve names in all caps, like README, for
distributions to use as documentation, examples, and whatnot.

> In general, if a package or some system function is likely to be used
> on multiple systems, the package developers or the distribution SHOULD
> get a registered name through LANA, and disrtibutions should strive to
                                             ^^
> use the same name whenever possible.  For applications which may not
> be "core" or may not be commonly installed, the hierarchical namespace
> may be more appropriate.  An advantage to the hierarchical namespace
> is that there is no need to consult with the LANA before obtaining an
> assigned name.
> 
> This specification shall pre-define the following script names as:
> 
> 	apmd atd crond dhclient dhcpcd gpm halt identd inet
> 	httpd kudzu klogd lpd mcserv named nfs nfslock pcmcia
> 	portmap random routed rstatd rusersd rwhod sendmail smb
> 	snmpd sshd syslog xfs xntpd ypbind

Hmmm. May I suggest two lists? Generic services (httpd, smtpd, named,
etc) and specific implementations (apache, exim, bind, etc).

There's a list of the 250 or so init.d scripts currently in Debian at
http://master.debian.org/~ajt/initd-scripts.txt if that's of any help.

> XXX Some of these packages, such as sshd, aren't currently being
> distributed by distributions, but may in the future.

I can assure you, sshd definitely is distributed by some distributions :)

> Functions
> =========
> 
> Each LSB complaint init.d script must source the file
                ^^
> /usr/lib/lsb/init-functions.  This file must cause the following shell
                                          ^^^^ will?
> script commands to be defined.  This can be done either by adding a
> directory to the PATH variable which defines these commands, or by
> defining bash aliases.

Or using shell functions, too.

> While the distribution-provided aliases may
> choose to use bash extensions (at the distribution's option), the LSB
> init.d files themselves should only depend in /bin/sh features as
> defined by POSIX.2.

Or specify /bin/bash as their interpretor? (And have the entire package
Depend: on bash, presumably)

There's probably no big deal eitherway here. Note that their are lots
of little bashisms people fall into when /bin/sh is bash. Using `==' in
[ ... ] clauses, instead of `=' for example. It may be a better idea
just to encourage people to use /bin/bash and be done with it, as far
as the user experience goes.

> 	start_daemon [-f] [-n nicelevel] pathname [args]
> 	killproc basename [signal]
> 	pidofproc basename

Hmmm. Giving start_daemon a `fork to background' option might be useful.
Debian's start-stop-daemon utility lets you specify a pid-file for
killing a process, or an executable (in which case it compares against
/proc/<foo>/exe), and some other things. It'd probably be a good idea
to compare against that, and incorporate the good features.

> 	log_success_msg "message"
> 	log_failure_msg "message"
> 	log_warning_msg "message"

What do these buy us over `echo' or `gettext -s' ?

Debian's init scripts tend to be of the form:

	echo -n "Starting foo: foo"
	start-stop-daemon --start foo
	echo "."

which is pretty and helpful if your startup dies. Someway of achieving
something vaguely equivalent might be nice.

Cheers,
aj

[0] http://azure.humbug.org.au/~aj/run-scripts-1.0.tgz
    Warning. Modem link. Only 10k, though.

[1] Which is on CVS at sourceforge. Project name ifupdown. It's also
    in netbase in Debian, and installed for non-PCMCIA setups by the
    potato (frozen) bootfloppies.

-- 
Anthony Towns <aj@humbug.org.au> <http://azure.humbug.org.au/~aj/>
I don't speak for anyone save myself. GPG encrypted mail preferred.

 ``The thing is: trying to be too generic is EVIL. It's stupid, it 
        results in slower code, and it results in more bugs.''
                                        -- Linus Torvalds

Attachment: pgpxTx7Z2BjGt.pgp
Description: PGP signature


Reply to: