Defining the workgroup objectives

Gerrit Pape pape at gmn.smarden.org
Fri Aug 5 19:33:31 UTC 2005


On Fri, Aug 05, 2005 at 01:18:54AM +0200, Sven Mueller wrote:
> Gerrit Pape wrote on 03/08/2005 20:41:
> > On Mon, Aug 01, 2005 at 06:00:20PM +0200, Sven Mueller wrote:
> >>Sorry, but your runit concept doesn't seem to handle dependencies at
> >>all, at least not during startup. It might make sure all dependency
> > Hmm, I'm pretty sure it does, and already explained it in this thread.
> > Maybe it doesn't do it the way you think it should be done, or you
> > didn't grasp it yet.  How about you name two or three services in Debian
> > you currently use, and which need dependency handling, and I show you a
> > runit configuration for them that works, on startup as well as while
> > system uptime?
> 
> Ok, real-world example:
> drbd (network shared) partition must be mount for
> mysql daemon to be able to start.
> mysql must be up and running for postfix to start
> spampd depends on mysql as well and is needed by postfix
> postgrey depends on mysql and is needed by postfix
> Note that the way postfix is configured, it disables greylisting if
> postgrey isn't up, but starts and works as intended otherwise (accepts
> mail....)
> 
> So this is:
> drbd
> 	depends on networking
> mysql
> 	depends on drbd
> postgrey
> 	depends on mysql
> spampd
> 	depends on mysql
> postfix
> 	depends on mysql
> 	depends on spampd
> 	depends on postgrey

Great, thanks for your interest.  The network is not considered as a
service in runit currently, but as a 'system's one time task' on boot.
So should be drbd I think, it doesn't use a daemon process.  I'll start
with mysql.  To actually follow the examples, you don't need to replace
sysvinit, just install the runit package, not the runit-run package.

Create a mysql run script /etc/mysql/run, and make it executable
 #!/bin/sh
 exec 2>&1
 exec mysqld_safe

Stop mysql through the init script, and disable the init script.  Enable
the runit service by linking the service directory into /var/service/

 # ln -s /etc/mysql /var/service/

You can check the service with 'sv status mysql'.

Now postgrey, create /etc/postgrey/run, and make it executable
 #!/bin/sh
 exec 2>&1
 test -S /var/run/mysqld/mysqld.sock || exit 1
 exec postgrey --inet=127.0.0.1:60000

Run /etc/init.d/postgrey stop, disable the init script, enable the runit
service, and check with 'sv status postgrey'

 # ln -s /etc/postgrey /var/service/

In the postgrey run script the 'test -S /var/run/mysqld/mysqld.sock'
checks for the existence of the mysql socket, and the postgrey service
daemon is not started until it's there (better would be to actually try
to connect to the socket).

Create the spampd run script /etc/spampd/run
 #!/bin/sh
 exec 2>&1
 test -S /var/run/mysqld/mysqld.sock || exit 1
 exec spampd --auto-whitelist --tagall --port=10025 --host=127.0.0.1 \
   --relayport=10026 --relayhost=127.0.0.1 --pid=/var/run/spampd.pid \
   --children=3 --user=spampd --group=spampd --logsock=unix --nodetach

Again the test for the mysql socket.  Stop spampd through the init
script, disable the script, and enable the runit service

 # ln -s /etc/spampd /var/service/

Finally postfix, create /etc/postfix/run[0], and chmod +x

 #!/bin/sh
 exec 2>&1
 nc -z 127.0.0.1 10025 || exit 1
 nc -z 127.0.0.1 60000 || exit 1
 exec /usr/lib/postfix/master

netcat is used to check for the availablity of the postgrey and spampd
services, master is not started until connecting to both succeeded.  Run
/etc/init.d/postfix stop, disable the init script, and

 # ln -s /etc/postfix /var/service/

Hopefully all went fine, check with

 # sv status postfix mysql postgrey spampd

These should be the basic run scripts for these services.  On system
boot, all will be started (nearly) at once, and the dependencies sort
aut automatically.  More importantly, the dependencies also are
controlled while whole system uptime, not only on startup.

> > Take a look an the sv(8) man page, it implements an LSB init scripts
> > interface, and lets you send signals to the service daemon, reliably,
> > without the need of pid files.
> 
> Cool, once again something I overlooked. Seems I got carried away by the
> (simple) way you described runit in your mails.
> 
> >>What I really expect of any init system are various things:
> >>1) Make sure no service is started when its dependencies are not met

