GW3: s6 init/rc

Posted on Sun 02 February 2020 in linux

Today is 20200202.

Openrc analysis


  • need: hard dep
  • want: start available service even if not in runlevel
  • use: use it if it is available and in runlevel
  • before, after: valid when both in runlevel; void otherwise
  • keyword: see man openrc-run


unseen in openrc: mount proc

  • 01 dmesg : dmesg -n $level
  • 02 sysfs : /sys and its content
    • mount /sys if 'sysfs' in /proc/filesystems
    • mount debugfs, selinuxfs, pstore, efivarfs, securityfs, configfs, fusectl inside /sys
  • 03 devfs(=dev-mount) : /dev and its content
    • ensure /dev is mounted
    • mknod console, tty, tty1, null, kmsg (they been already there though)
    • ln fd, stdin, stdout, stderr, core
    • mount mqueue, pts, shm inside /dev
  • 03->04 kmod-static-nodes : mkdir -p /run/tmpfiles.d, write nodes to /run/tmpfiles.d/kmod.conf for systemd-tmpfiles
  • 02+03->05 udev : longrun daemon , /proc/sys/kernel/hotplug
  • 05->06 hostname xyz
  • 05->07 udev-trigger(=dev)
    • (udev monitor)
    • /dev/root symlink
    • populate coldplug devices
    • (retain/kill monitor), display hotplugged devices

Also: termencoding, keymaps, hwclock, modules, fsck, /lib/rc/sh/, sysctl


  • 11 root : mount root rw
  • 11->12 mtab : mtab symlink (it already been there)
  • 13 misc-dir : mkdir /tmp/{.X11, .ICE}, ln /var/{lock,run}, systemd-tmpfiles non-dev (cat-config)
  • 14 loopback : ip lo interface
  • 15 urandom-init : echo SEED > /dev/urandom
  • 16 /proc/sys/fs/binfmt_misc

Also: dumpkeys > /lib/rc/console/keymap, echo > /lib/rc/console/unicode, cgroups


s6 tree

s6-svscan[d,pid1] <-- s6-svscanctl[c]
|-- s6-supervise1[d] <-- s6-svc[c]
|   |-- service1
|-- s6-supervise2[d] <-- s6-svc[c]
    |-- service2

stage1 init

skarnet has offered an all-in-one init1; or see slew's step-by-step init1.

s6-linux-init slew rc.boot
-p initPATH emptyenv, then set $PATH
cd / cd /
umask & session leader setsid & umask
< /dev/null < /dev/null
ensure /run ensure /run
NA dmesg -n1 & hwclock
copy /run/service copy /run/service
parse env parse env
1> fifo 1> fifo
bg { kernel cmdline runlevel, await logger, then rc.init } bg { setsid, rc.init }
s6-svscan /run/service s6-svscan /run/service

stage2 init (s6-rc)

  • stdout & stderr > logger
  • s6-rc-init reads a read-only compiled service database
  • s6-rc launches (vital) boot-up services.

user provided files

s6-linux-init-maker -c /etc/s6-linux-init/cur -G "/sbin/agetty 38400 tty1 linux" -1 -p "/bin:/sbin:/usr/sbin:/usr/bin" -f /path/to/user/skel /tmp/blah

skel/rc.init brings up rc services (generated by s6-rc-compile)

My version is here.


init switch

Copying s6 init to /sbin will fail if the sysvinit /sbin/init is being used. Instead, create another boot entry (by efibootmgr or in Grub) with cmdline init=/path/to/s6init. In this way, you can switch init/rc systems easily.

When in an s6 env, call s6 poweroff/reboot (inside /etc/s6-linux-init/current/bin/ by default)

daemon loads forever till timeout (fatal error)

I mistakenly created a notification-fd file for a daemon which doesn't give readiness notification.

some changes

Module efivarfs is auto loaded in openrc env, while not in s6 env.

Worth reading