Runit tools in busybox - up to the task? Let's test busybox's runit applets in a hypothetical ;) scenario when someone needs to stop running, say, systemd on, say, a Fedora machine. No doubt this will expose various shortcomings. Started with the machine configured and running under systemd. Machine has xfce4 desktop environment installed. Created /var/service and copied busybox/examples/var_service/* there. Renamed/copied getty_tty1 to getty_tty9/10/11/12 (these consoles are not used by existing setup). Deleted dhcpd_if, ftpd, httpd, inetd, nmeter, tftpd (hmm, this needs a way to store inactive services somewhere in a separate directory). Adjusted fw/run (need more configurable way to do it; lacks a way to specify more than one "external" (firewalled) interface). Renamed/copied dhcp_if, dhcp_if_pinger, ifplugd_if each to a pair of services for eth0 and wlan0. Renamed supplicant_if only for wlan0. Renamed zcip_if only for eth0 (how exactly zeroconf supposed to coexist on more than one iface? They would all have 169.254/16 subnet - ?!). Created a user to save all logs under: groupadd -f --system logger useradd --system -g logger -d /tmp -s /bin/false logger Created /var/service/start: #!/bin/sh dir=/var/service export PATH=/sbin:/bin:/usr/sbin:/usr/bin exec /dev/null 2>&1 umask 022 cd "$dir" || exit $? exec env - PATH="$PATH" runsvdir -P "$dir" Created /etc/systemd/system/var.service: [Unit] Description=/var/service support [Service] ExecStart=/var/service/start Added symlink: /etc/systemd/system/multi-user.target.wants/var.service -> -> /etc/systemd/system/var.service Deinstalled NetworkManager. Rebooted and tested that services from /var/service do start, and nicely coexist with the rest of the system. Tested network (DHCP, zeroconf) and local DNS caching to work. Now we will pry off X startup from systemd. Changed /etc/systemd/system/default.target symlink to point to /lib/systemd/system/multi-user.target instead of a GUI link. Reboot. Now the system should start with Linux text VT's. Created /var/service/lightdm_tty8 service. For user's convenience, it's activated by pressing Enter at a chosen tty. This is the run file: #!/bin/sh tty="/dev/${PWD##*/lightdm_}" need "$tty" exec <"$tty" exec >"$tty" 2>&1 # If udevd is not up, X may fail to find any input devices. Wait for it. need /run/udevd_ready echo "Press Enter to start lightdm"; read junk echo "* Starting lightdm[$$]" exec \ env - PATH="$PATH" \ lightdm Hmm. A tool to wait for a file is needed. So far this should do - /bin/need: #!/bin/sh i=0 while ! test -e "$1"; do sleep "0.$i" test "$i" = 9 || i=$((i+1)) done Started it. Confirmed that GUI environment starts and seems to work just fine. The big one: make system boot without systemd. Final preparations are: * Create dbus and udevd services, start them only if systemd is not detected. * Create init scripts. The word "init" here has more than one meaning... Created /var/service/dbus-daemon service. run file: #!/bin/sh #exec >/dev/null exec 2>&1 exec /dev/null exec 2>&1 exec /run/udevd_ready echo "Done: trigger+settle" ) & echo "* Starting systemd-udevd[$$]" exec \ env - PATH="$PATH" \ /usr/lib/systemd/systemd-udevd It should auto-shutdown now, since systemd is detected. Created /init script. #!/bin/sh export PATH=/sbin:/bin:/usr/sbin:/usr/bin /etc/runit/1 exec 0>&- 1>&- 2>&- # In this form, shell won't have an open fd to the script file exec env - sh -c 'while :; do sleep 9999; done' Isn't it a cutie. In the spirit of runit tool, let's run system startup scripts from /etc/runit/1. Create it: #!/bin/sh dir_and_not_mounted() { test -d "$1" || return 1 ! mountpoint -q -- "$1" } if fsck -A; then true else echo "fsck exit code: $?. Boot will not continue." while true; do sleep 9999; done fi mount -o remount,rw / mount -a dir_and_not_mounted /proc && mount -t proc proc /proc dir_and_not_mounted /sys && mount -t sysfs sysfs /sys # These are mounted by systemd, for some reason not via fstab. Mimic for now: dir_and_not_mounted /tmp && mount -t tmpfs tmpfs /tmp dir_and_not_mounted /run && mount -t tmpfs tmpfs /run # Remove the mess left by systemd which possibly ran in initramfs: for d in /sys/fs/cgroup/* /sys/fs/cgroup /sys/kernel/security; do mountpoint -q -- "$d" && umount "$d" done # initramfs journald shit no one asked for: test -d /run/log/journal && rm -rf /run/log/journal # # Start service supervision /var/service/start & Added "init=/init" to the kernel command line. Reboot. Enjoy new view in "ps -AH". Reboot/poweroff does not need cooperation with init. Copied examples/shutdown-1.0 to /app/shutdown-1.0. Installed /sbin/* symlinks as described in README. What's missing or needs improvement? /var/service/syslog, /var/service/klogd. "need" (waiting for a file/device/directory/socket to appear) needs to be a real tool, not a shell loop. Maybe with an optional timeout? Maybe it already exists? ifplugd_handler needs a better way to code for the "if service FOO exists, start it, if it does not, it's fine" idiom. Admins would need a convenient tool to tail/page service logs just by name. Something along the lines of sview: #!/bin/sh test "$1" || { echo "Syntax: ${0##*/} SERVICE" exit 1 } cd "/var/service/$1" || exit $? test -x ./view && exec ./view cd "log/logdir" || exit $? h=`ttysize h` exec tail -n $((h-1)) -F current 2>&1 svpage: #!/bin/sh test "$1" || { echo "Syntax: ${0##*/} SERVICE" exit 1 } cd "/var/service/$1" || exit $? test -x ./page && exec ./page test "$PAGER" || PAGER=less cd "log/logdir" || exit $? cat @* current | $PAGER