runit

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit b371bd55212984b35eb4d4d4834f44e008b45e80
Author: Gerrit Pape <pape@smarden.org>
Date:   Fri, 16 Nov 2001 13:54:39 +0000

Initial revision

Diffstat:
AMakefile | 41+++++++++++++++++++++++++++++++++++++++++
Adebian/changelog | 9+++++++++
Adebian/conffiles | 6++++++
Adebian/control | 19+++++++++++++++++++
Adebian/copyright | 24++++++++++++++++++++++++
Adebian/dirs | 4++++
Adebian/docs | 3+++
Adebian/postinst | 48++++++++++++++++++++++++++++++++++++++++++++++++
Adebian/rules | 123+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adoc/index.html | 82+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adoc/install.html | 46++++++++++++++++++++++++++++++++++++++++++++++
Adoc/replaceinit.html | 106+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aetc/debian/1 | 8++++++++
Aetc/debian/2 | 2++
Aetc/debian/3 | 15+++++++++++++++
Aetc/debian/ctrlaltdel | 4++++
Aman/runit-halt.8 | 35+++++++++++++++++++++++++++++++++++
Aman/runit-init.8 | 38++++++++++++++++++++++++++++++++++++++
Aman/runit-reboot.8 | 35+++++++++++++++++++++++++++++++++++
Aman/runit.8 | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apackage/CHANGES | 8++++++++
Apackage/COPYING | 24++++++++++++++++++++++++
Apackage/README | 3+++
Apackage/commands | 4++++
Apackage/compile | 31+++++++++++++++++++++++++++++++
Apackage/install | 4++++
Apackage/replaceinit | 28++++++++++++++++++++++++++++
Apackage/sharing | 3+++
Apackage/upgrade | 30++++++++++++++++++++++++++++++
Asrc/Makefile | 27+++++++++++++++++++++++++++
Asrc/TARGETS | 4++++
Asrc/init.c | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/runit-halt | 7+++++++
Asrc/runit-reboot | 6++++++
Asrc/runit.c | 208+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
35 files changed, 1153 insertions(+), 0 deletions(-)

