Before update_cron was wired in, the plugin wrote directly to
/etc/cron.d/varaverk. That file persisted after the migration and
caused duplicate job firing (two watchdog instances at :00/:15/:30/:45).
The second instance hit the lock, exited with warn, and overwrote the
stat file — killing the running indicator while the first was still live.
vv_cron_rebuild() now unlinks the legacy file after every update_cron
call. Since rebuild_cron (boot event) calls vv_cron_rebuild(), the
cleanup runs on every reboot and every schedule save.
Create varaverk.plg on flash (/boot/config/plugins/varaverk/varaverk.plg).
On boot, rebuild_cron copies it to /var/log/plugins/ so update_cron natively
picks up varaverk.cron and merges it into /etc/cron.d/root.
With the .plg in place the dev-mode direct-inject fallback in vv_cron_rebuild()
is no longer needed and has been removed.
dcron uses the filename in /etc/cron.d/ as the username, so a file named
'varaverk' ran jobs as a non-existent user and was silently ignored.
Switch to writing /boot/config/plugins/varaverk/varaverk.cron and calling
update_cron (which merges all plugin .cron files into /etc/cron.d/root).
In dev mode (no varaverk.plg registered), fall back to injecting our entries
directly into the live root crontab via crontab -c /etc/cron.d -.
run_job.sh: new wrapper called by scheduler cron for every job.
Writes /var/log/varaverk/<id>.json (status/start/end/exit/pid)
and /var/log/varaverk/<id>.log (latest run output, overwritten).
Maps exit 0→ok, 1→warn, 2+→error so watchdog "took action" runs
show warn not error.
scheduler: cron now calls bash run_job.sh instead of inline bash -c.
Added vv_job_stat_path(). LOG_DIR moved to config.php (shared).
monitor: vv_scripts_status() now reads /var/log/varaverk/*.json and
*/*.json — no User Scripts tmpScripts dependency at all.
Stale running detection via /proc/<pid> check.
Returns error_count in addition to running/ok/warn counts.
pages/monitor.php: added error pill (red ✗), error icon/color in
list, duration shown next to age for each script entry.
Layout:
- Switch from three flex rows to single CSS grid (repeat(8,1fr)) — eliminates
gap-count discrepancy between rows; span 1/2/4/8 cards are now pixel-identical
across all rows regardless of how many cards share the row
New cards:
- Scripts card: last-run status (ok/warn/running/unknown), clickable filter pills,
7-row scroll, flex:1 matching Power/Parity
- Streams card: live per-second progress counters, color-coded play buttons
(blue=live, orange=transcoding, green=direct, yellow=paused), server badges
with counts, left-fill column layout (3 per col)
- Transcode card: NVMe indicator, active session count + scrollable list,
session rows with server icon + title + type + method
Dynamic thresholds:
- vv_disk_thresholds() reads /boot/config/plugins/dynamix/dynamix.cfg
- Disk utilization bars: green/orange/red based on warning/critical settings
- Temperature colors: hot/max for HDD, hotssd/maxssd for SSD/NVMe
- Thresholds update every poll cycle; changing Unraid settings takes effect automatically
Other:
- SSD path detection uses findmnt FSTYPE to exclude tmpfs/ramfs (fixes RAM
being reported as SSD transcode target)
- varaverk.css h3: add white-space:normal + overflow:hidden to neutralise
any Unraid global h3 styles that could force card width
- External IP: switch from DDNS domain lookup to curl ifconfig.me with 5-min
cache; DDNS approach broke because host detection uses HOST1_NAME but conf
has HOST1, so domain was never resolved
- Tailscale IP: switch from hardcoded tailscale0 iface to `tailscale ip -4`;
interface name varies (tailscale0, tailscale1) across kernels/installs
media.php: Emby/Jellyfin/Plex session poller for Streams card
confform.php: conf file form helpers for Config tab
script.php: per-script run/log API endpoint for Scheduler tab
vv_network_stats() calls vv_conf_vars() and vv_detect_host() which are defined in
config.php. monitor.php had no require for it, causing a PHP fatal error on every
poll → empty JSON → all monitor cards stuck on "Loading...".
Monitor tab:
- CPU card: per-core bars (freq-colored), overall usage bar, rolling history chart
- Memory card: breakdown by system/VM/ZFS/Docker/free with progress bars
- Network card: LAN + ext + Tailscale IP display, live RX/TX chart with auto-scale
- Streams card: Emby/Jellyfin/Plex sessions with playback bar and server badges
- GPU card: adds power draw, encode%, decode% meters
- Transcode card: ramdisk vs SSD location pill, session count, flip history
- Canvas chart helpers: vvDrawChart, vvDrawNetChart, vvMeter, vvFmtBps, vvFmtGib
api/monitor.php: adds cpu, mem, net to response payload
Unraid's system crond is dcron (dillon's cron daemon 4.5), which reads
/etc/cron.d/ for system crontabs WITHOUT a username field, and refuses
to execute files that are group- or world-writable.
vv_cron_rebuild() was writing "SCHED root bash ..." (with username field)
and leaving the file world-writable (666), so dcron silently ignored every
entry. Fixed:
- Remove CRON_USER from the generated cron line format
- chmod 0600 the cron file after writing it
- Change suggestion title color from bright green (#6fcf97) to soft grey-blue (#7a9eb5)
- Fix vv_parse_user_script_template() block-detection regex — $ end-anchor
failed on lines ending with multibyte U+2500 ─ chars; removed anchor so
parser now returns all 22 blocks from user_script_plug-in.sh
- Cron and Advanced button vertically aligned in their respective rows
- Verbose checkbox next to Log button — saves immediately, persists to schedule.json
- --log flag injected into cron lines, manual Run, and Dry Run when verbose enabled
- Coffee report rewritten as lean orchestrator over COFFEE_REPORT_SCRIPTS array
- COFFEE_REPORT_SCRIPTS added to master.conf (7 Sunday monitor scripts)
- Scheduler Advanced tab auto-discovers children via existing array detection
Cron input now sits right of the script label in the same row.
Below each row: one-line description pulled live from the script header
(PURPOSE block or first meaningful comment line) — updates whenever
scripts are edited, no plugin changes needed.
- Per-job log files replace single jobs.log: each script writes to
/var/log/varaverk/<Category>/<script>.log mirroring the job ID
- api/log.php: serves last 200 lines of a job's log file with mtime
timestamp; supports POST ?clear=1 to truncate
- Scheduler page redesigned as full-width cards (one per orchestrator)
with Save + Log buttons; Log toggles an inline panel that polls
every 3 seconds and auto-scrolls — same pattern as unRAID User Scripts
- Children shown under Advanced with identical per-job log panels
- CSS: vv-sched-card, vv-log-panel, vv-log-pre, vv-btn-sm
Non-greedy (.*?) stopped at the first ) found, which could be inside
a comment like '# gracefully stop fallback (not caught by ...)'.
Anchoring the closing paren to start-of-line (^\s*\)) ensures it only
matches the array's actual closing paren, not ) inside comment text.
Orchestrators using dynamic dispatch (array_started, watchdog_orchestrator,
daily/weekly/etc maintenance) iterate \${VARNAME_SCRIPTS[@]} arrays defined
in master.conf. The previous regex only caught static hardcoded paths.
Two-strategy approach, merged and deduped:
1. Static: \$VAR/../Category/script.sh and \$VAR/Category/script.sh patterns
2. Dynamic: detect \${VARNAME[@]} references in the orch, parse that array
from master.conf — handles inline args and skips commented entries
Changes to master.conf arrays are reflected immediately on next page load.
Previous regex only matched literal bash/source calls with bare paths.
Orchestrators use shell variables like \$SCRIPT_DIR/../Transcodes/script.sh
and \$SCRIPTS_ROOT/Category/script.sh — the old pattern missed all of these.
New regex captures the Category/script.sh portion from either pattern,
requires at least one subdirectory (excludes load_config.sh and root-level
utilities), and validates each candidate against the filesystem.
transcode_management now correctly shows transcode_cleanup and transcode_manager.
Orchestrators using master.conf config arrays for dynamic dispatch still show
no children — correct, as those lists cannot be statically parsed.
/var/log/ is RAM-based on unRAID — wiped on reboot. Creating the log
directory in vv_cron_rebuild() ensures it exists before the first cron
job fires, without needing a separate boot script.
- Rename varaverk.page → Varaverk.page: unRAID nginx only routes URLs
starting with a capital letter (~^/[A-Z].*), lowercase caused 404
- Add require_once config.php to include/scheduler.php and include/docs.php:
both used SCRIPTS_DIR constant without including the file that defines it
- Replace hardcoded SCRIPTS_DIR with cfg-file-backed setting: reads from
/boot/config/plugins/varaverk/varaverk.cfg, falls back to default on first run
- Add Plugin Settings card to Config tab with scripts path field
- Add api/settings.php to write the cfg file (validates directory exists)