Init scripts
------------
Init scripts take the form of mk rules contained in /etc/init.mk. Services are
-started by calling the `start-<service>' rule and stopped by calling
-`stop-service'. Services should use `:Pservice -[ud]:' to determine whether the
-script needs to be invoked.
+started by calling the `<service>-start' rule and stopped by calling
+`<service>-stop'. Services should use `:Pservice -[ud]:' to determine if the
+script needs to be run and call `service -[UD]' afterwards.
-For simple services consisting of a single start and stop command which no
-dependencies other than boot, the default start-stop rules can be used by
-setting `<service>_start_cmd' and `<service>_stop_cmd'.
+For simple services consisting of a single start and stop command with no
+dependencies other than `boot', the default start-stop rules can be used by
+setting `<service>-start_cmd' and `<service>-stop_cmd'.
-Dependencies are handled by adding `start-<dependency>' to the rules list of
-dependencies. When stopping a service, `stop-<service>' should be added to the
+Dependencies are handled by adding `<dependency>-start' to the rules list of
+dependencies. When stopping a service, `<service>-stop' should be added to the
list of dependencies for the dependency.
mkfile - For [un]installing mkinit
init.mk - Example database of init scripts
-bin/mkinit - The actual init program it runs main loop and calls mk on
- init.mk whenever services need to be started and stopped.
-bin/respawn - Used to respawn gettys and such
-bin/service - Set or query the state of a service
+src:
+mkinit - The actual init program it runs main loop and calls mk on init.mk
+ whenever services need to be started and stopped.
+mkinit.rc - Rc variant of mkinit, unforuntly I can't get the IO redirects
+ working, it also leave zombies laying around..
+initctld.c - Reads /dev/initctl (Sysvinit compatability for halt,reboot,etc)
+service - Set or query the state of a service
+respawn - Used to respawn gettys and such
# tw=80
# Runlevels
user = alsa keymap polipo spam dbus
-system = at cron hddtemp hostname hwclock i8k sshd swap syslog
-bare = cpufreq fsclean getty qingy localhost modules mounts uevents utmp
+system = at cron hddtemp hostname hwclock sshd swap syslog
+bare = cpufreq fsclean getty qingy initctl localhost modules mounts uevents utmp
default:V: user
$P reboot -ndfk
# Initial setup/shutdown for mkinit
-boot:QVEPservice -u: /
+boot:VEPservice -u: /
echo Starting init
$P mount -o remount,rw /
# mount proc here to make bootchart happier
$P mount -t proc proc /proc
- rm -f /lib/mkinit/state/*
+ service -F
service -U $target
# Kill all process, then remount and sync
halt:QVE: utmp-stop hwclock-stop alsa-stop
- echo Stopping init
- rm -f /lib/mkinit/state/*
-
echo TERMinating all processes
- $P pkill -15 -vg0
+ $P pkill -15 -vg0 >/dev/null >[2=1]
for (i in 1 2 3 4 5)
- $P pgrep -vg0 >/dev/null && $P sleep 1
-
+ $P pgrep -vg0 >/dev/null >[2=1] && $P sleep 1
echo KILLing all processes
- $P pkill -9 -vg0
+ $P pkill -9 -vg0 >/dev/null >[2=1]
for (i in 1 2 3)
- $P pgrep -vg0 >/dev/null && $P sleep 1
-
+ $P pgrep -vg0 >/dev/null >[2=1] && $P sleep 1
+ service -F
+ echo Remounting read-only
$P mount -o remount,ro /
$P sync
# Bare
# ----
+# Listener for /dev/initctl, for shutdown(8)
+initctl-start:VPservice -u: boot
+ fifo=/dev/initctl
+ if (! test -e $fifo)
+ $P mkfifo $fifo
+ { exec $P initctld $fifo |
+ while(line=`{line})
+ $P mkinit $line >/dev/console >[2=1]
+ } &
+ service -U $target
+initctl-stop_cmd=fuser -k /dev/initctl
+
# Proc, mtab, udev, fstab
-mounts-start:QVPservice -u: boot
- echo Starting mounts
- $P cat /proc/mounts > /etc/mtab
+mounts-start:VPservice -u: boot
+ $P cp /proc/mounts /etc/mtab
$P udevd --daemon
- $P mount -a
+ $P mount -a
service -U $target
# Load kernel modules
-modules-start:QVEPservice -u: boot
- echo Starting modules
+modules-start:VEPservice -u: boot
$P modprobe uvesafb
service -U $target
# Trigger udev uevents
-uevents-start:QVEPservice -u: mounts-start
- echo Starting uevents
+uevents-start:VEPservice -u: mounts-start
$P udevadm trigger
$P udevadm settle '--timeout=10'
service -U $target
# Clean out /tmp and /var/run directories
-fsclean-start:QVPservice -u: boot
- echo Starting fsclean
- $P rm -rf /tmp/*
- $P rm -rf /var/run/*
+fsclean-start:VPservice -u: boot
+ dirs=(/var/run /tmp)
+ $P mkdir -p /.old
+ $P mv $dirs /.old
+ $P mkdir -p $dirs
+ $P chmod 1777 /tmp
+ $P exec rm -rf /.old &
service -U $target
# Spawn gettys for tty[456]
-getty-start:QVPservice -u: hostname-start utmp-start
- echo Starting getty
- $P respawn /sbin/agetty 38400 tty4 linux &
- $P respawn /sbin/agetty 38400 tty5 linux &
- $P respawn /sbin/agetty 38400 tty6 linux &
+getty-start:VEPservice -u: hostname-start utmp-start
+ $P respawn /sbin/agetty 38400 tty4 linux
+ $P respawn /sbin/agetty 38400 tty5 linux
+ $P respawn /sbin/agetty 38400 tty6 linux
service -U $target
-getty-stop_cmd=pkill agetty
+getty-stop_cmd=fuser -k /dev/tty4 /dev/tty5 /dev/tty6
# Spawn qingys for tty[23]
-qingy-start:QVPservice -u: hostname-start utmp-start modules-start uevents-start
- echo Starting qingy
- $P respawn /sbin/qingy tty2 &
- $P respawn /sbin/qingy tty3 &
+qingy-start:VEPservice -u: hostname-start utmp-start modules-start uevents-start
+ $P respawn /sbin/qingy tty2
+ $P respawn /sbin/qingy tty3
service -U $target
-getty-stop_cmd=pkill qingy
+qingy-stop_cmd=fuser -k /dev/tty2 /dev/tty3
# Login records
-utmp-start:QVPservice -u: fsclean-start
- echo Starting utmp
+utmp-start:VPservice -u: fsclean-start
for (i in /var/run/utmp /var/log/wtmp) {
- echo -n > $i
- chgrp utmp $i
- chmod 0664 $i
+ $P eval 'echo -n > $i'
+ $P chgrp utmp $i
+ $P chmod 0664 $i
}
service -U $target
utmp-stop_cmd=halt -w
# CPU freq
-cpufreq-start:QVPservice -u: uevents-start
- echo Starting cpufreq
- cpufreq-set -g ondemand
+cpufreq-start:VPservice -u: uevents-start
+ $P cpufreq-set -g ondemand
service -U $target
# Keymap (us-cc = us with ctrl-capslock switched)
swap-start_cmd=swapon -a
swap-stop_cmd=swapoff -a
-syslog-start:QVPservice -u: mounts-start
- echo Starting syslog;
+syslog-start:VPservice -u: mounts-start
$P syslog-ng
service -U $target
syslog-stop_cmd=pkill syslog
-hddtemp-start:QVPservice -u: localhost-start
- echo Starting hddtemp
+hddtemp-start:VPservice -u: localhost-start
$P hddtemp -d -l 127.0.0.1 /dev/sda
service -U $target
hddtemp-stop_cmd=pkill hddtemp
sshd-start_cmd=/usr/sbin/sshd
sshd-stop_cmd=pkill sshd
-dbus-start:QVPservice -u: fsclean-start localhost-start
- echo Starting dbus
+dbus-start:VPservice -u: fsclean-start localhost-start
$P mkdir -p /var/run/dbus
$P /usr/bin/dbus-daemon --system
service -U $target
dbus-stop_cmd=pkill dbus-daemon
-spam-start:QVPservice -u: localhost-start
- echo Starting spam
+spam-start:VPservice -u: localhost-start
$P spamd -d
service -U $target
spam-stop_cmd=pkill spamd
-polipo-start:QVPservice -u: localhost-start
- echo Starting poliop
+polipo-start:VPservice -u: localhost-start
$P polipo
service -U $target
polipo-stop_cmd=pkill polipo
# Library
# -------
-%-start:QVPservice -u: boot
+%-start:VPservice -u: boot
if (~ $#($stem^-start_cmd) 0)
exit 0
- echo Starting $stem
$P $($stem^-start_cmd)
service -U $target
-%-stop:QVPservice -d: /
+%-stop:VPservice -d: /
if (~ $#($stem^-stop_cmd) 0)
exit 0
- echo Stopping $stem
$P $($stem^-stop_cmd)
service -D $target
-%-zap:QVPservice -d: /
+%-zap:VPservice -d: /
service -D $target
-%-status:QV:
+%-status:V:
service -q $target
rmdir /lib/mkinit/state/
rmdir /lib/mkinit/
-<../mkcommon
+<mkcommon
# vim: ft=mk
# See ../COPYING for terms
# GLobals
-TEST=false
-RELOAD=false
-FIFO=/lib/mkinit/cmd
-INITCTL=/dev/initctl
+COMMAND=boot
+TESTING=false
+if [ $$ == 1 ]; then
+ DAEMON=true
+else
+ DAEMON=false
+fi
+
PATH=/lib/mkinit/bin:/bin:/sbin:/usr/bin:/usr/sbin
export PATH
echo 'usage: '$0' [options] [command]'
echo
echo 'Options:'
- echo ' -h,--help Print usage information'
- echo ' -r,--relaod Prevent spawning listeners when reloading'
- echo ' -t,--test Fake all commands'
- echo
+ echo ' -h,--help Print usage information'
+ echo ' -t,--test Fake all commands'
+ echo ' -d,--daemon For spawning stdin listener'
+ echo ''
echo 'Command:'
- echo ' boot Execute boot-up procedures'
- echo ' halt Execute shutdown procedures'
- echo ' reload Re-execute init process'
- echo ' mk <rule> Execute mk rule'
+ echo ' boot Execute boot-up procedures'
+ echo ' halt Execute shutdown procedures'
+ echo ' reload Re-execute init process'
+ echo ' mk <rule> Execute mk rule'
echo ' start|stop|restart|zap|status <service>'
- echo ' Start,stop,restart,zap or query status of service'
- echo ' eval <cmd> Execute command in mkinit process'
+ echo ' Start,stop,restart,zap or query status of service'
+ echo ' eval <cmd> Execute command in mkinit process'
exit
}
+# Handle arguments
+function doopts {
+ TMP=`getopt -n "$0" -o htd -l help,test,daemon -- "$@"`
+ [ $? != 0 ] &&
+ usage
+ eval set -- "$TMP"
+
+ # Parse options
+ while [ ! "$1" == "--" ]; do
+ case "$1" in
+ -h|--help ) usage ;;
+ -t|--test ) TESTING=true ;;
+ -d|--daemon ) DAEMON=true ;;
+ esac
+ shift
+ done
+ shift
+ if [ "$*" ]; then
+ COMMAND=($@)
+ fi
+
+ # Debugging output
+ if $TESTING; then
+ echo 'Options' 1>&2
+ echo ' TESTING:' $TESTING 1>&2
+ echo ' DAEMON:' $DAEMON 1>&2
+ echo ' COMMAND:' $COMMAND 1>&2
+ fi
+}
+
# Run mk on the init scripts
function runamk {
- $TEST &&
- export P=true
+ if $TESTING; then
+ export P=echo
+ export MKINIT_STATE=/tmp/mkinit_state
+ mkdir -p $MKINIT_STATE
+ fi
/usr/lib/plan9/bin/mk \
-f /etc/init.mk \
-i -k "$@"
function process {
cmd=$1
shift
- arg=$*
- exec 1>/dev/console
+ echo mkinit -- running "$cmd" "$@"
case "$cmd" in
boot )
- echo
- echo mkinit -- booting
- runamk -a "$arg"
+ runamk -a "$@"
;;
restart )
- if [ "$arg" ]; then
- echo mkinit -- restarting $arg
- runamk "$arg"-stop
- runamk "$arg"-start
+ if [ "$*" ]; then
+ runamk "$@"-stop ||
+ runamk "$@"-zap
+ runamk "$@"-start
fi
;;
start|stop|zap|status )
- if [ "$arg" ]; then
- echo mkinit -- ${cmd}ing $arg
- runamk "$arg-$cmd"
- fi
- ;;
- mk|runlevel )
- if [ "$arg" ]; then
- [ "$cmd" = mk ] &&
- echo mkinit -- running mk cmd [$arg]
- [ "$cmd" = runlevel ] &&
- echo mkinit -- entering runlevel $arg
- runamk "$arg"
+ if [ "$*" ]; then
+ runamk "$@-$cmd"
fi
;;
reload )
- echo mkinit -- ${cmd}ing
- $TEST &&
+ $TESTING &&
opt=-t
exec $0 -r $opt
;;
+ poweroff|reboot|kexec|halt)
+ ( runamk "$cmd" "$@" & )
+ ;;
eval )
- eval $arg
+ eval "$@"
;;
?* )
- echo mkinit -- unknown command [$cmd] [$arg]
+ runamk "$cmd" "$@"
;;
esac
}
-# Telinit
-if [ $$ != 1 -a $1 != "-t" ]; then
- echo "$@" > $FIFO
- exit
-fi
-
-# Handle arguments
-TMP=`getopt -n "$0" \
- --options hrt \
- --longoptions help,reload,test \
- -- "$@"`
-[ $? != 0 ] &&
- usage
-eval set -- "$TMP"
-while [ ! "$1" == "--" ]; do
- $TEST &&
- echo '$1=' $1
- case "$1" in
- -h|--help )
- usage
- ;;
- -r|--reload )
- RELOAD=true
- ;;
- -t|--test )
- TEST=true
- FIFO=/tmp/pipe
- INITCTL=/tmp/initctl
- trap "pkill -HUP -P $$" EXIT
- ;;
- esac
- shift
-done
-shift; cmd=$1
-shift; arg=$*
+# Process arguments
+doopts "$@"
-# Debugging output
-if $TEST; then
- echo 'Options'
- echo ' test:' $TEST
- echo ' reload:' $RELOAD
- echo ' cmd:' $cmd
- echo ' arg:' $arg
-fi
-
-# Create fifos if they don't exist
-test ! -e $FIFO &&
- mkfifo $FIFO
-test ! -e $INITCTL &&
- mkfifo $INITCTL
-
-# Initial boot-up
-process $cmd $arg
-
-# Fork listeners
-if ! $RELOAD; then
- # Fork /dev/initctl listener
- ( exec 0<&- 1<&- 2<&-
- initctld $INITCTL |
- while read line; do
- echo $line > $FIFO
- done ) &
-
- # Fork console listener
- # Readline uses stdin,stderr
- ( exec 1<&-;
- while true; do
- while read -e -p "mkinit> " line; do
- echo $line > $FIFO
- history -s $line
- done
- $TEST && break
- exec 0</dev/console 2>/dev/console
- echo "Respawning on /dev/console.." >&2
- sleep 1
- done) <&0 &
-
- # Close stdin, stderr
- exec 0<&- 2<&-
-fi
+# Run whatever was requested
+process "${COMMAND[@]}"
-# Main loop
-while true; do
- while read line; do
+# Fork console listener
+while $DAEMON; do
+ while read -ep "mkinit> " line; do
process $line
- done < $FIFO
+ history -s $line
+ done
+ $TESTING && exit
+ exec 0</dev/console 1>/dev/console 2>&1
+ echo "Respawning on /dev/console.."
+ sleep 1
done
# See ../COPYING for terms
# GLobals
-TEST=false
-RELOAD=false
-FIFO=/lib/mkinit/cmd
-INITCTL=/dev/initctl
-PATH=/lib/mkinit/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/lib/plan9/bin
+COMMAND=boot
+TESTING=false
+if(~ $pid 1)
+ DAEMON=true
+if not
+ DAEMON=false
+
+PATH=/lib/mkinit/bin:/bin:/sbin:/usr/bin:/usr/sbin
# Functions
fn usage {
echo 'usage: '$0' [options] [command]'
echo
echo 'Options:'
- echo ' -h,--help Print usage information'
- echo ' -r,--relaod Prevent spawning listeners when reloading'
- echo ' -t,--test Fake all commands'
- echo
+ echo ' -h,--help Print usage information'
+ echo ' -t,--test Fake all commands'
+ echo ' -d,--daemon For spawning stdin listener'
+ echo ''
echo 'Command:'
- echo ' boot Execute boot-up procedures'
- echo ' halt Execute shutdown procedures'
- echo ' reload Re-execute init process'
- echo ' mk <rule> Execute mk rule'
+ echo ' boot Execute boot-up procedures'
+ echo ' halt Execute shutdown procedures'
+ echo ' reload Re-execute init process'
+ echo ' mk <rule> Execute mk rule'
echo ' start|stop|restart|zap|status <service>'
- echo ' Start,stop,restart,zap or query status of service'
- echo ' eval <cmd> Execute command in mkinit process'
+ echo ' Start,stop,restart,zap or query status of service'
+ echo ' eval <cmd> Execute command in mkinit process'
exit
}
+# Handle arguments
+fn doopts {
+ tmp=`{getopt -n $0 -o htd -l help,test,daemon -- $*}
+ if(~ $status 0)
+ usage
+ eval '*=('$"tmp')'
+
+ # Parse options
+ while(! ~ $1 --){
+ switch($1){
+ case -h --help
+ usage
+ case -t --test
+ TESTING=true
+ case -d --daemon
+ DAEMON=true
+ }
+ shift
+ }
+ shift
+ if(! ~ $#* 0)
+ COMMAND=$*
+
+ # Debugging output
+ if($TESTING){
+ echo 'Options' >[2=1]
+ echo ' TESTING:' $TESTING >[2=1]
+ echo ' DAEMON:' $DAEMON >[2=1]
+ echo ' COMMAND:' $COMMAND >[2=1]
+ }
+}
+
# Fake readline
fn prompt {
echo -n $1 >[1=2]
- read
+ line
}
# Run mk on the init scripts
fn runamk {
- if ($TEST)
- P=true
+ if($TESTING){
+ P=echo
+ MKINIT_STATE=/tmp/mkinit_state
+ mkdir -p $MKINIT_STATE
+ }
/usr/lib/plan9/bin/mk \
-f /etc/init.mk \
-i -k $*
fn process {
cmd=$1
shift
- arg=$*
+ echo mkinit -- running "$"cmd" "$"*"
switch($cmd){
case boot
- echo
- echo mkinit -- booting
- runamk -a $arg
+ runamk -a $*
case restart
if(~ $arg ?*){
- echo mkinit -- restarting $arg
- runamk $arg-stop
- runamk $arg-start
+ if (! runamk $"*-stop)
+ runamk $"*-zap
+ runamk $"*-start
}
case start stop zap status
- if(~ $arg ?*){
- echo mkinit -- $cmd^ing $arg
- runamk $arg-$cmd
- }
-
- case mk runlevel
- if(~ $arg ?*){
- if (~ $cmd mk)
- echo mkinit -- running mk cmd [$arg]
- if (~ $cmd runlevel)
- echo mkinit -- entering runlevel $arg
- runamk $arg
- }
+ if(~ $arg ?*)
+ runamk $"*-$cmd
case reload
- echo mkinit -- $cmd^ing
- if($TEST)
+ if($TESTING)
opt=-t
exec $0 -r $opt
- case eval
- eval $arg
+ case poweroff reboot kexec halt
+ { runamk $cmd $* & }
+ case eval
+ eval $*
+
case ?*
- echo mkinit -- unknown command [$cmd] [$arg]
+ runamk $cmd $*
+
}
}
-# Handle arguments
-tmp=`{getopt -n $0 \
- --options hrt \
- --longoptions help,reload,test \
- -- $*}
-if(~ $status ?*)
- usage
-eval '*=('$"tmp')'
-while(! ~ $1 --){
- if ($TEST)
- echo '$1=' $1
- switch($1){
- case -h --help
- usage
-
- case -r --reload
- RELOAD=true
+# Process arguments
+doopts $*
- case -t --test
- TEST=true
- FIFO=/tmp/pipe
- INITCTL=/tmp/initctl
- fn sigint { pkill -HUP -P $pid }
+# Run whatever was requested
+process $COMMAND
- }
- shift
-}
-shift; cmd=$1
-shift; arg=$*
-
-# Debugging output
-if($TEST){
- echo 'Options'
- echo ' test:' $TEST
- echo ' reload:' $RELOAD
- echo ' cmd:' $cmd
- echo ' arg:' $arg
+# Fork console listener
+fn listen1 {
+ while(line=`{prompt 'mkinit> '})
+ process $line
}
-
-# Create fifos if they don't exist
-if(test ! -e $FIFO)
- mkfifo $FIFO
-if(test ! -e $INITCTL)
- mkfifo $INITCTL
-
-# Initial boot-up
-process $cmd $arg
-
-# Fork listeners
-if(!$RELOAD){
- # Fork /dev/initctl listener
- { initctld $INITCTL |
- while(line=`{read})
- echo $line > $FIFO
- } <[0=] >[1=] >[2=] &
-
- # Fork console listener
- # Readline uses stdin,stderr
- if($TEST) {
- tty=`{tty}
- { while(line=`{prompt 'mkinit> '}) {
- echo line: $line
- echo $line > $FIFO
- } } <$"tty >[1=2] &
- }
- if not {
- { while(true){
- while(line=`{prompt 'mkinit> '})
- echo $line > $FIFO
- echo Respawning on /dev/console..
- sleep 1
- } } </dev/console >/dev/console >[1=2]
+if($DAEMON){
+ listen1
+ if ($TESTING)
+ exit
+ while($DAEMON) {
+ echo Respawning on /dev/console..
+ sleep 1
+ listen1 <[0]/dev/console \
+ >[1]/dev/console \
+ >[2=1]
}
}
-
-# Main loop
-while(true)
- { while(line=`{read})
- process $line
- } < $FIFO >[2=1]
# Copyright (C) 2009 Andy Spencer
# See ../COPYING for terms
-while(true){
- $*
- echo Process $! died, waiting 1 second to respawn
+{ while($*){
sleep 1
-}
+} } <[0=] >[1=] >[2=] &
echo ' -d,--is-down Test is service is stopped'
echo ' -U,--set-up Set service to running'
echo ' -D,--set-down Set service to stopped'
+ echo ' -F,--flush Resest all services to stopped'
echo ' -q,--query Print the state of a service'
exit
}
# Main
-STATE=/lib/mkinit/state
+state=/lib/mkinit/state
+if (~ $MKINIT_STATE ?*)
+ state=$MKINIT_STATE
action=$1
service=`{echo $2 | sed s/-.*//}
-if(~ $action '' || ~ $service '')
+if(~ $action '')
+ usage
+if(! ~ $action -F && ~ $service '')
usage
switch($1){
case -u --is-up
- test -e $STATE/$service
+ test -e $state/$service
case -d --is-down
- test ! -e $STATE/$service
+ test ! -e $state/$service
case -U --set-up
- touch $STATE/$service
+ touch $state/$service
case -D --set-down
- rm $STATE/$service
+ rm -f $state/$service
+case -F --flush
+ rm -f $state/*
case -q --query
echo -n Service "$service" is
- test -e $STATE/$service \
+ test -e $state/$service \
&& echo ' running' \
|| echo ' stopped'
case *