Denys,
As a long-time Fedora (mostly) user I found this very interesting!
Thanks!
Phil.
On 2018-04-20 01:18, Denys Vlasenko wrote:
After yet another incident of wandering among endless
directories/"targets"/links trying to figure out how to stop
the laptop from falling asleep on lid close, I've had enough.
Since no one had time/inspiration to create runit/daemontools
style servie supervision in Fedora, I'll going to create
something homegrown.
This also doubles as a test whether busybox's runit tools
are up to the task.
https://busybox.net/ -> [Life without systemd]
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
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
test "`pidof systemd`" && exec sv d .
mkdir -p /run/dbus
echo "* Starting dbus-daemon[$$]"
exec \
env - PATH="$PATH" \
dbus-daemon --nofork --nopidfile --system
I give it the standard log/ even though it does not talk much.
It should auto-shutdown now, since systemd is detected.
Created /var/service/udevd service - its run file:
#!/bin/sh
#exec >/dev/null
exec 2>&1
exec </dev/null
test "`pidof systemd`" && exec sv d .
mkdir -p /run/udev
rm -f /run/udev/control # just in case
rm -f /run/udevd_ready # just in case
(
need /run/udev/control # not sure we really need to wait for it
echo "Trigger+settle:"
udevadm --debug trigger --type=subsystems --action=add
udevadm --debug trigger --type=devices --action=add
udevadm --debug settle
>/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.
[todo: write it up here]
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
_______________________________________________
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox
--
Philip Rhoades
PO Box 896
Cowra NSW 2794
Australia
E-mail: p...@pricom.com.au
_______________________________________________
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox