refactor: pos system event-trigger → pos system schedule — per-job timers, notify policies, legacy migrate
The single-timer threshold monitor generalizes into a scheduler: each job is a
chmod-600 file in schedule.d/<name>.env (INTERVAL 5m..59m/1h..23h/hourly/daily/
weekly/OnCalendar=..., NOTIFY policy, optional MSG, RULE for threshold,
COMMAND = literal rest of line) with its own systemd user timer pair
(pos-schedule-<name>.timer + oneshot .service, Persistent, reconciled on
enable/disable — orphan units + the legacy pos-event-trigger timer
auto-removed). Policies: always (full output every run), onchange (diff vs
last run, first run sends), onerror (non-zero exit or empty output),
threshold (old event-trigger behavior: first numeric vs RULE, alert on
false→true + recovery, per-job firing state), never (silent side-effect jobs).
run [name|all], list, config (interactive add/edit/remove/enable/disable with
validation), enable/disable [name|all], status, migrate (converts legacy
event.env rules → rule-N.env threshold jobs, verbatim LHS as COMMAND, adopts
the legacy timer's OnCalendar or 5m, removes the old timer). Per-run logs +
state in ~/.local/share/linux_post_install/schedule/{logs,state}/.
config/event.env + event-rules.template → config/schedule.d/ starter jobs
(nvme-health, cpu-temp, disk-root, silent log-cleanup); postinstall installs
them no-clobber into an empty schedule.d/ (legacy event.env users get a
migrate hint instead). bin/pos EXAMPLES + INTERACTIVE_CMDS
(system-schedule config) updated; install.sh ships the renamed tool+lib.
This commit is contained in:
@@ -1,54 +0,0 @@
|
||||
# eventer rules template — copy/paste into ~/.config/linux_post_install/event.env
|
||||
# (or add each line via: pos system event-trigger config).
|
||||
#
|
||||
# One independent rule per line. Grammar:
|
||||
#
|
||||
# "<message>" if <check-command> <op> <threshold>
|
||||
# <check-command> <op> <threshold> (no message → auto-composed)
|
||||
#
|
||||
# <message> optional quoted alert text (quote-stripped)
|
||||
# <check-command> any shell command; first numeric output is the value
|
||||
# <op> > < >= <= == !=
|
||||
# <threshold> number with optional unit suffix: 60c, 80%, 10g
|
||||
#
|
||||
# Rules alert once on false→true (plus one recovery message on true→false)
|
||||
# via lib/notify.sh — Telegram by default. State is tracked per rule in
|
||||
# ~/.local/share/linux_post_install/eventer/state/ (keyed by rule-line hash).
|
||||
#
|
||||
# Verify each check on your machine first (adjust device names):
|
||||
# sensors -u coretemp-isa-0000 | awk '/Package id 0:/{f=1} f && /temp1_input:/{print $2; exit}'
|
||||
# smartctl -A /dev/sda | awk '/Temperature_Celsius/{print $10}'
|
||||
# nvme smart-log /dev/nvme0
|
||||
# vnstat -d 1
|
||||
#
|
||||
# ── CPU (lm-sensors) ──────────────────────────────────────────────
|
||||
"CPU too hot" if sensors -u coretemp-isa-0000 | awk '/Package id 0:/{f=1} f && /temp1_input:/{print $2; exit}' > 60c
|
||||
"CPU hot warning" if sensors -u coretemp-isa-0000 | awk '/Package id 0:/{f=1} f && /temp1_input:/{print $2; exit}' > 55c
|
||||
"Load high" if uptime | sed 's/.*load average: //' | awk -F'[, ]+' '{print $1}' > 4
|
||||
|
||||
# ── Memory (procps, always present) ───────────────────────────────
|
||||
"RAM high" if free -m | awk '/^Mem:/{print int($3/$2*100)}' > 90%
|
||||
"Swap in use" if free -m | awk '/^Swap:/{print $3+0}' > 1000
|
||||
|
||||
# ── Disk space ───────────────────────────────────────────────────
|
||||
"Disk / nearly full" if df -P / | awk 'NR==2{print $5+0}' > 80%
|
||||
"Disk /srv full" if df -P /srv | awk 'NR==2{print $5+0}' > 85%
|
||||
|
||||
# ── Disk health (smartmontools) ──────────────────────────────────
|
||||
"Disk sda SMART fail" if smartctl -H /dev/sda | grep -q PASSED && echo 0 || echo 1 == 1
|
||||
"SDA hot" if smartctl -A /dev/sda | awk '/Temperature_Celsius/{print $10}' > 50c
|
||||
|
||||
# ── NVMe (nvme-cli) ──────────────────────────────────────────────
|
||||
"NVMe hot" if nvme smart-log /dev/nvme0 | awk '/^temperature/{print $3}' > 65c
|
||||
"NVMe wear-out" if nvme smart-log /dev/nvme0 | awk '/percentage used/{print $NF+0}' > 80%
|
||||
|
||||
# ── Network (vnstat needs ~1 day of collected data) ──────────────
|
||||
"Big traffic day" if vnstat -d 1 | awk '/today/{print $10+0}' > 20000
|
||||
"Link eth0 down" if ethtool eth0 | grep -q 'Link detected: yes' && echo 0 || echo 1 == 1
|
||||
|
||||
# ── Processes ────────────────────────────────────────────────────
|
||||
"Top CPU 80%" if top -bn1 | awk 'NR==8{print $9+0}' > 80%
|
||||
"Top MEM 90%" if top -bn1 | awk 'NR==8{print $10+0}' > 90%
|
||||
|
||||
# Manage rules interactively: pos system event-trigger config
|
||||
# Schedule the timer: pos system event-trigger enable 5m
|
||||
@@ -1,21 +0,0 @@
|
||||
# eventer rules — evaluated by 'pos system event-trigger run' (systemd timer).
|
||||
# Copied to ~/.config/linux_post_install/event.env on install (no clobber).
|
||||
# One independent rule per line. Grammar:
|
||||
#
|
||||
# "<message>" if <check-command> <op> <threshold>
|
||||
# <check-command> <op> <threshold> (no message → auto-composed)
|
||||
#
|
||||
# The check command is run; its first numeric output is compared against the
|
||||
# threshold (float-safe, unit suffix on the threshold is fine: 60c, 80%, 10g).
|
||||
# Operators: > < >= <= == !=
|
||||
#
|
||||
# Rules alert once on false→true (plus one recovery message when the
|
||||
# condition clears) via lib/notify.sh — Telegram by default.
|
||||
#
|
||||
# Examples:
|
||||
# "CPU too hot" if sensors -u coretemp-isa-0000 | awk '/Package id 0:/{f=1} f && /temp1_input:/{print $2; exit}' > 60c
|
||||
# "Disk nearly full" if df -P / | awk 'NR==2{print $5+0}' > 80%
|
||||
# "Load high" if uptime | sed 's/.*load average: //; s/,.*//' >= 4
|
||||
#
|
||||
# Manage rules interactively: pos system event-trigger config
|
||||
# Schedule the timer: pos system event-trigger enable 5m
|
||||
@@ -0,0 +1,9 @@
|
||||
# CPU temperature threshold — alerts once while over 60c, one recovery message.
|
||||
# lm-sensors (in preinstall PACKAGES). Chip names differ per machine — check
|
||||
# `sensors -u` for the real key and pin the chip (a bare grep can match a
|
||||
# different chip's temp1_input first).
|
||||
INTERVAL=5m
|
||||
NOTIFY=threshold
|
||||
MSG=CPU too hot
|
||||
RULE="> 60c"
|
||||
COMMAND=sensors -u coretemp-isa-0000 | awk '/Package id 0:/{f=1} f && /temp1_input:/{print $2; exit}'
|
||||
@@ -0,0 +1,6 @@
|
||||
# Root filesystem usage threshold — alerts once while over 80%, one recovery.
|
||||
INTERVAL=30m
|
||||
NOTIFY=threshold
|
||||
MSG=Disk / nearly full
|
||||
RULE="> 80%"
|
||||
COMMAND=df -P / | awk 'NR==2{print $5+0}'
|
||||
@@ -0,0 +1,5 @@
|
||||
# Side-effect job: silently prune old pos invocation logs every week.
|
||||
# NOTIFY=never — runs and does its thing, no notification.
|
||||
INTERVAL=weekly
|
||||
NOTIFY=never
|
||||
COMMAND=find ~/.local/share/linux_post_install/logs -type f -name '*_pos_*.log' -mtime +30 -delete
|
||||
@@ -0,0 +1,11 @@
|
||||
# NVMe SMART health — notify when any monitored field changes.
|
||||
# Needs smartmontools (in preinstall PACKAGES) + passwordless sudo for
|
||||
# smartctl. Set it up once:
|
||||
# echo '%sudo ALL=(ALL) NOPASSWD: /usr/sbin/smartctl' | sudo tee /etc/sudoers.d/smartctl
|
||||
# Adjust /dev/nvme0n1 if your disk has a different device name.
|
||||
# Note: 'temperature' drifts, so onchange will fire most hours — drop the
|
||||
# temperature alternative from the grep if you only want fault-field alerts.
|
||||
INTERVAL=hourly
|
||||
NOTIFY=onchange
|
||||
MSG=NVMe health
|
||||
COMMAND=sudo -n smartctl -a /dev/nvme0n1 | grep -Ei 'critical_warning|temperature|available_spare|percentage_used|media_errors|error_information'
|
||||
Reference in New Issue
Block a user