Single-source the scheduler help from markdown the AI index can read
This commit is contained in:
+2
-2
@@ -145,8 +145,8 @@ done
|
||||
# misleading failure this tool can produce.
|
||||
if [[ -n "$KIND" ]]; then
|
||||
case "$KIND" in
|
||||
header|readme|manual|template|doc) ;;
|
||||
*) echo "Unknown --kind=$KIND (expected: header, readme, manual, template, doc)" >&2
|
||||
header|readme|manual|template|doc|ui) ;;
|
||||
*) echo "Unknown --kind=$KIND (expected: header, readme, manual, template, doc, ui)" >&2
|
||||
exit 1 ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
+7
-1
@@ -213,6 +213,12 @@ function capSize(chunks) {
|
||||
function classify(rel) {
|
||||
const base = path.basename(rel);
|
||||
if (rel.startsWith('Deployment/') && rel.endsWith('.template')) return 'template';
|
||||
// WebGUI page docs, written for whoever is using the tab rather than maintaining it. Their
|
||||
// own kind because every other kind here answers a maintainer's question: an operator asking
|
||||
// "how do I stop this" needs the click path, and a corpus that is three-quarters script
|
||||
// headers will otherwise always answer in conf edits. Matched on the folder, not the
|
||||
// filename, so these can be named whatever reads best.
|
||||
if (rel.startsWith('Plugin/unraid/pages/readme/') && base.endsWith('.md')) return 'ui';
|
||||
if (base.endsWith('.md')) {
|
||||
if (base.startsWith('Manual')) return 'manual';
|
||||
if (base.startsWith('README') || base === 'README.md') return 'readme';
|
||||
@@ -237,7 +243,7 @@ function chunkFile(absPath, rel) {
|
||||
} else if (kind === 'template') {
|
||||
raw = sectionsFromConfTemplate(text)
|
||||
.map(s => ({ section: null, heading: s.heading, content: s.content }));
|
||||
} else if (kind === 'readme' || kind === 'manual' || kind === 'doc') {
|
||||
} else if (kind === 'readme' || kind === 'manual' || kind === 'doc' || kind === 'ui') {
|
||||
raw = sectionsFromMarkdown(text)
|
||||
.map(s => ({ section: null, heading: s.heading, content: s.content }));
|
||||
}
|
||||
|
||||
@@ -503,6 +503,36 @@ body.vv-fullscreen #displaybox { padding-left: 1rem !important; padding-top: .5r
|
||||
.vv-info-cols li strong { color: #ccc; }
|
||||
.vv-info-cols code { background: #1a1a1a; padding: 0 4px; border-radius: 2px;
|
||||
font-size: 11px; color: #9ab; border: 1px solid #333; }
|
||||
/* ── Rendered page docs (include/docs.php → pages/readme/*.md) ─────────────────────────────── */
|
||||
/* Two columns so the reference tables and the task sections sit side by side rather than making
|
||||
the panel a long scroll. Headings span both, which is what keeps a task and its steps together
|
||||
instead of splitting across the gap. */
|
||||
.vv-doc { columns: 320px 2; column-gap: 26px; font-size: 12px; color: #aaa; line-height: 1.55; }
|
||||
.vv-doc > h1 { display: none; } /* the panel already has its own title */
|
||||
.vv-doc h2 { column-span: all; margin: 12px -4px 7px; padding: 4px 8px; background: #161a1d;
|
||||
border-left: 2px solid #1e6fa5; font-size: 10px; font-weight: bold;
|
||||
text-transform: uppercase; letter-spacing: .08em; color: #4a8ab5; }
|
||||
.vv-doc h2:first-child { margin-top: 2px; }
|
||||
.vv-doc p { margin: 0 0 7px; break-inside: avoid; }
|
||||
.vv-doc ul, .vv-doc ol { margin: 0 0 8px; padding-left: 16px; }
|
||||
.vv-doc li { margin-bottom: 4px; break-inside: avoid; }
|
||||
.vv-doc strong { color: #ccc; }
|
||||
.vv-doc em { color: #9a9a9a; font-style: italic; }
|
||||
.vv-doc hr { display: none; } /* h2 bars already separate the sections */
|
||||
.vv-doc code { background: #1a1a1a; padding: 0 4px; border-radius: 2px; font-size: 11px;
|
||||
color: #9ab; border: 1px solid #333; }
|
||||
.vv-doc blockquote { margin: 0 0 8px; padding: 6px 9px; background: #16130d;
|
||||
border-left: 2px solid #7a5a2a; color: #b39a72; break-inside: avoid; }
|
||||
.vv-doc .vv-live-var { color: #8fc98f; border-color: #2e4a2e; }
|
||||
.vv-doc .vv-unknown-var { color: #e57; border-color: #5a2a2a; }
|
||||
.vv-doc-table { width: 100%; border-collapse: collapse; margin: 0 0 9px; break-inside: avoid; }
|
||||
.vv-doc-table th { text-align: left; font-size: 9px; text-transform: uppercase; letter-spacing: .07em;
|
||||
color: #4a4a4a; border-bottom: 1px solid #2a2a2a; padding: 3px 6px 3px 0; }
|
||||
.vv-doc-table td { font-size: 11px; color: #999; border-bottom: 1px solid #1a1a1a;
|
||||
padding: 4px 6px 4px 0; vertical-align: top; }
|
||||
.vv-doc-code { background: #0d0d0d; border: 1px solid #222; border-radius: 3px; padding: 7px 9px;
|
||||
font-size: 11px; color: #9ab; overflow-x: auto; break-inside: avoid; }
|
||||
|
||||
.vv-info-divider { font-size: 10px; text-transform: uppercase; letter-spacing: 0.1em; color: #444;
|
||||
padding: 10px 12px 4px; border-top: 1px solid #2a2a2a; margin-top: 2px; }
|
||||
|
||||
|
||||
+136
-12
@@ -83,17 +83,26 @@ function vv_docs_render(string $rel, array $vars): string {
|
||||
if (strtolower(pathinfo($path, PATHINFO_EXTENSION)) !== 'md') return '<p>File not found.</p>';
|
||||
if (!is_file($path)) return '<p>File not found.</p>';
|
||||
|
||||
$md = file_get_contents($path);
|
||||
return vv_docs_markdown(file_get_contents($path), $vars);
|
||||
}
|
||||
|
||||
// Substitute `$VAR_NAME` markers with live conf values
|
||||
$md = preg_replace_callback('/`\$([A-Z0-9_]+)`/', function($m) use ($vars) {
|
||||
$key = $m[1];
|
||||
return isset($vars[$key])
|
||||
? '<code class="vv-live-var">' . htmlspecialchars($vars[$key]) . '</code>'
|
||||
: '<code class="vv-unknown-var">$' . htmlspecialchars($key) . '</code>';
|
||||
}, $md);
|
||||
|
||||
// Render markdown
|
||||
// Markdown → HTML for the subset these docs actually use: headings, paragraphs, bullet and
|
||||
// ordered lists, tables, blockquotes, fenced code, horizontal rules, and inline bold / italic /
|
||||
// code / links.
|
||||
//
|
||||
// Hand-rolled rather than vendored. Parsedown was the original plan and PARSEDOWN_PATH is still
|
||||
// honoured below if the file ever appears, but it has never been present on this system, so the
|
||||
// only path this function ever took was a <pre> dump of raw markdown — which is not a document,
|
||||
// it is the source of one. A renderer for a subset we control is a few dozen lines and adds
|
||||
// nothing to a repo that gets pushed.
|
||||
//
|
||||
// Escape first, then format. Every line is passed through htmlspecialchars() before any tag is
|
||||
// introduced, so the only HTML in the output is HTML this function put there. That is what makes
|
||||
// safe mode unnecessary rather than merely configured — and it is why the $VAR substitution runs
|
||||
// here, after escaping. Injecting <code> into the markdown before rendering, as this file used to
|
||||
// do, meant both Parsedown's safe mode and the <pre> fallback escaped the tags and printed them
|
||||
// as literal text. The feature never worked; nothing called it, so nothing reported it.
|
||||
function vv_docs_markdown(string $md, array $vars): string {
|
||||
if (file_exists(PARSEDOWN_PATH)) {
|
||||
require_once PARSEDOWN_PATH;
|
||||
$pd = new Parsedown();
|
||||
@@ -101,6 +110,121 @@ function vv_docs_render(string $rel, array $vars): string {
|
||||
return $pd->text($md);
|
||||
}
|
||||
|
||||
// Fallback: plain preformatted text
|
||||
return '<pre>' . htmlspecialchars($md) . '</pre>';
|
||||
$inline = function (string $s) use ($vars): string {
|
||||
$s = htmlspecialchars($s, ENT_QUOTES, 'UTF-8');
|
||||
// `$VAR` → the live conf value. Unresolved names render in their own class rather than
|
||||
// silently reading as prose, so a stale reference in a doc is visible as a defect.
|
||||
$s = preg_replace_callback('/`\$([A-Z0-9_]+)`/', function ($m) use ($vars) {
|
||||
return isset($vars[$m[1]])
|
||||
? '<code class="vv-live-var">' . htmlspecialchars($vars[$m[1]]) . '</code>'
|
||||
: '<code class="vv-unknown-var">$' . $m[1] . '</code>';
|
||||
}, $s);
|
||||
$s = preg_replace('/`([^`]+)`/', '<code>$1</code>', $s);
|
||||
$s = preg_replace('/\*\*([^*]+)\*\*/', '<strong>$1</strong>', $s);
|
||||
$s = preg_replace('/(?<![\w*])\*([^*]+)\*(?![\w*])/', '<em>$1</em>', $s);
|
||||
// Links are restricted to http/https and relative paths — a doc is trusted, but these
|
||||
// files sync between hosts, so javascript: must not be reachable through one.
|
||||
$s = preg_replace('/\[([^\]]+)\]\((https?:\/\/[^\s)]+|[^\s):]+)\)/', '<a href="$2">$1</a>', $s);
|
||||
return $s;
|
||||
};
|
||||
|
||||
$out = '';
|
||||
$list = null; // 'ul' | 'ol' | null
|
||||
$inTable = false;
|
||||
$inCode = false;
|
||||
$para = [];
|
||||
$quote = [];
|
||||
|
||||
$flushPara = function () use (&$para, &$out, $inline) {
|
||||
if (!$para) return;
|
||||
$out .= '<p>' . $inline(implode(' ', $para)) . "</p>\n";
|
||||
$para = [];
|
||||
};
|
||||
$flushQuote = function () use (&$quote, &$out, $inline) {
|
||||
if (!$quote) return;
|
||||
$out .= '<blockquote>' . $inline(implode(' ', $quote)) . "</blockquote>\n";
|
||||
$quote = [];
|
||||
};
|
||||
$closeList = function () use (&$list, &$out) {
|
||||
if ($list) { $out .= "</$list>\n"; $list = null; }
|
||||
};
|
||||
$closeTable = function () use (&$inTable, &$out) {
|
||||
if ($inTable) { $out .= "</tbody></table>\n"; $inTable = false; }
|
||||
};
|
||||
|
||||
foreach (explode("\n", str_replace("\r\n", "\n", $md)) as $line) {
|
||||
if (preg_match('/^```/', $line)) {
|
||||
$flushPara(); $closeList(); $closeTable();
|
||||
$out .= $inCode ? "</code></pre>\n" : '<pre class="vv-doc-code"><code>';
|
||||
$inCode = !$inCode;
|
||||
continue;
|
||||
}
|
||||
if ($inCode) { $out .= htmlspecialchars($line, ENT_QUOTES, 'UTF-8') . "\n"; continue; }
|
||||
|
||||
$t = trim($line);
|
||||
|
||||
// One guard rather than a flush in every branch: the quote ends the moment a line is
|
||||
// not a quote line, whatever that next line turns out to be.
|
||||
if ($quote && !str_starts_with($t, '>')) $flushQuote();
|
||||
|
||||
if ($t === '') { $flushPara(); $closeList(); $closeTable(); continue; }
|
||||
if (preg_match('/^(---+|\*\*\*+)$/', $t)) { $flushPara(); $closeList(); $closeTable(); $out .= "<hr>\n"; continue; }
|
||||
|
||||
if (preg_match('/^(#{1,6})\s+(.*)$/', $t, $m)) {
|
||||
$flushPara(); $closeList(); $closeTable();
|
||||
$n = strlen($m[1]);
|
||||
$out .= "<h$n>" . $inline($m[2]) . "</h$n>\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
// Consecutive > lines are one quote, not one per line — same wrapping convention as
|
||||
// paragraphs, which is how they are written.
|
||||
if (preg_match('/^>\s?(.*)$/', $t, $m)) {
|
||||
$closeList(); $closeTable();
|
||||
if (!$quote) $flushPara();
|
||||
$quote[] = $m[1];
|
||||
continue;
|
||||
}
|
||||
|
||||
// Tables: a header row, a separator of dashes, then body rows. The separator is what
|
||||
// identifies the block — a lone pipe in prose is not a table.
|
||||
if (strpos($t, '|') !== false && preg_match('/^\|?[\s:-]*-[\s|:-]*\|/', $t)) {
|
||||
continue; // separator consumed by the header below
|
||||
}
|
||||
if (strpos($t, '|') !== false && substr_count($t, '|') >= 2) {
|
||||
$cells = array_map('trim', explode('|', trim($t, '| ')));
|
||||
if (!$inTable) {
|
||||
$flushPara(); $closeList();
|
||||
$out .= '<table class="vv-doc-table"><thead><tr>';
|
||||
foreach ($cells as $c) $out .= '<th>' . $inline($c) . '</th>';
|
||||
$out .= "</tr></thead><tbody>\n";
|
||||
$inTable = true;
|
||||
} else {
|
||||
$out .= '<tr>';
|
||||
foreach ($cells as $c) $out .= '<td>' . $inline($c) . '</td>';
|
||||
$out .= "</tr>\n";
|
||||
}
|
||||
continue;
|
||||
}
|
||||
$closeTable();
|
||||
|
||||
if (preg_match('/^[-*]\s+(.*)$/', $t, $m)) {
|
||||
$flushPara();
|
||||
if ($list !== 'ul') { $closeList(); $out .= "<ul>\n"; $list = 'ul'; }
|
||||
$out .= '<li>' . $inline($m[1]) . "</li>\n";
|
||||
continue;
|
||||
}
|
||||
if (preg_match('/^\d+\.\s+(.*)$/', $t, $m)) {
|
||||
$flushPara();
|
||||
if ($list !== 'ol') { $closeList(); $out .= "<ol>\n"; $list = 'ol'; }
|
||||
$out .= '<li>' . $inline($m[1]) . "</li>\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
$para[] = $t;
|
||||
}
|
||||
|
||||
$flushQuote(); $flushPara(); $closeList(); $closeTable();
|
||||
if ($inCode) $out .= "</code></pre>\n";
|
||||
return $out;
|
||||
}
|
||||
|
||||
@@ -307,6 +307,7 @@ if (is_dir('/var/log/varaverk')) {
|
||||
<div>
|
||||
<select id="vv-ai-kind" title="Restrict retrieval to one kind of source">
|
||||
<option value="">All sources</option>
|
||||
<option value="ui">WebUI — how the pages work</option>
|
||||
<option value="readme">README — what things are</option>
|
||||
<option value="manual">Manual — how to do things</option>
|
||||
<option value="header">Script headers</option>
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
# Scheduler
|
||||
|
||||
Everything that runs on a timer is decided here. The page is the front end for two files:
|
||||
`schedule.json` holds when things fire, and `master.conf` holds which steps an orchestrator
|
||||
actually calls. Every control below writes to one of those two — nothing on this page needs a
|
||||
conf file opened by hand.
|
||||
|
||||
**An orchestrator is a job that calls other scripts in order.** The orchestrator has the cron
|
||||
entry; its steps do not. That one fact explains most of the behaviour below.
|
||||
|
||||
---
|
||||
|
||||
## Stopping one step without disabling the whole job
|
||||
|
||||
The common case: a nightly job is fine, but one script inside it should stop running.
|
||||
|
||||
1. Find the orchestrator's card — for example **Daily Sync Maintenance**.
|
||||
2. Click **Steps ▸** on the right of its row. The list of scripts it calls expands.
|
||||
3. Toggle off the one you want stopped.
|
||||
|
||||
The orchestrator keeps running on its schedule and simply skips that step. Under the hood the
|
||||
toggle comments the script out of that orchestrator's array in `master.conf`, which is the same
|
||||
edit you would make by hand — the toggle is just the safe way to make it.
|
||||
|
||||
Turn it back on with the same toggle. The commented line is left in place, so the step keeps its
|
||||
position in the sequence rather than being appended to the end.
|
||||
|
||||
> The button is called **Steps**, not Advanced. There is a separate **Advanced** button at the
|
||||
> top right of the panel that does something quite different — see *Advanced mode* below.
|
||||
|
||||
## Turning an orchestrator off entirely
|
||||
|
||||
Toggle the orchestrator itself off. Its cron entry stops firing and **every step inside it is
|
||||
suppressed** — an enabled step under a disabled orchestrator does not run, because the
|
||||
orchestrator is what calls it.
|
||||
|
||||
If you still want one of those scripts running while its orchestrator is off, give that step its
|
||||
own cron expression. With the orchestrator off, a step's cron field becomes live and it fires
|
||||
standalone.
|
||||
|
||||
## Running something right now
|
||||
|
||||
**Run** fires the script immediately and resets its cron timer, so the next scheduled fire is a
|
||||
full interval later rather than a few minutes away.
|
||||
|
||||
**Dry Run** passes `--dry-run`. Nothing is written to disk, and the full output is shown rather
|
||||
than a summary — with the cleanup scripts, reading the list of what *would* be removed is the
|
||||
entire point. Anything destructive offers both, and Run asks for confirmation first.
|
||||
|
||||
## Changing when something runs
|
||||
|
||||
Type into the cron field. It saves when the field loses focus, shows the schedule back to you in
|
||||
plain English, and turns red if the expression is invalid.
|
||||
|
||||
Two shortcuts worth knowing:
|
||||
|
||||
- **Suggested cron** — in the Orch tree on the right, each script shows a suggested cron badge.
|
||||
Click it to apply and save that schedule instantly.
|
||||
- **Cron Calculator** — accepts an expression or plain English, shows a description plus the next
|
||||
five fire times, and **Apply** pushes it into the cron field you last used.
|
||||
|
||||
For array events, put `array_start` or `array_stop` in the cron field instead of an expression.
|
||||
A badge appears and the script fires on Unraid's array start or stop. This works for any
|
||||
orchestrator or custom script.
|
||||
|
||||
## Finding out why something failed
|
||||
|
||||
**Log** opens that script's log in the right-hand panel. It auto-scrolls to the newest line,
|
||||
pauses when you scroll up, and resumes when you return to the bottom. **Invert** puts newest
|
||||
lines at the top. The **Search** box in the toolbar filters and highlights matches while dimming
|
||||
everything else.
|
||||
|
||||
Two blocks on the Scheduler Info panel get you there faster:
|
||||
|
||||
- **Recent Activity** — the last 24 runs. Click any row to open that log. Expands itself when
|
||||
there are errors.
|
||||
- **Recent Errors** — the most recent error per script over 7 days, so a failure that happened
|
||||
once at 3am is still visible days later.
|
||||
|
||||
The status dot in the Orch tree is green, orange or red for the last run's outcome, dim if the
|
||||
script has never run. Hover for detail.
|
||||
|
||||
## Stopping a script that is stuck
|
||||
|
||||
**Stop** sends SIGTERM, waits 3 seconds, then SIGKILL, and clears any lock files the script left
|
||||
behind.
|
||||
|
||||
Locks are never cleared automatically anywhere in Varaverk, and that is deliberate — a lock that
|
||||
looks stale may belong to a job that is still working. Stop is the explicit way to say you have
|
||||
decided otherwise.
|
||||
|
||||
## Moving a script between orchestrators
|
||||
|
||||
Use **Arrange** to drag scripts between orchestrators. Dropping one onto the right-hand panel
|
||||
removes it from its orchestrator. Nothing is written until you click **Save Arrangement**, which
|
||||
commits the new order to `master.conf`.
|
||||
|
||||
Order matters — an orchestrator runs its steps in the sequence shown.
|
||||
|
||||
## Adding your own script
|
||||
|
||||
Custom scripts live in `$CUSTOM_SCRIPTS_DIR`, outside the git repo. Any `*.sh` placed there is
|
||||
detected and listed automatically; it does not have to be registered anywhere. Being outside the
|
||||
repo means a `git pull` never touches your scripts and they are never committed by accident.
|
||||
|
||||
**+ Folder** creates a collapsible subfolder in Custom Scripts that you can drag scripts into.
|
||||
|
||||
While editing, **Cancel** discards your changes and returns to the Scheduler Info panel. The file
|
||||
on disk is never touched until you press Save.
|
||||
|
||||
---
|
||||
|
||||
## Reference — the controls on a job row
|
||||
|
||||
| Control | What it does |
|
||||
|---|---|
|
||||
| **Toggle** | Enable/disable. Saves immediately to `schedule.json` |
|
||||
| **Cron field** | Schedule. Auto-saves on focus-out; plain-English hint; red border means invalid |
|
||||
| **⚙ Cog** | Settings panel — the script's own header, matching README/Manual sections, and its config fields |
|
||||
| **Script name** | Jumps to that script's entry in the Orch tree on the right |
|
||||
| **Run** | Execute now; resets the cron timer |
|
||||
| **Dry Run** | Execute with `--dry-run`; writes nothing |
|
||||
| **Log** | Open this script's log in the right panel |
|
||||
| **Verbose** | Appends `--log` for per-item detail in the output |
|
||||
| **Steps ▸** | Expand the scripts this orchestrator calls |
|
||||
|
||||
## Reference — orchestrator and step behaviour
|
||||
|
||||
| State | Behaviour |
|
||||
|---|---|
|
||||
| Orchestrator **ON** | Sole trigger. Cron fires the orchestrator, which calls its steps in sequence |
|
||||
| Orchestrator **OFF** | Never runs automatically. Steps are suppressed; each can take its own cron |
|
||||
| Step, orchestrator ON | Toggle comments/uncomments the script in `master.conf` |
|
||||
| Step, orchestrator ON, no conf array | The orchestrator hardcodes the call — the toggle is display-only |
|
||||
| Step, orchestrator OFF | Enter a cron to run it standalone |
|
||||
| Rsync badge | Toggle writes `TIER_RSYNC_ENABLED` straight to `master.conf` |
|
||||
| Rsync, orchestrator OFF | Needs both a location and a standalone cron before it will fire independently |
|
||||
|
||||
## Reference — the Scheduler Info panel
|
||||
|
||||
The right-hand panel is the default view and everything returns to it. **← Scheduler Info** comes
|
||||
back here from any log, editor, conf form or script view.
|
||||
|
||||
- **Notification board** — how many jobs are scheduled out of the total, and what is running now.
|
||||
- **Next Runs** — what fires next, and when.
|
||||
- **Recent Activity** / **Recent Errors** — described above.
|
||||
- **Cron Calculator** — described above.
|
||||
|
||||
## Reference — Advanced mode
|
||||
|
||||
The **Advanced** button at the top right turns blue when active. It is a display and editing
|
||||
mode, unrelated to the **Steps ▸** expander on each orchestrator:
|
||||
|
||||
- The ⚙ cog switches to an enriched view — full script source, documentation and config together.
|
||||
- Raw conf editing unlocks, including direct buttons for each conf file.
|
||||
- **Git Pull** appears on the notification board, which pulls the latest scripts and runs a conf
|
||||
upgrade.
|
||||
|
||||
Raw conf editing writes the file directly. The toggles elsewhere on this page are surgical — they
|
||||
preserve the comment blocks that document every threshold — so prefer them where one exists.
|
||||
|
||||
## Reference — what this page writes
|
||||
|
||||
| File | Written by |
|
||||
|---|---|
|
||||
| `schedule.json` | Every toggle and cron field |
|
||||
| `master.conf` | Step toggles, Save Arrangement, rsync tier flags, raw conf editing |
|
||||
| `CUSTOM_SCRIPTS_DIR` | The custom script editor |
|
||||
|
||||
Cron changes take effect on the next cron rebuild. Nothing here edits the running crontab
|
||||
directly — `varaverk.cron` is regenerated from `schedule.json`.
|
||||
@@ -59,6 +59,15 @@
|
||||
// api/savefolders.php folder grouping api/reorderarray.php
|
||||
// api/rsync_standalone.php
|
||||
require_once dirname(__DIR__) . '/include/scheduler.php';
|
||||
require_once dirname(__DIR__) . '/include/docs.php';
|
||||
|
||||
// Live values for the `$VAR` markers in pages/readme/*.md. Conf variables, plus the derived
|
||||
// path constants — those are not conf keys, but they are exactly what a reader needs resolved
|
||||
// rather than described.
|
||||
$_vv_doc_vars = array_merge(vv_conf_vars(), [
|
||||
'CUSTOM_SCRIPTS_DIR' => CUSTOM_SCRIPTS_DIR,
|
||||
'SCRIPTS_DIR' => SCRIPTS_DIR,
|
||||
]);
|
||||
|
||||
// Setup mode — auto-open a conf file and force the editing sequence
|
||||
$vv_setup_conf = preg_match('/^[\w.]+\.conf$/', $_GET['vv_setup'] ?? '')
|
||||
@@ -495,38 +504,14 @@ $runningScripts = array_unique($runningScripts);
|
||||
<span class="vv-sug-chevron">▾</span>
|
||||
<span class="vv-sug-title">How do I use this</span>
|
||||
</div>
|
||||
<!-- Rendered from pages/readme/scheduler-readme.md, not maintained here. That file is
|
||||
also what the AI tab retrieves, so the panel you read and the answer the
|
||||
assistant gives are the same text and cannot drift — the same argument that
|
||||
makes this page parse script PURPOSE blocks instead of restating them. -->
|
||||
<div class="vv-sug-body vv-info-body">
|
||||
<ul class="vv-info-cols">
|
||||
<li><strong>Toggle</strong> — saves immediately to schedule.json</li>
|
||||
<li><strong>Cron field</strong> — auto-saved on focus-out; hint shows plain English; red border = invalid</li>
|
||||
<li><strong>⚙ Cog</strong> — opens settings panel: script header + matching README/Manual sections + config fields</li>
|
||||
<li><strong>Script name</strong> — click navigates to the matching entry in the Orch tree (right panel)</li>
|
||||
<li><strong>Run</strong> — fires script immediately; resets the cron timer so next fire is one full interval later</li>
|
||||
<li><strong>Dry Run</strong> — same as Run but passes <code>--dry-run</code>; no changes written to disk</li>
|
||||
<li><strong>Log</strong> — opens script log here; auto-scrolls; use Search box to filter/highlight lines</li>
|
||||
<li><strong>Stop</strong> — SIGTERM → 3 s → SIGKILL; clears stuck lock files</li>
|
||||
<li><strong>Verbose</strong> — appends <code>--log</code> flag for per-item detail output</li>
|
||||
<li><strong>Cancel</strong> — discards changes and returns here; file is never touched until Save</li>
|
||||
<li><strong>⚡ Array events</strong> — set any cron field to <code>array_start</code> or <code>array_stop</code>; badge appears; fires on Unraid array start/stop; works on any orch or custom script</li>
|
||||
<li><strong>Arrange</strong> — drag scripts between orchs; drop to right panel removes from orch; Save Arrangement commits to master.conf</li>
|
||||
<li><strong>+ Folder</strong> — collapsible subfolder in Custom Scripts; drag scripts in</li>
|
||||
<li><strong>Suggested cron</strong> — click the cron code badge in the Orch tree to apply and save instantly</li>
|
||||
<li><strong>Status dot (tree)</strong> — green/orange/red ● = last run ok/warn/error; dim = never run; hover for detail</li>
|
||||
<li><strong>Cron Calculator</strong> — type an expression or plain English; shows description + next 5 fires; Apply pushes to last-focused cron field</li>
|
||||
<li><strong>Recent Activity</strong> — last 24 runs; click a row to open that log; auto-expands on errors</li>
|
||||
<li><strong>Recent Errors</strong> — last error per script (7 days); click to open log; auto-expands on new errors</li>
|
||||
<li><strong>Advanced</strong> — top-right button, turns blue; ⚙ shows enriched view (header + docs + config); raw conf editing unlocked</li>
|
||||
<li><strong>Log search</strong> — filter box in toolbar when log is open; highlights matches, dims others</li>
|
||||
<li><strong>← Scheduler Info</strong> — returns here from any log, editor, conf, or script view</li>
|
||||
<li class="vv-info-sep">Orchestrator & Child Behaviour</li>
|
||||
<li><strong>Orch ON</strong> — sole trigger; cron fires the orch; it calls children in sequence</li>
|
||||
<li><strong>Orch OFF</strong> — never runs automatically; children suppressed; each can get its own standalone cron</li>
|
||||
<li><strong>Child (orch ON)</strong> — toggle comments/uncomments the script in master.conf</li>
|
||||
<li><strong>Child (orch ON, no array)</strong> — orch hardcodes the call; toggle is display-only</li>
|
||||
<li><strong>Child (orch OFF)</strong> — enter a cron to run it standalone</li>
|
||||
<li><strong>Rsync badge</strong> — toggle writes TIER_RSYNC_ENABLED directly to master.conf</li>
|
||||
<li><strong>Rsync (orch OFF)</strong> — fill location + standalone cron + Save; both required for independent firing</li>
|
||||
</ul>
|
||||
<div class="vv-doc">
|
||||
<?= vv_docs_render('Plugin/unraid/pages/readme/scheduler-readme.md', $_vv_doc_vars) ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user