openrc-run(8)
π openrc-run(8) π
From the System Manager's Manual, bestie. This is the whole vibe.
β¨ NAME β¨
openrc-run β a means of hooking shell commands into a service. Literally the glow-up between your scripts and the service world.
π« SYNOPSIS π«
openrc-run [-D, --nodeps] [-d, --debug] [-s, --ifstarted]
[-S, --ifstopped] [-Z, --dry-run] [command ...]
πΈ DESCRIPTION πΈ
Okay so openrc-run is basically an interpreter for shell scripts, and it gives you an easy interface to the often complex system commands and daemons. It's giving "translator, but make it Unix."
When a service runs a command, it first loads its multiplexed configuration file, then its master configuration file, then /etc/rc.conf, and finally the script itself. At that point, openrc-run runs the command given. Order matters, bestie β it's not a free-for-all.
Commands are defined as shell functions within the script. Here's a list of some functions that all scripts have by default:
π§ the default command squad
describeβ describes what the service does and each command the service defines.startβ first we ensure that any services we depend on are started. If any needed services fail to start, we exit with a suitable error; otherwise we call the suppliedstartfunction if it exists.stopβ first we ensure that any services that depend on us are stopped. If any services that need us fail to stop, we exit with a suitable error; otherwise we call the suppliedstopfunction if it exists.restartβ stops and starts the service, including dependencies. This cannot be overridden. See the description of theRC_CMDvariable below for the method to make your service behave differently whenrestartis being executed.statusβ shows the status of the service. The return code matches the status, with the exception ofstartedreturning0to match standard command behaviour.zapβ resets the service state to stopped and removes all saved data about the service.
π options / flags
-d,--debugβ setsxtraceon in the shell to assist in debugging.-D,--nodepsβ ignores all dependency information the service supplies.-s,--ifstartedβ only runs the command if the service has been started.-S,--ifstoppedβ only runs the command if the service has been stopped.-q,--quietβ turns off all informational output the service generates. Output from any non-OpenRC commands is not affected.-v,--verboseβ turns on any extra informational output the service generates.-Z,--dry-runβ shows which services would be stopped and/or started without actually stopping or starting them.
π variables you can set
extra_commandsβ space-separated list of extra commands the service defines. These should not depend on the service being stopped or started.extra_started_commandsβ space-separated list of extra commands the service defines. These only work if the service has already been started.extra_stopped_commandsβ space-separated list of extra commands the service defines. These only work if the service has already been stopped.descriptionβ string describing the service.description_$commandβ string describing the extra command.supervisorβ supervisor to use to monitor this daemon. If this is unset or invalid,start-stop-daemonwill be used. Currently, we supports6from skarnet software, andsupervise-daemon, which is a light-weight supervisor internal to OpenRC. To uses6, setsupervisor=s6, or setsupervisor=supervise-daemonto usesupervise-daemon.s6_service_pathβ the path to thes6service directory if you are monitoring this service with S6. The default is/var/svc.d/${RC_SVCNAME}.s6_svwait_options_startβ the options to pass tos6-svwaitwhen starting the service vias6.s6_force_killβ should we force-kill this service ifs6_service_timeout_stopexpires but the service doesn't go down during shutdown? The default is yes.s6_service_timeout_stopβ the amount of time, in milliseconds,s6-svcshould wait for the service to go down when stopping the service. The default is60000.start_stop_daemon_argsβ list of arguments passed tostart-stop-daemonwhen starting the daemon.supervise_daemon_argsβ list of arguments passed tosupervise-daemonwhen starting the daemon. If undefined,start_stop_daemon_argsis used as a fallback.commandβ daemon to start or stop viastart-stop-daemonorsupervise-daemonif nostartorstopfunction is defined by the service.command_argsβ list of arguments to pass to the daemon when starting viastart-stop-daemon.command_args_backgroundβ this variable should be used if the daemon you are starting withstart-stop-daemon(8)runs in the foreground by default but has its own command line options to request that it background and write a pid file. It should be set to those options. It should not be used at the same time ascommand_background, becausecommand_backgroundrequests thatstart-stop-daemon(8)go into the background before executing the daemon.command_args_foregroundβ list of arguments to pass to the daemon when starting viasupervise-daemon, to force the daemon to stay in the foreground.command_backgroundβ set this to"true","yes"or"1"(case-insensitive) if you wantstart-stop-daemon(8)to force the daemon into the background. This forces the--make-pidfileand--pidfileoptions, so thepidfilevariable must be set.command_progressβ set this to"true","yes"or"1"(case-insensitive) if you wantstart-stop-daemon(8)to display a progress meter when waiting for a daemon to stop.command_userβ if the daemon does not support changing to a different user id, you can use this to change the user id, and optionally group id, beforestart-stop-daemon(8)orsupervise-daemon(8)launches the daemon.input_fileβ this is the path to a file or named pipe to which the standard input of the service will be redirected to. If you are starting this service withstart-stop-daemon(8), you must setcommand_backgroundtotrue. Keep in mind that this path will be inside the chroot if thechrootvariable is set. Contrary to output and error redirection, input redirection assumes that the file exists already.output_logβ the same thing asinput_filebut for the standard output.error_logβ the same thing asinput_filebut for the standard error output.output_loggerβ this is a process which will be used to log the standard output from the service. If you are starting this service withstart-stop-daemon(8), you must setcommand_backgroundtotrue. Keep in mind that this command must be executable as a shell command inside the chroot if thechrootvariable is set. Keep in mind also that this command works by accepting the stdout of the service on stdin. An example of a command that can be run this way isloggerif you want your service output to go to syslog.error_loggerβ the same thing asoutput_loggerbut for the standard error output.directoryβstart-stop-daemon(8)andsupervise-daemon(8)willchdirto this directory before starting the daemon.chrootβstart-stop-daemon(8)andsupervise-daemon(8)willchrootinto this path before writing the pid file or starting the daemon.pidfileβ pidfile to use for the above defined command.nameβ display name used for the above defined command.procnameβ process name to match when signaling the daemon.stopsigβ signal to send when stopping the daemon.respawn_delayβ respawn delaysupervise-daemon(8)will use for this daemon. Seesupervise-daemon(8)for more information about this setting.respawn_maxβ respawn maxsupervise-daemon(8)will use for this daemon. Seesupervise-daemon(8)for more information about this setting.respawn_periodβ respawn periodsupervise-daemon(8)will use for this daemon. Seesupervise-daemon(8)for more information about this setting.retryβ retry schedule to use when stopping the daemon. It can either be a timeout in seconds or multiple signal/timeout pairs (likeSIGTERM/5).required_dirsβ a list of directories which must exist for the service to start.required_filesβ a list of files which must exist for the service to start.start_inactiveβ set toyesto have the service marked inactive when it starts. This is used along within_background_faketo support re-entrant services.in_background_fakeβ space-separated list of commands which should always succeed whenin_backgroundisyes.umaskβ set the umask of the daemon.
π«Ά eval heads-up
Keep in mind that eval is used to process chroot, command, command_args_*, command_user, pidfile and procname. This may affect how they are evaluated depending on how they are quoted. So quote like you mean it, bestie.
notifyβ this is how your daemon slides into the service manager's DMs to say "bestie, I'm up π ". Accepted values arefd:num, which expects a newline in the open file descriptornumwhen the daemon is ready, andsocket:ready, which will export$NOTIFY_SOCKETand listen for notifications. At the moment it supportsREADY=1β that's the one vibe it's checking for, periodt.
πΈ Default start/stop πΈ
Okay so here's the whole gossip chart of which variables actually get used by the default start and stop functions, and where each one shows up. The columns are start-stop-daemon, supervise-daemon, and s6, and a β just means "not used there, she's off duty π".
capabilitiesβstart-stop-daemon:startΒ·supervise-daemon:startΒ·s6: βchrootβstart-stop-daemon:startΒ·supervise-daemon:start,stopΒ·s6:startcommandβstart-stop-daemon:stopΒ·supervise-daemon:stopΒ·s6:startcommand_argsβstart-stop-daemon: β Β·supervise-daemon: β Β·s6:startcommand_args_foregroundβstart-stop-daemon: β Β·supervise-daemon: β Β·s6:startcommand_userβstart-stop-daemon:startΒ·supervise-daemon:startΒ·s6:startdirectoryβstart-stop-daemon:startΒ·supervise-daemon:startΒ·s6:starterror_logβstart-stop-daemon:startΒ·supervise-daemon:startΒ·s6:starterror_loggerβstart-stop-daemon:startΒ·supervise-daemon:startΒ·s6:starthealthcheck_delayβstart-stop-daemon: β Β·supervise-daemon:startΒ·s6: βhealthcheck_timerβstart-stop-daemon: β Β·supervise-daemon:startΒ·s6: βinput_fileβstart-stop-daemon:startΒ·supervise-daemon:startΒ·s6:startno_new_privsβstart-stop-daemon:startΒ·supervise-daemon:startΒ·s6: βnotifyβstart-stop-daemon:startΒ·supervise-daemon:startΒ·s6:startoutput_logβstart-stop-daemon:startΒ·supervise-daemon:startΒ·s6:startoutput_loggerβstart-stop-daemon:startΒ·supervise-daemon:startΒ·s6:startpidfileβstart-stop-daemon:start,stopΒ·supervise-daemon:start,stopΒ·s6: βprocnameβstart-stop-daemon:start,stopΒ·supervise-daemon: β Β·s6: βrespawn_delayβstart-stop-daemon: β Β·supervise-daemon:startΒ·s6: βrespawn_maxβstart-stop-daemon: β Β·supervise-daemon:startΒ·s6: βrespawn_periodβstart-stop-daemon: β Β·supervise-daemon:startΒ·s6: βretryβstart-stop-daemon:stopΒ·supervise-daemon:startΒ·s6: βs6_log_argumentsβstart-stop-daemon: β Β·supervise-daemon: β Β·s6:startsecbitsβstart-stop-daemon:startΒ·supervise-daemon:startΒ·s6: βstopsigβstart-stop-daemon:stopΒ·supervise-daemon: β Β·s6:stopsupervise_daemon_argsβstart-stop-daemon: β Β·supervise-daemon:startΒ·s6: βtimeout_downβstart-stop-daemon: β Β·supervise-daemon: β Β·s6:stoptimeout_killβstart-stop-daemon: β Β·supervise-daemon: β Β·s6:stoptimeout_readyβstart-stop-daemon: β Β·supervise-daemon: β Β·s6:startumaskβstart-stop-daemon:startΒ·supervise-daemon:startΒ·s6:start
β¨ Ambient process capabilities β¨
So on Linux your processes have β¨ambient capabilitiesβ¨ and these options are the ones that mess with them. Go read capabilities(7) if you want the full lore, bestie β it's giving required reading.
no_new_privsβ setsno_new_privson the daemon process, which means it literally cannot gain any additional privilege, including throughsetuid/setgidbinaries, file capabilities, etc. Like, the privilege glow-up is cancelled π₯.capabilitiesCAPABILITIES β sets additional ambient capabilities for the process. Give her the power-ups, you decide which ones π.secbitsAR SECBITS β sets the-securebitsfor the process, which adjusts how the kernel treats ambient capabilities for this process. Yeah it's very "trust me the kernel knows what it's doing" energy, but that's the deal π«Ά.
π DEPENDENCIES π
okay bestie, listen β you gotta define a depend function for your service so openrc-run knows the β¨orderβ¨ to start and stop it in relative to all the other services. and because it's a function, it can be seriously flexible β the example is down below, keep reading π«Ά
here's the whole menu of functions you can use inside a depend function. the way it works: you just pass the names of the services you want to add to that dependency type to the function, or β fun trick β prefix the names with ! to remove them from the dependencies π
needβ the service will attempt to start any services it needs regardless of whether they've been added to the runlevel. it will refuse to start until all the services it needs have started, and it will refuse to stop until all the services that need it have stopped. highkey the strictest one πuseβ the service will attempt to start any services it uses that have been added to the runlevel.wantβ the service will attempt to start any services it wants, regardless of whether they've been added to the runlevel.afterβ the service will start after these services and stop before these services.beforeβ the service will start before these services and stop after these services.provideβ the service provides this virtual service. for example,namedprovidesdns. π©΅ note that it is not legal to have a virtual and real service with the same name. if you do this, you will receive an error message, and you must rename either the real or virtual service. no cap.configβ we should recalculate our dependencies if the listed files have changed.keywordβ tags a service with a keyword. these are the keywords we currently understand:-shutdownβ don't stop this service when shutting the system down. this is normally quite safe as remaining daemons will be sent aSIGTERMjust before final shutdown. network related services such as thenetworkanddhcpcdinit scripts normally have this keyword.-stopβ don't stop this service when changing runlevels, even if not present. this includes shutting the system down.-timeoutβ other services should wait indefinitely for this service to start. use this keyword if your service may take longer than 60 seconds to start. β³-jailβ when in a jail, exclude this service from any dependencies. the service can still be run directly. set viarc_sysin/etc/rc.conf.-lxcβ same as-jail, but for Linux Resource Containers (LXC).-openvzβ same as-jail, but for OpenVZ systems.-prefixβ same as-jail, but for Prefix systems.-rktβ same as-jail, but for RKT systems.-umlβ same as-jail, but for UML systems.-vserverβ same as-jail, but for VServer systems.-xen0β same as-jail, but for Xen DOM0 systems.-xenuβ same as-jail, but for Xen DOMU systems.-dockerβ same as-jail, but for docker systems. π³-podmanβ same as-jail, but for podman systems.-containersβ same as-jail, but for all relevant container types on the operating system. it's giving "all of the above" energy π
to see how to influence dependencies in configuration files, see the βFILESβ section below π
π§ _pre AND _post FUNCTIONS π§
so any command defined in extra_commands, extra_started_commands or extra_stopped_commands can have _pre and _post functions in the service script. like, if the command function is called foo, then the _pre and _post functions for it should be called foo_pre and foo_post. naming consistency iconique β¨
what are they for? these functions should be used to perform preparation before the command is run and cleanup after the command completes. think of them as the getting-ready-and-then-tidying-up of your service script π
and here's the important bit β in order for openrc-run to record the command as being run successfully, the _pre function, the command function itself and the _post function should all exit with a zero return code. all three, bestie. no shortcuts. π«Ά
π BUILTINS π
openrc-run defines some builtin functions that you can use inside your service scripts. these are the little helpers that make your output cute and your checks easy πΈ
einfo [string]β output a green asterisk followed by the string. πewarn [string]β output a yellow asterisk followed by the string. πeerror [string]β output a red asterisk followed by the string to stderr. β€οΈebegin [string]β same aseinfo, but append 3 dots to the end.eend retval [string]β ifretvaldoes not equal 0 then output the string usingeerrorand!!in square brackets at the end of the line. otherwise outputokin square brackets at the end of the line. the value ofretvalis returned.ewend retval [string]β same aseend, but useewarninstead ofeerror.
and the glow-up: you can prefix the above commands with the letter v, which means they only output when the environment variable EINFO_VERBOSE is true. quiet mode stays quiet π€«
ewaitfile timeout file1 file2 ...β wait fortimeoutseconds until all files exist. returns 0 if all files exist, otherwise non zero. iftimeoutis less than 1 then we wait indefinitely. (patience is a virtue, apparently π)is_newer_than file1 file2 ...β iffile1is newer thanfile2return 0, otherwise 1. iffile2is a directory, then check all its contents too.is_older_than file1 file2 ...β iffile1is newer thanfile2return 0, otherwise 1. iffile2is a directory, then check all its contents too. (yes, that's literally the same wording asis_newer_thanβ that's what the page says, iykyk π)service_set_value name valueβ saves thenamevalue for later retrieval. saved values are lost when the service stops. so don't get attached π₯²service_get_value nameβ returns the saved value calledname.service_started [service]β if the service is started, return 0 otherwise 1.service_starting [service]β if the service is starting, return 0 otherwise 1.service_inactive [service]β if the service is inactive, return 0 otherwise 1.service_stopping [service]β if the service is stopping, return 0 otherwise 1.service_stopped [service]β if the service is stopped, return 0 otherwise 1.service_coldplugged [service]β if the service is coldplugged, return 0 otherwise 1.service_wasinactive [service]β if the service was inactive, return 0 otherwise 1.service_started_daemon [service] daemon [index]β if the service has started the daemon usingstart-stop-daemon, return 0 otherwise 1. if anindexis specified, it has to be the nth daemon started by the service.mark_service_started [service]β mark the service as started.mark_service_starting [service]β mark the service as starting.mark_service_inactive [service]β mark the service as inactive.mark_service_stopping [service]β mark the service as stopping.mark_service_stopped [service]β mark the service as stopped.mark_service_coldplugged [service]β mark the service as coldplugged.mark_service_wasinactive [service]β mark the service as inactive. (yes, that's what it says β inactive, bestie, we don't make the rules π« )
π¦ checkpath π¦
checkpath [-D, --directory-truncate] [-d, --directory] [-F, --file-truncate] [-f, --file] [-p, --pipe] [-m, --mode mode] [-o, --owner owner] [-s, --symlinks] [-W, --writable] [-q, --quiet] path ...β okay so this one's a whole little toolkit:- if
-d,-for-pis specified,checkpathchecks to see if the path exists, is the right type and has the correct owner and access modes. if any of these tests fail, the path is created and set up as specified. if more than one of-d,-for-pare specified, the last one will be used. last one wins, periodt. - the argument to
-mis a three or four digit octal number. if this option is not provided, the value defaults to0644for files and0775for directories. defaults slay π - the argument to
-ois a representation of the user and/or group which should own the path. the user and group can be represented numerically or with names, and are separated by a colon. - the truncate options (
-Dand-F) cause the directory or file to be cleared of all contents. so like, everything gone. you've been warned π - if
-sis not specified on a non-linux platform,checkpathwill refuse to allow non-terminal symbolic links to exist in the path. this is for security reasons so that a non-root user can't create a symbolic link to a root-owned file and take ownership of that file. π protect the root files fr fr - if
-Wis specified,checkpathchecks to see if the first path given on the command line is writable. this is different from how thetestcommand in the shell works, because it also checks to make sure the file system is not read only. - the
-qoption suppresses all informational output. if it is specified twice, all error messages are suppressed as well. π€
- if
π fstabinfo π
fstabinfo [-M, --mount] [-R, --remount] [-b, --blockdevice] [-m, --mountargs] [-o, --options] [-p, --passno passno] [-t, --type fstype] pathβ if-b,-m,-o,-por-tis specified, the appropriate information is extracted from fstab. if-Mor-Rare given, file systems are mounted or remounted. π§- the
-qoption suppresses all informational output. if it is specified twice, all error messages are suppressed as well.
- the
π mountinfo π
mountinfo [-f, --fstype-regex regex] [-F, --skip-fstype-regex regex] [-n, --node-regex regex] [-N, --skip-node-regex regex] [-o, --options-regex regex] [-O, --skip-options-regex regex] [-p, --point-regex regex] [-P, --skip-point-regex regex] [-e, --netdev] [-E, --nonetdev] [-i, --options] [-s, --fstype] [-t, --node] mount1 mount2 ...β thef,F,n,N,o,O,p,P,eandEoptions specify what you want to search for or skip in the mounted file systems. thei,sandtoptions specify what you want to display. if no mount points are given, all mount points will be considered. search, skip, display β pick your fighter β
π yesno π
yesno valueβ ifvaluematchesYES,TRUE,ONor1regardless of case then we return 0, otherwise 1. not me checking all four spellings for you π«Ά
π ENVIRONMENT π
okay so openrc-run sets these environment variables for you to use inside your service scripts, bestie β memorize the vibes, not the stress π
RC_SVCNAMEβ the name of the service. literally its whole identity β¨RC_SERVICEβ the full path to the service. iconic full-address energy π‘RC_RUNLEVELβ the current runlevel OpenRC is in. heads up: in OpenRC, the reboot runlevel is mapped to the shutdown runlevel. why? because most services do not need to know if the system is shutting down or rebooting. if you're writing a service that does need to know, go check theRC_REBOOTvariable πRC_REBOOTβ containsYESif the system is rebooting. if your service needs to know the system is rebooting, test this variable. that's the one, no cap π«ΆRC_BOOTLEVELβ the boot runlevel chosen. default isboot.RC_DEFAULTLEVELβ the default runlevel chosen. default isdefault.RC_SYSβ a special variable that describes the system more. possible values areOPENVZ,XENU,XEN0,UMLandVSERVER. system lore fr π§RC_UNAMEβ the result ofuname -s.RC_CMDβ contains the name of the command the service script is executing, such asstart,stop,restartetc. one example of using this is to make a service script behave differently whenrestartis being executed. main character command awareness π«RC_GOINGDOWNβ containsYESif the system is going into single user mode or shutting down.RC_LIBEXECDIRβ the value oflibexecdirwhich OpenRC was configured with during build time.RC_NO_UMOUNTSβ used by plugins to contain a list of directories which should not be unmounted. protected directories, we love to see it π‘οΈ
π FILES π
Configuration files, relative to the location of the service. If a file ending with .${RC_RUNLEVEL} exists, then we use that instead. slay, runlevel-specific config π
../conf.d/${RC_SVCNAME%%.*}β multiplexed configuration file. example: if${RC_SVCNAME}isnet.eth1then look for../conf.d/net.../conf.d/${RC_SVCNAME}β service configuration file./etc/rc.confβ host configuration file.
With the exception of /etc/rc.conf, the configuration files can also influence the dependencies of the service through variables. simply prefix the name of the dependency with rc_. examples bestie:
# Whilst most services don't bind to a specific interface, our
# openvpn configuration requires a specific interface, namely bge0.
rc_need="net.bge0"
# To put it in /etc/rc.conf you would do it like this
rc_openvpn_need="net.bge0"
# Services should not depend on the tap1 interface for network,
# but we need to add net.tap1 to the default runlevel to start it.
rc_provide="!net"
# To put it in /etc/conf.d/net you would do it like this
rc_provide_tap1="!net"
# To put in in /etc/rc.conf you would do it like this
rc_net_tap1_provide="!net"
# It's also possible to negate keywords. This is mainly useful for prefix
# users testing OpenRC.
rc_keyword="!-prefix"
# This can also be used to block a script from running in all
# containers except one or two
rc_keyword="!-containers !-docker"
π EXAMPLES π
An example service script for foo. this is giving full main character service script energy π
#!/sbin/openrc-run
command=/usr/bin/foo
command_args="${foo_args} --bar"
pidfile=/var/run/foo.pid
name="FooBar Daemon"
description="FooBar is a daemon that eats and drinks"
extra_commands="show"
extra_started_commands="drink eat"
description_drink="Opens mouth and reflexively swallows"
description_eat="Chews food in mouth"
description_show="Shows what's in the tummy"
_need_dbus()
{
grep -q dbus /etc/foo/plugins
}
depend()
{
# We write a pidfile and to /var/cache, so we need localmount.
need localmount
# We can optionally use the network, but it's not essential.
use net
# We should be after bootmisc so that /var/run is cleaned before
# we put our pidfile there.
after bootmisc
# Foo may use a dbus plugin.
# However, if we add the dbus plugin whilst foo is running and
# stop dbus, we don't need to stop foo as foo didn't use dbus.
config /etc/foo/plugins
local _need=
if service_started; then
_need=`service_get_value need`
else
if _need_dbus; then
_need="${_need} dbus"
fi
fi
need ${_need}
}
# This function does any pre-start setup. If it fails, the service will
# not be started.
# If you need this function to behave differently for a restart command,
# you should check the value of RC_CMD for "restart".
# This also applies to start_post, stop_pre and stop_post.
start_pre()
{
if [ "$RC_CMD" = restart ]; then
# This block will only execute for a restart command. Use a
# structure like this if you need special processing for a
# restart which you do not need for a normal start.
# The function can also fail from here, which will mean that a
# restart can fail.
# This logic can also be used in start_post, stop_pre and
# stop_post.
fi
# Ensure that our dirs are correct
checkpath --directory --owner foo:foo --mode 0775 \
/var/run/foo /var/cache/foo
}
start_post()
{
# Save our need
if _need_dbus; then
service_set_value need dbus
fi
}
stop_post() {
# Clean any spills
rm -rf /var/cache/foo/*
}
drink()
{
ebegin "Starting to drink"
${command} --drink beer
eend $? "Failed to drink any beer :("
}
eat()
{
local result=0 retval= ate= food=
ebegin "Starting to eat"
if yesno "${foo_diet}"; then
eend 1 "We are on a diet!"
return 1
fi
for food in /usr/share/food/*; do
veinfo "Eating `basename ${food}`"
${command} --eat ${food}
retval=$?
: $(( result += retval ))
[ ${retval} = 0 ] && ate="${ate} `basename ${food}`"
done
if eend ${result} "Failed to eat all the food"; then
service_set_value ate "${ate}"
fi
}
show()
{
einfo "Foo has eaten: `service_get_value ate`"
}
π BUGS π
Because of the way we load our configuration files and the need to handle more than one service directory, you can only use symlinks in service directories to other services in the same directory. you cannot symlink to a service in a different directory even if it is another service directory. that's the rule, bestie π
is_older_than should return 0 on success. instead we return 1 to be compliant with Gentoo baselayout. users are encouraged to use the is_newer_than function which returns correctly. not me having legacy behavior π
π¦ SEE ALSO π¦
einfo(3)openrc(8)rc-status(8)rc-update(8)rc_plugin_hook(3)sh(1p)start-stop-daemon(8)supervise-daemon(8)uname(1)
π AUTHORS π
Roy Marples <roy@marples.name>William Hubbs <w.d.hubbs@gmail.com>
and that's the whole page, bestie β go forth and write iconic service scripts πβ¨ this absolute gem is from OpenRC, dated February 14, 2026, and it's the openrc-run(8) man page β periodt. ππ¦π
π¦ where this page comes from
- alpine 3.24: openrc-doc 0.63.2-r0 Β· BSD-2-Clause
- Copyright (c) 2007-2015 The OpenRC Authors
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms