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

Bug#2439: rc?.d scripts sometimes not run



Package: sysvinit
Version: 2.58-2

In July, Bruce wrote:
> The following is a replacement for /etc/init.d/rc with one added feature.
>
> If the previous run-level has the exact same start and kill scripts for a
> particular feature as the present run level, those scripts are _not_ run,
> becuse there would be no change.

There followed a brief discussion (attached below), and I had the
impression that I had established to people's satisfaction that this
was a bad idea.

I see, however, that in the most recent sysvinit this has been done.
(I've only just upgraded to the ELF init, so I don't know how long it
has been like this).

This has already led me to submit a spurious bug (which I'll close
soon) report against syslogd, because syslogd wasn't running after a
few runlevel changes and other system state changes.  I was expecting
the rc?.d scripts to ensure that the syslogd was running correctly.

Can we have the old behaviour back, please ?

Ian.

------- start of digest (5 messages) (RFC 934 encapsulation) -------
Resent-From: debian-devel@Pixar.com
Resent-Message-ID: <"cjPBRC.A.gOD.pOHGw"@mongo>
Resent-Sender: debian-devel-request@Pixar.com
From: <bruce@beagle.pixar.com> (Bruce Perens)
To: debian-devel@pixar.com
Subject: Please try this
Date: Fri, 28 Jul 1995 05:21:46 GMT
Message-ID: <mlist0728062146-10000.iwj10@cus.cam.ac.uk>

The following is a replacement for /etc/init.d/rc with one added feature.

If the previous run-level has the exact same start and kill scripts for a
particular feature as the present run level, those scripts are _not_ run,
becuse there would be no change.

If you have the same scripts in runlevel 3 as you have in runlevel 4, you
should be able to switch between them without anything being started or
stopped. This should help the people who want to change just one or two
things when switching between these run levels without stopping all of the
telnet and FTP sessions, etc.

The files are compared by their inode/device numbers. If the files are
symbolic links to the same file or hard links, they will be treated as
the same. If they are copies of the same data in separate files, they
will be treated as different. The other alternative would have been to
actually compare the contents of the files, this would have been a bit
slower and would have rattled the disk more.

Save your old copy of the file before installing this. Be sure to make
it owned by root, mode 755.

	Thanks

	Bruce

#!/bin/bash
#
# rc		This file is responsible for starting/stopping
#		services when the runlevel changes. It is also
#		responsible for the very first setup of basic
#		things, such as setting the hostname.
#
# Version:	@(#) /etc/init.d/rc Debian 2.56-6 Thu Jul 27 21:05:01 PDT 1995
#
#
# Author:	Miquel van Smoorenburg, <miquels@drinkel.ow.org>
#		Hacked to bits by Bruce Perens <Bruce@Pixar.com>
#

