Documentation
¶
Overview ¶
Package misc is the MISC_CHECK health check: run a script and read the verdict from its exit status.
The exit status is not a boolean. Three ranges mean different things and one of them changes meaning depending on whether `misc_dynamic` is set (check_misc.c:363-408):
0 healthy, contributing no weight adjustment
1 failed, always — never a dynamic weight
2..255 failed, unless misc_dynamic, in which case healthy with
a weight of (status - 2)
So a script that returns 1 on error and 2 on a different error is reporting "down" and "up with weight 0" respectively once misc_dynamic is set. The gap at 1 is deliberate — it is what lets a dynamic script still say "down" — but it is easy to trip over when converting a script from static to dynamic.
Index ¶
Constants ¶
const DynamicWeightOffset = 2
DynamicWeightOffset is subtracted from the exit status to get the weight (check_misc.c:376). Statuses 2..255 map to weights 0..253.
const TermGrace = 2 * time.Second
TermGrace is how long C waits after SIGTERM before escalating to SIGKILL (check_misc.c:322-326).
Variables ¶
var ErrNotRun = errors.New("misc: script could not be run")
ErrNotRun is returned when the script could not be started at all, which is a local failure and not a statement about the backend.
Functions ¶
This section is empty.
Types ¶
type Script ¶
type Script struct {
// Path is the executable.
Path string
// Args are the arguments, not including the program name.
Args []string
// UID and GID are the credentials to drop to. Both zero means run as
// the current user.
UID, GID uint32
// SetCredentials enables the credential drop. It is explicit rather than
// inferred from UID being non-zero, because dropping *to* root is a
// distinct intention from not dropping at all.
SetCredentials bool
// Timeout bounds the run. Zero means the caller's context governs.
Timeout time.Duration
// Dynamic enables misc_dynamic weight reporting.
Dynamic bool
}
Script describes what to run.
type Verdict ¶
type Verdict struct {
// Healthy reports whether the check passed.
Healthy bool
// ExitStatus is the process's exit status, valid unless Signalled.
ExitStatus int
// Signalled reports that the script was killed rather than exiting.
Signalled bool
// Signal is the signal that killed it.
Signal syscall.Signal
// TimedOut reports that the kill was ours, because the script outran
// its timeout.
TimedOut bool
// DynamicWeight is the weight the exit status asks for, valid only when
// Dynamic was set and Healthy is true.
DynamicWeight int
// Reason is a short description for logging, worded as C words it.
Reason string
}
Verdict is what one run of the script established.
func Classify ¶
Classify turns a completed run into a verdict (misc_check_child_thread, check_misc.c:361-434).
It is separated from running the script so the status arithmetic — the part with the off-by-two and the special case at 1 — can be exercised without spawning anything.
func Run ¶
Run executes the script and classifies the result.
Three things about the process setup matter:
- It runs in its own process group (setpgid(0,0), notify.c:260), so the timeout kill reaches the whole tree. A script that backgrounds work would otherwise leave orphans accumulating once per check interval.
- PR_SET_PDEATHSIG is set to SIGTERM (notify.c:270), so a script outlives neither keepalived nor, here, the daemon that replaces it.
- IFS, LD_PRELOAD and LD_LIBRARY_PATH are removed from the environment (notify.c:263-266) before exec. The script frequently runs with dropped privileges, and these three are the standard ways to make a privilege-dropping exec do something other than what it says.