You can now try, disable the spampd service, and then try to restart
postfix
 # sv stop spampd
 ok: down: spampd: 0s, normally up
 # sv restart postfix
 timeout: down: postfix: 0s, normally up, want up
 # 
You might as well get a success message here, depending on your system.
Check with 'sv status spampd postfix', or 'sv status /var/service/*'
 # sv status spampd postfix
 down: spampd: 31s, normally up
 down: postfix: 1s, normally up, want up
 # 
runit will try to restart the postfix service every second, the
configuration is inconsistent, and it tries to recover.  To make the
service configuration consistent, stop the postfix service manually, or
see 2).

> >>2) Allow a graceful shutdown, taking services down before their
> >>   dependencies are stopped

Ok, let's say if the postgrey service is stopped, the postfix service
should be stopped also, before postgrey exits.  You can tell runit to do
so through a 'control' hook, see runsv(8).  Provide a script for the
postgrey service that will be run when the service should be taken down,
and make it executably (you'll need to create the control subdirectory).
Create /var/service/postgrey/control/d
 #!/bin/sh
 sv stop postfix || exit 0
 exit 1

Now first start all four services again, and then take down the postgrey
service, check with 'sv status'
 # sv start spampd mysql postgrey postfix
 ok: run: spampd: (pid 3228) 0s
 ok: run: mysql: (pid 3025) 68s
 ok: run: postgrey: (pid 3075) 67s
 ok: run: postfix: (pid 3242) 0s
 # sv stop postgrey
 ok: down: postgrey: 0s, normally up
 # sv status postfix postgrey
 down: postfix: 24s, normally up
 down: postgrey: 24s, normally up
 # 

If you want to have the postgrey service automatically taken up when
runit is told to start the postfix service, change the postfix run
script like this
 #!/bin/sh
 exec 2>&1
 sv start spampd
 nc -z 127.0.0.1 10025 || exit 1
 sv start postgrey
 nc -z 127.0.0.1 60000 || exit 1
 exec /usr/lib/postfix/master

> >>3) Allow manual stopping and starting of services, handling dependencies
> >>   and giving feedback what services were actually started/stopped or
> >>   failed to start/stop

We have seen starting/stopping, check which service are running or fail
to start with 'cd /var/service && sv status *'.

> >>4) Allow some equivalent to the /etc/init.d/<service> (force-)?reload
> >>   functionality

Divert the spampd init script, and replace it with a symlink to
/usr/bin/sv, then run '/etc/init.d/spampd force-reload'.

> >>On a truely dependency based init system, I would also expect the system
> >>to allow the local admin to:
> >>a) ask the system which services some service depends on
> >>b) ask the system which services depend on some service

This also is possible, but would require some better organization
of the dependency information, I haven't documented yet anythin about
it.

> Ok then. Please show me for the dependencies I listed above how I
> achieve 1 and 2 (it's Ok to shortcut on checks in the scripts, simply
> write check_for_X or something in place of an actual check), if not too
> difficult, 3 would also be nice. I checked the docs again (though not
> thoroughly), but I still don't see how you actually work with the
> dependencies. Maybe it's simply too late at night already but anyway...
> Also it would be nice to give an example of how to add/remove a
> dependency or ask the system what dependencies need to be fulfilled for
> some service to start.
> 
> Not only for me, but also for the other readers. I think seeing actual
> examples of the runit system helps to understand it far better than
> everyone reading the docs.

I hope the examples help.  I admit, runit does things differently, and
it's most probably not easy to grasp at a first glance, if you're not
familiar with it.

Regards, Gerrit.


[0] Most probably it's desired to run the postfix checks before starting
the master, this seems to work:
 #!/bin/sh
 exec 2>&1
 nc -z 127.0.0.1 10025 || exit 1
 nc -z 127.0.0.1 60000 || exit 1
 
 daemon_directory=/usr/lib/postfix \
 command_directory=/usr/sbin \
 config_directory=/etc/postfix \
 queue_directory=/var/spool/postfix \
 mail_owner=postfix \
 setgid_group=postdrop \
 /etc/postfix/postfix-script check || exit 1
 
 exec /usr/lib/postfix/master
-- 
Open projects at http://smarden.org/pape/.



More information about the initscripts-ng-devel mailing list