OwlCyberSecurity - MANAGER
Edit File: comet_account_capture_refresh
#!/usr/local/cpanel/3rdparty/bin/perl # Copyright 2026 WebPros International, LLC # All rights reserved. # copyright@cpanel.net http://cpanel.net # This code is subject to the cPanel license. Unauthorized copying is prohibited. package scripts::comet_account_capture_refresh; use cPstrict; use Getopt::Long qw(GetOptions); use Pod::Usage qw(pod2usage); use Cpanel::Logger; use Cpanel::Debug (); use Fcntl qw( :flock O_CREAT O_RDWR ); use Whostmgr::CometBackup::AccountCapture (); my $LOCK_FILE = '/var/run/comet_account_capture_refresh.lock'; my $logger = Cpanel::Logger->new(); =encoding utf-8 =head1 NAME comet_account_capture_refresh - Nightly full refresh of per-account Comet capture artifacts (the account manifest). =head1 SYNOPSIS comet_account_capture_refresh [options] Options: --help, -h Show this help --verbose, -v Verbose logging --debug, -d Enable debug logging =head1 DESCRIPTION Iterates every account this plugin backs up (the union of accounts across all active backup jobs) and refreshes each account's manifest and secret artifact by driving L<Whostmgr::CometBackup::AccountCapture/refresh_all_backed_up_accounts>. Designed to be run once nightly from cron alongside the account-lifecycle hooks (L<Whostmgr::CometBackup::Hooks::AccountCapture>), which keep artifacts current between sweeps. The sweep is failure-isolated per account: one account's failure is logged and the sweep continues. An C<flock> prevents overlapping runs. =cut sub main { # Plugin policy: nothing in this process should be world-readable. The # secret artifact is written 0600 by the exporter, but keep the whole # process defensive. umask 0027; my ( $help, $verbose, $debug ); GetOptions( 'help|h' => \$help, 'verbose|v' => \$verbose, 'debug|d' => \$debug, ) or pod2usage(2); pod2usage(1) if $help; if ($debug) { $Cpanel::Debug::level = 1; } # Single-instance guard, held for the life of this process. # # An flock rather than an existence check (review suggestion, PR #2556): the # previous exists() / unlink / create() sequence was a TOCTOU. Two invocations # could both decide the same lock file was stale, and the second would unlink # the lock the first had just created and take its own -- so both sweeps ran, # which is exactly what the guard exists to prevent. There is also no stale lock # to reclaim with an flock: the kernel drops it when the holder exits, however # it exits, so the "previous process died without cleaning up" branch that made # the race necessary is gone rather than fixed. # # The lock FILE is deliberately never unlinked -- unlinking is what reintroduces # the race. A 0-byte file under /var/run is the normal cost of an flock guard. my $lock_fh; unless ( sysopen( $lock_fh, $LOCK_FILE, O_CREAT | O_RDWR, 0600 ) ) { $logger->error("Failed to open lock file $LOCK_FILE: $!; cannot proceed."); exit 1; ## no critic (Cpanel::NoExitsFromSubroutines) } unless ( flock( $lock_fh, LOCK_EX | LOCK_NB ) ) { $logger->info('Another comet_account_capture_refresh is already running; exiting.'); exit 0; } $logger->info("Starting nightly Comet account capture refresh") if $verbose; my $summary = eval { Whostmgr::CometBackup::AccountCapture::refresh_all_backed_up_accounts() }; my $run_err = $@; if ($run_err) { chomp $run_err; $logger->error("Error in comet_account_capture_refresh: $run_err"); exit 1; } if ( $verbose && ref $summary eq 'HASH' ) { $logger->info( "Comet account capture refresh complete: " . "total=$summary->{total} refreshed=$summary->{refreshed} failed=$summary->{failed}" ); } return; } # Run the main function if this script is executed directly. main() if !caller; 1; __END__ =head1 SEE ALSO L<Whostmgr::CometBackup::AccountCapture>, L<Whostmgr::CometBackup::Hooks::AccountCapture>, L<Whostmgr::CometBackup::AccountManifestExporter> =head1 AUTHOR WebPros International, LLC =head1 COPYRIGHT Copyright 2026 WebPros International, LLC. All rights reserved. =cut