User:Hfern/Drafts/openrc-init

From Gentoo Wiki
Jump to: navigation, search
Openrc-init
Supervise-daemon
Warning
This page has been nominated for deletion.

The given reason is: This was a working page prior to publishing it on the wiki. The contents have since been placed in OpenRC/supervise-daemon and OpenRC/openrc-init. -- Hfern (talk) 14:22, 18 August 2019 (UTC)

If you disagree with its deletion, do not remove this notice; discuss your objections on the associated discussion page.

Administrators, please remember to check if anything links here and the page history before deleting.

This notice should remain for a minimum of 1 month after it was placed on the page. If discussion is still ongoing it should remain until a consensus is reached, at which time the page may be deleted or this notice may be removed. (However, if the page has only been edited by the user who nominated it for deletion and/or is in the nominator's user space, then a speedy deletion may be called for.)

Openrc has developed itself and has gained some new features. In this article two features are highlighted:

  • Openrc-init, is openrc's own init system, and can act as a replacement for sysvinit, and
  • Supervise-daemon, which can supervise daemon processes. Supervise-daemon could replace start-stop-daemon, which is used by quite a few services.
Warning
In the source code of the current version of supervise-daemon it is still stated that it is experimental. Use supervise-daemon at own risk.

Openrc-init

Replacing sysvinit with openrc-init takes a few steps. The description that follows refers to grub.

  • Pass init=/sbin/openrc-init on the kernel's commandline.
  • Openrc-init does not start the agetty processes so it needs to be done using supervise-daemon

Update /etc/default/grub as follows:

FILE /etc/default/grub
#GRUB_CMDLINE_LINUX_DEFAULT=""
GRUB_CMDLINE_LINUX_DEFAULT="init=/sbin/openrc-init"

Regenerate /boot/grub/grub.cfg:

root #grub-mkconfig -o /boot/grub/grub.cfg

Make sure agetty processes for tty1 to tty6 will be started under openrc-init:

root #cd /etc/init.d
root #for n in `seq 1 6`; do ln -s agetty agetty.tty$n; rc-config add agetty.tty$n default; done

Reboot your system:

root # reboot

Be aware that commands like reboot, and shutdown are no longer working under openrc-init. Use openrc-shupdown -r now, or openrc-shutdown now instead.

Supervise-daemon

Openrc traditionally uses start-stop-daemon, often called s-s-d for starting, and stopping programs. When s-s-d starts a process it saves the process' PID somewhere on permanent storage, and backgrounds (daemonizes) the process it started. When the time comes to stop, kill, or signal the daemon it uses the saved PID file to find the right process.

Supervising on the other hand usually keeps the started daemon as a child process of the supervisor. Backgrounding the daemon is therefore not needed, and not desired. An advantage of supervising a daemon is also that any terminal output sent to stdout and stderr can be caught by the supervisor, and sent to the system logger or to a file.

Bringing a service under supervision theoretically should be as easy as adding supervisor="supervisor-daemon" to its conf file in /etc/conf.d. It turns out to be a little more complex in some cases.

Openrc has the concept that services' startup code, the init files in /etc/init.d/ can be adjusted through configuration files in /etc/conf.d. With this concept it is possible to add environment variables, or commandline options in the configuration file and not change the init file. Some init files however don't implemement this concept fully and define variables in the init file that cannot be adjusted in the conf file. Examples are:

  • defining a pidfile variable in an init file, e.g. in /etc/init.d/bluetooth: pidfile="/run/bluetoothd.pid"
  • defining variables in the init file, rather then in the conf file, e.g. in /etc/init.d/iwd: command_background="yes"
  • not allowing for expansion of a variable, e.g. in /etc/init.d/dbus: command_args="--system"

In such cases it might be needed to adjust the init file and not just the conf file.

Other cases that might need adjusting the init files are explicit references to the underlying utility s-s-d, which is not used in case of supervising.

agetty

agetty was already brought under supervise-daemon in the previous chapter. Verify with:

root #ps aux | grep agetty
root      1171  0.0  0.1   3020  1832 pts/1    S+   10:16   0:00 grep --colour=auto agetty
root      2666  0.0  0.1   2984  1492 ?        S    Jun08   0:00 supervise-daemon agetty-autologin.tty1 --start --pidfile /run/agetty-autologin.tty1.pid --respawn-period 60 /sbin/agetty -- --autologin hfern --noclear tty1 linux
root      2694  0.0  0.1   2984  1440 ?        S    Jun08   0:00 supervise-daemon agetty.tty2 --start --pidfile /run/agetty.tty2.pid --respawn-period 60 /sbin/agetty -- tty2 linux
root      2695  0.0  0.2   4732  2584 tty2     Ss+  Jun08   0:00 /sbin/agetty tty2 linux
root      2723  0.0  0.1   2984  1492 ?        S    Jun08   0:00 supervise-daemon agetty.tty3 --start --pidfile /run/agetty.tty3.pid --respawn-period 60 /sbin/agetty -- tty3 linux
root      2724  0.0  0.2   4732  2428 tty3     Ss+  Jun08   0:00 /sbin/agetty tty3 linux
root      2770  0.0  0.1   2984  1412 ?        S    Jun08   0:00 supervise-daemon agetty.tty4 --start --pidfile /run/agetty.tty4.pid --respawn-period 60 /sbin/agetty -- tty4 linux
root      2771  0.0  0.2   4732  2344 tty4     Ss+  Jun08   0:00 /sbin/agetty tty4 linux
root      2828  0.0  0.1   2984  1516 ?        S    Jun08   0:00 supervise-daemon agetty.tty5 --start --pidfile /run/agetty.tty5.pid --respawn-period 60 /sbin/agetty -- tty5 linux
root      2830  0.0  0.2   4732  2476 tty5     Ss+  Jun08   0:00 /sbin/agetty tty5 linux
root      2869  0.0  0.1   2984  1420 ?        S    Jun08   0:00 supervise-daemon agetty.tty6 --start --pidfile /run/agetty.tty6.pid --respawn-period 60 /sbin/agetty -- tty6 linux
root      2870  0.0  0.2   4732  2584 tty6     Ss+  Jun08   0:00 /sbin/agetty tty6 linux

acpid

Reviewing the man page of acppid reveals:

  • .. will run as background process ..
  • .. -f, --foreground .. keeps acpid in the foreground by not forking at startup, and makes it log to stderr instead of syslog.

Edit /etc/conf.d/acpid as follows to make acpid run under supervise-daemon:

FILE /etc/conf.d/acpid
#ACPID_ARGS=""
ACPID_ARGS="--foreground"
supervisor="supervise-daemon"

Verify if acpid is now running under supervise-daemon:

root #ps aux | grep acpid
root       564  0.0  0.1   2984  1712 ?        S    09:10   0:00 supervise-daemon acpid --start /usr/sbin/acpid -- --foreground
root       575  0.0  0.1   2444  1700 ?        Ss   09:11   0:00 /usr/sbin/acpid --foreground

Check the logs as well:

root #tail /var/log/messages
Jun 10 09:10:27 [supervise-daemon] Supervisor command line: supervise-daemon acpid --start /usr/sbin/acpid -- --foreground
Jun 10 09:10:27 [supervise-daemon] Child command line: /usr/sbin/acpid --foreground

And when you create an acpid event it will be logged:

root #tail /var/log/messages
Jun 10 09:15:08 [user] ACPI event unhandled: button/mute MUTE 00000080 00000000 K

Lastly, check if supervise-daemon will restart acpid when it terminates:

root #kill 575
root #tail /var/log/messages
Jun 10 09:54:20 [supervise-daemon] /usr/sbin/acpid, pid 575, exited with return code 0
Jun 10 09:54:20 [supervise-daemon] Child command line: /usr/sbin/acpid --foreground 
root #ps aux | grep acpid
root       564  0.0  0.1   2984  1712 ?        S    09:10   0:00 supervise-daemon acpid --start /usr/sbin/acpid -- --foreground
root       961  0.0  0.1   2444  1932 ?        Ss   09:54   0:00 /usr/sbin/acpid --foreground 

Notice the different PID.

avahi-daemon

net-dns/avahi contains a service avahi-daemon for service discovery. Execute the following steps to bring it under supervision.

Stop the service:

root #rc-service avahi-daemon stop
avahi-daemon           | * Stopping avahi-daemon ...                                     [ ok ]

Edit or create /etc/conf.d/avahi-daemon as follows:

FILE /etc/conf.d/avahi-daemon
supervisor="supervise-daemon"

Avahi-daemon's init file /etc/init.d/avahi-daemon does not make use s-s-d, but calls the binary /usr/sbin/avahi-daemon directly and gives it the instruction to daemonize: /usr/sbin/avahi-daemon -D on startup. We can simply adjust that by defining the command variable as command="/usr/sbin/avahi-daemon", and removing the start and stop functions from the file. Edit /etc/init.d/avahi-daemon as follows:

CODE /etc/init.d/avahi-daemon
#!/sbin/openrc-run
# Copyright 1999-2016 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2

extra_started_commands="reload"
command="/usr/sbin/avahi-daemon"

depend() {
        before netmount nfsmount
        use net
        need dbus
}

#start() {
#       ebegin "Starting avahi-daemon"
#       /usr/sbin/avahi-daemon -D
#       eend $?
#}
#
#stop() {
#       ebegin "Stopping avahi-daemon"
#       /usr/sbin/avahi-daemon -k
#       eend $?
#}

reload() {
       ebegin "Reloading avahi-daemon"
#      /usr/sbin/avahi-daemon -r
       ${command} -r
       eend $?
}


Start the service back up:

root #rc-service avahi-daemon start
avahi-daemon           | * Caching service dependencies ...                              [ ok ]
avahi-daemon           | * Starting avahi-daemon ...                                     [ ok ]

Verify that the service is now supervised:

root #ps -ef | grep avahi
root     27390     1  0 10:30 ?        00:00:00 supervise-daemon avahi-daemon --start /usr/sbin/avahi-daemon --
avahi    27392 27390  0 10:30 ?        00:00:00 avahi-daemon: running [e485.local]
avahi    27397 27392  0 10:30 ?        00:00:00 avahi-daemon: chroot helper

bluetooth

Net-wireless/bluez provides bluetooth services. Bring it under supervise-daemon with the following steps:

Stop it:

root #rc-service bluetoothd stop
bluetooth              | * Caching service dependencies ...                          [ ok ]
bluetooth              | * Stopping bluetooth ...                                    [ ok ]

Edit its init file:

CODE
#pidfile="/run/bluetoothd.pid"
command="/usr/libexec/bluetooth/bluetoothd"
#command_background=1
supervisor="supervise-daemon"

And start it back up:

root #rc-service bluetooth start
bluetooth              | * Starting bluetooth ...                                    [ ok ]


cupsd

Cups is the well known printing system of linux. Its daemon cupsd' is provided by net-print/cups. The following steps will bring it under supervision:

Stop the service:

root #rc-service cupsd stop
cupsd                  | * Stopping cupsd ...                                            [ ok ]

Create /etc/conf.d/cupsd with the following content:

FILE /etc/conf.d/cupsd
supervisor="supervise-daemon"

Remove the pidfile and s-s-d instructions from /etc/init.d/cupsd by commenting them out:

CODE
#pidfile="/var/run/cupsd.pid"
#start_stop_daemon_args="-b -m --pidfile ${pidfile}"

dnsmasq

Dnsmasq, provided by package net-dns/dnsmasq, is a lightweight DHCP and caching DNS server.

Take the following steps to bring it under supervision: Stop the service:

root #rc-service dnsmasq stop
dnsmasq                | * Stopping dnsmasq ...                                                                                                         [ ok ]

Dnsmasq's init file contains a references to s-s-d, and pidfiles. The daemon needs to be configured to run in foreground.

Edit /etc/init.d/dnsmasq as follows:

CODE
pidfile="/var/run/dnsmasq.pid"
command="/usr/sbin/dnsmasq"
#command_args="-x ${pidfile} ${DNSMASQ_OPTS}"
command_args="${DNSMASQ_OPTS} --keep-in-foreground"
supervisor="supervise-daemon"
retry="TERM/3/TERM/5"

depend() {
        provide dns
        need localmount net
        after bootmisc
        use logger
}

start_pre() {
        checkpath --owner dnsmasq:dnsmasq \
                --mode 0644 \
                --file /var/lib/misc/dnsmasq.leases
}

reload() {
        ebegin "Reloading ${RC_SVCNAME}"
#       start-stop-daemon --signal HUP --pidfile "${pidfile}"
        ${supervisor} ${RC_SVCNAME} --signal HUP
        eend $?
}

rotate() {
        ebegin "Reopening ${RC_SVCNAME} log file"
#       start-stop-daemon --signal USR2 --pidfile "${pidfile}"
        ${supervisor} ${RC_SVCNAME}  --signal USR2
        eend $?
}

Start the service back up:

root #rc-service dnsmasq start
dnsmasq                | * dnsmasq                | * Starting dnsmasq ...                                                                                                         [ ok ]


fcron

sys-process/fcron is a cron daemon implementation.

Stop the service:

root #rc-service fcron stop
fcron                  | * Stopping dcron ...                                            [ ok ]

Edit or create /etc/conf.d/fcron as follows:

FILE /etc/conf.d/fcron
FCRON_OPTS="--foreground"
supervisor="supervise-daemon"

Fcron's init file has an few references to s-s-d, defines command_args so that we cannot adjust it in /etc/conf.d/fcron, and has a pidfile instruction that needs to be removed. The init file also does not honor any configuration option setting in the conf file. Edit /etc/init.d/fcron as follows:

CODE
#command_args="-c \"${FCRON_CONFIGFILE}\""
command_args="-c \"${FCRON_CONFIGFILE}\" ${FCRON_OPTS}"
#start_stop_daemon_args=${FCRON_SSDARGS:-"--wait 1000"}
#pidfile="$(getconfig pidfile /run/fcron.pid)"

Start the service:

root #rc-service fcron start
fcron                  | * Caching service dependencies ...                               [ ok ]
fcron                  | * Starting fcron ...                                             [ ok ]

And look that pids to confirm that fcron is now under supervisor-daemon:

root #ps -ef | grep fcron
root     10097     1  0 16:30 ?        00:00:00 supervise-daemon fcron --start /usr/libexec/fcron -- -c /etc/fcron/fcron.conf --foreground
root     10098 10097  0 16:30 ?        00:00:00 /usr/libexec/fcron -c /etc/fcron/fcron.conf --foreground

iwd

Iwd (iNet wireless daemon) is provided by net-wireless/iwd and aims to replace net-wireless/wpa_supplicant. Take the following steps to bring iwd under supervision:

Stop the service:

root #rc-service syslog-ng stop
iwd                    | * Stopping iwd ...                                              [ ok ]

Create /etc/conf.d/iwd:

FILE /etc/conf.d/iwd
supervisor="supervise-daemon"

Comment out command_background="yes" in /etc/init.d/iwd to avoid backgrounding by s-s-d:

CODE /etc/init.d/syslog-ng
#command_background="yes"

Start the service back up:

root #rc-service syslog-ng start
iwd                    | * Starting iwd ...                                              [ ok ]

Verify that it works as intended:

root #ps -ef
root # grep iwd
root     30622     1  0 12:51 ?        00:00:00 supervise-daemon iwd --start --pidfile /run/iwd.pid /usr/libexec/iwd --
root     30623 30622  0 12:51 ?        00:00:00 /usr/libexec/iwd

ntpd

The network time protocol daemon ntpd, net-misc/ntp can be brought under supervision with a few steps: Edit the init file to remove the pidfile reference, add "-n" to the command line of the ntpd daemon, and define the supervisor:

FILE /etc/conf.d/syslog-ng
#pidfile="/var/run/ntpd.pid"
command="/usr/sbin/ntpd"
#command_args="-p ${pidfile} ${NTPD_OPTS}"
command_args="-n -p ${pidfile} ${NTPD_OPTS}"
#start_stop_daemon_args="--pidfile ${pidfile}"
supervisor="supervise-daemon"


syslog-ng

app-admin/syslog-ng is an interesting case. Without any change, running syslog-ng under s-s-d it looks like this:

root #ps -ef | grep syslog-ng
root      7800     1  0 09:16 ?        00:00:00 supervising syslog-ng
root      7802  7800  4 09:16 ?        00:03:56 /usr/sbin/syslog-ng --cfgfile /etc/syslog-ng/syslog-ng.conf --control /run/syslog-ng.ctl --persist-file /var/lib/syslog-ng/syslog-ng.persist --pidfile /run/syslog-ng.pid

There is a process with in this case PID 7800 'supervising syslog-ng' with a parent-PID (PPID) of 1, which means it's parent is the init process. There is also the process with PID 7802, which looks more like what we might expect, referencing the binary. This process' PPID is 7800, i.e. the supervising process.

The supervise process is actually also the same binary of syslog-ng:

root #pgrep -lf syslog
7800 syslog-ng
7802 syslog-ng

Syslog-ng appears to be supervising itself. What it does after startup is:

  • double fork, to become a background daemon process (PID 7800) and get it to be adopted by the init process (PID 1);
  • fork again to create the worker process (PID 7802) as it's child process;
  • rename the process (PID 7800) to "supervise syslog-ng", in the parent process, and supervise its child (PID 7802).

If and when "supervise syslog-ng" detects that it's worker process (PID 7802) has terminated it will restart it. Syslog-ng calls this process mode "safe-background".

In order to get syslog-ng to work well under supervise-daemon it needs to run in the foreground though.

First stop syslog-ng:

root #rc-service syslog-ng stop
syslog-ng              | * Stopping syslog-ng ...                                        [ ok ]

Edit /etc/conf.d/syslog-ng as follows to make syslog-ng run onder supervise-daemon:

FILE /etc/conf.d/syslog-ng
#SYSLOG_NG_OPTS=""
SYSLOG_NG_OPTS="--foreground --process-mode=foreground"
supervisor="supervise-daemon"
supervise_daemon_args="--respawn-max 5 --respawn-period 10"

With the standard init scripts syslog-ng writes a pid file. This interferes with the operation of supervise-daemon so will have to be removed. Edit /etc/init.d/syslog-ng to remove the --pidfile option in the command_args, and comment out the pidfile variable:

CODE /etc/init.d/syslog-ng
#command_args="--cfgfile \"${SYSLOG_NG_CONFIGFILE}\" --control \"${SYSLOG_NG_CONTROLFILE}\" --persist-file \"${SYSLOG_NG_STATEFILE}\" --pidfile \"${SYSLOG_NG_PIDFILE}\" ${SYSLOG_NG_OPTS}"
command_args="--cfgfile \"${SYSLOG_NG_CONFIGFILE}\" --control \"${SYSLOG_NG_CONTROLFILE}\" --persist-file \"${SYSLOG_NG_STATEFILE}\" ${SYSLOG_NG_OPTS}"
command_user="${SYSLOG_NG_USER}:${SYSLOG_NG_GROUP}"
extra_commands="checkconfig"
extra_started_commands="reload"
#pidfile="${SYSLOG_NG_PIDFILE}"

Start syslog-ng again:

root #rc-service syslog-ng start
syslog-ng              | * Checking your configfile (/etc/syslog-ng/syslog-ng.conf) ...   [ ok ]
syslog-ng              | * Starting syslog-ng ...                                         [ ok ]


Verify that it works:

root #ps -ef | grep syslog-ng
root     10881     1  0 11:14 ?        00:00:00 supervise-daemon syslog-ng --start --user root root --respawn-max 5 --respawn-period 10 /usr/sbin/syslog-ng -- --cfgfile /etc/syslog-ng/syslog-ng.conf --control /run/syslog-ng.ctl --persist-file /var/lib/syslog-ng/syslog-ng.persist --foreground --process-mode=foreground
root     10882 10881  0 11:14 ?        00:00:00 /usr/sbin/syslog-ng --cfgfile /etc/syslog-ng/syslog-ng.conf --control /run/syslog-ng.ctl --persist-file /var/lib/syslog-ng/syslog-ng.persist --foreground --process-mode=foreground

Notice that supervise-daemon is started with PID 10881, and syslog-ng with PID 10882, and PPID 10881, ie the supervise-daemon process.

sshd

The sshd (Secure Shell daemon) is the daemon program for ssh(1). The following steps bring it under supervision:

Stop the service:

root #rc-service sshd stop
sshd                   | * Caching service dependencies ...                  [ ok ]
sshd                   | * Stopping sshd ...                                 [ ok ]


In /etc/init.d/sshd we need to configure the daemon to run in foreground. In this case it is the same as configuring it debug mode, so there may be some more text logged. References s-s-d and pid files need to be adjusted. Edit /etc/init.d/sshd at the beginning of the file as follows:

CODE /etc/init.d/sshd
#pidfile="${SSHD_PIDFILE}"
#command_args="${SSHD_OPTS} -o PidFile=${pidfile} -f ${SSHD_CONFIG}"
command_args="${SSHD_OPTS} -f ${SSHD_CONFIG} -D"
supervisor="supervise-daemon"

# Wait one second (length chosen arbitrarily) to see if sshd actually
# creates a PID file, or if it crashes for some reason like not being
# able to bind to the address in ListenAddress (bug 617596).
#: ${SSHD_SSD_OPTS:=--wait 1000}
#start_stop_daemon_args="${SSHD_SSD_OPTS}"

All the way at the end there is the reload function that needs adjusting:

CODE /etc/init.d/sshd
reload() {
        checkconfig || return $?
        ebegin "Reloading ${SVCNAME}"
#       start-stop-daemon --signal HUP --pidfile "${pidfile}"
        ${supervisor} ${SVCNAME} --signal HUP
        eend $?
}


Start the service back up:

root #rc-service sshd start
sshd                   | * Starting sshd ...                                 [ ok ]

Useful tools

rc-status

Rc-status has an option to view supervised services:

root #rc-status -S
 bluetooth                                                                                  [  started 00:28:26 (0) ]
 syslog-ng                                                                                  [  started 00:41:40 (0) ]
 acpid                                                                                      [  started 00:41:39 (0) ]
 avahi-daemon                                                                               [  started 00:41:39 (0) ]
 dnsmasq                                                                                    [  started 00:41:39 (0) ]
 cupsd                                                                                      [  started 00:41:39 (0) ]
 fcron                                                                                      [  started 00:41:39 (0) ]
 iwd                                                                                        [  started 00:41:39 (0) ]
 sshd                                                                                       [  started 00:41:39 (0) ]
 agetty.tty3                                                                                [  started 00:41:38 (0) ]
 agetty.tty4                                                                                [  started 00:41:38 (0) ]
 agetty.tty1                                                                                [  started 00:41:38 (0) ]
 agetty.tty6                                                                                [  started 00:41:38 (0) ]
 agetty.tty5                                                                                [  started 00:41:38 (0) ]
 agetty.tty2                                                                                [  started 00:41:38 (0) ]

Services which won't run under a supervisor

Unfortunately not all services are easy to run under supervisor-daemon, or other supervisors. The requirement that the daemon needs to run in foreground is not satisfied with all daemons, or it simply does not work. Sometimes there are alternatives available.

dcron

Sys-process/dcron version 4.5-r1 crashes without an error message when it is run under a supervisor. Consider an alternative like sys-process/fcron.


vixie-cron

Gentoo's sys-process/vixie-cronhas no option to run in foreground, even though in other linux distributions the cron process would accept a -f flag. Consider an alternative like sys-process/fcron.

See also