Varaverk: rsync flag toggle + stop button
- Rsync/rsync.sh children in Advanced now show as conf_flag type when the parent orch controls a *_RSYNC_ENABLED tier flag; toggle writes true/false to master.conf instead of comment/uncommenting a SCRIPTS array entry - Added vv_conf_flag_value() and vv_conf_flag_set() helpers in scheduler.php - Added api/flag_toggle.php endpoint (validates *_RSYNC_ENABLED pattern) - Added api/stop.php: kills process group, sweeps stuck locks, updates stat - vv-flag-badge CSS (amber, monospace) to distinguish from event/script rows - vvSaveChild() routes conf_flag children to flag_toggle.php unconditionally - vvApplyOrchState() keeps conf_flag toggle at real flag value; disables when orch off - vvSaveAll() skips conf_flag children (immediate-save only)
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
require_once dirname(__DIR__) . '/include/scheduler.php';
|
||||
|
||||
$name = trim($_POST['name'] ?? '');
|
||||
$enabled = ($_POST['enabled'] ?? '0') === '1';
|
||||
|
||||
if (!$name || !preg_match('/^[A-Z_]+_RSYNC_ENABLED$/', $name)) {
|
||||
echo json_encode(['ok' => false, 'error' => 'Invalid flag name']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$ok = vv_conf_flag_set($name, $enabled);
|
||||
echo json_encode(['ok' => $ok, 'error' => $ok ? null : 'Failed to write master.conf']);
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
require_once dirname(__DIR__) . '/include/scheduler.php';
|
||||
|
||||
$id = trim($_POST['id'] ?? '');
|
||||
|
||||
if (!$id || !preg_match('/^[a-zA-Z0-9_.\/\-]+\.sh$/', $id) || str_contains($id, '..')) {
|
||||
echo json_encode(['ok' => false, 'error' => 'Invalid id']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$statFile = vv_job_stat_path($id);
|
||||
if (!file_exists($statFile)) {
|
||||
echo json_encode(['ok' => false, 'error' => 'No stat file — script may not be running']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stat = json_decode(file_get_contents($statFile) ?: '{}', true) ?: [];
|
||||
|
||||
if (($stat['status'] ?? '') !== 'running') {
|
||||
echo json_encode(['ok' => true, 'msg' => 'Not running']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$pid = (int)($stat['pid'] ?? 0);
|
||||
if ($pid < 2) {
|
||||
echo json_encode(['ok' => false, 'error' => 'No valid PID in stat file']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Kill the whole process group so the script and all its children die together.
|
||||
// pgid is usually the same as the session leader PID from run_job.sh.
|
||||
$pgid = (int)trim(shell_exec("ps -o pgid= -p $pid 2>/dev/null") ?: '0');
|
||||
|
||||
if ($pgid > 1) {
|
||||
shell_exec("kill -TERM -$pgid 2>/dev/null");
|
||||
} else {
|
||||
// Fallback: kill the direct PID and its children
|
||||
shell_exec("pkill -TERM -P $pid 2>/dev/null");
|
||||
shell_exec("kill -TERM $pid 2>/dev/null");
|
||||
}
|
||||
|
||||
// Give it up to 3s to exit gracefully
|
||||
$dead = false;
|
||||
for ($i = 0; $i < 6; $i++) {
|
||||
usleep(500000);
|
||||
if (!file_exists("/proc/$pid")) { $dead = true; break; }
|
||||
}
|
||||
|
||||
// Force-kill if still alive
|
||||
if (!$dead) {
|
||||
if ($pgid > 1) shell_exec("kill -KILL -$pgid 2>/dev/null");
|
||||
shell_exec("pkill -KILL -P $pid 2>/dev/null");
|
||||
shell_exec("kill -KILL $pid 2>/dev/null");
|
||||
usleep(300000);
|
||||
$dead = !file_exists("/proc/$pid");
|
||||
}
|
||||
|
||||
// Clear any lock files in /tmp/unraid_locks whose content matches this PID
|
||||
$lockDir = '/tmp/unraid_locks';
|
||||
$cleared = [];
|
||||
foreach (glob("$lockDir/*.lock") ?: [] as $lf) {
|
||||
$content = trim(file_get_contents($lf) ?: '');
|
||||
$lockPid = (int)explode(':', $content)[0];
|
||||
if ($lockPid === $pid || !file_exists("/proc/$lockPid")) {
|
||||
@unlink($lf);
|
||||
$cleared[] = basename($lf);
|
||||
}
|
||||
}
|
||||
|
||||
// Also clear by script name in case PID rotated
|
||||
$scriptBase = basename($id, '.sh');
|
||||
$namedLock = "$lockDir/{$scriptBase}.lock";
|
||||
if (file_exists($namedLock)) {
|
||||
@unlink($namedLock);
|
||||
if (!in_array(basename($namedLock), $cleared)) $cleared[] = basename($namedLock);
|
||||
}
|
||||
|
||||
// Update stat file
|
||||
$now = time();
|
||||
$stat['status'] = 'stopped';
|
||||
$stat['end'] = $now;
|
||||
$stat['exit'] = -1;
|
||||
unset($stat['pid']);
|
||||
file_put_contents($statFile, json_encode($stat));
|
||||
|
||||
echo json_encode([
|
||||
'ok' => true,
|
||||
'killed' => $dead,
|
||||
'locks' => $cleared,
|
||||
]);
|
||||
Reference in New Issue
Block a user