# Un-comment the following for debugging.
# debug=echo

  # Source function library.
  . /etc/init.d/functions

  # Now find out what the current and what the previous runlevel are.

  runlevel=$RUNLEVEL
  # Get first argument. Set new runlevel to this argument.
  [ "$1" != "" ] && runlevel=$1

  previous=$PREVLEVEL

  export runlevel previous


  # Is there an rc directory for this new runlevel?
  if [ -d /etc/rc$runlevel.d ]
  then
	avoid=""	# A list of start scripts I don't have to run.

	# First, run the KILL scripts.
	if [ $previous != N ]
	then
		for i in /etc/rc$runlevel.d/K[0-9][0-9]*
		do
			# Check if the script is there.
			[ ! -f $i ] && continue

			suffix=${i#/etc/rc$runlevel.d/K[0-9][0-9]}

			# Generate the name of the start script corresponding
			# to this stop script, the start script in the previous
			# level, and the stop script in the previous level.
			# Check these files, and see if the previous level's
			# files are links to the ones for this level.
			# If they are, this level treats this feature the same
			# as the previous level, and I don't have to run these
			# files.
			identical=0
			start=/etc/rc$runlevel.d/S[0-9][0-9]$suffix
			previous_start=/etc/rc$previous.d/S[0-9][0-9]$suffix
			previous_stop=/etc/rc$previous.d/K[0-9][0-9]$suffix

			if [ -f $previous_stop ] && [ $i -ef $previous_stop ]
			then
				identical=1
				if [ -f $start ] || [ -f $previous_start ]
				then
					if [ ! -f $start ] \
					 || [ ! -f $previous_start ] \
					 || [ ! $start -ef $previous_start ]
					then
						identical=0
					else
						avoid=$avoid" "$start
					fi
				fi
			fi

			# Kill it.
			[ $identical = 0 ] && $debug $i stop
		done
	fi
	# Now run the START scripts for this runlevel.
	for i in /etc/rc$runlevel.d/S*
	do
		identical=0
		for j in $avoid
		do
			if [ $i = $j ]
			then
				identical=1
				break
			fi
		done
		if [ $identical = 0 ]
		then
			suffix=${i#/etc/rc$runlevel.d/S[0-9][0-9]}
			previous_start=/etc/rc$previous.d/S[0-9][0-9]$suffix
			stop=/etc/rc$runlevel.d/K[0-9][0-9]$suffix
			if [ -f $previous_start ] \
			 && [ $i -ef $previous_start ] \
			 && [ ! -f $stop ]
			then
				identical=1
			fi

		fi

		[ $identical = 0 ] && [ -f $i ] && $debug $i start
	done
  fi
# eof /etc/init.d/rc

------------------------------
To: debian-devel@pixar.com
Subject: Re: Please try this

Bruce Perens writes ("Please try this"):
> The following is a replacement for /etc/init.d/rc with one added feature.
>
> If the previous run-level has the exact same start and kill scripts for a
> particular feature as the present run level, those scripts are _not_ run,
> becuse there would be no change.

This should not be necessary.

The latest (dpkg 0.93.42.1 and later) update-rc.d will not create K
links and S links in the same directories.  Since the scripts when
invoked as `start' should do nothing when the service is already
running runlevel changes should not disturb unaffected services.

I have arranged for things to be this way on my system and it works
fine.

Unfortunately if you installed your system before dpkg 0.93.42.1 you
will still have these links, as they are configuration data which the
system won't change under your feet.

My advice would be to go to /etc/rc[2345].d and delete unnecessary K
links.

There may be good reasons for wanting to shut down and restart a
service on a runlevel change - perhaps another service needs to be
running first for it to find it, for example.

Ian.
------------------------------
From: Bruce Perens <bruce@Pixar.com>
To: iwj10@cus.cam.ac.uk (Ian Jackson)
cc: debian-devel@Pixar.com, bruce@Pixar.com
Subject: /etc/init.d/rc
Date: Sat, 29 Jul 1995 18:23:22 -0700
Message-Id: <m0scN6B-000CzHC@mongo.pixar.com>

> Since the scripts when invoked as `start' should do nothing when
> the service is already running, runlevel changes should not disturb
> unaffected services.

Many existing rc scripts will start additional copies of the same
daemon when you change from one level to another. To get the behavior
you describe, every script would have to use start-stop-daemon or something
to carefully check that a daemon isn't already running before attempting
to start it. This is a complication that we should not have to require
of each individual init script.

> There may be good reasons for wanting to shut down and restart a
> service on a runlevel change - perhaps another service needs to be
> running first for it to find it, for example.

The behavior I was going after was something a bit closer to the way
/etc/inittab works for a service that exists in more than one runlevel.

	Bruce

------------------------------
To: debian-devel@Pixar.com
Subject: Re: /etc/init.d/rc

Bruce Perens writes ("/etc/init.d/rc"):
> > Since the scripts when invoked as `start' should do nothing when
> > the service is already running, runlevel changes should not disturb
> > unaffected services.
>
> Many existing rc scripts will start additional copies of the same
> daemon when you change from one level to another.

These should be fixed.  I've already reported a several such problems
as bugs, and the maintainers of changed their packages.

>  To get the behavior
> you describe, every script would have to use start-stop-daemon or something
> to carefully check that a daemon isn't already running before attempting
> to start it.  This is a complication that we should not have to require
> of each individual init script.

Firstly, I believe that that is *already* what we require.

Secondly, this is the whole reason why I wrote start-stop-daemon.
start-stop-daemon is very easy to use in most cases.  IMO requiring
its use (or the use of something with similar functionality) is not at
all unreasonable.

The only way to do this job reliably is to check what the current
state of the system is before attempting to change it.

Furthermore, K scripts that don't use start-stop-daemon will probably
occasionally kill unwisely-named user programs (most of these use
hacks involving `ps' or `killall' which are not specific enough).

> > There may be good reasons for wanting to shut down and restart a
> > service on a runlevel change - perhaps another service needs to be
> > running first for it to find it, for example.
>
> The behavior I was going after was something a bit closer to the way
> /etc/inittab works for a service that exists in more than one runlevel.

It is possible to do things like

xd:3:respawn:/usr/bin/X11/xdm -nodaemon
xe:4:respawn:/usr/bin/X11/xdm -nodaemon

to get xdm shut down and respawned on runlevel change.  The init.d
scripts are supposed to be *more* powerful, not less ...

Ian.
------- end -------


Reply to: