OpenRC is a dependency-based init system that was designed to work with Unix-like computer operating systems. It keeps compatibility with the system-provided init system, which is usually found in /sbin/init. Also it manages the entire system’s startup and shutdown, including services.
It consists of various modular components. The most important ones are: an init, a core dependency management system, and a daemon supervisor. It’s written in C and uses a POSIX-compliant shell, so it will run on BSD systems and Linux.
OpenRC will start the required system services in the right order at boot, handle them while the system is running, and shut them down when the system is finished. It can manage daemons installed from the Gentoo repository, monitor the processes it launches, and start processes in parallel (where possible) to save boot time.
Installation and configuration
The commands used to install openrc are:
- sudo apt-get update
- sudo apt-get install openrc
The name of the OpenRC service package is “package name-openrc”, which is usually in /etc/init.d, and the name of the OpenRC service package is /etc/rc.conf.
By default, OpenRC does not log anything. Uncomment and set the RC logger option in /etc/rc.conf to log OpenRC’s output on boot. By default, the log is saved to /var/log/rc.log.
You can use OpenRC with any of the various network managers, or with none at all. For examples of static and dynamic network configuration, see /etc/conf.d/net. The netifrc package contains a set of modules for setting and managing network interfaces through separate scripts in the /etc/init.d/ directory. It just includes /etc/init.d/net.lo (for the loopback interface), but it doesn’t include any hard coded operations. The same piece can handle several interfaces (as net.interface name -> net.lo) as a cost-effective alternative to deploying numerous scripts. OpenRC does not require Netifrc. You can leave it unused in favor of another network manager.
In order to accommodate more complex installations, it may be necessary to change the default dependencies of init scripts. To change the default behavior, go to /etc/rc.conf and look for the rc depending on the strict option. In addition, the following networking examples prove OpenRC’s versatility.
If the soft level argument is given, OpenRC will start the runlevel defined by the softlevel parameter instead of the default. With the following example grub.conf settings, you can choose whether to boot into the default, nonetwork, or single-user runlevels:
title = Regular start-up
kernel (hd0,0)/boot/vmlinuz-linux root=/dev/sda3
title = Start without networking
kernel (hd0,0)/boot/vmlinuz-linux root=/dev/sda3 softlevel=nonetwork
title = Single-user mode
kernel (hd0,0)/boot/vmlinuz-linux root=/dev/sda3 softlevel=single
OpenRC uses Runlevels in a similar way to sysvinit (or BSD init). At any given time, the system is in one of the defined runlevels. Three internal and four user-defined runlevels are available.
Internal Runlevels, the names are self-explanatory:
- boot: Starts all system-necessary services for other runlevels
- default: Used for day-to-day-operations
- nonetwork: Used when no network connectivity is required
- single: Single-user mode
You can use the openrc command to change the system’s runlevel. For example: Openrc nonetwork.
The OpenRC commands
There are multiple commands that you can use to control and configure OpenRC.
Add and remove services:
- # rc-update add service runlevel
- # rc-update del service runlevel
Start, restart and stop service:
- # rc-service service start
- # rc-service service restart
- # rc-service service stop
Display all available init scripts and their current runlevel:
- # rc-update show -v
View the state of all services:
- # rc-status –servicelist
Check failed services:
- # rc-status –crashed
It’s common to find yourself in a state where orphaned processes are working, processes that were previously part of a service. For example, suppose you’re using a supervise daemon to monitor a service and it dies for no apparent cause. Each system will have a different approach to dealing with this.
The cgroup cleanup command is added to all services on Linux systems with cgroups enabled. When the service stops, you can manually run it by typing:
- # rc-service someservice cgroup_cleanup
Set the rc cgroup cleanup parameter to yes to make this happen automatically when the service ends.
Other functions of OpenRC
You can use the rc_ulimit variable to set ulimit and nice values per service.
OpenRC may also use cgroups for process management on Linux. You should use the rc_cgroup_mode parameter in /etc/rc.conf to control whether cgroups version one, two, or both are used after the kernel has been configured properly. If both are accessible, the default is to use both.
You can apply limit per service by modifying certain settings in the conf.d file. The default /etc/rc.conf under LINUX CGROUPS RESOURCE MANAGEMENT documents these settings in great detail.
Many typical output tasks in libeinfo have wrappers in OpenRC. This enables to print color coded status messages and other information. The bundled service scripts all use ebegin/eend to print nice messages to keep the output consistent.
An enabled service is a symlink to the init.d file, and a runlevel is merely a directory in /etc/runlevels. Adding the sshd service to the default runlevel, for example, involves creating a symlink in /etc/runlevels/ default to /etc/init.d/sshd. As a result, creating a new runlevel necessitates the creation of a new directory under /etc/runlevels.
When switching to the office runlevel, you usually don’t want to disable all of your default services. You can actually add a runlevel to another if you use the -s flag with rc-update. For example, if you wanted to set up an office runlevel that was the same as default but included the myvpn service, you would perform the following
# mkdir /etc/runlevels/office
# rc-update -s add default office
# rc-update add myvpn office
You can use the openrc command to switch to a custom runlevel once you’ve created one. Also, you would use openrc office to switch to your new runlevel, and openrc default to switch back, as shown above.
In the “default” runlevel, the SSH service must start with eth0 (not wlan0), however in the “office” runlevel, it must start with wlan0 (not eth0).
Make symlinks to sshd with the names of the network interfaces:
# ln -s sshd /etc/init.d/sshd.eth0
# ln -s sshd /etc/init.d/sshd.wlan0
/etc/conf.d/sshd.eth0 and /etc/conf.d/sshd.wlan0 are now read for settings:
# cp /etc/conf.d/sshd /etc/conf.d/sshd.eth0
# cp /etc/conf.d/sshd /etc/conf.d/sshd.wlan0
Add the dependencies:
# echo 'rc_need="!net net.eth0"' >> /etc/conf.d/sshd.eth0
# echo 'rc_need="!net net.wlan0"' >> /etc/conf.d/sshd.wlan0
Depending on the active runlevel, net.eth0 and net.wlan0 read their settings from /etc/conf.d/net or /etc/conf.d/net.office.
Add all of the runscripts to the various runlevels:
# rc-update add sshd.eth0 default
# rc-update add sshd.wlan0 office
# rc-update add net.eth0 default office
# rc-update add net.wlan0 default office
Change to “nonetwork” runlevel in between “default” and “office” runlevels to avoid having to reboot the computer. This will stop the network interfaces and force them to re-read their runlevel-specific configuration. The display manager and other non-network services should be added to the “nonetwork” runlevel only.
nonetwork runlevel —> default runlevel office
To fix the problem, zap the service:
# rc nonetwork && rc office
# rc nonetwork && rc default
- Respawning crashed services
To provide stateful init scripts and automatic respawning, OpenRC can return the state of services to the Runlevel setting state.
Run openrc: crashed services will be started and any manually run services will be ended to respawn crashed services from the default Runlevel. Run openrc –no-stop or openrc -n to keep manually started services running.
By default, openrc will seek to launch, rather than restart, crashed services. The /etc/rc.conf parameters rc crashed stop (default NO) and rc crashed start (default YES) regulate this.
- Recovering crashed services manually
When you want to start, end, or show the status of a service after it has crashed during starting, an error or warning message will appear. For example, when using the “docker” service:
root #rc-service docker status
* status: crashed
root #rc-service docker start
* WARNING: docker has already been started
root #rc-service docker stop
* Caching service dependencies ... [ ok ]
* Stopping docker ...
* Failed to stop docker [ !! ]
* ERROR: docker failed to stop
To fix the problem, zap the service:
root #rc-service docker zap