OpenRC

OpenRC用户指南

目的与描述

OpenRC是适用于类Unix操作系统的初始化系统。它负责整个系统(包括各项服务)的启动和关闭。

它源自Gentoo的“基础布局”软件包,该软件包是一种定制的纯Shell启动解决方案。(这种解决方案既难以维护和调试,性能也不是很好)

出于性能和灵活性方面的考虑,其大部分核心部分是用C99编写的,而其他部分则使用的是符合POSIX标准的shell脚本。

目前,它的C语言代码量约为10000行,shell脚本代码量约为4000行。

众所周知,OpenRC可在Linux、许多BSD系统(至少包括FreeBSD、OpenBSD、DragonFlyBSD )以及HURD系统上运行。

服务是有状态的(也就是说,如果已经执行了“启动”操作,再次执行“启动”会提示“该服务已启动”)。

启动

通常,PID1(又名 init)会调用 OpenRC 二进制文件(默认情况下为 /sbin/openrc)。 (默认设置假定在此情况下使用 sysvinit)

OpenRC会扫描运行级别(默认路径是 /etc/runlevels)并构建一个依赖图,然后启动所需的服务脚本,既可以按顺序执行(默认方式),也可以并行执行。

当所有服务脚本启动后,OpenRC就会终止,它不会以守护进程的形式持续运行。不过,OpenRC可以与诸如monit、runit或s6等工具进行集成。

关闭

当系统运行级别变更为 0 或 6,或者执行reboothalt等命令时,OpenRC会停止所有已启动的服务,并运行shutdown运行级别里的服务。

修改服务脚本

任何服务都可以随时通过执行 ‘rc-service someservice start’、‘rc-service someservice stop’ 等来启动/停止/重启。 另一种不太受欢迎的方法是直接运行服务脚本,例如 ‘/etc/init.d/service start’、’/etc/init.d/service stop’ 等。

OpenRC会处理依赖性问题,例如启动apache会先启动network,而停止network会先停止apache。

有一个特殊的命令 ‘zap’ 可以让 OpenRC ‘忘记’ 服务已启动;这对于将崩溃的服务重置为 Stopped 状态非常有用,而无需调用服务脚本的(可能已损坏的)Stop 函数。

在没有任何参数的情况下调用 ‘openrc’ 将尝试重置所有服务,以便满足当前运行级别;如果您手动启动Apache,它将被停止,如果Squid死亡但处于当前运行级别,它将重新启动。

运行级别

OpenRC has a concept of runlevels, similar to what sysvinit historically offered. A runlevel is basically 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 “powersaving” runlevel where some services are disabled.

The rc-status helper will print all currently active runlevels and the state of services in them:

# rc-status
 * Caching service dependencies ... [ ok ]
Runlevel: default
 modules                     [  started  ]
 lvm                         [  started  ]

All runlevels are represented as folders in /etc/runlevels/ with symlinks to the actual service scripts.

Calling openrc with an argument (openrc default) will switch to that runlevel; this will start and stop services as needed.

Managing runlevels is usually done through the rc-update helper, but could of course be done by hand if desired. e.g. rc-update add nginx default - add nginx to the default runlevel Note: rc-update will not start nginx! You’d still have to trigger rc, or run the service script by hand, or start it with rc-service nginx start.

FIXME: Document stacked runlevels

The default startup uses the runlevels sysinit, boot, and default, in that order. Shutdown uses the shutdown runlevel.

The Magic of conf.d

Most service scripts need default values. It would be fragile to explicitly source some arbitrary files. By convention openrc-run will source the matching file in /etc/conf.d/ for any script in /etc/init.d/

This allows you to set random startup-related things easily. Example:

conf.d/foo:
START_OPTS="--extraparameter sausage"

init.d/foo:
start() {
	/usr/sbin/foo-daemon ${START_OPTS}
}

The big advantage of this split is that most of the time editing of the service script can be avoided.

Start-Stop-Daemon

OpenRC has its own modified version of s-s-d, which is historically related and mostly syntax-compatible to Debian’s s-s-d, but has been rewritten from scratch.

It helps with starting daemons, backgrounding, creating PID files and many other convenience functions related to managing daemons.

/etc/rc.conf

This file manages the default configuration for OpenRC, and it has examples of per-service-script variables.

Among these are rc_parallel (for parallelized startup), rc_log (logs all boot messages to a file), and a few others.

ulimit and CGroups

Setting ulimit values per service can be done through the rc_ulimit variable.

Under Linux, OpenRC can use cgroups for process management as well. Once the kernel is configured appropriately, the rc_cgroup_mode setting in /etc/rc.conf should be used to control whether cgroups version one, two, or both are used. The default is to use both if they are available.

By changing certain settings in the service’s conf.d file limits can be enforced per service. These settings are documented in detail in the default /etc/rc.conf under LINUX CGROUPS RESOURCE MANAGEMENT.

Dealing with Orphaned Processes

It is possible to get into a state where there are orphaned processes running which were part of a service. For example, if you are monitoring a service with supervise-daemon and supervise-daemon dies for an unknown reason. The way to deal with this will be different for each system.

On Linux systems with cgroups enabled, the cgroup_cleanup command is added to all services. You can run it manually, when the service is stopped, by using:

# rc-service someservice cgroup_cleanup

The rc_cgroup_cleanup setting can be changed to yes to make this happen automatically when the service is stopped.

Caching

For performance reasons OpenRC keeps a cache of pre-parsed service metadata (e.g. depend). The default location for this is /${RC_SVCDIR}/cache.

The cache uses mtime to check for file staleness. Should any service script change it’ll re-source the relevant files and update the cache

Convenience functions

OpenRC has wrappers for many common output tasks in libeinfo. This allows to print colour-coded status notices and other things. To make the output consistent the bundled service scripts all use ebegin/eend to print nice messages.

User services – Experimental

OpenRC supports managing services for users.

The init scripts are loaded from /etc/user/init.d, and ${XDG_CONFIG_HOME}/rc/init.d with ~/.config should XDG_CONFIG_HOME be unset.

Configurations in ~/.config/rc/conf.d should overwrite /etc/user/conf.d, and similarly options set in ~/.config/rc/rc.conf overrides /etc/rc.conf.

Runlevels are kept in ~/.config/rc/runlevels.

openrc and all rc-* tools provide a –user/-U flag to operate with user-mode services and runlevels.

The XDG_RUNTIME_DIR variable must be set before calling openrc –user, as it’s used to store state for openrc itself and the services it runs.

Auto-starting

OpenRC supports automatically managing user service sessions via PAM modules.

Add pam_openrc.so to the pam configuration of the preferred login method (i.e. login, ssh), and set up the pam configuration for openrc-user as to a similar configuration as a usual login session (if XDG_RUNTIME_DIR is set via pam modules, it should be included, as well as anything required for a usual user session).

Launching at boot

To start a given session at boot, multiplex the user system service, by symlinking init.d/user to init.d/user.$username, where username is the desired users to start at boot.