From 9ea1bff7b049ce152767460c68bb61f6aa500cef Mon Sep 17 00:00:00 2001 From: Nathan Wagner Date: Wed, 27 Feb 2013 22:05:27 +0000 Subject: [PATCH] added startup scripts --- scripts/README | 99 ++++++++++++++++++++++++++++++ scripts/example.rc | 21 +++++++ scripts/functions.rc | 24 ++++++++ scripts/ifdown | 42 +++++++++++++ scripts/ifup | 34 +++++++++++ scripts/inittab | 40 +++++++++++++ scripts/network | 29 +++++++++ scripts/rc.conf | 18 ++++++ scripts/rc.local | 11 ++++ scripts/rc.multi | 10 ++++ scripts/rc.shutdown | 5 ++ scripts/rc.single | 10 ++++ scripts/rc.sysinit | 140 +++++++++++++++++++++++++++++++++++++++++++ 13 files changed, 483 insertions(+) create mode 100644 scripts/README create mode 100755 scripts/example.rc create mode 100644 scripts/functions.rc create mode 100755 scripts/ifdown create mode 100755 scripts/ifup create mode 100644 scripts/inittab create mode 100755 scripts/network create mode 100644 scripts/rc.conf create mode 100644 scripts/rc.local create mode 100644 scripts/rc.multi create mode 100644 scripts/rc.shutdown create mode 100644 scripts/rc.single create mode 100644 scripts/rc.sysinit diff --git a/scripts/README b/scripts/README new file mode 100644 index 0000000..d5a3d63 --- /dev/null +++ b/scripts/README @@ -0,0 +1,99 @@ +These scripts are intended to handle both boot time and +run-time management of system services and general configuration. + +In general, the philosophy is to be as simple as possible. The +admin who has to debug a boottime or service start up script +that he hasn't looked at in a year and a half and that was set +up by his predecessor anyway doesn't want something that can't +be understood with a basic knowledge of init, the shell, and +a couple of man pages. + +A system administrators accumulated knowledge should also be +respected as far as possible. There is no point in throwing +away years of experience merely for the sake of being different. +Further, the system should follow, as much as possible the +principle of least surprise. + +Where possible, configuration scripts should be simple /bin/sh +compatible files that do nothing other than set variables +and do not call any programs. This allows other scripts +to simply source them without any complicated parsing. + +However, where existing tools use configuration files that don't adhere +to that principle, those files and tools should continue to be used +unchanged. As examples, /etc/fstab, /etc/sysctl.conf. + +In keeping with the above, these scripts work as follows: + +Run-levels are little used, and so they will be kept to doing +as little as possible. This system uses the following: + +Run Level S: single user mode +Run Level 1: also single user mode +Run Level 2: multi user mode, but with as little running as +might be needed for maintaining the box. Typically this +will be networking and sshd, but nothing else. For some +systems even these may not be needed. + +Run Level 3: This is the normal "everything running" level. +Run Level 6: System shutdown + +No other run levels are used, though a system admin could +set them up if needed. + +System Scripts +-------------- + +These scripts live in /etc + +fstab: lists filesystems, this file is not changed from it's usual +format, and is used as such + +rc.sysinit: done once at start time. responsible for performing any +necessary early system initialization. This reads rc.conf for some +of its actions + +* do any boot time /tmp cleanup or similar +* fsck and mount filesystems +* load any kernel modules needed +* set the host name +* set up /dev (via udev on modern linux systems) +* sysctl +* do any utmp/wtmp initialization needed +* configure the console +* set timezone and clock + +Since all of this has to be done before we do anything else, +and the order won't generally change, this can and should be +a single script. + +rc.multi: brings up the system into multi user mode. reads rc.conf + +* start any startup scripts listed in DAEMONS + +rc.conf: + +responsible for setting variables used by other scripts. this script will +be sourced by several other scripts and thus shouldn't actually perform +any actions of its own. It can call other programs if needed to set variables, +but this should be minimized (e.g. it could cat /etc/hostname to set the HOSTNAME +variable, but shouldn't actually set the hostname, and it would be better to just +set the hostname directly) + +DAEMONS: a set of scripts from /etc/rc.d/init.d to run. These will +be run in the order listed. + +HOSTNAME: the system hostname to set. + +TZ: the system time zone + +Robustness +---------- + +Each daemon start-up script should register somehow the fact that it +is running and started. A monitoring daemon then should be run *out of init* +to check these daemons and restart them if they crash. If the monitor +is not run from init, it could itself crash. This should perhaps be +run level 4 for this daemon. Ideally, nothing would be run as a daemon +and init could handle the monitoring itself, but this would be a major +change to the usual practice. diff --git a/scripts/example.rc b/scripts/example.rc new file mode 100755 index 0000000..b72880c --- /dev/null +++ b/scripts/example.rc @@ -0,0 +1,21 @@ +#!/bin/sh + +. /etc/rc.conf + +case "$1" in + start) + exit 0 + ;; + stop) + exit 0; + ;; + restart) + exit 0; + ;; + status) + exit 0; + ;; + *) + echo "usage: $0 {start | stop | restart | status }" + exit 1 +esac diff --git a/scripts/functions.rc b/scripts/functions.rc new file mode 100644 index 0000000..031eaa1 --- /dev/null +++ b/scripts/functions.rc @@ -0,0 +1,24 @@ +status_starting() { + echo -n "[ ] Starting $1" +} + +status_begin() { + echo -n "[ ] $*" +} + +status_stopping() { + echo -n "[ ] Stopping $1" +} + +status_ok() { + echo "\r[ OK ]" +} + +status_fail() { + echo "\r[FAILED]" +} + +status_check() { + local r=$1 + test ${r:=$?} -eq 0 && status_ok || status_fail +} diff --git a/scripts/ifdown b/scripts/ifdown new file mode 100755 index 0000000..784b1e2 --- /dev/null +++ b/scripts/ifdown @@ -0,0 +1,42 @@ +#!/bin/sh + +net=$1 + +IFS=';' + +# TODO allow for /etc/sysconfig/$net also +test -f /etc/sysconfig/$net.net || echo "unknown network configuration '$net'" >&2 && exit 1 + +ifdown_post() { + return 0 +} + +ifdown_pre() { + return 0 +} + +. /etc/sysconfig/$net.net + +#if [ $enable = 'no' || $enable -eq 0 ]; then; exit 0; fi + +ifdown_pre + +#ip link set dev $dev up + +for r in $route; do + ip route del $r +done + +for address in $addr do + ip addr del $address dev $dev +done + +# how do we determine if we should bring the link down? +# there could be other configurations that also set up IP +# addresses. Also, what happens exactly if the primary +# ip address is removed, but not the secondary ones also? + +# for now, just leave the link up, I don't think it hurts +# anything + +ifdown_post diff --git a/scripts/ifup b/scripts/ifup new file mode 100755 index 0000000..98b5c59 --- /dev/null +++ b/scripts/ifup @@ -0,0 +1,34 @@ +#!/bin/sh + +net=$1 + +IFS=';' + +# TODO allow for /etc/sysconfig/$net also +test -f /etc/sysconfig/$net.net || echo "unknown network configuration '$net'" >&2 && exit 1 + +ifup_post() { + return 0 +} + +ifup_pre() { + return 0 +} + +. /etc/sysconfig/$net.net + +if [ $enable = 'no' || $enable -eq 0 ]; then; exit 0; fi + +ifup_pre + +ip link set dev $dev up + +for address in $addr do + ip addr add $address dev $dev +done + +for r in $route; do + ip route add $r +done + +ifup_post diff --git a/scripts/inittab b/scripts/inittab new file mode 100644 index 0000000..5c451c7 --- /dev/null +++ b/scripts/inittab @@ -0,0 +1,40 @@ +# run levels +# +# 1 S single user +# 2 maintenance +# 3 multi user +# 4 monitored +# 0 6 shutdown + +# remaining levels not used + +id:3:initdefault: + +rc::bootwait:/etc/rc.sysinit +rs:S1:wait:/etc/rc.single +rm:2345:wait:/etc/rc.multi +rh:06:wait:/etc/rc.shutdown +su:S:wait:/sbin/sulogin -p + +kl:2345:respawn:/sbin/klogd -n -f /var/log/kernel.log + +c1:2345:respawn:/sbin/agetty --noclear -8 -s 38400 tty1 linux +c2:2345:respawn:/sbin/agetty -8 -s 38400 tty2 linux +c3:2345:respawn:/sbin/agetty -8 -s 38400 tty3 linux +c4:2345:respawn:/sbin/agetty -8 -s 38400 tty4 linux +c5:2345:respawn:/sbin/agetty -8 -s 38400 tty5 linux +c6:2345:respawn:/sbin/agetty -8 -s 38400 tty6 linux + +ca::ctrlaltdel:/sbin/shutdown -t3 -r now + +# permanently running daemons +#sl:2:respawn:/usr/sbin/sshd -D +#dm:4:respawn:/sbin/monitor + +#s0:2345:respawn:/sbin/agetty -8 -s 9600 ttyS0 linux + +#x:5:respawn:/usr/bin/xdm -nodaemon +#x:5:respawn:/usr/sbin/gdm -nodaemon +#x:5:respawn:/usr/bin/kdm -nodaemon +#x:5:respawn:/usr/bin/slim >/dev/null 2>&1 + diff --git a/scripts/network b/scripts/network new file mode 100755 index 0000000..4e7040b --- /dev/null +++ b/scripts/network @@ -0,0 +1,29 @@ +#!/bin/sh + +. /etc/rc.conf + +case "$1" in + start) + for n in $NETWORKS ; do + /sbin/ifup $n + done + ;; + stop) + # NETWORKS might have changed + # TODO record the network somewhere under /var/run/startuptools + for n in $NETWORKS ; do + /sbin/ifdown $n + done + ;; + restart) + $0 stop + sleep 1 + $0 start + ;; + status) + exit 0 + ;; + *) + echo "usage: $0 {start | stop | restart | status }" + exit 1 +esac diff --git a/scripts/rc.conf b/scripts/rc.conf new file mode 100644 index 0000000..8daedd2 --- /dev/null +++ b/scripts/rc.conf @@ -0,0 +1,18 @@ +# This file sets system configuration variables. It should be posix shell +# compatible (e.g. no arrays), and should not run *any* programs. If defaults +# or more complex calculations are needed, these should be done in the startup +# scripts. + +# set your hostname here. defaults (via rc.sysinit) to uname -s, which is +# probably 'Linux' + +# HOSTNAME= + +# space separated list of scripts in /etc/rc.d to run in multi +# user startup. These will be start in the order given +# it doesn't have to be set + +DAEMONS='network' + +# list of network configurations to run on network start +NETWORKS='localhost' diff --git a/scripts/rc.local b/scripts/rc.local new file mode 100644 index 0000000..318e991 --- /dev/null +++ b/scripts/rc.local @@ -0,0 +1,11 @@ +#!/bin/sh + +# any local configuration can go here. this script will be called last + +# uncomment the following if you want to pull in the variables defined in +# rc.conf +# . /etc/rc.conf + +# this isn't needed as such, but is a placeholder to note that the script isn't +# intended to do anything +exit 0 diff --git a/scripts/rc.multi b/scripts/rc.multi new file mode 100644 index 0000000..0505411 --- /dev/null +++ b/scripts/rc.multi @@ -0,0 +1,10 @@ +#!/bin/sh + +. /etc/rc.d/functions.rc +. /etc/rc.conf + +for d in $DAEMONS ; do + test -x /etc/rc.d/$d && /etc/rc.d/$d start +done + +test -x /etc/rc.local && status_begin running rc.local && /etc/rc.local && status_check diff --git a/scripts/rc.shutdown b/scripts/rc.shutdown new file mode 100644 index 0000000..ffb4038 --- /dev/null +++ b/scripts/rc.shutdown @@ -0,0 +1,5 @@ +#!/bin/sh + +# TODO stop all the daemons + +reboot -f -i diff --git a/scripts/rc.single b/scripts/rc.single new file mode 100644 index 0000000..d2404ae --- /dev/null +++ b/scripts/rc.single @@ -0,0 +1,10 @@ +#!/bin/sh + +#. /etc/rc.conf + +# sulogin will do what we want. this script is a placeholder +# the system admin can use it if something else needs +# to be done specially for single user mode + +exit 0 + diff --git a/scripts/rc.sysinit b/scripts/rc.sysinit new file mode 100644 index 0000000..52ddc70 --- /dev/null +++ b/scripts/rc.sysinit @@ -0,0 +1,140 @@ +#!/bin/sh + +# fstab: lists filesystems, this file is not changed from it's usual +# format, and is used as such +# +# rc.sysinit: done once at start time. responsible for performing any +# necessary early system initialization. This reads rc.conf for some +# of its actions + +#PATH=/sbin:/usr/sbin:/bin:/usr/bin + +. /etc/rc.d/functions.rc +. /etc/rc.conf + +# * load any kernel modules needed + +# TODO check for /etc/fstab +# write one if missing? + +# need to mount sys because fsck might use it +# try to mount them directly if they fail from fstab? +# TODO bail to emergency shell if these fail? +# try to mount them directly if they fail from fstab? +# TODO bail to emergency shell if these fail? +status_begin mounting virtual filesystems +mountpoint -q /proc || mount -t proc proc /proc -o nosuid,noexec,nodev +mountpoint -q /sys || mount -t sysfs sys /sys -o nosuid,noexec,nodev +mountpoint -q /var/run || mount -t tmpfs run /var/run -o mode=0755,nosuid,nodev +mountpoint -q /dev || mount -t devtmpfs dev /dev -o mode=0755,nosuid +mkdir -p /dev/{pts,shm} +mountpoint -q /dev/pts || mount -t devpts devpts /dev/pts -o mode=0620,gid=5,nosuid,noexec +mountpoint -q /dev/shm || mount -t tmpfs shm /dev/shm -o mode=1777,nosuid,nodev +# and make sure they all passed +mountpoint -q /proc && +mountpoint -q /sys && +mountpoint -q /var/run && +mountpoint -q /dev && +mountpoint -q /dev/pts && +mountpoint -q /dev/shm +status_check + +#status_begin mounting virtual filesystems +#mount /proc && +#mount /sys && +#mount /dev +#status_check + +# * set the host name +status_begin Setting hostname +hostname ${HOSTNAME:=$(uname -s)} +status_check + +# TODO should probably bail out if the /sys mount fails + +# TODO decide if the loopback network interface should be done here or later +# I think later, it's not actually necessary + +# * sysctl + +status_begin loading sysctl.conf +sysctl -q -p +status_check + +# * set up /dev (via udev on modern linux systems) + +## +## begin voodoo scripting from lfs-initscripts +## + +# udev will handle hotplugs +echo > /proc/sys/kernel/hotplug + +# start udev +# this should probably be moved to inittab or started via +# something that could monitor it +status_starting udevd daemon +/lib/udev/udevd --daemon +status_check + +# Now traverse /sys in order to "coldplug" devices that have +# already been discovered +# this is going to fail if sys isn't mounted +status_begin populating udevadm triggers +udevadm trigger --action=add --type=subsystems && +udevadm trigger --action=add --type=devices && +udevadm trigger --action=change --type=devices +status_check + +# Now wait for udevd to process the uevents we triggered +# if ! is_true "$OMIT_UDEV_SETTLE"; then +status_begin waiting for udevadm to settle +udevadm settle +status_check +# fi + +# If any LVM based partitions are on the system, ensure they +# are activated so they can be used. +# if [ -x /sbin/vgchange ]; then /sbin/vgchange -a y >/dev/null; fi + +# log_success_msg2 + +## +## end voodoo scripting +## + +# * set up swap + +swapon -a + +# * fsck and mount filesystems + +status_starting fsck of / +mount -o remount,ro / +fsck -AT +# TODO actually check the return value +mount -o remount,rw / +status_check + +# mount any remaining filesystems +status_begin mounting remaining filesystems +mount -a -t noproc,sysfs,devtmpfs,devpts +status_check + +rm -f /etc/mtab +mount -af + +# * do any boot time /tmp cleanup or similar + +# * do any utmp/wtmp initialization needed + +touch /var/run/utmp +touch /var/log/wtmp + +# * configure the console + +# * set timezone and clock + +status_begin setting system clock from hardware clock +hwclock -s +status_check -- 2.40.0