Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5df7ee0564 | ||
|
|
b731c02a38 | ||
|
|
c42916ea19 | ||
|
|
f973354ccd | ||
|
|
69349f7b57 | ||
|
|
1b1a70ecca | ||
|
|
05cfbb8348 | ||
|
|
a70b65f851 | ||
|
|
0660d2455d | ||
|
|
01c5b98d38 |
@@ -1,3 +1,3 @@
|
||||
NAME= openrc
|
||||
VERSION= 0.39
|
||||
VERSION= 0.35.3
|
||||
PKG= ${NAME}-${VERSION}
|
||||
|
||||
51
NEWS.md
51
NEWS.md
@@ -4,57 +4,6 @@ OpenRC NEWS
|
||||
This file will contain a list of notable changes for each release. Note
|
||||
the information in this file is in reverse order.
|
||||
|
||||
## OpenRC 0.39
|
||||
|
||||
This version removes the support for addons.
|
||||
The only place I know that this was used was Gentoo Baselayout 1.x, so
|
||||
it shouldn't affect anyone since baselayout-1 has been dead for a few
|
||||
years.
|
||||
|
||||
Since all supported Linux kernel versions now make efivarfs immutable
|
||||
and all of the tools that access efivarfs are aware of this, we no
|
||||
longer mount efivarfs read-only. See the following github issue for more
|
||||
information:
|
||||
|
||||
https://github.com/openrc/openrc/issues/238
|
||||
|
||||
This version adds timed shutdown and cancelation of shutdown to
|
||||
openrc-shutdown. Shutdowns can now be delayed for a certain amount of
|
||||
time or scheduled for an exact time.
|
||||
|
||||
supervise-daemon supports health checks, which are a periodic way to make sure a
|
||||
service is healthy. For more information on setting this up, please see
|
||||
supervise-daemon-guide.md.
|
||||
|
||||
The --first-time switch has been added to all modprobe commands in the
|
||||
modules service. This means that, on Linux, you will see failures if a
|
||||
module was loaded by an initramfs or device manager before this service
|
||||
runs. These messages are harmless, but to clean them up, you should adjust your
|
||||
modules autoload configuration.
|
||||
|
||||
## OpenRC 0.37
|
||||
|
||||
start-stop-daemon now supports logging stdout and stderr of daemons to
|
||||
processes instead of files. These processes are defined by the
|
||||
output_logger and error_logger variables in standard service scripts, or
|
||||
by the -3/--output-logger or -4/--error-logger switches if you use
|
||||
start-stop-daemon directly. For more information on this, see the
|
||||
start-stop-daemon man page.
|
||||
|
||||
## OpenRC 0.36
|
||||
|
||||
In this release, the modules-load service has been combined into the
|
||||
modules service since there is no reason I know of to keep them
|
||||
separate. However, modules also provides modules-load in case you were
|
||||
using modules-load in your dependencies.
|
||||
|
||||
The consolefont, keymaps, numlock and procfs service scripts no longer
|
||||
have a dependency on localmount.
|
||||
If you are a linux user and are still separaating / from /usr,
|
||||
you will need to add the following line to the appropriate conf.d files:
|
||||
|
||||
rc_need="localmount"
|
||||
|
||||
## OpenRC 0.35
|
||||
|
||||
In this version, the cgroups mounting logic has been moved from the
|
||||
|
||||
@@ -8,6 +8,11 @@
|
||||
#modules_2="ipv6"
|
||||
#modules="ohci1394"
|
||||
|
||||
# Linux users can give modules a different name when they load - the new name
|
||||
# will also be used to pick arguments below.
|
||||
# This is not supported on FreeBSD.
|
||||
#modules="dummy:dummy1"
|
||||
|
||||
# Linux users can give the modules some arguments if needed, per version
|
||||
# if necessary.
|
||||
# Again, the most specific versioned variable will take precedence.
|
||||
|
||||
@@ -19,10 +19,10 @@ SRCS-FreeBSD= hostid.in modules.in moused.in newsyslog.in pf.in rarpd.in \
|
||||
rc-enabled.in rpcbind.in savecore.in syslogd.in
|
||||
# These are FreeBSD specific
|
||||
SRCS-FreeBSD+= adjkerntz.in devd.in dumpon.in encswap.in ipfw.in \
|
||||
mixer.in nscd.in powerd.in syscons.in
|
||||
modules-load.in mixer.in nscd.in powerd.in syscons.in
|
||||
|
||||
SRCS-Linux= agetty.in binfmt.in devfs.in cgroups.in dmesg.in hwclock.in \
|
||||
consolefont.in keymaps.in killprocs.in modules.in \
|
||||
consolefont.in keymaps.in killprocs.in modules.in modules-load.in \
|
||||
mount-ro.in mtab.in numlock.in procfs.in net-online.in sysfs.in \
|
||||
termencoding.in
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ term_type="${term_type:-linux}"
|
||||
command=/sbin/agetty
|
||||
command_args_foreground="${agetty_options} ${port} ${baud} ${term_type}"
|
||||
pidfile="/run/${RC_SVCNAME}.pid"
|
||||
export EINFO_QUIET="${quiet:-yes}"
|
||||
|
||||
depend() {
|
||||
after local
|
||||
@@ -28,12 +29,5 @@ start_pre() {
|
||||
eerror "symbolic links to it for the ports you want to start"
|
||||
eerror "agetty on and add those to the appropriate runlevels."
|
||||
return 1
|
||||
else
|
||||
export EINFO_QUIET="${quiet:-yes}"
|
||||
fi
|
||||
}
|
||||
|
||||
stop_pre()
|
||||
{
|
||||
export EINFO_QUIET="${quiet:-yes}"
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ description="Sets a font for the consoles."
|
||||
|
||||
depend()
|
||||
{
|
||||
need termencoding
|
||||
need localmount termencoding
|
||||
after hotplug bootmisc modules
|
||||
keyword -docker -lxc -openvz -prefix -systemd-nspawn -uml -vserver -xenu
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ description="Applies a keymap for the consoles."
|
||||
|
||||
depend()
|
||||
{
|
||||
need termencoding
|
||||
need localmount termencoding
|
||||
after bootmisc clock
|
||||
keyword -docker -lxc -openvz -prefix -systemd-nspawn -uml -vserver -xenu
|
||||
}
|
||||
|
||||
72
init.d/modules-load.in
Normal file
72
init.d/modules-load.in
Normal file
@@ -0,0 +1,72 @@
|
||||
#!@SBINDIR@/openrc-run
|
||||
# Copyright (c) 2016 The OpenRC Authors.
|
||||
# See the Authors file at the top-level directory of this distribution and
|
||||
# https://github.com/OpenRC/openrc/blob/master/AUTHORS
|
||||
#
|
||||
# This file is part of OpenRC. It is subject to the license terms in
|
||||
# the LICENSE file found in the top-level directory of this
|
||||
# distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
|
||||
# This file may not be copied, modified, propagated, or distributed
|
||||
# except according to the terms contained in the LICENSE file.
|
||||
|
||||
description="Loads a list of modules from systemd-compatible locations."
|
||||
|
||||
depend()
|
||||
{
|
||||
keyword -docker -lxc -openvz -prefix -systemd-nspawn -vserver
|
||||
}
|
||||
|
||||
find_modfiles()
|
||||
{
|
||||
local dirs="/usr/lib/modules-load.d /run/modules-load.d /etc/modules-load.d"
|
||||
local basenames files fn x y
|
||||
for x in $dirs; do
|
||||
[ ! -d $x ] && continue
|
||||
for y in $x/*.conf; do
|
||||
[ -f $y ] && basenames="${basenames}\n${y##*/}"
|
||||
done
|
||||
done
|
||||
basenames=$(printf "$basenames" | sort -u)
|
||||
for x in $basenames; do
|
||||
for y in $dirs; do
|
||||
[ -r $y/$x ] &&
|
||||
fn=$y/$x
|
||||
done
|
||||
files="$files $fn"
|
||||
done
|
||||
echo $files
|
||||
}
|
||||
|
||||
load_modules()
|
||||
{
|
||||
local file m modules rc x
|
||||
file=$1
|
||||
[ -z "$file" ] && return 0
|
||||
while read m x; do
|
||||
case $m in
|
||||
\;*) continue ;;
|
||||
\#*) continue ;;
|
||||
*) modules="$modules $m"
|
||||
;;
|
||||
esac
|
||||
done < $file
|
||||
for x in $modules; do
|
||||
ebegin "Loading module $x"
|
||||
case "$RC_UNAME" in
|
||||
FreeBSD) kldload "$x"; rc=$? ;;
|
||||
Linux) modprobe --use-blacklist -q "$x"; rc=$? ;;
|
||||
*) ;;
|
||||
esac
|
||||
eend $rc "Failed to load $x"
|
||||
done
|
||||
}
|
||||
|
||||
start()
|
||||
{
|
||||
local x
|
||||
files=$(find_modfiles)
|
||||
for x in $files; do
|
||||
load_modules $x
|
||||
done
|
||||
return 0
|
||||
}
|
||||
@@ -14,66 +14,10 @@ description="Loads a user defined list of kernel modules."
|
||||
depend()
|
||||
{
|
||||
use isapnp
|
||||
provide modules-load
|
||||
want modules-load
|
||||
keyword -docker -lxc -openvz -prefix -systemd-nspawn -vserver
|
||||
}
|
||||
|
||||
find_modfiles()
|
||||
{
|
||||
local dirs="/usr/lib/modules-load.d /run/modules-load.d /etc/modules-load.d"
|
||||
local basenames files fn x y
|
||||
for x in $dirs; do
|
||||
[ ! -d $x ] && continue
|
||||
for y in $x/*.conf; do
|
||||
[ -f $y ] && basenames="${basenames}\n${y##*/}"
|
||||
done
|
||||
done
|
||||
basenames=$(printf "$basenames" | sort -u)
|
||||
for x in $basenames; do
|
||||
for y in $dirs; do
|
||||
[ -r $y/$x ] &&
|
||||
fn=$y/$x
|
||||
done
|
||||
files="$files $fn"
|
||||
done
|
||||
echo $files
|
||||
}
|
||||
|
||||
load_modules()
|
||||
{
|
||||
local file m modules rc x
|
||||
file=$1
|
||||
[ -z "$file" ] && return 0
|
||||
while read m x; do
|
||||
case $m in
|
||||
\;*) continue ;;
|
||||
\#*) continue ;;
|
||||
*) modules="$modules $m"
|
||||
;;
|
||||
esac
|
||||
done < $file
|
||||
for x in $modules; do
|
||||
ebegin "Loading module $x"
|
||||
case "$RC_UNAME" in
|
||||
FreeBSD) kldload "$x"; rc=$? ;;
|
||||
Linux) modprobe --first-time -q --use-blacklist "$x"; rc=$? ;;
|
||||
*) ;;
|
||||
esac
|
||||
eend $rc "Failed to load $x"
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
modules_load_d()
|
||||
{
|
||||
local x
|
||||
files=$(find_modfiles)
|
||||
for x in $files; do
|
||||
load_modules $x
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
FreeBSD_modules()
|
||||
{
|
||||
local cnt=0 x
|
||||
@@ -104,7 +48,7 @@ Linux_modules()
|
||||
x=${x%.*}
|
||||
done
|
||||
|
||||
local list= x= xx= y= args=
|
||||
local list= x= xx= y= args= mpargs= a=
|
||||
for x in $kv_variant_list ; do
|
||||
eval list=\$modules_$(shell_var "$x")
|
||||
[ -n "$list" ] && break
|
||||
@@ -113,13 +57,24 @@ Linux_modules()
|
||||
|
||||
[ -n "$list" ] && ebegin "Loading kernel modules"
|
||||
for x in $list; do
|
||||
a=${x#*:}
|
||||
if [ "$a" = "$x" ]; then
|
||||
unset mpargs
|
||||
else
|
||||
x=${x%%:*}
|
||||
mpargs="-o $a"
|
||||
fi
|
||||
aa=$(shell_var "$a")
|
||||
xx=$(shell_var "$x")
|
||||
for y in $kv_variant_list ; do
|
||||
eval args=\$module_${aa}_args_$(shell_var "$y")
|
||||
[ -n "${args}" ] && break
|
||||
eval args=\$module_${xx}_args_$(shell_var "$y")
|
||||
[ -n "${args}" ] && break
|
||||
done
|
||||
[ -z "$args" ] && eval args=\$module_${aa}_args
|
||||
[ -z "$args" ] && eval args=\$module_${xx}_args
|
||||
eval modprobe --first-time --use-blacklist --verbose "$x" "$args"
|
||||
eval modprobe --use-blacklist --verbose "$mpargs" "$x" "$args"
|
||||
done
|
||||
[ -n "$list" ] && eend
|
||||
}
|
||||
@@ -127,10 +82,7 @@ Linux_modules()
|
||||
start()
|
||||
{
|
||||
case "$RC_UNAME" in
|
||||
FreeBSD|Linux)
|
||||
modules_load_d
|
||||
${RC_UNAME}_modules
|
||||
;;
|
||||
FreeBSD|Linux) ${RC_UNAME}_modules ;;
|
||||
*) ;;
|
||||
esac
|
||||
return 0
|
||||
|
||||
@@ -13,7 +13,7 @@ description="Delays until the network is online or a specific timeout"
|
||||
|
||||
depend()
|
||||
{
|
||||
after modules net
|
||||
after modules
|
||||
need sysfs
|
||||
provide network-online
|
||||
keyword -docker -jail -lxc -openvz -prefix -systemd-nspawn -uml -vserver
|
||||
|
||||
@@ -15,6 +15,7 @@ ttyn=${rc_tty_number:-${RC_TTY_NUMBER:-12}}
|
||||
|
||||
depend()
|
||||
{
|
||||
need localmount
|
||||
keyword -docker -lxc -openvz -prefix -systemd-nspawn -vserver
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ depend()
|
||||
after clock
|
||||
use devfs
|
||||
want modules
|
||||
need localmount
|
||||
keyword -docker -lxc -openvz -prefix -systemd-nspawn -vserver
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ start()
|
||||
fi
|
||||
ebegin "Saving dependency cache"
|
||||
local rc=0 save=
|
||||
for x in depconfig deptree rc.log shutdowntime softlevel; do
|
||||
for x in shutdowntime softlevel rc.log; do
|
||||
[ -e "$RC_SVCDIR/$x" ] && save="$save $RC_SVCDIR/$x"
|
||||
done
|
||||
if [ -n "$save" ]; then
|
||||
|
||||
@@ -101,7 +101,7 @@ mount_misc()
|
||||
if [ -d /sys/firmware/efi/efivars ] &&
|
||||
! mountinfo -q /sys/firmware/efi/efivars; then
|
||||
ebegin "Mounting efivarfs filesystem"
|
||||
mount -n -t efivarfs -o ${sysfs_opts} \
|
||||
mount -n -t efivarfs -o ro \
|
||||
efivarfs /sys/firmware/efi/efivars 2> /dev/null
|
||||
eend 0
|
||||
fi
|
||||
|
||||
@@ -119,9 +119,6 @@ The amount of time, in milliseconds, s6-svc should wait for the service
|
||||
to go down when stopping the service. The default is 60000.
|
||||
.It Ar start_stop_daemon_args
|
||||
List of arguments passed to start-stop-daemon when starting the daemon.
|
||||
.It Ar supervise_daemon_args
|
||||
List of arguments passed to supervise-daemon when starting the daemon.
|
||||
If undefined, start_stop_daemon_args is used as a fallback.
|
||||
.It Ar command
|
||||
Daemon to start or stop via
|
||||
.Nm start-stop-daemon
|
||||
@@ -173,23 +170,6 @@ variable is set.
|
||||
The same thing as
|
||||
.Pa output_log
|
||||
but for the standard error output.
|
||||
.It Ar output_logger
|
||||
This is a process which will be used to log the standard output from the
|
||||
service. If you are starting this service with
|
||||
.Xr start-stop-daemon 8 ,
|
||||
, you must set
|
||||
.Pa command_background
|
||||
to true. Keep in mind that this command must be executable as a shell
|
||||
command inside the chroot if the
|
||||
.Pa chroot
|
||||
variable 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 is logger if you want
|
||||
your service output to go to syslog.
|
||||
.It Ar error_logger
|
||||
The same thing as
|
||||
.Pa output_logger
|
||||
but for the standard error output.
|
||||
.It Ar directory
|
||||
.Xr start-stop-daemon 8
|
||||
and
|
||||
@@ -614,7 +594,7 @@ 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
|
||||
# This can also be used to block a script from runining in all
|
||||
# containers except one or two
|
||||
rc_keyword="!-containers !-docker"
|
||||
.Ed
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
.Nd bring the system down
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl c , -cancel
|
||||
.Op Fl d , -no-write
|
||||
.Op Fl D , -dry-run
|
||||
.Op Fl H , -halt
|
||||
@@ -33,8 +32,6 @@ is the utility that communicates with
|
||||
to bring down the system or instruct openrc-init to re-execute itself.
|
||||
It supports the following options:
|
||||
.Bl -tag -width "poweroff"
|
||||
.It Fl c , -cancel
|
||||
Cancel a pending shutdown.
|
||||
.It Fl d , -no-write
|
||||
Do not write the wtmp boot record.
|
||||
.It Fl D , -dry-run
|
||||
|
||||
@@ -20,14 +20,6 @@
|
||||
.Ar service cmd
|
||||
.Op Ar ...
|
||||
.Nm
|
||||
.Fl d , -debug
|
||||
.Ar service cmd
|
||||
.Op Ar ...
|
||||
.Nm
|
||||
.Fl D , -nodeps
|
||||
.Ar service cmd
|
||||
.Op Ar ...
|
||||
.Nm
|
||||
.Op Fl i , -ifexists
|
||||
.Ar service cmd
|
||||
.Op Ar ...
|
||||
@@ -40,21 +32,9 @@
|
||||
.Ar service cmd
|
||||
.Op Ar ...
|
||||
.Nm
|
||||
.Op Fl s , -ifstarted
|
||||
.Ar service cmd
|
||||
.Op Ar ...
|
||||
.Nm
|
||||
.Op Fl S , -ifstopped
|
||||
.Ar service cmd
|
||||
.Op Ar ...
|
||||
.Nm
|
||||
.Fl e , -exists
|
||||
.Ar service
|
||||
.Nm
|
||||
.Fl Z , -dry-run
|
||||
.Ar service cmd
|
||||
.Op Ar ...
|
||||
.Nm
|
||||
.Fl l , -list
|
||||
.Nm
|
||||
.Fl r , -resolve
|
||||
@@ -88,15 +68,6 @@ return 0 if it can find
|
||||
otherwise -1.
|
||||
.Fl r , -resolve
|
||||
does the same and also prints the full path of the service to stdout.
|
||||
.Pp
|
||||
.Fl d , -debug
|
||||
sets -x when running the service script(s).
|
||||
.Pp
|
||||
.Fl D , -nodeps
|
||||
ignores dependencies when running the service.
|
||||
.Pp
|
||||
.Fl Z , -dry-run
|
||||
displays commands rather than executing them.
|
||||
.Sh SEE ALSO
|
||||
.Xr openrc 8 ,
|
||||
.Xr stdout 3
|
||||
|
||||
@@ -131,34 +131,9 @@ Modifies the scheduling priority of the daemon.
|
||||
.It Fl 1 , -stdout Ar logfile
|
||||
Redirect the standard output of the process to logfile when started with
|
||||
.Fl background .
|
||||
The logfile Must be an absolute pathname, but relative to the path
|
||||
optionally given with
|
||||
Must be an absolute pathname, but relative to the path optionally given with
|
||||
.Fl r , -chroot .
|
||||
The logfile can also be a named pipe.
|
||||
.It Fl 2 , -stderr Ar logfile
|
||||
Redirect the standard error of the process to logfile when started with
|
||||
.Fl background .
|
||||
The logfile must be an absolute pathname, but relative to the path
|
||||
optionally given with
|
||||
.Fl r , -chroot .
|
||||
The logfile can also be a named pipe.
|
||||
.It Fl 3 , -stdout-logger Ar cmd
|
||||
Run cmd as a child process redirecting the standard output to the
|
||||
standard input of cmd when started with
|
||||
.Fl background .
|
||||
Cmd must be an absolute pathname, but relative to the path optionally given with
|
||||
.Fl r , -chroot .
|
||||
This process must be prepared to accept input on stdin and be able to
|
||||
log it or send it to another location.
|
||||
.It Fl 4 , -stderr-logger Ar cmd
|
||||
Run cmd as a child process and
|
||||
Redirect the standard error of the process to the standard input of cmd
|
||||
when started with
|
||||
.Fl background .
|
||||
Cmd must be an absolute pathname, but relative to the path optionally given with
|
||||
.Fl r , -chroot .
|
||||
This process must be prepared to accept input on stdin and be able to
|
||||
log it or send it to another location.
|
||||
.It Fl w , -wait Ar milliseconds
|
||||
Wait
|
||||
.Ar milliseconds
|
||||
@@ -176,7 +151,6 @@ These options are only used for stopping daemons:
|
||||
.It Fl R , -retry Ar timeout | Ar signal Ns / Ns Ar timeout
|
||||
The retry specification can be either a timeout in seconds or multiple
|
||||
signal/timeout pairs (like SIGTERM/5).
|
||||
If this option is not given, the default is SIGTERM/5.
|
||||
.El
|
||||
.Sh ENVIRONMENT
|
||||
.Va SSD_IONICELEVEL
|
||||
|
||||
@@ -16,10 +16,6 @@
|
||||
.Nd starts a daemon and restarts it if it crashes
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Fl a , -healthcheck-timer
|
||||
.Ar seconds
|
||||
.Fl A , -healthcheck-delay
|
||||
.Ar seconds
|
||||
.Fl D , -respawn-delay
|
||||
.Ar seconds
|
||||
.Fl d , -chdir
|
||||
@@ -94,11 +90,6 @@ Print the action(s) that are taken just before doing them.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width indent
|
||||
.Fl a , -healthcheck-timer Ar seconds
|
||||
Run the healthcheck() command, possibly followed by the unhealthy()
|
||||
command every time this number of seconds passes.
|
||||
.Fl A , -healthcheck-delay Ar seconds
|
||||
Wait this long before the first health check.
|
||||
.It Fl D , -respawn-delay Ar seconds
|
||||
wait this number of seconds before restarting a daemon after it crashes.
|
||||
The default is 0.
|
||||
@@ -129,7 +120,6 @@ description of --respawn-max for more information.
|
||||
.It Fl R , -retry Ar timeout | Ar signal Ns / Ns Ar timeout
|
||||
The retry specification can be either a timeout in seconds or multiple
|
||||
signal/timeout pairs (like SIGTERM/5).
|
||||
If this option is not given, the default is SIGTERM/5.
|
||||
.It Fl r , -chroot Ar path
|
||||
chroot to this directory before starting the daemon. All other paths, such
|
||||
as the path to the daemon, chdir and pidfile, should be relative to the chroot.
|
||||
|
||||
@@ -12,4 +12,4 @@
|
||||
|
||||
include ${MK}/os-BSD.mk
|
||||
|
||||
CPPFLAGS+= -D_BSD_SOURCE
|
||||
CPPFLAGS+= -D_WITH_GETLINE
|
||||
|
||||
@@ -13,6 +13,6 @@
|
||||
SFX= .GNU-kFreeBSD.in
|
||||
PKG_PREFIX?= /usr
|
||||
|
||||
CPPFLAGS+= -D_BSD_SOURCE
|
||||
CPPFLAGS+= -D_BSD_SOURCE -D_XOPEN_SOURCE=700
|
||||
LIBDL= -Wl,-Bdynamic -ldl
|
||||
LIBKVM?=
|
||||
|
||||
@@ -11,5 +11,5 @@
|
||||
SFX= .GNU.in
|
||||
PKG_PREFIX?= /usr
|
||||
|
||||
CPPFLAGS+= -D_DEFAULT_SOURCE -DMAXPATHLEN=4096 -DPATH_MAX=4096
|
||||
CPPFLAGS+= -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=700 -DMAXPATHLEN=4096 -DPATH_MAX=4096
|
||||
LIBDL= -Wl,-Bdynamic -ldl
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
SFX= .Linux.in
|
||||
PKG_PREFIX?= /usr
|
||||
|
||||
CPPFLAGS+= -D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200809L
|
||||
CPPFLAGS+= -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=700
|
||||
LIBDL= -Wl,-Bdynamic -ldl
|
||||
|
||||
ifeq (${MKSELINUX},yes)
|
||||
|
||||
@@ -45,20 +45,20 @@ SBINDIR?= ${PREFIX}/sbin
|
||||
SBINMODE?= 0755
|
||||
|
||||
INCDIR?= ${UPREFIX}/include
|
||||
INCMODE?= 0644
|
||||
INCMODE?= 0444
|
||||
|
||||
_LIBNAME_SH= case `readlink /lib` in /lib64|lib64) echo "lib64";; *) echo "lib";; esac
|
||||
_LIBNAME:= $(shell ${_LIBNAME_SH})
|
||||
LIBNAME?= ${_LIBNAME}
|
||||
LIBDIR?= ${UPREFIX}/${LIBNAME}
|
||||
LIBMODE?= 0644
|
||||
LIBMODE?= 0444
|
||||
SHLIBDIR?= ${PREFIX}/${LIBNAME}
|
||||
|
||||
LIBEXECDIR?= ${PREFIX}/libexec/rc
|
||||
|
||||
MANPREFIX?= ${UPREFIX}/share
|
||||
MANDIR?= ${MANPREFIX}/man
|
||||
MANMODE?= 0644
|
||||
MANMODE?= 0444
|
||||
|
||||
BASHCOMPDIR?= ${UPREFIX}/share/bash-completion/completions
|
||||
|
||||
|
||||
@@ -29,9 +29,7 @@ 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 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.
|
||||
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.
|
||||
|
||||
Extra functions can be added easily:
|
||||
|
||||
|
||||
1
sh/.gitignore
vendored
1
sh/.gitignore
vendored
@@ -1,5 +1,6 @@
|
||||
functions.sh
|
||||
gendepends.sh
|
||||
rc-functions.sh
|
||||
openrc-run.sh
|
||||
cgroup-release-agent.sh
|
||||
init.sh
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
DIR= ${LIBEXECDIR}/sh
|
||||
SRCS= init.sh.in functions.sh.in gendepends.sh.in \
|
||||
openrc-run.sh.in ${SRCS-${OS}}
|
||||
openrc-run.sh.in rc-functions.sh.in ${SRCS-${OS}}
|
||||
INC= rc-mount.sh functions.sh rc-functions.sh runit.sh s6.sh \
|
||||
start-stop-daemon.sh supervise-daemon.sh
|
||||
BIN= gendepends.sh init.sh openrc-run.sh ${BIN-${OS}}
|
||||
|
||||
@@ -133,10 +133,11 @@ _status()
|
||||
elif service_inactive; then
|
||||
ewarn "status: inactive"
|
||||
return 16
|
||||
elif service_crashed; then
|
||||
eerror "status: crashed"
|
||||
return 32
|
||||
elif service_started; then
|
||||
if service_crashed; then
|
||||
eerror "status: crashed"
|
||||
return 32
|
||||
fi
|
||||
einfo "status: started"
|
||||
return 0
|
||||
else
|
||||
|
||||
@@ -62,7 +62,7 @@ cgroup_set_values()
|
||||
while [ -n "$1" ] && [ "$controller" != "cpuacct" ]; do
|
||||
case "$1" in
|
||||
$controller.*)
|
||||
if [ -n "${name}" ] && [ -w "${cgroup}/${name}" ] &&
|
||||
if [ -n "${name}" ] && [ -w "${cgroup}/${name}" ] &&
|
||||
[ -n "${val}" ]; then
|
||||
veinfo "$RC_SVCNAME: Setting $cgroup/$name to $val"
|
||||
printf "%s" "$val" > "$cgroup/$name"
|
||||
|
||||
@@ -2,6 +2,42 @@
|
||||
# Copyright (c) 2007-2009 Roy Marples <roy@marples.name>
|
||||
# Released under the 2-clause BSD license.
|
||||
|
||||
has_addon()
|
||||
{
|
||||
[ -e /@LIB@/rc/addons/"$1".sh -o -e /@LIB@/rcscripts/addons/"$1".sh ]
|
||||
}
|
||||
|
||||
_addon_warn()
|
||||
{
|
||||
eindent
|
||||
ewarn "$RC_SVCNAME uses addon code which is deprecated"
|
||||
ewarn "and may not be available in the future."
|
||||
eoutdent
|
||||
}
|
||||
|
||||
import_addon()
|
||||
{
|
||||
if [ -e /@LIB@/rc/addons/"$1".sh ]; then
|
||||
_addon_warn
|
||||
. /@LIB@/rc/addons/"$1".sh
|
||||
elif [ -e /@LIB@/rcscripts/addons/"$1".sh ]; then
|
||||
_addon_warn
|
||||
. /@LIB@/rcscripts/addons/"$1".sh
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
start_addon()
|
||||
{
|
||||
( import_addon "$1-start" )
|
||||
}
|
||||
|
||||
stop_addon()
|
||||
{
|
||||
( import_addon "$1-stop" )
|
||||
}
|
||||
|
||||
net_fs_list="afs ceph cifs coda davfs fuse fuse.sshfs gfs glusterfs lustre
|
||||
ncpfs nfs nfs4 ocfs2 shfs smbfs"
|
||||
is_net_fs()
|
||||
2
sh/s6.sh
2
sh/s6.sh
@@ -57,7 +57,7 @@ s6_stop()
|
||||
ebegin "Stopping ${name:-$RC_SVCNAME}"
|
||||
s6-svc -d -wD -T ${s6_service_timeout_stop:-60000} "${s6_service_link}"
|
||||
set -- $(s6-svstat "${s6_service_link}")
|
||||
[ "$1" = "up" ] &&
|
||||
[ "$1" = "up" ] &&
|
||||
yesno "${s6_force_kill:-yes}" &&
|
||||
_s6_force_kill "$@"
|
||||
set -- $(s6-svstat "${s6_service_link}")
|
||||
|
||||
@@ -38,10 +38,6 @@ ssd_start()
|
||||
service_inactive && _inactive=true
|
||||
mark_service_inactive
|
||||
fi
|
||||
[ -n "$output_logger" ] &&
|
||||
output_logger_arg="--stdout-logger \"$output_logger\""
|
||||
[ -n "$error_logger" ] &&
|
||||
error_logger_arg="--stderr-logger \"$error_logger\""
|
||||
#the eval call is necessary for cases like:
|
||||
# command_args="this \"is a\" test"
|
||||
# to work properly.
|
||||
@@ -51,8 +47,6 @@ ssd_start()
|
||||
${directory:+--chdir} $directory \
|
||||
${output_log+--stdout} $output_log \
|
||||
${error_log+--stderr} $error_log \
|
||||
${output_logger_arg} \
|
||||
${error_logger_arg} \
|
||||
${procname:+--name} $procname \
|
||||
${pidfile:+--pidfile} $pidfile \
|
||||
${command_user+--user} $command_user \
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
# This file may not be copied, modified, propagated, or distributed
|
||||
# except according to the terms contained in the LICENSE file.
|
||||
|
||||
extra_commands="healthcheck unhealthy ${extra_commands}"
|
||||
|
||||
supervise_start()
|
||||
{
|
||||
if [ -z "$command" ]; then
|
||||
@@ -34,11 +32,9 @@ supervise_start()
|
||||
${respawn_delay:+--respawn-delay} $respawn_delay \
|
||||
${respawn_max:+--respawn-max} $respawn_max \
|
||||
${respawn_period:+--respawn-period} $respawn_period \
|
||||
${healthcheck_delay:+--healthcheck-delay} $healthcheck_delay \
|
||||
${healthcheck_timer:+--healthcheck-timer} $healthcheck_timer \
|
||||
${command_user+--user} $command_user \
|
||||
${umask+--umask} $umask \
|
||||
${supervise_daemon_args:-${start_stop_daemon_args}} \
|
||||
$supervise_daemon_args \
|
||||
$command \
|
||||
-- $command_args $command_args_foreground
|
||||
rc=$?
|
||||
@@ -102,13 +98,3 @@ supervise_status()
|
||||
return 3
|
||||
fi
|
||||
}
|
||||
|
||||
healthcheck()
|
||||
{
|
||||
return 0
|
||||
}
|
||||
|
||||
unhealthy()
|
||||
{
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -66,6 +66,9 @@ int parse_mode(mode_t *, char *);
|
||||
/* Handy function so we can wrap einfo around our deptree */
|
||||
RC_DEPTREE *_rc_deptree_load (int, int *);
|
||||
|
||||
/* Test to see if we can see pid 1 or not */
|
||||
bool _rc_can_find_pids(void);
|
||||
|
||||
RC_SERVICE lookup_service_state(const char *service);
|
||||
void from_time_t(char *time_string, time_t tv);
|
||||
time_t to_time_t(char *timestring);
|
||||
|
||||
@@ -883,7 +883,7 @@ eindent(void)
|
||||
{
|
||||
char *env = getenv("EINFO_INDENT");
|
||||
int amount = 0;
|
||||
char *num;
|
||||
char num[10];
|
||||
|
||||
if (env) {
|
||||
errno = 0;
|
||||
@@ -894,9 +894,8 @@ eindent(void)
|
||||
amount += INDENT_WIDTH;
|
||||
if (amount > INDENT_MAX)
|
||||
amount = INDENT_MAX;
|
||||
xasprintf(&num, "%08d", amount);
|
||||
snprintf(num, 10, "%08d", amount);
|
||||
setenv("EINFO_INDENT", num, 1);
|
||||
free(num);
|
||||
}
|
||||
hidden_def(eindent)
|
||||
|
||||
@@ -904,7 +903,7 @@ void eoutdent(void)
|
||||
{
|
||||
char *env = getenv("EINFO_INDENT");
|
||||
int amount = 0;
|
||||
char *num = NULL;
|
||||
char num[10];
|
||||
int serrno = errno;
|
||||
|
||||
if (!env)
|
||||
@@ -918,9 +917,8 @@ void eoutdent(void)
|
||||
if (amount <= 0)
|
||||
unsetenv("EINFO_INDENT");
|
||||
else {
|
||||
xasprintf(&num, "%08d", amount);
|
||||
snprintf(num, 10, "%08d", amount);
|
||||
setenv("EINFO_INDENT", num, 1);
|
||||
free(num);
|
||||
}
|
||||
errno = serrno;
|
||||
}
|
||||
|
||||
@@ -23,13 +23,13 @@
|
||||
static bool
|
||||
pid_is_exec(pid_t pid, const char *exec)
|
||||
{
|
||||
char *buffer = NULL;
|
||||
char buffer[32];
|
||||
FILE *fp;
|
||||
int c;
|
||||
bool retval = false;
|
||||
|
||||
exec = basename_c(exec);
|
||||
xasprintf(&buffer, "/proc/%d/stat", pid);
|
||||
snprintf(buffer, sizeof(buffer), "/proc/%d/stat", pid);
|
||||
if ((fp = fopen(buffer, "r"))) {
|
||||
while ((c = getc(fp)) != EOF && c != '(')
|
||||
;
|
||||
@@ -41,27 +41,23 @@ pid_is_exec(pid_t pid, const char *exec)
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
free(buffer);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static bool
|
||||
pid_is_argv(pid_t pid, const char *const *argv)
|
||||
{
|
||||
char *cmdline = NULL;
|
||||
char cmdline[32];
|
||||
int fd;
|
||||
char buffer[PATH_MAX];
|
||||
char *p;
|
||||
ssize_t bytes;
|
||||
|
||||
xasprintf(&cmdline, "/proc/%u/cmdline", pid);
|
||||
if ((fd = open(cmdline, O_RDONLY)) < 0) {
|
||||
free(cmdline);
|
||||
snprintf(cmdline, sizeof(cmdline), "/proc/%u/cmdline", pid);
|
||||
if ((fd = open(cmdline, O_RDONLY)) < 0)
|
||||
return false;
|
||||
}
|
||||
bytes = read(fd, buffer, sizeof(buffer));
|
||||
close(fd);
|
||||
free(cmdline);
|
||||
if (bytes == -1)
|
||||
return false;
|
||||
|
||||
@@ -92,7 +88,7 @@ rc_find_pids(const char *exec, const char *const *argv, uid_t uid, pid_t pid)
|
||||
char proc_ns[30];
|
||||
size_t len = 0;
|
||||
pid_t p;
|
||||
char *buffer = NULL;
|
||||
char buffer[PATH_MAX];
|
||||
struct stat sb;
|
||||
pid_t openrc_pid = 0;
|
||||
char *pp;
|
||||
@@ -153,22 +149,18 @@ rc_find_pids(const char *exec, const char *const *argv, uid_t uid, pid_t pid)
|
||||
continue;
|
||||
if (pid != 0 && pid != p)
|
||||
continue;
|
||||
xasprintf(&buffer, "/proc/%d/ns/pid", p);
|
||||
snprintf(buffer, sizeof(buffer), "/proc/%d/ns/pid", p);
|
||||
if (exists(buffer)) {
|
||||
rc = readlink(buffer, proc_ns, sizeof(proc_ns));
|
||||
if (rc <= 0)
|
||||
proc_ns[0] = '\0';
|
||||
}
|
||||
free(buffer);
|
||||
if (strlen(my_ns) && strlen (proc_ns) && strcmp(my_ns, proc_ns))
|
||||
continue;
|
||||
if (uid) {
|
||||
xasprintf(&buffer, "/proc/%d", p);
|
||||
if (stat(buffer, &sb) != 0 || sb.st_uid != uid) {
|
||||
free(buffer);
|
||||
snprintf(buffer, sizeof(buffer), "/proc/%d", p);
|
||||
if (stat(buffer, &sb) != 0 || sb.st_uid != uid)
|
||||
continue;
|
||||
}
|
||||
free(buffer);
|
||||
}
|
||||
if (exec && !pid_is_exec(p, exec))
|
||||
continue;
|
||||
@@ -177,10 +169,9 @@ rc_find_pids(const char *exec, const char *const *argv, uid_t uid, pid_t pid)
|
||||
continue;
|
||||
/* If this is an OpenVZ host, filter out container processes */
|
||||
if (openvz_host) {
|
||||
xasprintf(&buffer, "/proc/%d/status", p);
|
||||
snprintf(buffer, sizeof(buffer), "/proc/%d/status", p);
|
||||
if (exists(buffer)) {
|
||||
fp = fopen(buffer, "r");
|
||||
free(buffer);
|
||||
if (! fp)
|
||||
continue;
|
||||
while (! feof(fp)) {
|
||||
@@ -324,13 +315,12 @@ _match_daemon(const char *path, const char *file, RC_STRINGLIST *match)
|
||||
{
|
||||
char *line = NULL;
|
||||
size_t len = 0;
|
||||
char *ffile = NULL;
|
||||
char ffile[PATH_MAX];
|
||||
FILE *fp;
|
||||
RC_STRING *m;
|
||||
|
||||
xasprintf(&ffile, "%s/%s", path, file);
|
||||
snprintf(ffile, sizeof(ffile), "%s/%s", path, file);
|
||||
fp = fopen(ffile, "r");
|
||||
free(ffile);
|
||||
|
||||
if (!fp)
|
||||
return false;
|
||||
@@ -356,22 +346,29 @@ _match_list(const char *exec, const char *const *argv, const char *pidfile)
|
||||
{
|
||||
RC_STRINGLIST *match = rc_stringlist_new();
|
||||
int i = 0;
|
||||
size_t l;
|
||||
char *m;
|
||||
|
||||
if (exec) {
|
||||
xasprintf(&m, "exec=%s", exec);
|
||||
l = strlen(exec) + 6;
|
||||
m = xmalloc(sizeof(char) * l);
|
||||
snprintf(m, l, "exec=%s", exec);
|
||||
rc_stringlist_add(match, m);
|
||||
free(m);
|
||||
}
|
||||
|
||||
while (argv && argv[i]) {
|
||||
xasprintf(&m, "argv_0=%s", argv[i++]);
|
||||
l = strlen(*argv) + strlen("argv_=") + 16;
|
||||
m = xmalloc(sizeof(char) * l);
|
||||
snprintf(m, l, "argv_0=%s", argv[i++]);
|
||||
rc_stringlist_add(match, m);
|
||||
free(m);
|
||||
}
|
||||
|
||||
if (pidfile) {
|
||||
xasprintf(&m, "pidfile=%s", pidfile);
|
||||
l = strlen(pidfile) + 9;
|
||||
m = xmalloc(sizeof(char) * l);
|
||||
snprintf(m, l, "pidfile=%s", pidfile);
|
||||
rc_stringlist_add(match, m);
|
||||
free(m);
|
||||
}
|
||||
@@ -384,8 +381,8 @@ rc_service_daemon_set(const char *service, const char *exec,
|
||||
const char *const *argv,
|
||||
const char *pidfile, bool started)
|
||||
{
|
||||
char *dirpath = NULL;
|
||||
char *file = NULL;
|
||||
char dirpath[PATH_MAX];
|
||||
char file[PATH_MAX];
|
||||
int nfiles = 0;
|
||||
char oldfile[PATH_MAX] = { '\0' };
|
||||
bool retval = false;
|
||||
@@ -400,7 +397,8 @@ rc_service_daemon_set(const char *service, const char *exec,
|
||||
return false;
|
||||
}
|
||||
|
||||
xasprintf(&dirpath, RC_SVCDIR "/daemons/%s", basename_c(service));
|
||||
snprintf(dirpath, sizeof(dirpath), RC_SVCDIR "/daemons/%s",
|
||||
basename_c(service));
|
||||
|
||||
/* Regardless, erase any existing daemon info */
|
||||
if ((dp = opendir(dirpath))) {
|
||||
@@ -409,7 +407,8 @@ rc_service_daemon_set(const char *service, const char *exec,
|
||||
if (d->d_name[0] == '.')
|
||||
continue;
|
||||
|
||||
xasprintf(&file, "%s/%s", dirpath, d->d_name);
|
||||
snprintf(file, sizeof(file), "%s/%s",
|
||||
dirpath, d->d_name);
|
||||
nfiles++;
|
||||
|
||||
if (!*oldfile) {
|
||||
@@ -422,7 +421,6 @@ rc_service_daemon_set(const char *service, const char *exec,
|
||||
rename(file, oldfile);
|
||||
strlcpy(oldfile, file, sizeof(oldfile));
|
||||
}
|
||||
free(file);
|
||||
}
|
||||
closedir(dp);
|
||||
rc_stringlist_free(match);
|
||||
@@ -431,7 +429,8 @@ rc_service_daemon_set(const char *service, const char *exec,
|
||||
/* Now store our daemon info */
|
||||
if (started) {
|
||||
if (mkdir(dirpath, 0755) == 0 || errno == EEXIST) {
|
||||
xasprintf(&file, "%s/%03d", dirpath, nfiles + 1);
|
||||
snprintf(file, sizeof(file), "%s/%03d",
|
||||
dirpath, nfiles + 1);
|
||||
if ((fp = fopen(file, "w"))) {
|
||||
fprintf(fp, "exec=");
|
||||
if (exec)
|
||||
@@ -447,12 +446,10 @@ rc_service_daemon_set(const char *service, const char *exec,
|
||||
fclose(fp);
|
||||
retval = true;
|
||||
}
|
||||
free(file);
|
||||
}
|
||||
} else
|
||||
retval = true;
|
||||
|
||||
free(dirpath);
|
||||
return retval;
|
||||
}
|
||||
librc_hidden_def(rc_service_daemon_set)
|
||||
@@ -461,8 +458,8 @@ bool
|
||||
rc_service_started_daemon(const char *service,
|
||||
const char *exec, const char *const *argv, int indx)
|
||||
{
|
||||
char *dirpath = NULL;
|
||||
char *file = NULL;
|
||||
char dirpath[PATH_MAX];
|
||||
char file[16];
|
||||
RC_STRINGLIST *match;
|
||||
bool retval = false;
|
||||
DIR *dp;
|
||||
@@ -471,13 +468,13 @@ rc_service_started_daemon(const char *service,
|
||||
if (!service || !exec)
|
||||
return false;
|
||||
|
||||
xasprintf(&dirpath, RC_SVCDIR "/daemons/%s", basename_c(service));
|
||||
snprintf(dirpath, sizeof(dirpath), RC_SVCDIR "/daemons/%s",
|
||||
basename_c(service));
|
||||
match = _match_list(exec, argv, NULL);
|
||||
|
||||
if (indx > 0) {
|
||||
xasprintf(&file, "%03d", indx);
|
||||
snprintf(file, sizeof(file), "%03d", indx);
|
||||
retval = _match_daemon(dirpath, file, match);
|
||||
free(file);
|
||||
} else {
|
||||
if ((dp = opendir(dirpath))) {
|
||||
while ((d = readdir(dp))) {
|
||||
@@ -492,7 +489,6 @@ rc_service_started_daemon(const char *service,
|
||||
}
|
||||
|
||||
rc_stringlist_free(match);
|
||||
free(dirpath);
|
||||
return retval;
|
||||
}
|
||||
librc_hidden_def(rc_service_started_daemon)
|
||||
|
||||
@@ -237,9 +237,13 @@ static void rc_config_set_value(RC_STRINGLIST *config, char *value)
|
||||
if (token[i] == '\n')
|
||||
token[i] = 0;
|
||||
|
||||
xasprintf(&newline, "%s=%s", entry, token);
|
||||
i = strlen(entry) + strlen(token) + 2;
|
||||
newline = xmalloc(sizeof(char) * i);
|
||||
snprintf(newline, i, "%s=%s", entry, token);
|
||||
} else {
|
||||
xasprintf(&newline, "%s=", entry);
|
||||
i = strlen(entry) + 2;
|
||||
newline = xmalloc(sizeof(char) * i);
|
||||
snprintf(newline, i, "%s=", entry);
|
||||
}
|
||||
|
||||
replaced = false;
|
||||
@@ -296,7 +300,8 @@ static RC_STRINGLIST *rc_config_kcl(RC_STRINGLIST *config)
|
||||
|
||||
if (value != NULL) {
|
||||
len = varlen + strlen(value) + 2;
|
||||
xasprintf(&tmp, "%s=%s", override->value, value);
|
||||
tmp = xmalloc(sizeof(char) * len);
|
||||
snprintf(tmp, len, "%s=%s", override->value, value);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -50,7 +50,6 @@ static const rc_service_state_name_t rc_service_state_names[] = {
|
||||
{ RC_SERVICE_HOTPLUGGED, "hotplugged" },
|
||||
{ RC_SERVICE_FAILED, "failed" },
|
||||
{ RC_SERVICE_SCHEDULED, "scheduled"},
|
||||
{ RC_SERVICE_CRASHED, "crashed"},
|
||||
{ 0, NULL}
|
||||
};
|
||||
|
||||
@@ -849,10 +848,6 @@ rc_service_state(const char *service)
|
||||
}
|
||||
}
|
||||
|
||||
if (state & RC_SERVICE_STARTED) {
|
||||
if (rc_service_daemons_crashed(service) && errno != EACCES)
|
||||
state |= RC_SERVICE_CRASHED;
|
||||
}
|
||||
if (state & RC_SERVICE_STOPPED) {
|
||||
dirs = ls_dir(RC_SVCDIR "/scheduled", 0);
|
||||
TAILQ_FOREACH(dir, dirs, entries) {
|
||||
|
||||
@@ -188,8 +188,7 @@ typedef enum
|
||||
/* Optional states service could also be in */
|
||||
RC_SERVICE_FAILED = 0x0200,
|
||||
RC_SERVICE_SCHEDULED = 0x0400,
|
||||
RC_SERVICE_WASINACTIVE = 0x0800,
|
||||
RC_SERVICE_CRASHED = 0x1000,
|
||||
RC_SERVICE_WASINACTIVE = 0x0800
|
||||
} RC_SERVICE;
|
||||
|
||||
/*! Add the service to the runlevel
|
||||
|
||||
1
src/rc/.gitignore
vendored
1
src/rc/.gitignore
vendored
@@ -56,7 +56,6 @@ mark_service_inactive
|
||||
mark_service_wasinactive
|
||||
mark_service_hotplugged
|
||||
mark_service_failed
|
||||
mark_service_crashed
|
||||
rc-abort
|
||||
rc
|
||||
openrc
|
||||
|
||||
@@ -5,8 +5,8 @@ include ${MK}/os.mk
|
||||
SRCS= checkpath.c do_e.c do_mark_service.c do_service.c \
|
||||
do_value.c fstabinfo.c is_newer_than.c is_older_than.c \
|
||||
mountinfo.c openrc-run.c rc-abort.c rc.c \
|
||||
rc-depend.c rc-logger.c rc-misc.c rc-pipes.c \
|
||||
rc-plugin.c rc-service.c rc-status.c rc-update.c \
|
||||
rc-depend.c rc-logger.c rc-misc.c rc-plugin.c \
|
||||
rc-service.c rc-status.c rc-update.c \
|
||||
shell_var.c start-stop-daemon.c supervise-daemon.c swclock.c _usage.c
|
||||
|
||||
ifeq (${MKSELINUX},yes)
|
||||
@@ -14,7 +14,7 @@ SRCS+= rc-selinux.c
|
||||
endif
|
||||
|
||||
ifeq (${OS},Linux)
|
||||
SRCS+= kill_all.c openrc-init.c openrc-shutdown.c broadcast.c rc-wtmp.c
|
||||
SRCS+= kill_all.c openrc-init.c openrc-shutdown.c rc-wtmp.c
|
||||
endif
|
||||
|
||||
CLEANFILES= version.h rc-selinux.o
|
||||
@@ -41,7 +41,6 @@ RC_SBINPROGS= mark_service_starting mark_service_started \
|
||||
mark_service_stopping mark_service_stopped \
|
||||
mark_service_inactive mark_service_wasinactive \
|
||||
mark_service_hotplugged mark_service_failed \
|
||||
mark_service_crashed \
|
||||
rc-abort swclock
|
||||
|
||||
ifeq (${OS},Linux)
|
||||
@@ -124,8 +123,7 @@ is_older_than: is_older_than.o rc-misc.o
|
||||
mark_service_starting mark_service_started \
|
||||
mark_service_stopping mark_service_stopped \
|
||||
mark_service_inactive mark_service_wasinactive \
|
||||
mark_service_hotplugged mark_service_failed \
|
||||
mark_service_crashed: do_mark_service.o rc-misc.o
|
||||
mark_service_hotplugged mark_service_failed: do_mark_service.o rc-misc.o
|
||||
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
|
||||
|
||||
mountinfo: mountinfo.o _usage.o rc-misc.o
|
||||
@@ -134,7 +132,7 @@ mountinfo: mountinfo.o _usage.o rc-misc.o
|
||||
openrc rc: rc.o rc-logger.o rc-misc.o rc-plugin.o _usage.o
|
||||
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
|
||||
|
||||
openrc-shutdown: openrc-shutdown.o rc-misc.o _usage.o broadcast.o rc-wtmp.o
|
||||
openrc-shutdown: openrc-shutdown.o _usage.o rc-wtmp.o
|
||||
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
|
||||
|
||||
openrc-run runscript: openrc-run.o _usage.o rc-misc.o rc-plugin.o
|
||||
@@ -158,10 +156,10 @@ rc-service: rc-service.o _usage.o rc-misc.o
|
||||
rc-update: rc-update.o _usage.o rc-misc.o
|
||||
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
|
||||
|
||||
start-stop-daemon: start-stop-daemon.o _usage.o rc-misc.o rc-pipes.o rc-schedules.o
|
||||
start-stop-daemon: start-stop-daemon.o _usage.o rc-misc.o rc-schedules.o
|
||||
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
|
||||
|
||||
supervise-daemon: supervise-daemon.o _usage.o rc-misc.o rc-plugin.o rc-schedules.o
|
||||
supervise-daemon: supervise-daemon.o _usage.o rc-misc.o rc-schedules.o
|
||||
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
|
||||
|
||||
service_get_value service_set_value get_options save_options: do_value.o rc-misc.o
|
||||
|
||||
@@ -1,209 +0,0 @@
|
||||
/*
|
||||
* broadcast.c
|
||||
* broadcast a message to every logged in user
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2018 Sony Interactive Entertainment Inc.
|
||||
*
|
||||
* This file is part of OpenRC. It is subject to the license terms in
|
||||
* the LICENSE file found in the top-level directory of this
|
||||
* distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
|
||||
* This file may not be copied, modified, propagated, or distributed
|
||||
* except according to the terms contained in the LICENSE file.
|
||||
*/
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/sysmacros.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <utmpx.h>
|
||||
#include <pwd.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <setjmp.h>
|
||||
#include <paths.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#include "broadcast.h"
|
||||
#include "helpers.h"
|
||||
|
||||
#ifndef _PATH_DEV
|
||||
# define _PATH_DEV "/dev/"
|
||||
#endif
|
||||
|
||||
#ifndef UT_LINESIZE
|
||||
#define UT_LINESIZE __UT_LINESIZE
|
||||
#endif
|
||||
|
||||
static sigjmp_buf jbuf;
|
||||
|
||||
/*
|
||||
* Alarm handler
|
||||
*/
|
||||
/*ARGSUSED*/
|
||||
# ifdef __GNUC__
|
||||
static void handler(int arg __attribute__((unused)))
|
||||
# else
|
||||
static void handler(int arg)
|
||||
# endif
|
||||
{
|
||||
siglongjmp(jbuf, 1);
|
||||
}
|
||||
|
||||
static void getuidtty(char **userp, char **ttyp)
|
||||
{
|
||||
struct passwd *pwd;
|
||||
uid_t uid;
|
||||
char *tty;
|
||||
static char uidbuf[32];
|
||||
static char ttynm[UT_LINESIZE + 4];
|
||||
|
||||
uid = getuid();
|
||||
if ((pwd = getpwuid(uid)) != NULL) {
|
||||
uidbuf[0] = 0;
|
||||
strncat(uidbuf, pwd->pw_name, sizeof(uidbuf) - 1);
|
||||
} else {
|
||||
if (uid)
|
||||
sprintf(uidbuf, "uid %d", (int) uid);
|
||||
else
|
||||
sprintf(uidbuf, "root");
|
||||
}
|
||||
|
||||
if ((tty = ttyname(0)) != NULL) {
|
||||
const size_t plen = strlen(_PATH_DEV);
|
||||
if (strncmp(tty, _PATH_DEV, plen) == 0) {
|
||||
tty += plen;
|
||||
if (tty[0] == '/')
|
||||
tty++;
|
||||
}
|
||||
snprintf(ttynm, sizeof(ttynm), "(%.*s) ",
|
||||
UT_LINESIZE, tty);
|
||||
} else
|
||||
ttynm[0] = 0;
|
||||
|
||||
*userp = uidbuf;
|
||||
*ttyp = ttynm;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether the given filename looks like a tty device.
|
||||
*/
|
||||
static int file_isatty(const char *fname)
|
||||
{
|
||||
struct stat st;
|
||||
int major;
|
||||
|
||||
if (stat(fname, &st) < 0)
|
||||
return 0;
|
||||
|
||||
if (st.st_nlink != 1 || !S_ISCHR(st.st_mode))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* It would be an impossible task to list all major/minors
|
||||
* of tty devices here, so we just exclude the obvious
|
||||
* majors of which just opening has side-effects:
|
||||
* printers and tapes.
|
||||
*/
|
||||
major = major(st.st_dev);
|
||||
if (major == 1 || major == 2 || major == 6 || major == 9 ||
|
||||
major == 12 || major == 16 || major == 21 || major == 27 ||
|
||||
major == 37 || major == 96 || major == 97 || major == 206 ||
|
||||
major == 230)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* broadcast function.
|
||||
*/
|
||||
void broadcast(char *text)
|
||||
{
|
||||
char *tty;
|
||||
char *user;
|
||||
struct utsname name;
|
||||
time_t t;
|
||||
char *date;
|
||||
char *p;
|
||||
char *line = NULL;
|
||||
struct sigaction sa;
|
||||
int fd;
|
||||
FILE *tp;
|
||||
int flags;
|
||||
char *term = NULL;
|
||||
struct utmpx *utmp;
|
||||
|
||||
getuidtty(&user, &tty);
|
||||
|
||||
/*
|
||||
* Get and report current hostname, to make it easier to find out
|
||||
* which machine is being shut down.
|
||||
*/
|
||||
uname(&name);
|
||||
|
||||
/* Get the time */
|
||||
time(&t);
|
||||
date = ctime(&t);
|
||||
p = strchr(date, '\n');
|
||||
if (p)
|
||||
*p = 0;
|
||||
|
||||
xasprintf(&line, "\007\r\nBroadcast message from %s@%s %s(%s):\r\n\r\n",
|
||||
user, name.nodename, tty, date);
|
||||
|
||||
/*
|
||||
* Fork to avoid hanging in a write()
|
||||
*/
|
||||
if (fork() != 0)
|
||||
return;
|
||||
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sa_handler = handler;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sigaction(SIGALRM, &sa, NULL);
|
||||
|
||||
setutxent();
|
||||
|
||||
while ((utmp = getutxent()) != NULL) {
|
||||
if (utmp->ut_type != USER_PROCESS || utmp->ut_user[0] == 0)
|
||||
continue;
|
||||
if (strncmp(utmp->ut_line, _PATH_DEV, strlen(_PATH_DEV)) == 0)
|
||||
xasprintf(&term, "%s", utmp->ut_line);
|
||||
else
|
||||
xasprintf(&term, "%s%s", _PATH_DEV, utmp->ut_line);
|
||||
if (strstr(term, "/../")) {
|
||||
free(term);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Open it non-delay
|
||||
*/
|
||||
if (sigsetjmp(jbuf, 1) == 0) {
|
||||
alarm(2);
|
||||
flags = O_WRONLY|O_NDELAY|O_NOCTTY;
|
||||
if (file_isatty(term) && (fd = open(term, flags)) >= 0) {
|
||||
if (isatty(fd) && (tp = fdopen(fd, "w")) != NULL) {
|
||||
fputs(line, tp);
|
||||
fputs(text, tp);
|
||||
fflush(tp);
|
||||
}
|
||||
}
|
||||
}
|
||||
alarm(0);
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
if (tp != NULL)
|
||||
fclose(tp);
|
||||
free(term);
|
||||
}
|
||||
endutxent();
|
||||
free(line);
|
||||
exit(0);
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 Sony Interactive Entertainment Inc.
|
||||
*
|
||||
* This file is part of OpenRC. It is subject to the license terms in
|
||||
* the LICENSE file found in the top-level directory of this
|
||||
* distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
|
||||
* This file may not be copied, modified, propagated, or distributed
|
||||
* except according to the terms contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef BROADCAST_H
|
||||
#define BROADCAST_H
|
||||
|
||||
void broadcast(char *text);
|
||||
|
||||
#endif
|
||||
@@ -269,13 +269,11 @@ int main(int argc, char **argv)
|
||||
switch (opt) {
|
||||
case 'D':
|
||||
trunc = true;
|
||||
/* falls through */
|
||||
case 'd':
|
||||
type = inode_dir;
|
||||
break;
|
||||
case 'F':
|
||||
trunc = true;
|
||||
/* falls through */
|
||||
case 'f':
|
||||
type = inode_file;
|
||||
break;
|
||||
|
||||
@@ -68,7 +68,9 @@ int main(int argc, char **argv)
|
||||
ok = rc_service_started_daemon(service, exec, NULL, idx);
|
||||
|
||||
} else if (strcmp(applet, "service_crashed") == 0) {
|
||||
ok = ( rc_service_daemons_crashed(service) && errno != EACCES);
|
||||
ok = (_rc_can_find_pids() &&
|
||||
rc_service_daemons_crashed(service) &&
|
||||
errno != EACCES);
|
||||
} else
|
||||
eerrorx("%s: unknown applet", applet);
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ static int mount_proc(void)
|
||||
if (exists("/proc/version"))
|
||||
return 0;
|
||||
pid = fork();
|
||||
switch (pid) {
|
||||
switch(pid) {
|
||||
case -1:
|
||||
syslog(LOG_ERR, "Unable to fork");
|
||||
return -1;
|
||||
@@ -248,7 +248,7 @@ int main(int argc, char **argv)
|
||||
usage(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
openlog(applet, LOG_CONS|LOG_PID, LOG_DAEMON);
|
||||
if (mount_proc() != 0) {
|
||||
rc_stringlist_free(omits);
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
@@ -45,7 +44,7 @@ static pid_t do_openrc(const char *runlevel)
|
||||
sigset_t signals;
|
||||
|
||||
pid = fork();
|
||||
switch (pid) {
|
||||
switch(pid) {
|
||||
case -1:
|
||||
perror("fork");
|
||||
break;
|
||||
@@ -97,15 +96,12 @@ static void handle_reexec(char *my_name)
|
||||
static void handle_shutdown(const char *runlevel, int cmd)
|
||||
{
|
||||
pid_t pid;
|
||||
struct timespec ts;
|
||||
|
||||
pid = do_openrc(runlevel);
|
||||
while (waitpid(pid, NULL, 0) != pid);
|
||||
printf("Sending the final term signal\n");
|
||||
kill(-1, SIGTERM);
|
||||
ts.tv_sec = 3;
|
||||
ts.tv_nsec = 0;
|
||||
nanosleep(&ts, NULL);
|
||||
sleep(3);
|
||||
printf("Sending the final kill signal\n");
|
||||
kill(-1, SIGKILL);
|
||||
sync();
|
||||
@@ -139,7 +135,7 @@ static void reap_zombies(void)
|
||||
|
||||
static void signal_handler(int sig)
|
||||
{
|
||||
switch (sig) {
|
||||
switch(sig) {
|
||||
case SIGINT:
|
||||
handle_shutdown("reboot", RB_AUTOBOOT);
|
||||
break;
|
||||
|
||||
@@ -1268,9 +1268,6 @@ int main(int argc, char **argv)
|
||||
case_RC_COMMON_GETOPT
|
||||
}
|
||||
|
||||
if (rc_yesno(getenv("RC_NODEPS")))
|
||||
deps = false;
|
||||
|
||||
/* If we're changing runlevels and not called by rc then we cannot
|
||||
work with any dependencies */
|
||||
if (deps && getenv("RC_PID") == NULL &&
|
||||
@@ -1285,8 +1282,6 @@ int main(int argc, char **argv)
|
||||
unsetenv("IN_BACKGROUND");
|
||||
}
|
||||
|
||||
if (rc_yesno(getenv("IN_DRYRUN")))
|
||||
dry_run = true;
|
||||
if (rc_yesno(getenv("IN_HOTPLUG"))) {
|
||||
if (!service_plugable())
|
||||
eerrorx("%s: not allowed to be hotplugged", applet);
|
||||
|
||||
@@ -25,24 +25,20 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#include "broadcast.h"
|
||||
#include "einfo.h"
|
||||
#include "rc.h"
|
||||
#include "helpers.h"
|
||||
#include "rc-misc.h"
|
||||
#include "_usage.h"
|
||||
#include "rc-wtmp.h"
|
||||
|
||||
const char *applet = NULL;
|
||||
const char *extraopts = NULL;
|
||||
const char *getoptstring = "cdDfFHKpRrsw" getoptstring_COMMON;
|
||||
const char *getoptstring = "dDHKpRrsw" getoptstring_COMMON;
|
||||
const struct option longopts[] = {
|
||||
{ "cancel", no_argument, NULL, 'c'},
|
||||
{ "no-write", no_argument, NULL, 'd'},
|
||||
{ "dry-run", no_argument, NULL, 'D'},
|
||||
{ "halt", no_argument, NULL, 'H'},
|
||||
@@ -55,7 +51,6 @@ const struct option longopts[] = {
|
||||
longopts_COMMON
|
||||
};
|
||||
const char * const longopts_help[] = {
|
||||
"cancel a pending shutdown",
|
||||
"do not write wtmp record",
|
||||
"print actions instead of executing them",
|
||||
"halt the system",
|
||||
@@ -69,12 +64,8 @@ const char * const longopts_help[] = {
|
||||
};
|
||||
const char *usagestring = NULL;
|
||||
const char *exclusive = "Select one of "
|
||||
"--cancel, --halt, --kexec, --poweroff, --reexec, --reboot, --single or \n"
|
||||
"--write-only";
|
||||
const char *nologin_file = RC_SYSCONFDIR"/nologin";
|
||||
const char *shutdown_pid = "/run/openrc-shutdown.pid";
|
||||
"--halt, --kexec, --poweroff, --reexec, --reboot, --single or --write-only";
|
||||
|
||||
static bool do_cancel = false;
|
||||
static bool do_dryrun = false;
|
||||
static bool do_halt = false;
|
||||
static bool do_kexec = false;
|
||||
@@ -85,40 +76,6 @@ static bool do_single = false;
|
||||
static bool do_wtmp = true;
|
||||
static bool do_wtmp_only = false;
|
||||
|
||||
static void cancel_shutdown(void)
|
||||
{
|
||||
pid_t pid;
|
||||
|
||||
pid = get_pid(applet, shutdown_pid);
|
||||
if (pid <= 0)
|
||||
eerrorx("%s: Unable to cancel shutdown", applet);
|
||||
|
||||
if (kill(pid, SIGTERM) != -1)
|
||||
einfo("%s: shutdown canceled", applet);
|
||||
else
|
||||
eerrorx("%s: Unable to cancel shutdown", applet);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the nologin file.
|
||||
*/
|
||||
static void create_nologin(int mins)
|
||||
{
|
||||
FILE *fp;
|
||||
time_t t;
|
||||
|
||||
time(&t);
|
||||
t += 60 * mins;
|
||||
|
||||
if ((fp = fopen(nologin_file, "w")) != NULL) {
|
||||
fprintf(fp, "\rThe system is going down on %s\r\n", ctime(&t));
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a command to our init
|
||||
*/
|
||||
static void send_cmd(const char *cmd)
|
||||
{
|
||||
FILE *fifo;
|
||||
@@ -142,59 +99,16 @@ static void send_cmd(const char *cmd)
|
||||
fclose(fifo);
|
||||
}
|
||||
|
||||
/*
|
||||
* sleep without being interrupted.
|
||||
* The idea for this code came from sysvinit.
|
||||
*/
|
||||
static void sleep_no_interrupt(int seconds)
|
||||
{
|
||||
struct timespec duration;
|
||||
struct timespec remaining;
|
||||
|
||||
duration.tv_sec = seconds;
|
||||
duration.tv_nsec = 0;
|
||||
|
||||
while(nanosleep(&duration, &remaining) < 0 && errno == EINTR)
|
||||
duration = remaining;
|
||||
}
|
||||
|
||||
static void stop_shutdown(int sig)
|
||||
{
|
||||
/* use the sig parameter so the compiler will not complain */
|
||||
if (sig == SIGINT)
|
||||
;
|
||||
unlink(nologin_file);
|
||||
unlink(shutdown_pid);
|
||||
einfo("Shutdown canceled");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char *ch = NULL;
|
||||
int opt;
|
||||
int cmd_count = 0;
|
||||
int hour = 0;
|
||||
int min = 0;
|
||||
int shutdown_delay = 0;
|
||||
struct sigaction sa;
|
||||
struct tm *lt;
|
||||
time_t tv;
|
||||
bool need_warning = false;
|
||||
char *msg = NULL;
|
||||
char *state = NULL;
|
||||
char *time_arg = NULL;
|
||||
FILE *fp;
|
||||
|
||||
applet = basename_c(argv[0]);
|
||||
while ((opt = getopt_long(argc, argv, getoptstring,
|
||||
longopts, (int *) 0)) != -1)
|
||||
{
|
||||
switch (opt) {
|
||||
case 'c':
|
||||
do_cancel = true;
|
||||
cmd_count++;
|
||||
break;
|
||||
case 'd':
|
||||
do_wtmp = false;
|
||||
break;
|
||||
@@ -203,17 +117,14 @@ int main(int argc, char **argv)
|
||||
break;
|
||||
case 'H':
|
||||
do_halt = true;
|
||||
xasprintf(&state, "%s", "halt");
|
||||
cmd_count++;
|
||||
break;
|
||||
case 'K':
|
||||
do_kexec = true;
|
||||
xasprintf(&state, "%s", "reboot");
|
||||
cmd_count++;
|
||||
break;
|
||||
case 'p':
|
||||
do_poweroff = true;
|
||||
xasprintf(&state, "%s", "power off");
|
||||
cmd_count++;
|
||||
break;
|
||||
case 'R':
|
||||
@@ -222,12 +133,10 @@ int main(int argc, char **argv)
|
||||
break;
|
||||
case 'r':
|
||||
do_reboot = true;
|
||||
xasprintf(&state, "%s", "reboot");
|
||||
cmd_count++;
|
||||
break;
|
||||
case 's':
|
||||
do_single = true;
|
||||
xasprintf(&state, "%s", "go down for maintenance");
|
||||
cmd_count++;
|
||||
break;
|
||||
case 'w':
|
||||
@@ -237,88 +146,12 @@ int main(int argc, char **argv)
|
||||
case_RC_COMMON_GETOPT
|
||||
}
|
||||
}
|
||||
if (geteuid() != 0)
|
||||
if (geteuid() != 0 && ! do_dryrun)
|
||||
eerrorx("%s: you must be root\n", applet);
|
||||
if (cmd_count != 1) {
|
||||
eerror("%s: %s\n", applet, exclusive);
|
||||
usage(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (do_cancel) {
|
||||
cancel_shutdown();
|
||||
exit(EXIT_SUCCESS);
|
||||
} else if (do_reexec) {
|
||||
send_cmd("reexec");
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
if (optind >= argc) {
|
||||
eerror("%s: No shutdown time specified", applet);
|
||||
usage(EXIT_FAILURE);
|
||||
}
|
||||
time_arg = argv[optind];
|
||||
if (*time_arg == '+')
|
||||
time_arg++;
|
||||
if (strcasecmp(time_arg, "now") == 0)
|
||||
strcpy(time_arg, "0");
|
||||
for (ch=time_arg; *ch; ch++)
|
||||
if ((*ch < '0' || *ch > '9') && *ch != ':') {
|
||||
eerror("%s: invalid time %s", applet, time_arg);
|
||||
usage(EXIT_FAILURE);
|
||||
}
|
||||
if (strchr(time_arg, ':')) {
|
||||
if ((sscanf(time_arg, "%2d:%2d", &hour, &min) != 2) ||
|
||||
(hour > 23) || (min > 59)) {
|
||||
eerror("%s: invalid time %s", applet, time_arg);
|
||||
usage(EXIT_FAILURE);
|
||||
}
|
||||
time(&tv);
|
||||
lt = localtime(&tv);
|
||||
shutdown_delay = (hour * 60 + min) - (lt->tm_hour * 60 + lt->tm_min);
|
||||
if (shutdown_delay < 0)
|
||||
shutdown_delay += 1440;
|
||||
} else {
|
||||
shutdown_delay = atoi(time_arg);
|
||||
}
|
||||
|
||||
fp = fopen(shutdown_pid, "w");
|
||||
if (!fp)
|
||||
eerrorx("%s: fopen `%s': %s", applet, shutdown_pid, strerror(errno));
|
||||
fprintf(fp, "%d\n", getpid());
|
||||
fclose(fp);
|
||||
|
||||
openlog(applet, LOG_PID, LOG_DAEMON);
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sa_handler = stop_shutdown;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sigaction(SIGINT, &sa, NULL);
|
||||
sigaction(SIGTERM, &sa, NULL);
|
||||
while (shutdown_delay > 0) {
|
||||
need_warning = false;
|
||||
if (shutdown_delay > 180)
|
||||
need_warning = (shutdown_delay % 60 == 0);
|
||||
else if (shutdown_delay > 60)
|
||||
need_warning = (shutdown_delay % 30 == 0);
|
||||
else if (shutdown_delay > 10)
|
||||
need_warning = (shutdown_delay % 15 == 0);
|
||||
else
|
||||
need_warning = true;
|
||||
if (shutdown_delay <= 5)
|
||||
create_nologin(shutdown_delay);
|
||||
if (need_warning) {
|
||||
xasprintf(&msg, "\rThe system will %s in %d minutes\r\n",
|
||||
state, shutdown_delay);
|
||||
broadcast(msg);
|
||||
free(msg);
|
||||
}
|
||||
sleep_no_interrupt(60);
|
||||
shutdown_delay--;
|
||||
}
|
||||
xasprintf(&msg, "\rThe system will %s now\r\n", state);
|
||||
broadcast(msg);
|
||||
syslog(LOG_NOTICE, "The system will %s now", state);
|
||||
unlink(nologin_file);
|
||||
unlink(shutdown_pid);
|
||||
if (do_halt)
|
||||
send_cmd("halt");
|
||||
else if (do_kexec)
|
||||
@@ -327,9 +160,11 @@ int main(int argc, char **argv)
|
||||
send_cmd("poweroff");
|
||||
else if (do_reboot)
|
||||
send_cmd("reboot");
|
||||
else if (do_reexec)
|
||||
send_cmd("reexec");
|
||||
else if (do_wtmp_only)
|
||||
log_wtmp("shutdown", "~~", 0, RUN_LVL, "~~");
|
||||
else if (do_single)
|
||||
send_cmd("single");
|
||||
else if (do_wtmp_only)
|
||||
log_wtmp("shutdown", "~~", 0, RUN_LVL, "~~");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -87,8 +87,6 @@ write_log(int logfd, const char *buffer, size_t bytes)
|
||||
}
|
||||
|
||||
if (!in_escape) {
|
||||
if (!isprint((int) *p) && *p != '\n')
|
||||
goto cont;
|
||||
if (write(logfd, p++, 1) == -1)
|
||||
eerror("write: %s", strerror(errno));
|
||||
continue;
|
||||
|
||||
@@ -51,8 +51,7 @@ rc_conf_yesno(const char *setting)
|
||||
|
||||
static const char *const env_whitelist[] = {
|
||||
"EERROR_QUIET", "EINFO_QUIET",
|
||||
"IN_BACKGROUND", "IN_DRYRUN", "IN_HOTPLUG",
|
||||
"RC_DEBUG", "RC_NODEPS",
|
||||
"IN_BACKGROUND", "IN_HOTPLUG",
|
||||
"LANG", "LC_MESSAGES", "TERM",
|
||||
"EINFO_COLOR", "EINFO_VERBOSE",
|
||||
NULL
|
||||
@@ -411,6 +410,34 @@ RC_DEPTREE * _rc_deptree_load(int force, int *regen)
|
||||
return rc_deptree_load();
|
||||
}
|
||||
|
||||
bool _rc_can_find_pids(void)
|
||||
{
|
||||
RC_PIDLIST *pids;
|
||||
RC_PID *pid;
|
||||
RC_PID *pid2;
|
||||
bool retval = false;
|
||||
|
||||
if (geteuid() == 0)
|
||||
return true;
|
||||
|
||||
/* If we cannot see process 1, then we don't test to see if
|
||||
* services crashed or not */
|
||||
pids = rc_find_pids(NULL, NULL, 0, 1);
|
||||
if (pids) {
|
||||
pid = LIST_FIRST(pids);
|
||||
if (pid) {
|
||||
retval = true;
|
||||
while (pid) {
|
||||
pid2 = LIST_NEXT(pid, entries);
|
||||
free(pid);
|
||||
pid = pid2;
|
||||
}
|
||||
}
|
||||
free(pids);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
static const struct {
|
||||
const char * const name;
|
||||
RC_SERVICE bit;
|
||||
@@ -423,7 +450,6 @@ static const struct {
|
||||
{ "service_hotplugged", RC_SERVICE_HOTPLUGGED, },
|
||||
{ "service_wasinactive", RC_SERVICE_WASINACTIVE, },
|
||||
{ "service_failed", RC_SERVICE_FAILED, },
|
||||
{ "service_crashed", RC_SERVICE_CRASHED, },
|
||||
};
|
||||
|
||||
RC_SERVICE lookup_service_state(const char *service)
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* rc-pipes.c
|
||||
* Helper to handle spawning processes and connecting them to pipes.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2018 The OpenRC Authors.
|
||||
* See the Authors file at the top-level directory of this distribution and
|
||||
* https://github.com/OpenRC/openrc/blob/master/AUTHORS
|
||||
*
|
||||
* This file is part of OpenRC. It is subject to the license terms in
|
||||
* the LICENSE file found in the top-level directory of this
|
||||
* distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
|
||||
* This file may not be copied, modified, propagated, or distributed
|
||||
* except according to the terms contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "rc-pipes.h"
|
||||
|
||||
static const int pipe_read_end = 0;
|
||||
static const int pipe_write_end = 1;
|
||||
|
||||
/*
|
||||
* Starts a command with stdin redirected from a pipe
|
||||
* Returns the write end of the pipe or -1
|
||||
*/
|
||||
int rc_pipe_command(char *cmd)
|
||||
{
|
||||
int pfd[2];
|
||||
pid_t pid;
|
||||
|
||||
if (pipe(pfd) < 0)
|
||||
return -1;
|
||||
|
||||
pid = fork();
|
||||
if (pid > 0) {
|
||||
/* parent */
|
||||
close(pfd[pipe_read_end]);
|
||||
return pfd[pipe_write_end];
|
||||
} else if (pid == 0) {
|
||||
/* child */
|
||||
close(pfd[pipe_write_end]);
|
||||
if (pfd[pipe_read_end] != STDIN_FILENO) {
|
||||
if (dup2(pfd[pipe_read_end], STDIN_FILENO) < 0)
|
||||
exit(1);
|
||||
close(pfd[pipe_read_end]);
|
||||
}
|
||||
execl("/bin/sh", "sh", "-c", cmd, NULL);
|
||||
exit(1);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 The OpenRC Authors.
|
||||
* See the Authors file at the top-level directory of this distribution and
|
||||
* https://github.com/OpenRC/openrc/blob/master/AUTHORS
|
||||
*
|
||||
* This file is part of OpenRC. It is subject to the license terms in
|
||||
* the LICENSE file found in the top-level directory of this
|
||||
* distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
|
||||
* This file may not be copied, modified, propagated, or distributed
|
||||
* except according to the terms contained in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef RC_PIPES_H
|
||||
#define RC_PIPES_H
|
||||
|
||||
int rc_pipe_command(char *cmd);
|
||||
|
||||
#endif
|
||||
@@ -351,9 +351,8 @@ int run_stop_schedule(const char *applet,
|
||||
|
||||
tkilled += nkilled;
|
||||
break;
|
||||
case SC_FOREVER:
|
||||
case SC_TIMEOUT:
|
||||
if (item->type == SC_TIMEOUT && item->value < 1) {
|
||||
if (item->value < 1) {
|
||||
item = NULL;
|
||||
break;
|
||||
}
|
||||
@@ -361,7 +360,7 @@ int run_stop_schedule(const char *applet,
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = POLL_INTERVAL;
|
||||
|
||||
for (nsecs = 0; item->type == SC_FOREVER || nsecs < item->value; nsecs++) {
|
||||
for (nsecs = 0; nsecs < item->value; nsecs++) {
|
||||
for (nloops = 0;
|
||||
nloops < ONE_SECOND / POLL_INTERVAL;
|
||||
nloops++)
|
||||
|
||||
@@ -29,25 +29,18 @@
|
||||
|
||||
const char *applet = NULL;
|
||||
const char *extraopts = NULL;
|
||||
const char *getoptstring = "cdDe:ilr:INsSZ" getoptstring_COMMON;
|
||||
const char *getoptstring = "ce:ilr:IN" getoptstring_COMMON;
|
||||
const struct option longopts[] = {
|
||||
{ "debug", 0, NULL, 'd' },
|
||||
{ "nodeps", 0, NULL, 'D' },
|
||||
{ "exists", 1, NULL, 'e' },
|
||||
{ "ifcrashed", 0, NULL, 'c' },
|
||||
{ "ifexists", 0, NULL, 'i' },
|
||||
{ "ifinactive", 0, NULL, 'I' },
|
||||
{ "ifnotstarted", 0, NULL, 'N' },
|
||||
{ "ifstarted", 0, NULL, 's' },
|
||||
{ "ifstopped", 0, NULL, 'S' },
|
||||
{ "list", 0, NULL, 'l' },
|
||||
{ "resolve", 1, NULL, 'r' },
|
||||
{ "dry-run", 0, NULL, 'Z' },
|
||||
longopts_COMMON
|
||||
};
|
||||
const char * const longopts_help[] = {
|
||||
"set xtrace when running the command",
|
||||
"ignore dependencies",
|
||||
"tests if the service exists or not",
|
||||
"if the service is crashed then run the command",
|
||||
"if the service exists then run the command",
|
||||
@@ -55,7 +48,6 @@ const char * const longopts_help[] = {
|
||||
"if the service is not started then run the command",
|
||||
"list all available services",
|
||||
"resolve the service name to an init script",
|
||||
"dry run (show what would happen)",
|
||||
longopts_help_COMMON
|
||||
};
|
||||
const char *usagestring = "" \
|
||||
@@ -75,8 +67,6 @@ int main(int argc, char **argv)
|
||||
bool if_exists = false;
|
||||
bool if_inactive = false;
|
||||
bool if_notstarted = false;
|
||||
bool if_started = false;
|
||||
bool if_stopped = false;
|
||||
|
||||
applet = basename_c(argv[0]);
|
||||
/* Ensure that we are only quiet when explicitly told to be */
|
||||
@@ -86,12 +76,6 @@ int main(int argc, char **argv)
|
||||
longopts, (int *) 0)) != -1)
|
||||
{
|
||||
switch (opt) {
|
||||
case 'd':
|
||||
setenv("RC_DEBUG", "yes", 1);
|
||||
break;
|
||||
case 'D':
|
||||
setenv("RC_NODEPS", "yes", 1);
|
||||
break;
|
||||
case 'e':
|
||||
service = rc_service_resolve(optarg);
|
||||
opt = service ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
@@ -128,15 +112,6 @@ int main(int argc, char **argv)
|
||||
free(service);
|
||||
return EXIT_SUCCESS;
|
||||
/* NOTREACHED */
|
||||
case 's':
|
||||
if_started = true;
|
||||
break;
|
||||
case 'S':
|
||||
if_stopped = true;
|
||||
break;
|
||||
case 'Z':
|
||||
setenv("IN_DRYRUN", "yes", 1);
|
||||
break;
|
||||
|
||||
case_RC_COMMON_GETOPT
|
||||
}
|
||||
@@ -158,10 +133,6 @@ int main(int argc, char **argv)
|
||||
return 0;
|
||||
if (if_notstarted && (state & RC_SERVICE_STARTED))
|
||||
return 0;
|
||||
if (if_started && ! (state & RC_SERVICE_STARTED))
|
||||
return 0;
|
||||
if (if_stopped && ! (state & RC_SERVICE_STOPPED))
|
||||
return 0;
|
||||
*argv = service;
|
||||
execv(*argv, argv);
|
||||
eerrorx("%s: %s", applet, strerror(errno));
|
||||
|
||||
@@ -54,6 +54,7 @@ const char *usagestring = "" \
|
||||
"Usage: rc-status [options] <runlevel>...\n" \
|
||||
" or: rc-status [options] [-a | -c | -l | -m | -r | -s | -u]";
|
||||
|
||||
static bool test_crashed = false;
|
||||
static RC_DEPTREE *deptree;
|
||||
static RC_STRINGLIST *types;
|
||||
|
||||
@@ -75,7 +76,7 @@ print_level(const char *prefix, const char *level)
|
||||
printf("%s\n", level);
|
||||
}
|
||||
|
||||
static char *get_uptime(const char *service)
|
||||
static void get_uptime(const char *service, char *uptime, int uptime_size)
|
||||
{
|
||||
RC_SERVICE state = rc_service_state(service);
|
||||
char *start_count;
|
||||
@@ -87,8 +88,8 @@ static char *get_uptime(const char *service)
|
||||
time_t diff_hours = (time_t) 0;
|
||||
time_t diff_mins = (time_t) 0;
|
||||
time_t diff_secs = (time_t) 0;
|
||||
char *uptime = NULL;
|
||||
|
||||
uptime[0] = '\0';
|
||||
if (state & RC_SERVICE_STARTED) {
|
||||
start_count = rc_service_value_get(service, "start_count");
|
||||
start_time_string = rc_service_value_get(service, "start_time");
|
||||
@@ -110,24 +111,23 @@ static char *get_uptime(const char *service)
|
||||
diff_secs %= diff_mins * (time_t) 60;
|
||||
}
|
||||
if (diff_days > 0)
|
||||
xasprintf(&uptime,
|
||||
snprintf(uptime, uptime_size,
|
||||
"%ld day(s) %02ld:%02ld:%02ld (%s)",
|
||||
diff_days, diff_hours, diff_mins, diff_secs,
|
||||
start_count);
|
||||
else
|
||||
xasprintf(&uptime,
|
||||
snprintf(uptime, uptime_size,
|
||||
"%02ld:%02ld:%02ld (%s)",
|
||||
diff_hours, diff_mins, diff_secs, start_count);
|
||||
}
|
||||
}
|
||||
return uptime;
|
||||
}
|
||||
|
||||
static void
|
||||
print_service(const char *service)
|
||||
{
|
||||
char *status = NULL;
|
||||
char *uptime = NULL;
|
||||
char status[60];
|
||||
char uptime [40];
|
||||
char *child_pid = NULL;
|
||||
char *start_time = NULL;
|
||||
int cols = printf(" %s", service);
|
||||
@@ -136,45 +136,42 @@ print_service(const char *service)
|
||||
ECOLOR color = ECOLOR_BAD;
|
||||
|
||||
if (state & RC_SERVICE_STOPPING)
|
||||
xasprintf(&status, "stopping ");
|
||||
snprintf(status, sizeof(status), "stopping ");
|
||||
else if (state & RC_SERVICE_STARTING) {
|
||||
xasprintf(&status, "starting ");
|
||||
snprintf(status, sizeof(status), "starting ");
|
||||
color = ECOLOR_WARN;
|
||||
} else if (state & RC_SERVICE_INACTIVE) {
|
||||
xasprintf(&status, "inactive ");
|
||||
snprintf(status, sizeof(status), "inactive ");
|
||||
color = ECOLOR_WARN;
|
||||
} else if (state & RC_SERVICE_STARTED) {
|
||||
errno = 0;
|
||||
if (rc_service_daemons_crashed(service) && errno != EACCES)
|
||||
if (test_crashed &&
|
||||
rc_service_daemons_crashed(service) &&
|
||||
errno != EACCES)
|
||||
{
|
||||
child_pid = rc_service_value_get(service, "child_pid");
|
||||
start_time = rc_service_value_get(service, "start_time");
|
||||
if (start_time && child_pid)
|
||||
xasprintf(&status, " unsupervised ");
|
||||
snprintf(status, sizeof(status), " unsupervised ");
|
||||
else
|
||||
xasprintf(&status, " crashed ");
|
||||
snprintf(status, sizeof(status), " crashed ");
|
||||
free(child_pid);
|
||||
free(start_time);
|
||||
} else {
|
||||
uptime = get_uptime(service);
|
||||
if (uptime) {
|
||||
xasprintf(&status, " started %s", uptime);
|
||||
free(uptime);
|
||||
} else
|
||||
xasprintf(&status, " started ");
|
||||
get_uptime(service, uptime, 40);
|
||||
snprintf(status, sizeof(status), " started %s", uptime);
|
||||
color = ECOLOR_GOOD;
|
||||
}
|
||||
} else if (state & RC_SERVICE_SCHEDULED) {
|
||||
xasprintf(&status, "scheduled");
|
||||
snprintf(status, sizeof(status), "scheduled");
|
||||
color = ECOLOR_WARN;
|
||||
} else
|
||||
xasprintf(&status, " stopped ");
|
||||
snprintf(status, sizeof(status), " stopped ");
|
||||
|
||||
errno = 0;
|
||||
if (c && *c && isatty(fileno(stdout)))
|
||||
printf("\n");
|
||||
ebracket(cols, color, status);
|
||||
free(status);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -243,6 +240,8 @@ int main(int argc, char **argv)
|
||||
char *p, *runlevel = NULL;
|
||||
int opt, retval = 0;
|
||||
|
||||
test_crashed = _rc_can_find_pids();
|
||||
|
||||
applet = basename_c(argv[0]);
|
||||
while ((opt = getopt_long(argc, argv, getoptstring, longopts,
|
||||
(int *) 0)) != -1)
|
||||
|
||||
@@ -62,7 +62,7 @@ add(const char *runlevel, const char *service)
|
||||
|
||||
if (!rc_service_exists(service)) {
|
||||
if (errno == ENOEXEC)
|
||||
eerror("%s: service `%s' is not executable",
|
||||
eerror("%s: service `%s' is not executeable",
|
||||
applet, service);
|
||||
else
|
||||
eerror("%s: service `%s' does not exist",
|
||||
|
||||
@@ -42,7 +42,7 @@ void log_wtmp(const char *user, const char *id, pid_t pid, int type,
|
||||
strncpy(utmp.ut_name, user, sizeof(utmp.ut_name));
|
||||
strncpy(utmp.ut_id , id , sizeof(utmp.ut_id ));
|
||||
strncpy(utmp.ut_line, line, sizeof(utmp.ut_line));
|
||||
|
||||
|
||||
/* Put the OS version in place of the hostname */
|
||||
if (uname(&uname_buf) == 0)
|
||||
strncpy(utmp.ut_host, uname_buf.release, sizeof(utmp.ut_host));
|
||||
|
||||
40
src/rc/rc.c
40
src/rc/rc.c
@@ -101,6 +101,7 @@ clean_failed(void)
|
||||
{
|
||||
DIR *dp;
|
||||
struct dirent *d;
|
||||
size_t l;
|
||||
char *path;
|
||||
|
||||
/* Clean the failed services state dir now */
|
||||
@@ -111,11 +112,16 @@ clean_failed(void)
|
||||
(d->d_name[1] == '.' && d->d_name[2] == '\0')))
|
||||
continue;
|
||||
|
||||
xasprintf(&path, RC_SVCDIR "/failed/%s", d->d_name);
|
||||
if (unlink(path))
|
||||
eerror("%s: unlink `%s': %s",
|
||||
applet, path, strerror(errno));
|
||||
free(path);
|
||||
l = strlen(RC_SVCDIR "/failed/") +
|
||||
strlen(d->d_name) + 1;
|
||||
path = xmalloc(sizeof(char) * l);
|
||||
snprintf(path, l, RC_SVCDIR "/failed/%s", d->d_name);
|
||||
if (path) {
|
||||
if (unlink(path))
|
||||
eerror("%s: unlink `%s': %s",
|
||||
applet, path, strerror(errno));
|
||||
free(path);
|
||||
}
|
||||
}
|
||||
closedir(dp);
|
||||
}
|
||||
@@ -385,7 +391,7 @@ static void
|
||||
handle_signal(int sig)
|
||||
{
|
||||
int serrno = errno;
|
||||
char *signame = NULL;
|
||||
char signame[10] = { '\0' };
|
||||
pid_t pid;
|
||||
RC_PID *pi;
|
||||
int status = 0;
|
||||
@@ -416,16 +422,16 @@ handle_signal(int sig)
|
||||
break;
|
||||
|
||||
case SIGINT:
|
||||
if (!signame)
|
||||
xasprintf(&signame, "SIGINT");
|
||||
if (!signame[0])
|
||||
snprintf(signame, sizeof(signame), "SIGINT");
|
||||
/* FALLTHROUGH */
|
||||
case SIGTERM:
|
||||
if (!signame)
|
||||
xasprintf(&signame, "SIGTERM");
|
||||
if (!signame[0])
|
||||
snprintf(signame, sizeof(signame), "SIGTERM");
|
||||
/* FALLTHROUGH */
|
||||
case SIGQUIT:
|
||||
if (!signame)
|
||||
xasprintf(&signame, "SIGQUIT");
|
||||
if (!signame[0])
|
||||
snprintf(signame, sizeof(signame), "SIGQUIT");
|
||||
eerrorx("%s: caught %s, aborting", applet, signame);
|
||||
/* NOTREACHED */
|
||||
case SIGUSR1:
|
||||
@@ -506,11 +512,14 @@ runlevel_config(const char *service, const char *level)
|
||||
{
|
||||
char *init = rc_service_resolve(service);
|
||||
char *conf, *dir;
|
||||
size_t l;
|
||||
bool retval;
|
||||
|
||||
dir = dirname(init);
|
||||
dir = dirname(init);
|
||||
xasprintf(&conf, "%s/conf.d/%s.%s", dir, service, level);
|
||||
l = strlen(dir) + strlen(level) + strlen(service) + 10;
|
||||
conf = xmalloc(sizeof(char) * l);
|
||||
snprintf(conf, l, "%s/conf.d/%s.%s", dir, service, level);
|
||||
retval = exists(conf);
|
||||
free(conf);
|
||||
free(init);
|
||||
@@ -735,7 +744,7 @@ int main(int argc, char **argv)
|
||||
bool going_down = false;
|
||||
int depoptions = RC_DEP_STRICT | RC_DEP_TRACE;
|
||||
char *krunlevel = NULL;
|
||||
char *pidstr = NULL;
|
||||
char pidstr[10];
|
||||
int opt;
|
||||
bool parallel;
|
||||
int regen = 0;
|
||||
@@ -835,9 +844,8 @@ int main(int argc, char **argv)
|
||||
setenv("EINFO_LOG", "openrc", 1);
|
||||
|
||||
/* Export our PID */
|
||||
xasprintf(&pidstr, "%d", getpid());
|
||||
snprintf(pidstr, sizeof(pidstr), "%d", getpid());
|
||||
setenv("RC_PID", pidstr, 1);
|
||||
free(pidstr);
|
||||
|
||||
/* Create a list of all services which should be started for the new or
|
||||
* current runlevel including those in boot, sysinit and hotplugged
|
||||
|
||||
@@ -59,14 +59,13 @@ static struct pam_conv conv = { NULL, NULL};
|
||||
#include "queue.h"
|
||||
#include "rc.h"
|
||||
#include "rc-misc.h"
|
||||
#include "rc-pipes.h"
|
||||
#include "rc-schedules.h"
|
||||
#include "_usage.h"
|
||||
#include "helpers.h"
|
||||
|
||||
const char *applet = NULL;
|
||||
const char *extraopts = NULL;
|
||||
const char *getoptstring = "I:KN:PR:Sa:bc:d:e:g:ik:mn:op:s:tu:r:w:x:1:2:3:4:" \
|
||||
const char *getoptstring = "I:KN:PR:Sa:bc:d:e:g:ik:mn:op:s:tu:r:w:x:1:2:" \
|
||||
getoptstring_COMMON;
|
||||
const struct option longopts[] = {
|
||||
{ "ionice", 1, NULL, 'I'},
|
||||
@@ -94,8 +93,6 @@ const struct option longopts[] = {
|
||||
{ "exec", 1, NULL, 'x'},
|
||||
{ "stdout", 1, NULL, '1'},
|
||||
{ "stderr", 1, NULL, '2'},
|
||||
{ "stdout-logger",1, NULL, '3'},
|
||||
{ "stderr-logger",1, NULL, '4'},
|
||||
{ "progress", 0, NULL, 'P'},
|
||||
longopts_COMMON
|
||||
};
|
||||
@@ -125,8 +122,6 @@ const char * const longopts_help[] = {
|
||||
"Binary to start/stop",
|
||||
"Redirect stdout to file",
|
||||
"Redirect stderr to file",
|
||||
"Redirect stdout to process",
|
||||
"Redirect stderr to process",
|
||||
"Print dots each second while waiting",
|
||||
longopts_help_COMMON
|
||||
};
|
||||
@@ -167,20 +162,20 @@ handle_signal(int sig)
|
||||
{
|
||||
int status;
|
||||
int serrno = errno;
|
||||
char *signame = NULL;
|
||||
char signame[10] = { '\0' };
|
||||
|
||||
switch (sig) {
|
||||
case SIGINT:
|
||||
if (!signame)
|
||||
xasprintf(&signame, "SIGINT");
|
||||
if (!signame[0])
|
||||
snprintf(signame, sizeof(signame), "SIGINT");
|
||||
/* FALLTHROUGH */
|
||||
case SIGTERM:
|
||||
if (!signame)
|
||||
xasprintf(&signame, "SIGTERM");
|
||||
if (!signame[0])
|
||||
snprintf(signame, sizeof(signame), "SIGTERM");
|
||||
/* FALLTHROUGH */
|
||||
case SIGQUIT:
|
||||
if (!signame)
|
||||
xasprintf(&signame, "SIGQUIT");
|
||||
if (!signame[0])
|
||||
snprintf(signame, sizeof(signame), "SIGQUIT");
|
||||
eerrorx("%s: caught %s, aborting", applet, signame);
|
||||
/* NOTREACHED */
|
||||
|
||||
@@ -199,9 +194,6 @@ handle_signal(int sig)
|
||||
eerror("%s: caught unknown signal %d", applet, sig);
|
||||
}
|
||||
|
||||
/* free signame */
|
||||
free(signame);
|
||||
|
||||
/* Restore errno */
|
||||
errno = serrno;
|
||||
}
|
||||
@@ -210,6 +202,7 @@ static char *
|
||||
expand_home(const char *home, const char *path)
|
||||
{
|
||||
char *opath, *ppath, *p, *nh;
|
||||
size_t len;
|
||||
struct passwd *pw;
|
||||
|
||||
if (!path || *path != '~')
|
||||
@@ -240,7 +233,9 @@ expand_home(const char *home, const char *path)
|
||||
return xstrdup(home);
|
||||
}
|
||||
|
||||
xasprintf(&nh, "%s%s", home, ppath);
|
||||
len = strlen(ppath) + strlen(home) + 1;
|
||||
nh = xmalloc(len);
|
||||
snprintf(nh, len, "%s%s", home, ppath);
|
||||
free(opath);
|
||||
return nh;
|
||||
}
|
||||
@@ -281,8 +276,6 @@ int main(int argc, char **argv)
|
||||
int tid = 0;
|
||||
char *redirect_stderr = NULL;
|
||||
char *redirect_stdout = NULL;
|
||||
char *stderr_process = NULL;
|
||||
char *stdout_process = NULL;
|
||||
int stdin_fd;
|
||||
int stdout_fd;
|
||||
int stderr_fd;
|
||||
@@ -386,7 +379,6 @@ int main(int argc, char **argv)
|
||||
case 'c': /* --chuid <username>|<uid> */
|
||||
/* DEPRECATED */
|
||||
ewarn("WARNING: -c/--chuid is deprecated and will be removed in the future, please use -u/--user instead");
|
||||
/* falls through */
|
||||
case 'u': /* --user <username>|<uid> */
|
||||
{
|
||||
p = optarg;
|
||||
@@ -508,14 +500,6 @@ int main(int argc, char **argv)
|
||||
redirect_stderr = optarg;
|
||||
break;
|
||||
|
||||
case '3': /* --stdout-logger "command to run for stdout logging" */
|
||||
stdout_process = optarg;
|
||||
break;
|
||||
|
||||
case '4': /* --stderr-logger "command to run for stderr logging" */
|
||||
stderr_process = optarg;
|
||||
break;
|
||||
|
||||
case_RC_COMMON_GETOPT
|
||||
}
|
||||
|
||||
@@ -567,9 +551,6 @@ int main(int argc, char **argv)
|
||||
if (redirect_stdout || redirect_stderr)
|
||||
eerrorx("%s: --stdout and --stderr are only relevant"
|
||||
" with --start", applet);
|
||||
if (stdout_process || stderr_process)
|
||||
eerrorx("%s: --stdout-logger and --stderr-logger are only relevant"
|
||||
" with --start", applet);
|
||||
if (start_wait)
|
||||
ewarn("using --wait with --stop has no effect,"
|
||||
" use --retry instead");
|
||||
@@ -582,15 +563,6 @@ int main(int argc, char **argv)
|
||||
if ((redirect_stdout || redirect_stderr) && !background)
|
||||
eerrorx("%s: --stdout and --stderr are only relevant"
|
||||
" with --background", applet);
|
||||
if ((stdout_process || stderr_process) && !background)
|
||||
eerrorx("%s: --stdout-logger and --stderr-logger are only relevant"
|
||||
" with --background", applet);
|
||||
if (redirect_stdout && stdout_process)
|
||||
eerrorx("%s: do not use --stdout and --stdout-logger together",
|
||||
applet);
|
||||
if (redirect_stderr && stderr_process)
|
||||
eerrorx("%s: do not use --stderr and --stderr-logger together",
|
||||
applet);
|
||||
}
|
||||
|
||||
/* Expand ~ */
|
||||
@@ -631,6 +603,7 @@ int main(int argc, char **argv)
|
||||
*exec_file ? exec_file : exec);
|
||||
free(exec_file);
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
}
|
||||
if (start && retry)
|
||||
ewarn("using --retry with --start has no effect,"
|
||||
@@ -688,7 +661,7 @@ int main(int argc, char **argv)
|
||||
parse_schedule(applet, NULL, sig);
|
||||
if (pidfile) {
|
||||
pid = get_pid(applet, pidfile);
|
||||
if (pid == -1 && errno != ENOENT)
|
||||
if (pid == -1)
|
||||
exit(EXIT_FAILURE);
|
||||
} else {
|
||||
pid = 0;
|
||||
@@ -913,12 +886,6 @@ int main(int argc, char **argv)
|
||||
eerrorx("%s: unable to open the logfile"
|
||||
" for stdout `%s': %s",
|
||||
applet, redirect_stdout, strerror(errno));
|
||||
}else if (stdout_process) {
|
||||
stdout_fd = rc_pipe_command(stdout_process);
|
||||
if (stdout_fd == -1)
|
||||
eerrorx("%s: unable to open the logging process"
|
||||
" for stdout `%s': %s",
|
||||
applet, stdout_process, strerror(errno));
|
||||
}
|
||||
if (redirect_stderr) {
|
||||
if ((stderr_fd = open(redirect_stderr,
|
||||
@@ -927,21 +894,13 @@ int main(int argc, char **argv)
|
||||
eerrorx("%s: unable to open the logfile"
|
||||
" for stderr `%s': %s",
|
||||
applet, redirect_stderr, strerror(errno));
|
||||
}else if (stderr_process) {
|
||||
stderr_fd = rc_pipe_command(stderr_process);
|
||||
if (stderr_fd == -1)
|
||||
eerrorx("%s: unable to open the logging process"
|
||||
" for stderr `%s': %s",
|
||||
applet, stderr_process, strerror(errno));
|
||||
}
|
||||
|
||||
if (background)
|
||||
dup2(stdin_fd, STDIN_FILENO);
|
||||
if (background || redirect_stdout || stdout_process
|
||||
|| rc_yesno(getenv("EINFO_QUIET")))
|
||||
if (background || redirect_stdout || rc_yesno(getenv("EINFO_QUIET")))
|
||||
dup2(stdout_fd, STDOUT_FILENO);
|
||||
if (background || redirect_stderr || stderr_process
|
||||
|| rc_yesno(getenv("EINFO_QUIET")))
|
||||
if (background || redirect_stderr || rc_yesno(getenv("EINFO_QUIET")))
|
||||
dup2(stderr_fd, STDERR_FILENO);
|
||||
|
||||
for (i = getdtablesize() - 1; i >= 3; --i)
|
||||
|
||||
@@ -61,18 +61,15 @@ static struct pam_conv conv = { NULL, NULL};
|
||||
#include "queue.h"
|
||||
#include "rc.h"
|
||||
#include "rc-misc.h"
|
||||
#include "rc-plugin.h"
|
||||
#include "rc-schedules.h"
|
||||
#include "_usage.h"
|
||||
#include "helpers.h"
|
||||
|
||||
const char *applet = NULL;
|
||||
const char *extraopts = NULL;
|
||||
const char *getoptstring = "A:a:D:d:e:g:H:I:Kk:m:N:p:R:r:Su:1:2:3" \
|
||||
const char *getoptstring = "D:d:e:g:I:Kk:m:N:p:R:r:Su:1:2:3" \
|
||||
getoptstring_COMMON;
|
||||
const struct option longopts[] = {
|
||||
{ "healthcheck-timer", 1, NULL, 'a'},
|
||||
{ "healthcheck-delay", 1, NULL, 'A'},
|
||||
{ "respawn-delay", 1, NULL, 'D'},
|
||||
{ "chdir", 1, NULL, 'd'},
|
||||
{ "env", 1, NULL, 'e'},
|
||||
@@ -94,8 +91,6 @@ const struct option longopts[] = {
|
||||
longopts_COMMON
|
||||
};
|
||||
const char * const longopts_help[] = {
|
||||
"set an initial health check delay",
|
||||
"set a health check timer",
|
||||
"Set a respawn delay",
|
||||
"Change the PWD",
|
||||
"Set an environment string",
|
||||
@@ -118,9 +113,6 @@ const char * const longopts_help[] = {
|
||||
};
|
||||
const char *usagestring = NULL;
|
||||
|
||||
static int healthcheckdelay = 0;
|
||||
static int healthchecktimer = 0;
|
||||
static volatile sig_atomic_t do_healthcheck = 0;
|
||||
static int nicelevel = 0;
|
||||
static int ionicec = -1;
|
||||
static int ioniced = 0;
|
||||
@@ -191,15 +183,10 @@ static void handle_signal(int sig)
|
||||
re_exec_supervisor();
|
||||
}
|
||||
|
||||
static void healthcheck(int sig)
|
||||
{
|
||||
if (sig == SIGALRM)
|
||||
do_healthcheck = 1;
|
||||
}
|
||||
|
||||
static char * expand_home(const char *home, const char *path)
|
||||
{
|
||||
char *opath, *ppath, *p, *nh;
|
||||
size_t len;
|
||||
struct passwd *pw;
|
||||
|
||||
if (!path || *path != '~')
|
||||
@@ -230,7 +217,9 @@ static char * expand_home(const char *home, const char *path)
|
||||
return xstrdup(home);
|
||||
}
|
||||
|
||||
xasprintf(&nh, "%s%s", home, ppath);
|
||||
len = strlen(ppath) + strlen(home) + 1;
|
||||
nh = xmalloc(len);
|
||||
snprintf(nh, len, "%s%s", home, ppath);
|
||||
free(opath);
|
||||
return nh;
|
||||
}
|
||||
@@ -243,8 +232,8 @@ static char *make_cmdline(char **argv)
|
||||
|
||||
for (c = argv; c && *c; c++)
|
||||
len += (strlen(*c) + 1);
|
||||
cmdline = xmalloc(len+1);
|
||||
memset(cmdline, 0, len+1);
|
||||
cmdline = xmalloc(len);
|
||||
memset(cmdline, 0, len);
|
||||
for (c = argv; c && *c; c++) {
|
||||
strcat(cmdline, *c);
|
||||
strcat(cmdline, " ");
|
||||
@@ -437,14 +426,10 @@ static void child_process(char *exec, char **argv)
|
||||
static void supervisor(char *exec, char **argv)
|
||||
{
|
||||
FILE *fp;
|
||||
pid_t wait_pid;
|
||||
int i;
|
||||
int nkilled;
|
||||
struct timespec ts;
|
||||
time_t respawn_now= 0;
|
||||
time_t first_spawn= 0;
|
||||
pid_t health_pid;
|
||||
int health_status;
|
||||
|
||||
#ifndef RC_DEBUG
|
||||
signal_setup_restart(SIGHUP, handle_signal);
|
||||
@@ -505,88 +490,44 @@ static void supervisor(char *exec, char **argv)
|
||||
* Supervisor main loop
|
||||
*/
|
||||
i = 0;
|
||||
if (healthcheckdelay) {
|
||||
signal_setup(SIGALRM, healthcheck);
|
||||
alarm(healthcheckdelay);
|
||||
} else if (healthchecktimer) {
|
||||
signal_setup(SIGALRM, healthcheck);
|
||||
alarm(healthchecktimer);
|
||||
}
|
||||
while (!exiting) {
|
||||
wait_pid = wait(&i);
|
||||
if (wait_pid == -1) {
|
||||
if (do_healthcheck) {
|
||||
do_healthcheck = 0;
|
||||
alarm(0);
|
||||
syslog(LOG_DEBUG, "running health check for %s", svcname);
|
||||
health_pid = exec_service(svcname, "healthcheck");
|
||||
health_status = rc_waitpid(health_pid);
|
||||
if (WIFEXITED(health_status) && !WEXITSTATUS(health_status)) {
|
||||
alarm(healthchecktimer);
|
||||
wait(&i);
|
||||
if (exiting) {
|
||||
signal_setup(SIGCHLD, SIG_IGN);
|
||||
syslog(LOG_INFO, "stopping %s, pid %d", exec, child_pid);
|
||||
nkilled = run_stop_schedule(applet, exec, NULL, child_pid, 0,
|
||||
false, false, true);
|
||||
if (nkilled > 0)
|
||||
syslog(LOG_INFO, "killed %d processes", nkilled);
|
||||
} else {
|
||||
sleep(respawn_delay);
|
||||
if (respawn_max > 0 && respawn_period > 0) {
|
||||
respawn_now = time(NULL);
|
||||
if (first_spawn == 0)
|
||||
first_spawn = respawn_now;
|
||||
if (respawn_now - first_spawn > respawn_period) {
|
||||
respawn_count = 0;
|
||||
first_spawn = 0;
|
||||
} else
|
||||
respawn_count++;
|
||||
if (respawn_count >= respawn_max) {
|
||||
syslog(LOG_WARNING,
|
||||
"respawned \"%s\" too many times, exiting", exec);
|
||||
exiting = true;
|
||||
continue;
|
||||
} else {
|
||||
syslog(LOG_WARNING, "health check for %s failed", svcname);
|
||||
health_pid = exec_service(svcname, "unhealthy");
|
||||
rc_waitpid(health_pid);
|
||||
syslog(LOG_INFO, "stopping %s, pid %d", exec, child_pid);
|
||||
nkilled = run_stop_schedule(applet, NULL, NULL, child_pid, 0,
|
||||
false, false, true);
|
||||
if (nkilled > 0)
|
||||
syslog(LOG_INFO, "killed %d processes", nkilled);
|
||||
else if (errno != 0)
|
||||
syslog(LOG_INFO, "Unable to kill %d: %s",
|
||||
child_pid, strerror(errno));
|
||||
}
|
||||
} else if (exiting ) {
|
||||
alarm(0);
|
||||
syslog(LOG_INFO, "stopping %s, pid %d", exec, child_pid);
|
||||
nkilled = run_stop_schedule(applet, exec, NULL, child_pid, 0,
|
||||
false, false, true);
|
||||
if (nkilled > 0)
|
||||
syslog(LOG_INFO, "killed %d processes", nkilled);
|
||||
continue;
|
||||
}
|
||||
} else if (wait_pid == child_pid) {
|
||||
if (WIFEXITED(i))
|
||||
syslog(LOG_WARNING, "%s, pid %d, exited with return code %d",
|
||||
exec, child_pid, WEXITSTATUS(i));
|
||||
else if (WIFSIGNALED(i))
|
||||
syslog(LOG_WARNING, "%s, pid %d, terminated by signal %d",
|
||||
exec, child_pid, WTERMSIG(i));
|
||||
} else
|
||||
continue;
|
||||
|
||||
ts.tv_sec = respawn_delay;
|
||||
ts.tv_nsec = 0;
|
||||
nanosleep(&ts, NULL);
|
||||
if (respawn_max > 0 && respawn_period > 0) {
|
||||
respawn_now = time(NULL);
|
||||
if (first_spawn == 0)
|
||||
first_spawn = respawn_now;
|
||||
if (respawn_now - first_spawn > respawn_period) {
|
||||
respawn_count = 0;
|
||||
first_spawn = 0;
|
||||
} else
|
||||
respawn_count++;
|
||||
if (respawn_count > respawn_max) {
|
||||
syslog(LOG_WARNING,
|
||||
"respawned \"%s\" too many times, exiting", exec);
|
||||
exiting = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
alarm(0);
|
||||
child_pid = fork();
|
||||
if (child_pid == -1)
|
||||
eerrorx("%s: fork: %s", applet, strerror(errno));
|
||||
if (child_pid == 0)
|
||||
child_process(exec, argv);
|
||||
if (healthcheckdelay) {
|
||||
signal_setup(SIGALRM, healthcheck);
|
||||
alarm(healthcheckdelay);
|
||||
} else if (healthchecktimer) {
|
||||
signal_setup(SIGALRM, healthcheck);
|
||||
alarm(healthchecktimer);
|
||||
child_pid = fork();
|
||||
if (child_pid == -1)
|
||||
eerrorx("%s: fork: %s", applet, strerror(errno));
|
||||
if (child_pid == 0)
|
||||
child_process(exec, argv);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -671,16 +612,6 @@ int main(int argc, char **argv)
|
||||
while ((opt = getopt_long(argc, argv, getoptstring, longopts,
|
||||
(int *) 0)) != -1)
|
||||
switch (opt) {
|
||||
case 'a': /* --healthcheck-timer <time> */
|
||||
if (sscanf(optarg, "%d", &healthchecktimer) != 1 || healthchecktimer < 1)
|
||||
eerrorx("%s: invalid health check timer %s", applet, optarg);
|
||||
break;
|
||||
|
||||
case 'A': /* --healthcheck-delay <time> */
|
||||
if (sscanf(optarg, "%d", &healthcheckdelay) != 1 || healthcheckdelay < 1)
|
||||
eerrorx("%s: invalid health check delay %s", applet, optarg);
|
||||
break;
|
||||
|
||||
case 'D': /* --respawn-delay time */
|
||||
n = sscanf(optarg, "%d", &respawn_delay);
|
||||
if (n != 1 || respawn_delay < 1)
|
||||
@@ -737,11 +668,6 @@ int main(int argc, char **argv)
|
||||
gid = gr->gr_gid;
|
||||
break;
|
||||
|
||||
case 'H': /* --healthcheck-timer <minutes> */
|
||||
if (sscanf(optarg, "%d", &healthchecktimer) != 1 || healthchecktimer < 1)
|
||||
eerrorx("%s: invalid health check timer %s", applet, optarg);
|
||||
break;
|
||||
|
||||
case 'k':
|
||||
if (parse_mode(&numask, optarg))
|
||||
eerrorx("%s: invalid mode `%s'",
|
||||
@@ -909,7 +835,7 @@ int main(int argc, char **argv)
|
||||
|
||||
if (respawn_delay * respawn_max > respawn_period)
|
||||
ewarn("%s: Please increase the value of --respawn-period to more "
|
||||
"than %d to avoid infinite respawning", applet,
|
||||
"than %d to avoid infinite respawning", applet,
|
||||
respawn_delay * respawn_max);
|
||||
|
||||
if (retry) {
|
||||
@@ -937,13 +863,10 @@ int main(int argc, char **argv)
|
||||
varbuf = NULL;
|
||||
xasprintf(&varbuf, "%i", respawn_delay);
|
||||
rc_service_value_set(svcname, "respawn_delay", varbuf);
|
||||
free(varbuf);
|
||||
xasprintf(&varbuf, "%i", respawn_max);
|
||||
rc_service_value_set(svcname, "respawn_max", varbuf);
|
||||
free(varbuf);
|
||||
xasprintf(&varbuf, "%i", respawn_period);
|
||||
rc_service_value_set(svcname, "respawn_period", varbuf);
|
||||
free(varbuf);
|
||||
child_pid = fork();
|
||||
if (child_pid == -1)
|
||||
eerrorx("%s: fork: %s", applet, strerror(errno));
|
||||
@@ -971,7 +894,6 @@ int main(int argc, char **argv)
|
||||
}
|
||||
xasprintf(&varbuf, "%d", x);
|
||||
rc_service_value_set(svcname, "argc", varbuf);
|
||||
free(varbuf);
|
||||
rc_service_value_set(svcname, "exec", exec);
|
||||
supervisor(exec, argv);
|
||||
} else
|
||||
|
||||
@@ -7,109 +7,44 @@ terminates unexpectedly.
|
||||
|
||||
The following is a brief guide on using this capability.
|
||||
|
||||
* Use Default start, stop and status functions
|
||||
If you write your own start, stop and status functions in your service
|
||||
script, none of this will work. You must allow OpenRC to use the default
|
||||
functions.
|
||||
## Use Default start, stop and status functions
|
||||
|
||||
* Daemons must not fork
|
||||
Any deamon that you would like to have monitored by supervise-daemon
|
||||
must not fork. Instead, it must stay in the foreground. If the daemon
|
||||
forks, the supervisor will be unable to monitor it.
|
||||
If you write your own start, stop and status functions in your service
|
||||
script, none of this will work. You must allow OpenRC to use the default
|
||||
functions.
|
||||
|
||||
If the daemon can be configured to not fork, this should be done in the
|
||||
daemon's configuration file, or by adding a command line option that
|
||||
instructs it not to fork to the command_args_foreground variable shown
|
||||
below.
|
||||
## Daemons must not fork
|
||||
|
||||
# Health Checks
|
||||
Any deamon that you would like to have monitored by supervise-daemon
|
||||
must not fork. Instead, it must stay in the foreground. If the daemon
|
||||
itself forks, the supervisor will be unable to monitor it.
|
||||
|
||||
Health checks are a way to make sure a service monitored by
|
||||
supervise-daemon stays healthy. To configure a health check for a
|
||||
service, you need to write a healthcheck() function, and optionally an
|
||||
unhealthy() function in the service script. Also, you will need to set
|
||||
the healthcheck_timer and optionally healthcheck_delay variables.
|
||||
If the daemon can be configured to not fork, this should be done in the
|
||||
daemon's configuration file, or by adding a command line option that
|
||||
instructs it not to fork to the command_args_foreground variable shown
|
||||
below.
|
||||
|
||||
## healthcheck() function
|
||||
|
||||
The healthcheck() function is run repeatedly based on the settings of
|
||||
the healthcheck_* variables. This function should return zero if the
|
||||
service is currently healthy or non-zero otherwise.
|
||||
|
||||
## unhealthy() function
|
||||
|
||||
If the healthcheck() function returns non-zero, the unhealthy() function
|
||||
is run, then the service is restarted. Since the service will be
|
||||
restarted by the supervisor, the unhealthy function should not try to
|
||||
restart it; the purpose of the function is to allow any cleanup tasks
|
||||
other than restarting the service to be run.
|
||||
|
||||
# Variable Settings
|
||||
## Variable Settings
|
||||
|
||||
The most important setting is the supervisor variable. At the top of
|
||||
your service script, you should set this variable as follows:
|
||||
|
||||
``` sh
|
||||
supervisor=supervise-daemon
|
||||
```
|
||||
|
||||
Several other variables affect the way services behave under
|
||||
supervise-daemon. They are documented on the openrc-run man page, but I
|
||||
will list them here for convenience:
|
||||
|
||||
``` sh
|
||||
pidfile=/pid/of/supervisor.pid
|
||||
```
|
||||
|
||||
If you are using start-stop-daemon to monitor your scripts, the pidfile
|
||||
is the path to the pidfile the daemon creates. If, on the other hand,
|
||||
you are using supervise-daemon, this is the path to the pidfile the
|
||||
supervisor creates.
|
||||
|
||||
``` sh
|
||||
command_args_foreground="arguments"
|
||||
```
|
||||
|
||||
This should be used if the daemon you want to monitor
|
||||
command_args_foreground should be used if the daemon you want to monitor
|
||||
forks and goes to the background by default. This should be set to the
|
||||
command line option that instructs the daemon to stay in the foreground.
|
||||
|
||||
``` sh
|
||||
healthcheck_delay=seconds
|
||||
```
|
||||
|
||||
This is the delay, in seconds, before the first health check is run.
|
||||
If it is not set, we use the value of healthcheck_timer.
|
||||
|
||||
``` sh
|
||||
healthcheck_timer=seconds
|
||||
```
|
||||
|
||||
This is the number of seconds between health checks. If it is not set,
|
||||
no health checks will be run.
|
||||
|
||||
``` sh
|
||||
respawn_delay
|
||||
```
|
||||
|
||||
This is the number of seconds to delay before attempting to respawn a
|
||||
supervised process after it dies unexpectedly.
|
||||
The default is to respawn immediately.
|
||||
|
||||
``` sh
|
||||
respawn_max=x
|
||||
```
|
||||
|
||||
This is the maximum number of times to respawn a supervised process
|
||||
during the given respawn period. The default is unlimited.
|
||||
|
||||
``` sh
|
||||
respawn_period=seconds
|
||||
```
|
||||
|
||||
This works in conjunction with respawn_max and respawn_delay above to
|
||||
decide if a process should not be respawned for some reason.
|
||||
|
||||
For example, if respawn_period is 60, respawn_max is 2 and respawn_delay
|
||||
is 3 and a process dies more than 4 times, the process will not be
|
||||
respawned and the supervisor will terminate.
|
||||
This is very early support, so feel free to file bugs if you have
|
||||
issues.
|
||||
|
||||
@@ -90,8 +90,8 @@ the service script by hand.
|
||||
|
||||
FIXME: Document stacked runlevels
|
||||
|
||||
The default startup uses the runlevels `sysinit`, `boot`, and `default`,
|
||||
in that order. Shutdown uses the `shutdown` runlevel.
|
||||
The default startup uses the runlevels `boot`, `sysinit` and `default`, in that
|
||||
order. Shutdown uses the `shutdown` runlevel.
|
||||
|
||||
# The Magic of `conf.d`
|
||||
|
||||
@@ -162,6 +162,7 @@ stopped, by using:
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user