mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-09-11 19:05:11 +08:00
121 lines
3.4 KiB
Bash
121 lines
3.4 KiB
Bash
#!/bin/sh /etc/rc.common
|
|
# Keeps the scheduled-measurement cron entry in step with UCI. There is no
|
|
# daemon here: measurements are one-shot runs of librespeed-run, and the rpcd
|
|
# interface needs no service of its own.
|
|
|
|
START=95
|
|
USE_PROCD=1
|
|
|
|
CRONTAB=/etc/crontabs/root
|
|
RUN=/usr/libexec/librespeed-run
|
|
AGG=/usr/libexec/librespeed-aggregate
|
|
|
|
# Builds the cron time fields from UCI. For sub-daily intervals `hours`
|
|
# restricts when measurements may run; for a daily one it is the window a
|
|
# random time is drawn from, drawn here at sync time. That keeps the herd
|
|
# apart -- every router lands on its own minute -- without any process
|
|
# sleeping through the night, at the cost of re-drawing on every reload.
|
|
cron_expr() {
|
|
local interval="$1" days="$2" hours="$3"
|
|
local start end m h v
|
|
|
|
case "$interval" in
|
|
*m)
|
|
v=${interval%m}
|
|
case "$v" in ''|0|*[!0-9]*) return 1 ;; esac
|
|
[ "$v" -le 59 ] || return 1
|
|
echo "*/$v ${hours:-*} * * $days"
|
|
;;
|
|
*h)
|
|
v=${interval%h}
|
|
case "$v" in ''|0|*[!0-9]*) return 1 ;; esac
|
|
[ "$v" -le 23 ] || return 1
|
|
if [ -n "$hours" ]; then
|
|
echo "0 $hours/$v * * $days"
|
|
else
|
|
echo "0 */$v * * $days"
|
|
fi
|
|
;;
|
|
1d|24h)
|
|
start=${hours%-*}; end=${hours#*-}
|
|
[ -n "$hours" ] || { start=0; end=23; }
|
|
# A window wrapping midnight (22-4) is not supported; treat it as the
|
|
# single starting hour rather than guessing.
|
|
[ "$end" -ge "$start" ] 2>/dev/null || end=$start
|
|
# Time xor pid as the seed: seconds-granular srand() alone would give
|
|
# two syncs in the same second the same draw.
|
|
set -- $(awk -v a="$start" -v b="$end" -v s="$(( $(date +%s) ^ $$ ))" 'BEGIN {
|
|
srand(s)
|
|
printf "%d %d", int(rand() * 60), a + int(rand() * (b - a + 1))
|
|
}')
|
|
echo "$1 $2 * * $days"
|
|
;;
|
|
*)
|
|
return 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
restart_cron() {
|
|
# Unconditional: on a stock system the crontab dir starts empty, so crond
|
|
# is not running at all -- restart starts a stopped procd service, and a
|
|
# guard on "running" would mean the schedule never fires until reboot.
|
|
/etc/init.d/cron restart >/dev/null 2>&1
|
|
return 0
|
|
}
|
|
|
|
sync_cron() {
|
|
local enabled interval days hours expr hist_enabled archive_path
|
|
|
|
config_load librespeed
|
|
config_get_bool enabled schedule enabled 0
|
|
config_get interval schedule interval 1d
|
|
config_get days schedule days '*'
|
|
config_get hours schedule hours ''
|
|
config_get_bool hist_enabled history enabled 1
|
|
config_get archive_path history archive_path ''
|
|
|
|
# These end up verbatim in root's crontab, so anything unexpected becomes
|
|
# the harmless default rather than a cron field it was not meant to be.
|
|
case "$days" in *[!0-9,-]*) days='*' ;; '') days='*' ;; esac
|
|
case "$hours" in *[!0-9-]*) hours='' ;; esac
|
|
|
|
mkdir -p "${CRONTAB%/*}"
|
|
touch "$CRONTAB"
|
|
sed -i "\\#$RUN#d;\\#$AGG#d" "$CRONTAB"
|
|
|
|
# The day completes at midnight; five past, it is reduced to one archive
|
|
# line. A missed run costs nothing to catch up: raw lives in RAM, so after
|
|
# a power cut there is nothing left to aggregate anyway.
|
|
if [ "$hist_enabled" = 1 ] && [ -n "$archive_path" ]; then
|
|
echo "5 0 * * * $AGG" >> "$CRONTAB"
|
|
fi
|
|
|
|
if [ "$enabled" = 1 ]; then
|
|
if expr=$(cron_expr "$interval" "$days" "$hours"); then
|
|
echo "$expr $RUN" >> "$CRONTAB"
|
|
else
|
|
logger -t librespeed "unsupported schedule interval '$interval'"
|
|
fi
|
|
fi
|
|
|
|
restart_cron
|
|
}
|
|
|
|
start_service() {
|
|
sync_cron
|
|
}
|
|
|
|
stop_service() {
|
|
sed -i "\\#$RUN#d;\\#$AGG#d" "$CRONTAB"
|
|
restart_cron
|
|
}
|
|
|
|
service_triggers() {
|
|
procd_add_reload_trigger "librespeed"
|
|
}
|
|
|
|
reload_service() {
|
|
sync_cron
|
|
}
|