Add Run Now button to schedules page
Adds a "Run Now" button in each schedule's Actions column that triggers the backup in the background, logging to the same cron log file. Forks the process and redirects immediately. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -22,6 +22,7 @@ if ($action eq 'add') { handle_add() }
|
|||||||
elsif ($action eq 'edit') { handle_edit() }
|
elsif ($action eq 'edit') { handle_edit() }
|
||||||
elsif ($action eq 'delete') { handle_delete() }
|
elsif ($action eq 'delete') { handle_delete() }
|
||||||
elsif ($action eq 'toggle_cron') { handle_toggle_cron() }
|
elsif ($action eq 'toggle_cron') { handle_toggle_cron() }
|
||||||
|
elsif ($action eq 'run_now') { handle_run_now() }
|
||||||
else { handle_list() }
|
else { handle_list() }
|
||||||
|
|
||||||
exit;
|
exit;
|
||||||
@@ -66,13 +67,21 @@ sub handle_list {
|
|||||||
print qq{<input type="checkbox" class="toggle toggle-sm toggle-success" data-schedule="$esc_name" onchange="gnizaToggleCron(this)"$checked>};
|
print qq{<input type="checkbox" class="toggle toggle-sm toggle-success" data-schedule="$esc_name" onchange="gnizaToggleCron(this)"$checked>};
|
||||||
print qq{</td>};
|
print qq{</td>};
|
||||||
print qq{<td>};
|
print qq{<td>};
|
||||||
print qq{<a href="schedules.cgi?action=edit&name=$esc_name" class="btn btn-ghost btn-sm">Edit</a> };
|
print qq{<div class="flex items-center gap-2">};
|
||||||
|
print qq{<form method="POST" action="schedules.cgi" style="display:inline">};
|
||||||
|
print qq{<input type="hidden" name="action" value="run_now">};
|
||||||
|
print qq{<input type="hidden" name="name" value="$esc_name">};
|
||||||
|
print GnizaWHM::UI::csrf_hidden_field();
|
||||||
|
print qq{<button type="submit" class="btn btn-secondary btn-sm" onclick="return confirm('Run backup for schedule $esc_name now?')">Run Now</button>};
|
||||||
|
print qq{</form>};
|
||||||
|
print qq{<a href="schedules.cgi?action=edit&name=$esc_name" class="btn btn-ghost btn-sm">Edit</a>};
|
||||||
print qq{<form method="POST" action="schedules.cgi" style="display:inline">};
|
print qq{<form method="POST" action="schedules.cgi" style="display:inline">};
|
||||||
print qq{<input type="hidden" name="action" value="delete">};
|
print qq{<input type="hidden" name="action" value="delete">};
|
||||||
print qq{<input type="hidden" name="name" value="$esc_name">};
|
print qq{<input type="hidden" name="name" value="$esc_name">};
|
||||||
print GnizaWHM::UI::csrf_hidden_field();
|
print GnizaWHM::UI::csrf_hidden_field();
|
||||||
print qq{<button type="submit" class="btn btn-error btn-sm" onclick="return confirm('Delete schedule $esc_name?')">Delete</button>};
|
print qq{<button type="submit" class="btn btn-error btn-sm" onclick="return confirm('Delete schedule $esc_name?')">Delete</button>};
|
||||||
print qq{</form>};
|
print qq{</form>};
|
||||||
|
print qq{</div>};
|
||||||
print qq{</td>};
|
print qq{</td>};
|
||||||
print qq{</tr>\n};
|
print qq{</tr>\n};
|
||||||
}
|
}
|
||||||
@@ -322,6 +331,78 @@ sub handle_delete {
|
|||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ── Run Now ──────────────────────────────────────────────────
|
||||||
|
|
||||||
|
sub handle_run_now {
|
||||||
|
if ($method ne 'POST') {
|
||||||
|
print "Status: 302 Found\r\n";
|
||||||
|
print "Location: schedules.cgi\r\n\r\n";
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
unless (GnizaWHM::UI::verify_csrf_token($form->{'gniza_csrf'})) {
|
||||||
|
GnizaWHM::UI::set_flash('error', 'Invalid or expired form token.');
|
||||||
|
print "Status: 302 Found\r\n";
|
||||||
|
print "Location: schedules.cgi\r\n\r\n";
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $name = $form->{'name'} // '';
|
||||||
|
my $name_err = GnizaWHM::Validator::validate_schedule_name($name);
|
||||||
|
if ($name_err) {
|
||||||
|
GnizaWHM::UI::set_flash('error', 'Invalid schedule name.');
|
||||||
|
print "Status: 302 Found\r\n";
|
||||||
|
print "Location: schedules.cgi\r\n\r\n";
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $conf_path = GnizaWHM::UI::schedule_conf_path($name);
|
||||||
|
unless (-f $conf_path) {
|
||||||
|
GnizaWHM::UI::set_flash('error', "Schedule '$name' not found.");
|
||||||
|
print "Status: 302 Found\r\n";
|
||||||
|
print "Location: schedules.cgi\r\n\r\n";
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $conf = GnizaWHM::Config::parse($conf_path, 'schedule');
|
||||||
|
my $remotes = $conf->{REMOTES} // '';
|
||||||
|
$remotes =~ s/^\s+|\s+$//g;
|
||||||
|
|
||||||
|
# Build command
|
||||||
|
my @cmd = ('/usr/local/bin/gniza', 'backup');
|
||||||
|
if ($remotes ne '') {
|
||||||
|
push @cmd, "--remote=$remotes";
|
||||||
|
}
|
||||||
|
|
||||||
|
my $log_file = "/var/log/gniza/cron-${name}.log";
|
||||||
|
|
||||||
|
# Fork to background
|
||||||
|
my $pid = fork();
|
||||||
|
if (!defined $pid) {
|
||||||
|
GnizaWHM::UI::set_flash('error', "Failed to fork backup process: $!");
|
||||||
|
print "Status: 302 Found\r\n";
|
||||||
|
print "Location: schedules.cgi\r\n\r\n";
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($pid == 0) {
|
||||||
|
# Child: detach and exec
|
||||||
|
close STDIN;
|
||||||
|
close STDOUT;
|
||||||
|
close STDERR;
|
||||||
|
open STDOUT, '>>', $log_file;
|
||||||
|
open STDERR, '>&', \*STDOUT;
|
||||||
|
exec @cmd;
|
||||||
|
exit 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Parent: don't wait, redirect immediately
|
||||||
|
GnizaWHM::UI::set_flash('success', "Backup started for schedule '$name'. Check Logs for progress.");
|
||||||
|
print "Status: 302 Found\r\n";
|
||||||
|
print "Location: schedules.cgi\r\n\r\n";
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
# ── Toggle Cron ──────────────────────────────────────────────
|
# ── Toggle Cron ──────────────────────────────────────────────
|
||||||
|
|
||||||
sub handle_toggle_cron {
|
sub handle_toggle_cron {
|
||||||
|
|||||||
Reference in New Issue
Block a user