User:Flexibeast/guides/OpenRC user services via s6
User services are not yet implemented in OpenRC (though such functionality is being worked on). This guide will demonstrate how a user service can be implemented by using s6 to provide service supervision (i.e. keeping a service running) and basic service management.
Service supervision with s6
Install sys-apps/s6 (and optionally, app-doc/s6-man-pages):
root #
emerge --ask sys-apps/s6
root #
emerge --ask app-doc/s6-man-pages
As an example, we'll set up an Emacs service.
Create a directory in which "servicedirs" ("service directories", documented here) will be created. We'll use ~/s6, and cd to the newly-created directory:
user $
mkdir ~/s6
user $
cd ~/s6
Create an emacs servicedir in that directory, and change to that directory:
user $
mkdir emacs
user $
cd emacs
Now use your editor to create a file called run. This file will be run by s6-supervise, and thus needs to be something executable. The lightweight execline scripting language can be used, but it's not compulsory; for the purposes of this example, we'll just use Bash:
#!/usr/bin/bash
exec /usr/bin/emacs --fg-daemon 1>>"${HOME}/.logs/emacs.log" 2>&1
Note the use of exec on the last line of the script; this is crucial. s6 (and other daemontools-style supervisors) start the supervised program as a direct child of the supervising process, and are therefore able to directly determine the status of the service process. This means that the program must not be backgrounded, and that exec must be used to replace the run script with the program as the direct child of the s6-supervise process.
The script also sets up basic logging via redirection to a (presumed preexisting) ${HOME}/.logs/emacs.log file. A more sophisticated approach to logging is provided by s6-rc.
Set the permissions of run to 700:
user $
chmod 700 run
And that's it! To start the service, run s6-supervise with the path to the servicedir:
user $
s6-supervise ~/s6/emacs
With this basic setup, s6-supervise will try to ensure the service is always up: manually terminating the process, e.g. via:
user $
pkill emacs
will subsequently result in a new Emacs server process being created:
user $
pgrep -a emacs
When supervising a program, s6-supervise creates two directories in the servicedir: events/, a fifodir for service-related events, and supervise/, for storing internal state.
The s6-svc program can be used to manage the service. For example, to force a restart:
user $
s6-svc -r ~/s6/emacs
or to stop the service:
user $
s6-svc -dx ~/s6/emacs
where the -d
option brings the service down, and the -x
option tells the s6-supervise process to exit once the service is down.
Assuming a console-based login, the emacs
service could be started at login, once the appropriate environment variables have been set up, via one of the shell's configuration files, e.g. ~/.bash_login:
s6-supervise ~/s6/emacs
Optional: Modify script to add D-Bus support
Some Emacs functionality requires the presence of a D-Bus session bus (which is distinct from the D-Bus system bus provided by the dbus
service). Assuming that a D-Bus session bus has been created and its value saved somewhere, e.g. via something like:
dbus-daemon --session --fork --print-address 4 4>|"${XDG_STATE_HOME}/session-bus-address"
The run script can be modified to set the value of DBUS_SESSION_BUS_ADDRESS for the Emacs service:
#!/usr/bin/bash
export DBUS_SESSION_BUS_ADDRESS=$(cat "${XDG_STATE_HOME}/session-bus-address" | tr -d '\n')
exec /usr/bin/emacs --fg-daemon 1>>"${HOME}/.logs/emacs.log" 2>&1