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

Reply via email to