In Nitrux, we utilize OpenRC as the init-system; it differs from the more widely used systemd software suite (which includes an init) in using scripts instead of “units” to start services. So, in today’s tutorial, we’ll check how to create service files (scripts) for use with OpenRC.
This tutorial is part one of two, with the second dealing with “user” services, as OpenRC does not use the concept of “user services.”
Difficulty: ★☆☆☆☆
Structure
Let’s start with an example.
- ⚠️ Important: Adding system services files requires adding files to the root directory; see XFS Features and Root Immutability in Nitrux.
#!/usr/bin/openrc-run # Copyright 2022 Nitrux Latinoamericana S.C. # Distributed under the terms of the 3-Clause BSD License PIDFILE=/run/mybinary.pid BIN=/path/to/mybinary start() { ebegin "Starting mybinary" start-stop-daemon --start --exec $BIN --pidfile $PIDFILE eend $? } stop() { ebegin "Stopping mybinary" start-stop-daemon --stop --exec $BIN --pidfile $PIDFILE eend $? }
The structure is straightforward to understand. First, we need to add the correct shebang; the shebang has to be ‘#!/usr/bin/openrc-run‘; otherwise, the script won’t run, and we can add a License header optionally. Then, we set two variables, ‘PIDFILE’ and ‘BIN’; these are variables where we specify the path of the PID file and the binary we want to run as a service.
- 🔰 Information: A PID file is a file that contains the PID (PID is the operating system’s unique identifier for active programs that are running) of the executable that generated it. The PID file must be in ‘/run/’ and use the same name as the binary.
Next, we have two shell functions, start and stop; these contain the command ‘start-stop-daemon,’ which we use to do just that, starting and stopping the binary we want as a daemon.
An additional function is called depend. The OpenRC user guide states, “A depend function declares the dependencies of this service script. All scripts must have start/stop/status functions, but defaults are provided and should be used unless you have a very strong reason not to use them.”
#!/usr/bin/openrc-run # Copyright 2022 Nitrux Latinoamericana S.C. # Distributed under the terms of the 3-Clause BSD License PIDFILE=/run/mybinary.pid BIN=/path/to/mybinary depend() { after service1 service2 } start() { ebegin "Starting mybinary" start-stop-daemon --start --exec $BIN --pidfile $PIDFILE eend $? } stop() { ebegin "Stopping mybinary" start-stop-daemon --stop --exec $BIN --pidfile $PIDFILE eend $? }
- 🔰 Information: For more information about ‘service dependencies,’ check The Depend Function in the OpenRC user guide.
Usage
Service scripts are in ‘/etc/init.d’; we must add them to a runlevel to use them. As described in the OpenRC user guide, “OpenRC has a concept of runlevels, similar to what sysvinit historically offered. A runlevel is a collection of services that needs to be started. Instead of random numbers, they are named, and users can create their own if needed. This allows, for example, to have a default runlevel with “everything” enabled and a “power-saving” runlevel where some services are disabled.”
- 🔰 Information: All runlevels are folders in ‘/etc/runlevels/’ with symlinks to ‘/etc/init.d‘ with the actual service scripts files. By default, there are seven runlevels in Nitrux; however, users can create custom runlevels.
❯ ll /etc/runlevels total 0 drwxr-xr-x 2 root root 3 abr 2 2021 boot drwxr-xr-x 2 root root 489 jul 6 17:06 default drwxr-xr-x 2 root root 28 jul 6 17:06 nonetwork drwxr-xr-x 2 root root 102 jul 6 17:06 off drwxr-xr-x 2 root root 62 jul 6 17:06 recovery drwxr-xr-x 2 root root 3 abr 2 2021 shutdown drwxr-xr-x 2 root root 499 jul 6 17:06 sysinit
The ‘rc-status‘ helper will print all currently active runlevels and the state of services in them.
To start and stop services anytime, we use the command ‘rc-service.’
sudo rc-service someservice start sudo rc-service someservice stop
To manage services in runlevels, we use the command ‘rc-update.’
- 🔰 Information: The option add will add the service to the specified run level; for example, default and option del will remove the service from the specified run level.
sudo rc-update add service default sudo rc-update del service default
If we run ‘rc-update‘ and press Enter, we will get a visualization of all the runlevels and all the services in them (but not the state).
Finally, to update the services list, do the following.
sudo rc-update -u
Troubleshooting
If a service we added is not working, we can check the log file created by OpenRC to find out why. To do so, run the following command.
tail -n +1 /var/log/rc.log
That’s it; this concludes today’s tutorial. Stay put for the second part, where we’ll check the equivalent of “user services.”