diff --git a/Makefile b/Makefile @@ -0,0 +1,41 @@ +DESTDIR= + +PACKAGE=runit-0.1.0 +DIRS=doc man etc package src +MANPAGES=man/runit.8 man/runit-init.8 man/runit-halt.8 man/runit-reboot.8 +DAEMONTOOLS_PD=daemontools-pd-0.76 + +all: clean .manpages $(DAEMONTOOLS_PD).tar.gz $(PACKAGE).tar.gz + +.manpages: + for i in $(MANPAGES); do \ + rman -S -f html -r '' < $$i | \ + sed -e 's}NAME="sect\([0-9]*\)" HREF="#toc[0-9]*">\(.*\)}NAME="sect\1">\2}g ; \ + s}<A HREF="#toc">Table of Contents</A>}<a href="http://innominate.org/~pape/">G. Pape</a><br><A HREF="index.html">runit</A><hr>}g ; \ + s}<!--.*-->}}g' \ + > doc/`basename $$i`.html ; \ + done ; \ + touch .manpages + +$(PACKAGE).tar.gz: + rm -rf TEMP + mkdir -p TEMP/admin/$(PACKAGE) + make -C src clean + cp -a $(DIRS) TEMP/admin/$(PACKAGE)/ + ln -s ../etc/debian TEMP/admin/$(PACKAGE)/doc/ + chmod -R g-ws TEMP/admin + chmod +t TEMP/admin + find TEMP -exec touch {} \; + su -c 'chown -R root:root TEMP/admin ; \ + ( cd TEMP ; tar cpfz ../$(PACKAGE).tar.gz admin --exclude CVS ) ; \ + rm -rf TEMP' + +clean: + find . -name \*~ -exec rm -f {} \; + find . -name .??*~ -exec rm -f {} \; + find . -name \#?* -exec rm -f {} \; + +cleaner: clean + rm -f $(PACKAGE).tar.gz + for i in $(MANPAGES); do rm -f doc/`basename $$i`.html; done + rm -f .manpages diff --git a/debian/changelog b/debian/changelog @@ -0,0 +1,9 @@ +runit (0.1.0-1) unstable; urgency=low + + * Initial Release. + + -- Gerrit Pape <pape@smarden.org> Fri, 16 Nov 2001 14:01:27 +0100 + +Local variables: +mode: debian-changelog +End: diff --git a/debian/conffiles b/debian/conffiles @@ -0,0 +1,6 @@ +/etc/runit/1 +/etc/runit/2 +/etc/runit/3 +/etc/runit/ctrlaltdel +/sbin/runit-halt +/sbin/runit-reboot diff --git a/debian/control b/debian/control @@ -0,0 +1,19 @@ +Source: runit +Section: admin +Priority: optional +Maintainer: Gerrit Pape <pape@smarden.org> +Build-Depends: debhelper (>> 3.0.0) +Standards-Version: 3.5.2 + +Package: runit +Architecture: any +Depends: ${shlibs:Depends} +Description: minimal replacement for sysvinit using daemontools + runit cooperates with djb's daemontools package to create a replacement for + sysvinit. runit currently runs on Debian GNU/Linux but may be easily adopted + to other unix operating systems using glibc. If runit runs for you on any + other operating system or linux distribution, please let me know. + . + Warning: Replacing sysvinit can cause the system's boot to fail. Make sure + you are able to recover and repair your system, for example if you run a + bootloader, it should be able to pass init=/bin/sh to the kernel. diff --git a/debian/copyright b/debian/copyright @@ -0,0 +1,24 @@ +Copyright (c) 2001, Gerrit Pape +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/debian/dirs b/debian/dirs @@ -0,0 +1,4 @@ +command +package +sbin +etc/runit diff --git a/debian/docs b/debian/docs @@ -0,0 +1,3 @@ +package/README +package/CHANGES +doc/ diff --git a/debian/postinst b/debian/postinst @@ -0,0 +1,48 @@ +#! /bin/sh +# postinst script for runit +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * <postinst> `configure' <most-recently-configured-version> +# * <old-postinst> `abort-upgrade' <new version> +# * <conflictor's-postinst> `abort-remove' `in-favour' <package> +# <new-version> +# * <deconfigured's-postinst> `abort-deconfigure' `in-favour' +# <failed-install-package> <version> `removing' +# <conflicting-package> <version> +# for details, see /usr/share/doc/packaging-manual/ +# +# quoting from the policy: +# Any necessary prompting should almost always be confined to the +# post-installation script, and should be protected with a conditional +# so that unnecessary prompting doesn't happen if a package's +# installation fails and the `postinst' is called with `abort-upgrade', +# `abort-remove' or `abort-deconfigure'. + +case "$1" in + configure) + ( \ + cd /package/admin/runit-0.1.0 + package/upgrade + ) + ;; + + abort-upgrade|abort-remove|abort-deconfigure) + + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 0 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/debian/rules b/debian/rules @@ -0,0 +1,123 @@ +#!/usr/bin/make -f +# Sample debian/rules that uses debhelper. +# GNU copyright 1997 to 1999 by Joey Hess. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +# This is the debhelper compatability version to use. +export DH_COMPAT=3 + +configure: configure-stamp +configure-stamp: + dh_testdir + # Add here commands to configure the package. + + + touch configure-stamp + +build: configure-stamp build-stamp +build-stamp: + dh_testdir + + # Add here commands to compile the package. + # $(MAKE) + #/usr/bin/docbook-to-man debian/runit.sgml > runit.1 + + tar xfzvp runit-0.1.0.tar.gz + mkdir -p admin/runit-0.1.0/compile + tar xfzvp daemontools-pd-0.76.tar.gz \ + -C admin/runit-0.1.0/compile + ( cd admin/runit-0.1.0/compile ; \ + ln -s daemontools-pd-0.76 support ) + ( \ + cd admin/runit-0.1.0 ; \ + package/compile ; \ + echo "/package/admin/runit-0.1.0" > compile/home ; \ + rm -f compile/src ; \ + ln -s /package/admin/runit-0.1.0/src compile/src ; \ + ) + touch build-stamp + +clean: + dh_testdir + dh_testroot + rm -f build-stamp configure-stamp + + # Add here commands to clean up after the build process. + # -$(MAKE) clean + + rm -rf admin + rm -f debian/links + dh_clean + +install: build + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + + # Add here commands to install the package into debian/runit. + # $(MAKE) install DESTDIR=$(CURDIR)/debian/runit + + chmod 1755 debian/runit/package + cp -a admin debian/runit/package/ + rm -rf debian/runit/package/admin/runit-0.1.0/compile + rm -rf debian/runit/package/admin/runit-0.1.0/man + rm -rf debian/runit/package/admin/runit-0.1.0/doc + rm -rf debian/runit/package/admin/runit-0.1.0/etc + + # /etc/runit + cp -p admin/runit-0.1.0/etc/debian/[123] \ + debian/runit/etc/runit/ + cp -p admin/runit-0.1.0/etc/debian/ctrlaltdel \ + debian/runit/etc/runit/ + # runit programs + cp -p debian/runit/package/admin/runit-0.1.0/command/runit* \ + debian/runit/sbin/ + + # cleanup + rm -rf debian/runit/package/admin/runit-0.1.0/compile + + # create debian/links + rm -f debian/links + for i in \ + `cat debian/runit/package/admin/runit-0.1.0/package/commands` ; \ + do \ + echo "/package/admin/runit/command/$$i /command/$$i" \ + >> debian/links ; \ + done +# for i in \ +# `cat debian/runit/package/admin/runit-0.1.0/package/commands` ; \ +# do \ +# echo "/command/$$i /usr/local/bin/$$i" \ +# >> debian/links ; \ +# done + + +# Build architecture-independent files here. +binary-indep: build install +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: build install + dh_testdir + dh_testroot +# dh_installdebconf + dh_installdocs + dh_installman man/runit*.8 + dh_installchangelogs + dh_link + dh_strip + dh_compress +# dh_fixperms +# dh_makeshlibs + dh_installdeb +# dh_perl + dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install configure diff --git a/doc/index.html b/doc/index.html @@ -0,0 +1,82 @@ +<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<html> +<head> +<title>runit - minimal replacement for sysvinit</title> +</head> +<body> +<a href="http://innominate.org/~pape/">G. Pape</a> +<hr> +<h1>runit - minimal replacement for <i>sysvinit</i></h1> +<hr> +<a href="install.html">How to install runit</a><br> +<a href="replaceinit.html">How to replace init</a> +<p> +<a href="runit.8.html">The <tt>runit</tt> program</a><br> +<a href="runit-init.8.html">The <tt>runit-init</tt> program</a><br> +<a href="runit-halt.8.html">The <tt>runit-halt</tt> program</a><br> +<a href="runit-reboot.8.html">The <tt>runit-reboot</tt> program</a> +<hr> +<i>runit</i> cooperates with djb's +<a href="http://cr.yp.to/daemontools.html">daemontools</a> package to create +a replacement for +<a href="ftp://ftp.cistron.nl/pub/people/miquels/sysvinit/">sysvinit</a>. +<i>runit</i> currently runs on +<a href="http://www.debian.org">Debian GNU/Linux</a> but may be easily +adopted to other unix operating systems using glibc. If <i>runit</i> runs for +you on any other operating system or linux distribution, please let me know. +<p> +<b>Warning:</b> Replacing <i>sysvinit</i> can cause the system's boot to fail. +Make sure you are able to recover and repair your system, for example if you +run a bootloader, it should be able to pass <tt>init=/bin/sh</tt> to the +kernel. +<hr> +The command <a href="runit.8.html">runit</a> is intended to run as Unix +process no 1, it is automatically started by the +<a href="runit-init.8.html">runit-init</a> replacement if this is started +by the kernel. +<p> +<a href="runit.8.html">runit</a> performs the system's <i>booting</i>, +<i>running</i> and <i>shutting down</i> in <b>three stages</b>: +<ul> + <li><b>Stage 1:</b><br> + <i>runit</i> starts <tt>/etc/runit/1</tt> and waits for it to + terminate. The system's one time tasks are done here. + <li><b>Stage 2:</b><br> + <i>runit</i> starts <tt>/etc/runit/2</tt> which should not return + until the system is going to halt or reboot, if it crashes, it will be + restarted. Normally, <tt>/etc/runit/2</tt> runs + <a href="http://cr.yp.to/daemontools/svscanboot.html">svscanboot</a>. + In Stage 2, <i>runit</i> is able to handle the ctrl-alt-del keyboard + request. + <li><b>Stage 3:</b><br> + If <i>runit</i> is told to halt or reboot the system, or the Stage 2 + returns without errors, it terminates Stage 2 if it is running and runs + <tt>/etc/runit/3</tt>. The systems tasks to shutdown and halt or + reboot are done here. +</ul> +These are working examples for debian woody: +<a href="debian/1">/etc/runit/1</a>, +<a href="debian/2">/etc/runit/2</a>, +<a href="debian/3">/etc/runit/3</a>. +<p> +The command <a href="runit-init.8.html">runit-init</a> is intended to replace +<tt>/sbin/init</tt>. sysvinit's command <tt>shutdown</tt> will keep working. +Runlevels are not implemented in this Unix process no 1, such can easily be +done in other programs, see +<a href="http://innominate.org/~pape/djb/daemontools/noinit.html"> +Dependencies and runlevels</a> +for an example, the amount of code in process no 1 should be minimal. +<hr> +See <a href="replaceinit.html">How to replace init</a> for smoothly migrating +from <i>sysvinit</i>. +<hr> +See <a href="http://innominate.org/~pape/runit/"> +http://innominate.org/~pape/runit/</a> +for recent informations. +<hr> +<address><a href="mailto:pape@smarden.org"> +Gerrit Pape &lt;pape@smarden.org&gt; +</a></address> +<small>$Id$</small> +</body> +</html> diff --git a/doc/install.html b/doc/install.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<html> +<head> +<title>runit - installation</title> +</head> +<body> +<a href="http://innominate.org/~pape/">G. Pape</a><br> +<a href="index.html">runit</a><br> +<hr> +<h1>runit - installation</h1> +<hr> +Check that you have the recent version of +<a href="http://cr.yp.to/daemontools.html">daemontools</a> installed. +<p> +Download +<a href="ftp://ftp.innominate.org/pub/pape/runit/runit-0.1.0.tar.gz"> +runit-0.1.0.tar.gz</a> into <tt>/package</tt> and unpack the archive +<pre> + # cd /package + # gunzip runit-0.1.0.tar + # tar -xpf runit-0.1.0.tar + # rm runit-0.1.0.tar + # cd admin/runit-0.1.0 +</pre> +Compile and install the <i>runit</i> programs +<pre> + # package/install +</pre> +gzip the man pages and copy them into a reasonable directory in your +<tt>$MANPATH</tt>, e.g. +<pre> + # mkdir -p /usr/local/man/man8/ + # gzip man/runit.8 && cp -f man/runit.8.gz /usr/local/man/man8/ + # gzip man/runit-init.8 && cp -f man/runit-init.8.gz /usr/local/man/man8/ + # gzip man/runit-halt.8 && cp -f man/runit-halt.8.gz /usr/local/man/man8/ + # gzip man/runit-reboot.8 && cp -f man/runit-reboot.8.gz /usr/local/man/man8/ +</pre> +Refer to <a href="replaceinit.html">replacing init</a> for +replacing <i>sysvinit</i> with <i>runit</i>. +<hr> +<address><a href="mailto:pape@smarden.org"> +Gerrit Pape &lt;pape@smarden.org&gt; +</a></address> +<small>$Id$</small> +</body> +</html> diff --git a/doc/replaceinit.html b/doc/replaceinit.html @@ -0,0 +1,106 @@ +<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<html> +<head> +<title>runit - replacing init</title> +</head> +<body> +<a href="http://innominate.org/~pape/">G. Pape</a><br> +<a href="index.html">runit</a> +<hr> +<h1>runit - replacing init</h1> +<hr> +Follow these steps to migrate from <i>sysvinit</i> to <i>runit</i> on +<a href="http://www.debian.org/releases/woody/">Debian GNU/Linux (woody)</a>. +The <tt>/sbin/init</tt> binary is not replaced until step 6, <i>runit</i> is +the default Unix process no 1 after step 7. +<h3>Step 1: The three stages</h3> +<i>runit</i> looks for the three stages implementing the system's +<i>booting</i>, <i>running</i> and <i>shutdown</i> in <tt>/etc/runit/1</tt>, +<tt>/etc/runit/2</tt> and <tt>/etc/runit/3</tt>, create the files now: +<pre> + # mkdir -p /etc/runit + # cp -p /package/admin/runit/etc/debian/[123] /etc/runit/ +</pre> +If you want <i>runit</i> to handle the ctrl-alt-del keyboard request, do: +<pre> + # cp -p /package/admin/runit/etc/debian/ctrlaltdel /etc/runit/ +</pre> +<h3>Step 2: The runit programs</h3> +The <i>runit</i> programs must reside on the root partition, copy them to +<tt>/sbin</tt>: +<pre> + # cp -p /package/admin/runit/command/runit* /sbin/ +</pre> +<h3>Step 3: The getties</h3> +At least one getty must run in stage 2 so you are able to login, choose a +free <tt>tty</tt>, say <tt>tty5</tt>, where <i>sysvinit</i> is not running +any getty (edit <tt>/etc/inittab</tt> and <tt>kill -HUP 1</tt> if +needed) and install a getty as <i>service</i>: +<pre> + # cp -pr /package/admin/runit/etc/debian/getty-tty5 /etc/runit/ + # ln -s /etc/runit/getty-tty5 /service/ +</pre> +Check if the getty is running. +<h3>Step 4: Reboot into runit for test</h3> +Boot your system with <i>runit</i> for the first time. This does not change +the default boot behavior of your system, <i>lilo</i> will be told to use +<i>runit</i> just once: +<ul> + <li>reboot the system + <li>enter the following on the lilo prompt:<br> + <tt>init=/sbin/runit-init</tt> + <li>watch the console output while runit boots up the system + <li>switch to <tt>tty5</tt> when stage 2 is reached, a <tt>getty</tt> + should run there, you are able to login. +</ul> +If you are not using <i>lilo</i> as boot loader, refer to the documentation +of your boot loader on how to pass <tt>init=/sbin/runit-init</tt> to the +kernel. +<h3>Step 5: Service migration</h3> +The goal is to migrate all services from <i>sysvinit</i> scheme to the +<a href="http://cr.yp.to/daemontools.html">daemontools</a> design. This +can be done smoothly. For those services that are not migrated to use +<tt>run</tt> scripts yet, add the corresponding <tt>init</tt>-script +startup to <tt>/etc/runit/1</tt>, e.g.: +<pre> + #!/bin/sh + # one time tasks + rm -f /etc/runit/stopit + /etc/init.d/rcS + + /etc/init.d/kerneld start + /etc/init.d/rmnologin + + exit 0 +</pre> +It is possible to just add <tt>/etc/init.d/rc 2</tt> for having all services +from the former runlevel 2 started as one time tasks, but keep the goal above +in mind, supervising services has great advantages. +<p> +Repeat step 4 and 5, using <tt>/sbin/runit-reboot</tt> to reboot the system, +until your are satisfied with your services startup. If anything goes wrong, +reboot the system with the default <i>sysvinit</i> <tt>/sbin/init</tt> +and repair the <i>runit</i> stages, then start again at step 4. +<h3>Step 6: Replace /sbin/init</h3> +Now it is time to replace the <i>sysvinit</i> <tt>/sbin/init</tt> binary: +<pre> + # mv /sbin/init /sbin/init.sysv + # ln -s runit-init /sbin/init +</pre> +<h3>Step 7: Final reboot</h3> +The last step is to do the final reboot to boot the system with the new +default Unix process no 1 <i>runit</i>. +<pre> + # shutdown -r now +</pre> +To report success: +<pre> + # ( uname -a ; cat /etc/runit/[123] ) | mail pape-runit-0.1.0@smarden.org +</pre> +<hr> +<address><a href="mailto:pape@smarden.org"> +Gerrit Pape &lt;pape@smarden.org&gt; +</a></address> +<small>$Id$</small> +</body> +</html> diff --git a/etc/debian/1 b/etc/debian/1 @@ -0,0 +1,8 @@ +#!/bin/sh +# system one time tasks +rm -f /etc/runit/stopit +/etc/init.d/rcS + +/etc/init.d/rmnologin + +exit 0 diff --git a/etc/debian/2 b/etc/debian/2 @@ -0,0 +1,2 @@ +#!/bin/sh +exec /command/svscanboot diff --git a/etc/debian/3 b/etc/debian/3 @@ -0,0 +1,15 @@ +#!/bin/sh + +LAST=0 +test -r /etc/runit/reboot && LAST=6 + +echo 'Stopping services...' +/command/svc -d /service/* +/bin/sleep 5 +echo 'Stopping log services...' +/command/svc -d /service/*/log +/bin/sleep 5 + +/etc/init.d/rc $LAST + +exit 0 diff --git a/etc/debian/ctrlaltdel b/etc/debian/ctrlaltdel @@ -0,0 +1,4 @@ +#!/bin/sh +MSG="System is going down in 10 seconds..." +/bin/echo "$MSG" | /usr/bin/wall +/bin/sleep 10 diff --git a/man/runit-halt.8 b/man/runit-halt.8 @@ -0,0 +1,35 @@ +.TH runit-halt 8 +.SH NAME +runit-halt \- stop the system +.SH SYNOPSIS +.B init +0 +.br +.B runit-halt +.SH DESCRIPTION +.B runit-halt +causes the Unix process no 1 +.BR runit (8) +to halt the system. Normally +.B runit-halt +is run by +.BR runit-init (8) +if called as +.B init 0\fR. +.P +To signal +.BR runit (8) +the system halt request, +.B runit-halt +removes the /etc/runit/reboot file and touches /etc/runit/stopit. Then a CONT +signal is sent to +.BR runit (8). +.SH EXIT CODES +.B runit-halt +always returns 0. +.SH SEE ALSO +runit-init(8), +runit(8), +runit-reboot(8) +.SH AUTHOR +Gerrit Pape <pape@smarden.org> diff --git a/man/runit-init.8 b/man/runit-init.8 @@ -0,0 +1,38 @@ +.TH runit-init 8 +.SH NAME +init \- the UNIX process no 1 +.SH SYNOPSIS +.B init +[ 0 | 6 ] +.SH DESCRIPTION +.B runit-init +is the first process the kernel starts. If +.B runit-init +is started as process no 1, it runs and replaces itself with +.BR runit (8). +.P +If +.B runit-init +is started while the system is up, it must be either called as +.B init 0 +or +.B init 6\fR: +.TP +.B init 0 +run +.BR runit-halt (8) +to halt the system. +.TP +.B init 6 +run +.BR runit-reboot (8) +to reboot the system. +.SH EXIT CODES +.B runit-init +returns 111 on error, 0 in all other cases. +.SH SEE ALSO +runit(8), +runit-halt(8), +runit-reboot(8) +.SH AUTHOR +Gerrit Pape <pape@smarden.org> diff --git a/man/runit-reboot.8 b/man/runit-reboot.8 @@ -0,0 +1,35 @@ +.TH runit-reboot 8 +.SH NAME +runit-reboot \- reboot the system +.SH SYNOPSIS +.B init +6 +.br +.B runit-reboot +.SH DESCRIPTION +.B runit-reboot +causes the Unix process no 1 +.BR runit (8) +to reboot the system. Normally +.B runit-reboot +is run by +.BR runit-init (8) +if called as +.B init 6\fR. +.P +To signal +.BR runit (8) +the system reboot request, +.B runit-reboot +touches the /etc/runit/reboot and /etc/runit/stopit files. Then a CONT +signal is sent to +.BR runit (8). +.SH EXIT CODES +.B runit-reboot +always returns 0. +.SH SEE ALSO +runit-init(8), +runit(8), +runit-halt(8) +.SH AUTHOR +Gerrit Pape <pape@smarden.org> diff --git a/man/runit.8 b/man/runit.8 @@ -0,0 +1,64 @@ +.TH runit 8 +.SH NAME +runit \- the UNIX process no 1 +.SH SYNOPSIS +.B runit +.SH DESCRIPTION +.B runit +must be run as Unix process no 1. It performs the system's +booting, running and shutdown in three stages: +.SH STAGE 1 +.B runit +runs +.I /etc/runit/1 +and waits for it to terminate. The system's one time tasks are done here. +.SH STAGE 2 +.B runit +runs +.IR /etc/runit/2 , +which should not return until system shutdown. Normally +.I /etc/runit/2 +starts +.BR svscanboot (8). +.B runit +is able to handle the ctrl-alt-del keyboard request in stage 2, see below. +.SH STAGE 3 +If +.B runit +is told to halt or reboot the system, or the Stage 2 +returns without errors, it terminates Stage 2 if it is running and runs +.IR /etc/runit/3 . +The systems tasks to shutdown and halt or reboot are done here. +.SH CTRL-ALT-DEL +If +.B runit +receives the ctrl-alt-del keyboard request and the file +.I /etc/runit/ctrlaltdel +exists, +.B runit +runs +.IR /etc/runit/ctrlaltdel , +waits for it to terminate and then enters stage 3 for system shutdown. +.SH SIGNALS +.B runit +only accepts signals in stage 2. +.P +If +.B runit +receives a CONT signal and the file +.I /etc/runit/stopit +exists, +.B runit +is told to shutdown the system. +.P +Normally in stage 3 +.I /etc/runit/3 +checks for the file +.IR /etc/runit/reboot . +If it exists, the system is rebooted, it is halted otherwise. +.SH SEE ALSO +init(8), +runit-halt(8), +runit-reboot(8) +.SH AUTHOR +Gerrit Pape <pape@smarden.org> diff --git a/package/CHANGES b/package/CHANGES @@ -0,0 +1,8 @@ +runit 0.1.0 +Fri, 16 Nov 2001 14:01:27 +0100 + * documention + * debian package + +runit 0.0.4 +Sun, 11 Nov 2001 19:07:49 +0100 + * initial release diff --git a/package/COPYING b/package/COPYING @@ -0,0 +1,24 @@ +Copyright (c) 2001, Gerrit Pape +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/package/README b/package/README @@ -0,0 +1,3 @@ +Copyright 2001 +G. Pape +http://innominate.org/~pape/runit/ diff --git a/package/commands b/package/commands @@ -0,0 +1,4 @@ +runit +runit-init +runit-halt +runit-reboot diff --git a/package/compile b/package/compile @@ -0,0 +1,31 @@ +#!/bin/sh -e + +umask 022 +test -d package || ( echo 'Wrong working directory.'; exit 1 ) +test -d src || ( echo 'Wrong working directory.'; exit 1 ) + +here=`env - PATH=$PATH pwd` + +mkdir -p compile command +test -r compile/home || echo $here > compile/home +test -h compile/src || ln -s $here/src compile/src + +echo 'Linking ./src/* into ./compile...' +for i in `ls src` +do + test -h compile/$i || ln -s src/$i compile/$i +done + +# support, default: ../daemontools/compile +test -h compile/support || ln -s ../../daemontools/compile compile/support + +echo 'Compiling everything in ./compile...' +( cd compile; exec make ) + +echo 'Copying commands into ./command...' +for i in `cat package/commands` +do + rm -f command/$i'{new}' + cp -p compile/$i command/$i'{new}' + mv -f command/$i'{new}' command/$i +done diff --git a/package/install b/package/install @@ -0,0 +1,4 @@ +#!/bin/sh -e + +package/compile +package/upgrade diff --git a/package/replaceinit b/package/replaceinit @@ -0,0 +1,28 @@ +#!/bin/sh -e + +umask 022 +test -d package || ( echo 'Wrong working directory.'; exit 1 ) +test -d src || ( echo 'Wrong working directory.'; exit 1 ) + +here=`env - PATH=$PATH pwd` + +echo 'Copying ./etc/runit into /etc...' +rm -f /etc/runit'{new}' +cp -pr ./etc/runit /etc/runit'{new}' +mv -f /etc/runit'{new}' /etc/runit + +echo 'Copying commands into /sbin...' +for i in `cat package/commands` +do + rm -f /sbin/$i'{new}' + cp -p command/$i /sbin/$i'{new}' + mv -f /sbin/$i'{new}' /sbin/$i +done + +echo 'Copying original /sbin/init to /sbin/init.orig...' +cp /sbin/init /sbin/init.orig + +echo 'Linking /sbin/runit-init to /sbin/init...' +rm -f /sbin/init'{new}' +ln -s /sbin/runit-init /sbin/init'{new}' +mv -f /sbin/init'{new}' /sbin/init diff --git a/package/sharing b/package/sharing @@ -0,0 +1,3 @@ +command:syst +package:dist +src:dist diff --git a/package/upgrade b/package/upgrade @@ -0,0 +1,30 @@ +#!/bin/sh -e + +umask 022 +test -d package || ( echo 'Wrong working directory.'; exit 1 ) +test -d src || ( echo 'Wrong working directory.'; exit 1 ) + +here=`env - PATH=$PATH pwd` +parent=`dirname $here` + +echo 'Creating symlink runit -> runit-0.1.0...' +rm -f runit +ln -s runit-0.1.0 runit +mv -f runit .. + +echo 'Making command links in /command...' +mkdir -p /command +for i in `cat package/commands` +do + rm -f /command/$i'{new}' + ln -s $parent/runit/command/$i /command/$i'{new}' + mv -f /command/$i'{new}' /command/$i +done +#echo 'Making compatibility links in /usr/local/bin...' +#mkdir -p /usr/local/bin +#for i in `cat package/commands` +#do +# rm -f /usr/local/bin/$i'{new}' +# ln -s /command/$i /usr/local/bin/$i'{new}' +# mv -f /usr/local/bin/$i'{new}' /usr/local/bin/$i +#done diff --git a/src/Makefile b/src/Makefile @@ -0,0 +1,27 @@ +DESTDIR= + +CC=gcc + +CFLAGS=-Wall -O3 -Isupport +LDFLAGS=-Wall -O3 -s + +all: runit runit-init + +runit: djb-publicdomain runit.o + $(CC) $(LDFLAGS) -o runit \ + runit.o support/unix.a support/byte.a + +runit-init: djb-publicdomain init.o + $(CC) $(LDFLAGS) -o runit-init \ + init.o support/unix.a support/byte.a + +djb-publicdomain: + ( cd support ; make ) + +clean: + find . -name \*~ -exec rm -f {} \; + find . -name .??*~ -exec rm -f {} \; + find . -name \#?* -exec rm -f {} \; + if test -h support; \ + then ( cd support ; $(MAKE) clean ); fi + rm -f `cat TARGETS` diff --git a/src/TARGETS b/src/TARGETS @@ -0,0 +1,4 @@ +runit +runit.o +runit-init +init.o diff --git a/src/init.c b/src/init.c @@ -0,0 +1,54 @@ +#include <sys/types.h> +#include <unistd.h> +#include "strerr.h" +#include "pathexec.h" + +#define USAGE " 0|6" +#define WARNING "init: warning: " +#define FATAL "init: fatal: " + +#define RUNIT "/sbin/runit" +#define HALT "/sbin/runit-halt" +#define REBOOT "/sbin/runit-reboot" + +const char *progname; + +void usage(void) { + strerr_die4x(1, "usage: ", progname, USAGE, "\n"); +} + +int main (int argc, const char * const *argv, const char * const *envp) { + const char *prog[2]; + + progname =*argv++; + + prog[1] =0; + + if (getpid() == 1) { + prog[0] ="runit"; + + /* kernel is starting init, runit does the job. */ + pathexec_run(RUNIT, (const char* const *) prog, envp); + + /* serious error */ + strerr_die4sys(111, FATAL, "unable to start ", prog[0], ": "); + } + + if (! *argv) usage(); + + if (**argv == '0') { + prog[0] =HALT; + pathexec_run(*prog, (const char* const *) prog, envp); + strerr_die4sys(111, FATAL, "unable to start ", prog[0], ": "); + } + if (**argv == '6') { + prog[0] =REBOOT; + pathexec_run(*prog, (const char* const *) prog, envp); + strerr_die4sys(111, FATAL, "unable to start ", prog[0], ": "); + } + + usage(); + + /* not reached */ + exit(0); +} diff --git a/src/runit-halt b/src/runit-halt @@ -0,0 +1,7 @@ +#!/bin/sh +( cd /etc/runit +rm -f reboot +touch stopit +kill -CONT 1 +) +exit 0 diff --git a/src/runit-reboot b/src/runit-reboot @@ -0,0 +1,6 @@ +#!/bin/sh +( cd /etc/runit +touch stopit reboot +kill -CONT 1 +) +exit 0 diff --git a/src/runit.c b/src/runit.c @@ -0,0 +1,208 @@ +/* this requires: */ +#include <poll.h> + +#include <sys/types.h> +#include <sys/reboot.h> +#include <signal.h> +#include <unistd.h> + +#include "sig.h" +#include "strerr.h" +#include "error.h" +#include "pathexec.h" +#include "iopause.h" +#include "coe.h" +#include "ndelay.h" +#include "wait.h" +#include "open.h" + +/* #define DEBUG */ + +#define INFO "- runit: " +#define WARNING "- runit: warning: " +#define FATAL "- runit: fatal: " + +#define STOPIT "/etc/runit/stopit" +#define CTRLALTDEL "/etc/runit/ctrlaltdel" + +const char * const take[3] ={ + "/etc/runit/1", + "/etc/runit/2", + "/etc/runit/3" }; +const char *progname; +int selfpipe[2]; +int sigc =0; +int sigi =0; + +void sig_cont_handler(void) { + sigc++; + write(selfpipe[1], "", 1); +} +void sig_int_handler(void) { + sigi++; + write(selfpipe[1], "", 1); +} +void sig_child_handler(void) { + write(selfpipe[1], "", 1); +} + +int main (int argc, const char * const *argv, const char * const *envp) { + int pid, pid2; + int wstat; + int fd; + int i; + int stopit =0; + iopause_fd x; + char ch; + + setsid(); + + sig_block(sig_alarm); + sig_block(sig_child); + sig_catch(sig_child, sig_child_handler); + sig_block(sig_cont); + sig_catch(sig_cont, sig_cont_handler); + sig_block(sig_hangup); + sig_block(sig_int); + sig_catch(sig_int, sig_int_handler); + sig_block(sig_pipe); + sig_block(sig_term); + + /* create selfpipe */ + while (pipe(selfpipe) == -1) { + strerr_warn2(FATAL, "unable to create selfpipe, pausing: ", &strerr_sys); + sleep(5); + } + coe(selfpipe[0]); + coe(selfpipe[1]); + ndelay_on(selfpipe[0]); + ndelay_on(selfpipe[1]); + + /* activate ctrlaltdel handling */ + reboot(0); + + strerr_warn3(INFO, "$Id$", ": booting.", 0); + + /* runit */ + for (i =0; i < 3; i++) { + while ((pid =fork()) == -1) { + strerr_warn4(FATAL, "unable to fork for \"", take[i], "\" pausing: ", + &strerr_sys); + sleep(5); + } + if (!pid) { + /* child */ + const char * prog[2]; + + prog[0] =take[i]; + prog[1] =0; + + setsid(); + + sig_unblock(sig_alarm); + sig_unblock(sig_child); + sig_uncatch(sig_child); + sig_unblock(sig_cont); + sig_ignore(sig_cont); + sig_unblock(sig_hangup); + sig_unblock(sig_int); + sig_uncatch(sig_int); + sig_unblock(sig_pipe); + sig_unblock(sig_term); + + strerr_warn3(INFO, "enter stage: ", take[i], 0); + pathexec_run(*prog, (const char* const *) prog, envp); + strerr_warn3(FATAL, "could not start child: ", take[i], &strerr_sys); + } + + x.fd =selfpipe[0]; + x.events =IOPAUSE_READ; + + for (;;) { + sig_unblock(sig_child); + sig_unblock(sig_cont); + sig_unblock(sig_int); + poll(&x, 1, -1); + sig_block(sig_cont); + sig_block(sig_child); + sig_block(sig_int); + + while (read(selfpipe[0], &ch, 1) == 1) {} + + if (wait_nohang(&wstat) == pid) { + if (wait_crashed(wstat) && !stopit) { + strerr_warn3(WARNING, "child crashed: ", take[i], 0); + if (i == 1) { + kill(-pid, SIGTERM); + sleep(1); + strerr_warn2(WARNING, "restarting.", 0); + i--; + break; + } + } + if (stopit) stopit =0; + strerr_warn3(INFO, "leave stage: ", take[i], 0); + break; + } + + /* sig */ + if ((sigc == 0) && (sigi == 0)) { +#ifdef DEBUG + strerr_warn2(WARNING, "poll: ", &strerr_sys); +#endif + continue; + } + if ((i != 1) || stopit) { + strerr_warn2(WARNING, "sigs only work in stage 2.", 0); + sigc =sigi =0; + continue; + } + if (sigc && ((fd =open_write(STOPIT)) != -1)) { + close(fd); + unlink(STOPIT); + kill(pid, SIGTERM); + sigc =sigi =0; + stopit =1; + continue; + } + if (sigi && ((fd =open_write(CTRLALTDEL)) != -1)) { + close(fd); + strerr_warn2(INFO, "ctrl-alt-del request...", 0); + while ((pid2 =fork()) == -1) { + strerr_warn4(FATAL, + "unable to fork for \"", CTRLALTDEL, "\" pausing: ", + &strerr_sys); + sleep(5); + } + if (!pid2) { + /* child */ + const char * prog[2]; + + prog[0] =CTRLALTDEL; + prog[1] =0; + + strerr_warn3(INFO, "enter stage: ", prog[0], 0); + pathexec_run(*prog, (const char* const *) prog, envp); + strerr_warn3(FATAL, "could not start child: ", prog[0], &strerr_sys); + } + if (wait_pid(&wstat, pid2) == -1) { + strerr_warn2(FATAL, "wait_pid: ", &strerr_sys); + } + if (wait_crashed(wstat)) { + strerr_warn3(WARNING, "child crashed: ", CTRLALTDEL, 0); + } + kill(pid, SIGTERM); + sigc =sigi =0; + stopit =1; + continue; + } + +#ifdef DEBUG + strerr_warn2(WARNING, "no request.", 0); +#endif + } + } + /* not reached */ + strerr_warn2(INFO, "exit.", 0); + exit(0); +}