diff --git a/whm/gniza-whm/schedules.cgi b/whm/gniza-whm/schedules.cgi
index d3d8285..592b7eb 100644
--- a/whm/gniza-whm/schedules.cgi
+++ b/whm/gniza-whm/schedules.cgi
@@ -22,6 +22,7 @@ if ($action eq 'add') { handle_add() }
elsif ($action eq 'edit') { handle_edit() }
elsif ($action eq 'delete') { handle_delete() }
elsif ($action eq 'toggle_cron') { handle_toggle_cron() }
+elsif ($action eq 'run_now') { handle_run_now() }
else { handle_list() }
exit;
@@ -66,13 +67,21 @@ sub handle_list {
print qq{};
print qq{};
print qq{
};
- print qq{Edit };
+ print qq{};
+ print qq{ };
+ print qq{ Edit};
print qq{ };
+ print qq{ };
print qq{ | };
print qq{\n};
}
@@ -322,6 +331,78 @@ sub handle_delete {
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 ──────────────────────────────────────────────
sub handle_toggle_cron {