Difference between pages "Cross-compiling with Crossdev" and "Package:OpenRC"

From Funtoo
(Difference between pages)
Jump to navigation Jump to search
(new how-to on Funtoo cross-compiling)
 
m (Better formatting on example of conf.d)
 
Line 1: Line 1:
== Introduction ==
{{Ebuild
Crossdev is a great feature of Funtoo that allows you to easily make a basic toolchain for your embedded devices and alternate platform computers. It can be used for distcc for example, so a slow x86 or ARM computer can be assisted on compiles by a much faster x86_64 computer(s). Some, but not all, packages can also be compiled stand-alone without distcc on the faster machine. You can also use the faster 64 bit machine to make kernels for these slower machines, a big advantage.
|Summary=OpenRC manages the services, startup and shutdown of a host.
|CatPkg=sys-apps/openrc
|Maintainer=William Hubbs, Drobbins, Oleg
|Repository=Funtoo Overlay
|Organization=Funtoo Technologies
|Overlay=Funtoo
}}
{{PageNeedsUpdates}}
Funtoo OpenRC is the current implementation of the system startup and init script framework for Funtoo Linux. Official development sources can be found on [http://www.github.com/funtoo/openrc GitHub].
 
Funtoo OpenRC is an independently-maintained, forked version of the [[Wikipedia:OpenRC|OpenRC]] init scripts ([http://www.gentoo.org/proj/en/base/openrc/ now maintained by Gentoo]). Funtoo Linux-specific changes generally relate to [[Funtoo Linux Networking|Funtoo network configuration]].
 
== Purpose and description ==
 
OpenRC is an init system for Unixoid operating systems. It takes care of startup and shutdown of the whole system, including services.
It evolved out of the Gentoo "Baselayout" package which was a custom pure-shell startup solution. (This was both hard to maintain and debug, and not very performant)
Most of the core parts are written in C99 for performance and flexibility reasons, while everything else is posix sh. The License is 2-clause BSD. Current size is about 10k LoC C, and about 4k LoC shell.
 
== Features ==
 
* OpenRC is known to work on Linux, many BSDs (FreeBSD, OpenBSD, DragonFlyBSD at least) and HURD.
* Services are stateful (i.e. start; start will lead to "it's already started")
* Dependency-based
* Allows creation of arbitrary runlevels with real-world names.
* [[Stacked Runlevels]]
 
== Startup ==
 
# Usually PID1 (aka. init) calls the OpenRC binary, <tt>/sbin/rc</tt>. (The default setup assumes sysvinit for this)
# rc scans the runlevels (default: <tt>/etc/runlevels</tt>) and builds a dependency graph, then starts the needed init scripts, either serialized (default) or in parallel.
# When all the init scripts are started rc terminates. There is no persistent daemon. (Integration with tools like monit, runit or s6 can be done)
 
== Shutdown ==
 
On change to runlevel 0/6 or running "reboot", "halt" etc., rc stops all  
services that are started and runs the scripts in the "shutdown" runlevel.
 
== Modifying single services ==
 
Any single service can, at any time, be:
* '''started:''' <console>###i## /etc/init.d/someservice start</console>
* '''stopped:''' <console>###i## /etc/init.d/someservice stop</console>
* '''restarted:''' <console>###i## /etc/init.d/someservice restart</console>
OpenRC will take care of dependencies, e.g starting apache will start network
first, and stopping network will stop apache first.
 
There is a special command <tt>zap</tt> that makes OpenRC 'forget' that a service is
started; this is mostly useful to reset a crashed service to stopped state
without invoking the (possibly broken) stop function of the init script.
 
Calling <tt>rc</tt> without any arguments will try to reset all services so that the
current runlevel is satisfied; if you manually started apache it will be
stopped, and if squid died but is in the default runlevel it'll be restarted.
 
There is a "service" helper that emulates the syntax seen on e.g. older Redhat
and Ubuntu ("service nginx start" etc.)
 
== Runlevels ==
 
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 <tt>rc-status</tt> helper will print all currently active runlevels and the state
of init scripts in them:


This is quite a big subject and the aim of this article is mainly to help new users with some Funtoo specific things relating to cross-compiling that are unique to Funtoo.  So we won't waste time here on things that are covered elsewhere, only those specific things.
== Let's get started! ==
The first step is to install crossdev.  Crossdev is written by Mike Frysinger who is quite a busy fellow and does a superb job.  But occasionally there are little hiccups with crossdev.  If ever you are having a problem with crossdev it doesn't hurt to try downgrading to previous versions.  I say this because on the date this article is written, 11-1-14, there are issues with the two latest versions of crossdev - 20140917 and 20141030 (see https://bugs.funtoo.org/browse/FL-1703).  But version 20140729 works flawlessly.  I have seen this happen from time to time, nothing to worry about.
<console>
<console>
###i## emerge -av crossdev
# ##i##rc-status
* Caching service dependencies ... [ ok ]
Runlevel: default
modules                    [  started  ]
lvm                        [  started  ]
</console>
</console>
== Funtoo Specific Considerations ==
The most important thing to understand is that Funtoo gcc ebuilds are different from Gentoo ebuilds.  This is because Daniel Robbins has made improvements to gcc to help with general usage.  Unfortunately, a side effect has been that they no longer work with crossdev.  But not to worry, there is an easy way around this issue and my understanding is that Funtoo intends to rectify it at a later date.


Another issue is that you cannot have a toolchain with exactly the same minor number as the current gcc on your system. You must use an ebuild of a slightly different vintage. I believe this issue occurs for Gentoo users also. For example, at the present time Funtoo current uses sys-devel/gcc-4.8.2-r3. So you could use gcc-4.8.1, or 4.8.0 but not any version of 4.8.2 (the revision -rx doesn't matter, can't do it). If you try to do that gcc will compile and then fail in the installation phase due to file collisions. In some cases with embedded devices you may wish to use much older versions, in which this becomes a moot point.
All runlevels are represented as folders in /etc/runlevels/ with symlinks to
the actual init scripts.
 
Calling rc with an argument ("rc 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. <tt>rc-update add nginx default</tt> - add nginx to the default runlevel
Note: This will not auto-start nginx! You'd still have to trigger "rc" or run
the initscript by hand.
 
FIXME: Document stacked runlevels
 
The default startup uses the runlevels "boot", "sysinit" and "default", in that  
order. Shutdown uses the "shutdown" runlevel.
 
 
== Syntax of init scripts ==
 
Init scripts are shell scripts. OpenRC aims at using only the standardized
POSIX sh subset for portability reasons. The default interpreter (build-time
toggle) is /bin/sh, so using for example mksh is not a problem.
 
OpenRC has been tested with busybox sh, ash, dash, bash, mksh, zsh and possibly
others. Using busybox sh has been difficult as it replaces commands with
builtins that don't offer the expected features.
 
The interpreter for initscripts is #!/sbin/runscript
Not using this interpreter will break the use of dependencies and is not
supported. (iow: if you insist on using #!/bin/sh you're on your own)
 
A "depend" function declares the dependencies of this init script. All scripts
must have start/stop/status functions, but defaults are provided. Extra
functions can be added easily:
 
<syntaxhighlight lang="bash">
extra_commands="checkconfig"
checkconfig() {
doSomething
}
</syntaxhighlight>
 
This exports the checkconfig function so that "/etc/init.d/someservice
checkconfig" will be available, and it "just" runs this function.
 
While extra_commands is always available, commands defined in
extra_started_commands will only work when the service is started. This can be
used for implementing graceful reload and similar behaviour.
 
Adding a restart function will not work, this is a design limitation within
OpenRC. Since there may be dependencies involved (e.g. network -> apache) a
restart function is in general not going to work.
restart is internally mapped to stop() + start() (plus handling dependencies)
(Figuring out a reliable improvement for this "bug" is appreciated)
 
 
== The depend function ==
 
This is a newline-separated list that uses builtins. A little bit 'dirty'
maybe, but simple:
 
<syntaxhighlight lang="bash">
depend() {
        need net
        use dns logger netmount
}
</syntaxhighlight>
 
;<tt>need</tt>: declares a hard dependency - net always needs to be started before this service does
;<tt>use</tt>: is a soft dependency - if dns, logger or netmount is in this runlevel start it before, but we don't care if it's not in this runlevel.
;<tt>before</tt>: declares that we need to be started before another service
;<tt>after</tt>: declares that we need to be started after another service, without creating a dependency (so on calling stop the two are independent)
;<tt>provide</tt>: allows multiple implementation to provide one service type, e.g.: <tt>provide cron</tt> is set in all cron-daemons, so any one of them started satisfies a cron dependency
;<tt>keyword</tt>: allows platform-specific overrides, e.g. <tt>keyword -lxc</tt> makes this init script a noop in lxc containers. Useful for things like keymaps, module loading etc. that are either platform-specific or not available in containers/virtualization/...
 
FIXME: Anything missing in this list?
 
== The default functions ==
 
All init scripts are assumed to have the following functions:
 
<syntaxhighlight lang="bash">
start()
stop()
status()
</syntaxhighlight>
 
There are default implementations in rc/sh/runscript.sh - this allows very
compact init scripts. These functions can be overriden per init script as
needed.
 
The default functions assume the following variables to be set in the init
script:
<syntaxhighlight lang="bash">
command=
command_args=
pidfile=
</syntaxhighlight>
 
Thus the 'smallest' init scripts can be half a dozen lines long
 
== The magic of conf.d ==
 
Most init scripts need default values. It would be fragile to explicitly source
some arbitrary files. By convention runscript will source the matching file in
/etc/conf.d/ for any script in /etc/init.d/
 
So you can set random startup-related things easily. Example:
 
conf.d/foo:
 
<syntaxhighlight lang="bash">
START_OPTS="--extraparameter sausage"
</syntaxhighlight>
 
init.d/foo:
<syntaxhighlight lang="bash">
start() {
/usr/sbin/foo-daemon ${STARTOPTS}
}
</syntaxhighlight>
 
The big advantage of this split is that most of the time editing of the init
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-initscript 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 in Linux ==
 
Setting ulimit and nice values per service can be done through the rc_ulimit
variable.
 
OpenRC can optionally use CGroups in the Linux kernel for process management.
By default each init script's processes are migrated to their own CGroup.
 
By changing certain values in the conf.d file limits can be enforced per
service. It is easy to find orphan processes of a service that persist after
stop(), but by default these will NOT be terminated.
To change this add rc_cgroup_cleanup="yes" in the conf.d files for services
where you desire this functionality.
 
== Caching ==
 
For performance reasons OpenRC keeps a cache of pre-parsed initscript metadata
(e.g. depend). The default location for this is /lib/rc/cache/
 
The cache uses mtime to check for file staleness. Should any initscript 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 initscripts all use ebegin/eend to
print nice messages.
 
== Commands ==
 
; rc-update
: add or remove a service from a particular runlevel, or implement [[Stacked Runlevels]]
; rc-status
: show current status of system services
; rc
: manage runlevel changes


Finally, a general issue with using crossdev with any distro is that you must sometimes juggle the various versions of binutils, gcc, glibc and linux-headers so that they are compatible with one another. This is the easiest problem to deal with, just use versions of the same time vintage, in extreme cases you may need to start changing revisions to get all of them to compile.
== FAQ ==
 
=== How do I tell one startup script to depend on another? ===
 
The easiest way to do this is to modify the <tt>/etc/conf.d</tt> script that corresponds to the service that needs to depend on something else, so let's call this service <tt>this_service</tt>. Add the following to its conf.d file:
 
<pre>
rc_need="other_service"
</pre>
 
Now, <tt>this_service</tt> will depend on <tt>other_service</tt>.
 
=== OpenRC is ignoring dependencies and not reacting to dependency changes ===
 
This can happen when your system's time changes suddenly (maybe due to realizing your system clock is wrong and resetting it) and OpenRC dependency cache files are created with future dates. To clear the OpenRC cache, type:


That's it, that's what you need to know.
== GCC Ebuilds ==
The workaround to make gcc compile is to use Gentoo gcc ebuilds.  They are readily available at the Gentoo attic: http://sources.gentoo.org/cgi-bin/viewvc.cgi/gentoo-x86/?hid
Going back historically for as far as you'd ever need.  Go to the sys-devel/gcc folder and right click on a version and copy the link.  I suggest a version that isn't even in the Funtoo tree, then there is no ambiguity about what is being used.
Next copy it to your local repository, we'll assume /usr/local/portage here.  So if you haven't already got a sys-devel/gcc directory there you could do
<console>
<console>
###i## install -d /usr/local/portage/sys-devel/gcc
###i## rc-update -u
</console>
</console>
Now go to that directory in your terminal and wget <the link you copied>.  At the end will be some fluff you don't want, delete all the way back to the word .ebuild and hit enter.  In a second or so you'll have that ebuild in your repository.
 
If you haven't done this before you'll need to link the files directory from the tree, so that it can find patches, etc.  So do this
Alternatively, you can perform this step manually:
<console>
<console>
###i## ln -s /usr/portage/sys-devel/gcc/files .
###i## rm /libexec/rc/cache/*
###i## rm /libexec/rc/init.d/deptree
</console>
</console>
Finally you must create the manifest
 
Now regenerate the cache by typing:
<console>
<console>
###i## ebuild gcc-<version>.ebuild manifest
###i## /libexec/rc/bin/rc-depend
</console>
</console>
And now you are ready!
The OpenRC dependency cache should now be up-to-date and OpenRC should behave properly again.
== Really, that's it? ==
 
Yes. Well, one other thing that you may need to do, if you've chosen a gcc version that is in the Funtoo tree, crossdev may get confused and try to install the tree version. At the beginning of the crossdev run it creates links in the crossdev repository, most people will just want this to be their local repository. So you can let crossdev run for a few seconds to create those links and then cancel it with ctl-c.  Then go to the crossdev repository and delete the gcc link and replace it with a link to /usr/local/portage/sys-devel/gcc. Here's an example in my local repository:
== History ==
<console>
The Gentoo modular init scripts were developed by Daniel Robbins for Gentoo Linux 1.0_rc6 during most of 2001 and released in September 2001 (TODO: add refs). After their development, the dependency-based init script system was maintained by a number of senior developers, starting with Azarah (Martin Schlemmer), with migration to the new init system assisted by Woodchip (Donnie Davies) who converted all ebuild init scripts to work with the new system. As Grant Goodyear notes:
###i## ls -l /usr/local/portage/cross-avr
 
total 0
''My recollection is that one of woodchip's more impressive early feats was the
lrwxrwxrwx 1 root root 50 Nov  1 00:41 avr-libc ->/usr/portage/dev-embedded/avr-libc
''complete replacement of all of the init scripts in Portage for Gentoo Linux
lrwxrwxrwx 1 root root 47 Nov  1 00:41 binutils -> /usr/portage/sys-devel/binutils
''1.0_rc6. Through 1.0_rc5 Gentoo had used fairly standard rc scripts modified
##g##lrwxrwxrwx 1 root root 32 Nov  1 00:41 gcc -> /usr/local/portage/sys-devel/gcc##!g##
''from Stampede Linux, but for 1.0_rc6 Daniel Robbins (drobbins) and Martin
lrwxrwxrwx 1 root root 42 Nov  1 00:41 gdb -> /usr/portage/sys-devel/gdb
''Schlemmer (azarah) had created a new dependency-based init script system that
</console>
''is still used today. Within a span of days Donny rewrote every single init
Note that the link for gcc is different from the others, which point to the normal Funtoo Portage tree, it points to my local repository, where the Gentoo ebuilds are stored.  Most of the time also you would be linked to sys-libs/glibc, avr-libc is a bit unusual but normal for avr cross toolchains.
''script in the Portage tree and committed new masked packages to await the
''release of 1.0_rc6. Thanks to woodchip (and drobbins and azarah, of course) the
''transition to the new init scripts was nearly painless.'' <ref>http://www.gentoo.org/news/en/gwn/20040426-newsletter.xml</ref>
 
Roy Marples became a Gentoo/Linux developer in 2004 and maintained the modular network scripts for the Gentoo baselayout package. Towards the end of 2005, he became the primary maintainer for baselayout and the init scripts.
 
At the start of 2007, Roy Marples announced the ongoing development of baselayout-2, containing a rewritten init script coded in C and allowing POSIX sh init scripts instead of forcing the use of bash. By mid 2007, Roy Marples had re-implemented the Gentoo init script design created by Daniel Robbins, using an entirely new code base. Alpha and pre-release baselayout-2 snapshots were added to Gentoo's Portage tree as an optional component.
 
Towards the end of 2007, Roy Marples retired as a Gentoo developer. Baselayout-2 was still in the pre stage, and aside from the gentoo-fbsd users, it was masked. However, Roy Marples desired to keep the baselayout-2 project moving forward as an independent project. The Gentoo Council permitted Roy Marples to release OpenRC under the 2-clause BSD license, managed by him as an external project.  


Once the link is fixed (if it even needed fixing), just hit your up arrow to get the same crossdev command line again and let it run through this time. You'll be rewarded with a shiny new cross toolchain at the end..
Around mid-2010, Roy Marples decided to no longer maintain OpenRC. At this point, he transferred development back to Gentoo. However, Daniel Robbins continues to maintain an independent, forked version of OpenRC for Funtoo Linux, which includes a Funtoo-specific network configuration
system.


Of course, there is a bit more to making a cross toolchain, but as stated at the beginning of this article, only the unique differences for Funtoo are shown here.
= References =
You should find nearly all the rest you need to know at https://www.gentoo.org/proj/en/base/embedded/handbook/cross-compiler.xml?style=printable.  Only the top 1/4 page is needed.
<references/>


One note, at the current time (11-1-14) you need to preface your crossdev command line statement with USE="-sanitize".  This is a known bug (not Funtoo specific) that will soon be fixed in crossdev.  You will find -sanitize in the package.use files, but you still must do it on the command line, else gcc will fail.  For example the following command line was successful for me today
[[Category:Projects]]
<console>
{{EbuildFooter}}
###i## USE="-sanitize" crossdev --binutils 2.23-2 --g 4.8.1-r1 --l 1.8.0 -t avr -P -v
</console>

Revision as of 17:48, November 2, 2014

OpenRC

   Tip

We welcome improvements to this page. To edit this page, Create a Funtoo account. Then log in and then click here to edit this page. See our editing guidelines to becoming a wiki-editing pro.

Funtoo OpenRC is the current implementation of the system startup and init script framework for Funtoo Linux. Official development sources can be found on GitHub.

Funtoo OpenRC is an independently-maintained, forked version of the OpenRC init scripts (now maintained by Gentoo). Funtoo Linux-specific changes generally relate to Funtoo network configuration.

Purpose and description

OpenRC is an init system for Unixoid operating systems. It takes care of startup and shutdown of the whole system, including services. It evolved out of the Gentoo "Baselayout" package which was a custom pure-shell startup solution. (This was both hard to maintain and debug, and not very performant) Most of the core parts are written in C99 for performance and flexibility reasons, while everything else is posix sh. The License is 2-clause BSD. Current size is about 10k LoC C, and about 4k LoC shell.

Features

  • OpenRC is known to work on Linux, many BSDs (FreeBSD, OpenBSD, DragonFlyBSD at least) and HURD.
  • Services are stateful (i.e. start; start will lead to "it's already started")
  • Dependency-based
  • Allows creation of arbitrary runlevels with real-world names.
  • Stacked Runlevels

Startup

  1. Usually PID1 (aka. init) calls the OpenRC binary, /sbin/rc. (The default setup assumes sysvinit for this)
  2. rc scans the runlevels (default: /etc/runlevels) and builds a dependency graph, then starts the needed init scripts, either serialized (default) or in parallel.
  3. When all the init scripts are started rc terminates. There is no persistent daemon. (Integration with tools like monit, runit or s6 can be done)

Shutdown

On change to runlevel 0/6 or running "reboot", "halt" etc., rc stops all services that are started and runs the scripts in the "shutdown" runlevel.

Modifying single services

Any single service can, at any time, be:

  • started:
    root # /etc/init.d/someservice start
  • stopped:
    root # /etc/init.d/someservice stop
  • restarted:
    root # /etc/init.d/someservice restart

OpenRC will take care of dependencies, e.g starting apache will start network first, and stopping network will stop apache first.

There is a special command zap that makes OpenRC 'forget' that a service is started; this is mostly useful to reset a crashed service to stopped state without invoking the (possibly broken) stop function of the init script.

Calling rc without any arguments will try to reset all services so that the current runlevel is satisfied; if you manually started apache it will be stopped, and if squid died but is in the default runlevel it'll be restarted.

There is a "service" helper that emulates the syntax seen on e.g. older Redhat and Ubuntu ("service nginx start" etc.)

Runlevels

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 init scripts in them:

root # 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 init scripts.

Calling rc with an argument ("rc 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: This will not auto-start nginx! You'd still have to trigger "rc" or run the initscript by hand.

FIXME: Document stacked runlevels

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


Syntax of init scripts

Init scripts are shell scripts. OpenRC aims at using only the standardized POSIX sh subset for portability reasons. The default interpreter (build-time toggle) is /bin/sh, so using for example mksh is not a problem.

OpenRC has been tested with busybox sh, ash, dash, bash, mksh, zsh and possibly others. Using busybox sh has been difficult as it replaces commands with builtins that don't offer the expected features.

The interpreter for initscripts is #!/sbin/runscript Not using this interpreter will break the use of dependencies and is not supported. (iow: if you insist on using #!/bin/sh you're on your own)

A "depend" function declares the dependencies of this init script. All scripts must have start/stop/status functions, but defaults are provided. Extra functions can be added easily:

extra_commands="checkconfig"
checkconfig() {
	doSomething
}

This exports the checkconfig function so that "/etc/init.d/someservice checkconfig" will be available, and it "just" runs this function.

While extra_commands is always available, commands defined in extra_started_commands will only work when the service is started. This can be used for implementing graceful reload and similar behaviour.

Adding a restart function will not work, this is a design limitation within OpenRC. Since there may be dependencies involved (e.g. network -> apache) a restart function is in general not going to work. restart is internally mapped to stop() + start() (plus handling dependencies) (Figuring out a reliable improvement for this "bug" is appreciated)


The depend function

This is a newline-separated list that uses builtins. A little bit 'dirty' maybe, but simple:

depend() {
        need net
        use dns logger netmount
}
need
declares a hard dependency - net always needs to be started before this service does
use
is a soft dependency - if dns, logger or netmount is in this runlevel start it before, but we don't care if it's not in this runlevel.
before
declares that we need to be started before another service
after
declares that we need to be started after another service, without creating a dependency (so on calling stop the two are independent)
provide
allows multiple implementation to provide one service type, e.g.: provide cron is set in all cron-daemons, so any one of them started satisfies a cron dependency
keyword
allows platform-specific overrides, e.g. keyword -lxc makes this init script a noop in lxc containers. Useful for things like keymaps, module loading etc. that are either platform-specific or not available in containers/virtualization/...

FIXME: Anything missing in this list?

The default functions

All init scripts are assumed to have the following functions:

start()
stop()
status()

There are default implementations in rc/sh/runscript.sh - this allows very compact init scripts. These functions can be overriden per init script as needed.

The default functions assume the following variables to be set in the init script:

command=
command_args=
pidfile=

Thus the 'smallest' init scripts can be half a dozen lines long

The magic of conf.d

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

So you can set random startup-related things easily. Example:

conf.d/foo:

START_OPTS="--extraparameter sausage"

init.d/foo:

start() {
	/usr/sbin/foo-daemon ${STARTOPTS}
}

The big advantage of this split is that most of the time editing of the init 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-initscript 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 in Linux

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

OpenRC can optionally use CGroups in the Linux kernel for process management. By default each init script's processes are migrated to their own CGroup.

By changing certain values in the conf.d file limits can be enforced per service. It is easy to find orphan processes of a service that persist after stop(), but by default these will NOT be terminated. To change this add rc_cgroup_cleanup="yes" in the conf.d files for services where you desire this functionality.

Caching

For performance reasons OpenRC keeps a cache of pre-parsed initscript metadata (e.g. depend). The default location for this is /lib/rc/cache/

The cache uses mtime to check for file staleness. Should any initscript 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 initscripts all use ebegin/eend to print nice messages.

Commands

rc-update
add or remove a service from a particular runlevel, or implement Stacked Runlevels
rc-status
show current status of system services
rc
manage runlevel changes

FAQ

How do I tell one startup script to depend on another?

The easiest way to do this is to modify the /etc/conf.d script that corresponds to the service that needs to depend on something else, so let's call this service this_service. Add the following to its conf.d file:

rc_need="other_service"

Now, this_service will depend on other_service.

OpenRC is ignoring dependencies and not reacting to dependency changes

This can happen when your system's time changes suddenly (maybe due to realizing your system clock is wrong and resetting it) and OpenRC dependency cache files are created with future dates. To clear the OpenRC cache, type:

root # rc-update -u

Alternatively, you can perform this step manually:

root # rm /libexec/rc/cache/*
root # rm /libexec/rc/init.d/deptree

Now regenerate the cache by typing:

root # /libexec/rc/bin/rc-depend

The OpenRC dependency cache should now be up-to-date and OpenRC should behave properly again.

History

The Gentoo modular init scripts were developed by Daniel Robbins for Gentoo Linux 1.0_rc6 during most of 2001 and released in September 2001 (TODO: add refs). After their development, the dependency-based init script system was maintained by a number of senior developers, starting with Azarah (Martin Schlemmer), with migration to the new init system assisted by Woodchip (Donnie Davies) who converted all ebuild init scripts to work with the new system. As Grant Goodyear notes:

My recollection is that one of woodchip's more impressive early feats was the complete replacement of all of the init scripts in Portage for Gentoo Linux 1.0_rc6. Through 1.0_rc5 Gentoo had used fairly standard rc scripts modified from Stampede Linux, but for 1.0_rc6 Daniel Robbins (drobbins) and Martin Schlemmer (azarah) had created a new dependency-based init script system that is still used today. Within a span of days Donny rewrote every single init script in the Portage tree and committed new masked packages to await the release of 1.0_rc6. Thanks to woodchip (and drobbins and azarah, of course) the transition to the new init scripts was nearly painless. [1]

Roy Marples became a Gentoo/Linux developer in 2004 and maintained the modular network scripts for the Gentoo baselayout package. Towards the end of 2005, he became the primary maintainer for baselayout and the init scripts.

At the start of 2007, Roy Marples announced the ongoing development of baselayout-2, containing a rewritten init script coded in C and allowing POSIX sh init scripts instead of forcing the use of bash. By mid 2007, Roy Marples had re-implemented the Gentoo init script design created by Daniel Robbins, using an entirely new code base. Alpha and pre-release baselayout-2 snapshots were added to Gentoo's Portage tree as an optional component.

Towards the end of 2007, Roy Marples retired as a Gentoo developer. Baselayout-2 was still in the pre stage, and aside from the gentoo-fbsd users, it was masked. However, Roy Marples desired to keep the baselayout-2 project moving forward as an independent project. The Gentoo Council permitted Roy Marples to release OpenRC under the 2-clause BSD license, managed by him as an external project.

Around mid-2010, Roy Marples decided to no longer maintain OpenRC. At this point, he transferred development back to Gentoo. However, Daniel Robbins continues to maintain an independent, forked version of OpenRC for Funtoo Linux, which includes a Funtoo-specific network configuration system.

References