PATH:
usr
/
local
/
cpanel
/
scripts
#!/usr/local/cpanel/3rdparty/bin/perl # cpanel - scripts/upcp Copyright 2022 cPanel, L.L.C. # All rights reserved. # copyright@cpanel.net http://cpanel.net # This code is subject to the cPanel license. Unauthorized copying is prohibited package scripts::upcp; BEGIN { unshift @INC, q{/usr/local/cpanel}; # if we are being called with a compile check flag ( perl -c ), skip the begin block # so we don't actually call upcp.static when just checking syntax and such is OK return if $^C; # static never gets --use-checked and should pass all the begin block checks return if $0 =~ /\.static$/; # let the '--use-check' instance compiled if ( grep { $_ eq '--use-check' } @ARGV ) { no warnings; # dynamic definition of the INIT block eval "INIT { exit(0); }"; return; } system("$0 --use-check >/dev/null 2>&1"); # compilation is ok with '--use-check', we will continue the non static version return if $? == 0; my $static = $0 . ".static"; if ( -f $static ) { print STDERR "We determined that $0 had compilation issues..\n"; print STDERR "Trying to exec $static " . join( ' ', @ARGV ) . "\n"; exec( $^X, $static, @ARGV ); } } use cPstrict; no warnings; ## no critic qw(ProhibitNoWarnings) use Try::Tiny; use Cpanel::OS::All (); # PPI USE OK -- make sure Cpanel::OS is embedded use Cpanel::HiRes ( preload => 'perl' ); use Cpanel::Env (); use Cpanel::Update::IsCron (); use Cpanel::Update::Logger (); use Cpanel::FileUtils::TouchFile (); use Cpanel::LoadFile (); use Cpanel::LoadModule (); use Cpanel::Usage (); use Cpanel::UPID (); use IO::Handle (); use POSIX (); use Cpanel::Unix::PID::Tiny (); my $pidfile = '/var/run/upcp.pid'; my $lastlog = '/var/cpanel/updatelogs/last'; my $upcp_disallowed_path = '/root/.upcp_controlc_disallowed'; my $version_upgrade_file = '/usr/local/cpanel/upgrade_in_progress.txt'; our $logger; # Global for logger object. our $logfile_path; my $now; my $forced = 0; my $fromself = 0; my $sync_requested = 0; my $bg = 0; my $from_version; my $pbar_starting_point; exit( upcp() || 0 ) unless caller(); sub usage { print <<EOS; Usage: scripts/upcp [--bg] [--cron] [--force] [--help] [--log=[path]] [--sync] Updates cPanel & WHM. Options: --bg Runs upcp in the background. Output is only visible in the log. --cron Follow WHM's Update Preferences (/etc/cpupdate.conf). --force Force a reinstall even if the system is up to date. --help Display this documentation. --log=[path] Overrides the default log file. --sync Updates the server to the currently-installed version instead of downloading a newer version. This will also run other maintenance items, such as package updates and repairs. You cannot use the --sync argument with the --force argument. EOS exit 1; ## no critic(Cpanel::NoExitsFromSubroutines) -- /scripts/upcp needs refactor to use Getopt } sub upcp { ## no critic(Subroutines::ProhibitExcessComplexity) - preserve original code Cpanel::Usage::wrap_options( \@ARGV, \&usage, {} ); #display usage information on --help open( STDERR, ">&STDOUT" ) or die $!; local $| = 1; umask(0022); $now = time(); setupenv(); unset_rlimits(); ############################################################################# # Record the arguments used when started, check for certain flags my $update_is_available_exit_code = 42; my @retain_argv = @ARGV; foreach my $arg (@ARGV) { if ( $arg =~ m/^--log=(.*)/ ) { $logfile_path = $1; } elsif ( $arg eq '--fromself' ) { $fromself = 1; } elsif ( $arg eq '--force' ) { $forced = 1; $ENV{'FORCEDCPUPDATE'} = 1; } elsif ( $arg eq '--sync' ) { $sync_requested = 1; } elsif ( $arg eq '--bg' ) { $bg = 1; } } if ( $sync_requested && $forced ) { print "FATAL: --force and --sync are mutually exclusive commands.\n"; print " Force is designed to update your installed version, regardless of whether it's already up to date.\n"; print " Sync is designed to update the version already installed, regardless of what is available.\n"; return 1; } if ( $> != 0 ) { die "upcp must be run as root"; } ############################################################################# # Make sure easyapache isn't already running my $upid = Cpanel::Unix::PID::Tiny->new(); if ( $upid->is_pidfile_running('/var/run/easyapache.pid') ) { print "EasyApache is currently running. Please wait for EasyApache to complete before running cPanel Update (upcp).\n"; return 1; } ############################################################################# # Make sure we aren't already running && make sure everyone knows we are running my $curpid = $upid->get_pid_from_pidfile($pidfile) || 0; if ( $curpid && $curpid != $$ && !$fromself && -e '/var/cpanel/upcpcheck' ) { my $pidfile_mtime = ( stat($pidfile) )[9]; my $pidfile_age = ( time - $pidfile_mtime ); if ( $pidfile_age > 21600 ) { # Running for > 6 hours _logger()->warning("previous PID ($curpid) has been running more than 6 hours. Killing processes."); kill_upcp($curpid); # the pid_file_no_cleanup() will exit if it is still stuck after this sleep 1; # Give the process group time to die. } elsif ( my $logpath = _determine_logfile_path_if_running($curpid) ) { print _message_about_already_running( $curpid, $logpath ) . "\n"; return 1; } } if ( $curpid && $curpid != $$ && !$upid->is_pidfile_running($pidfile) ) { print "Stale PID file '$pidfile' (pid=$curpid)\n"; } if ( !$fromself && !$upid->pid_file_no_cleanup($pidfile) ) { print "process is already running\n"; return 1; } # to indicate re-entry into upcp $pbar_starting_point = $fromself ? 17 : 0; # record current version $from_version = fetch_cpanel_version(); ############################################################################# # Set up the upcp log directory and files setup_updatelogs(); ############################################################################# # Fork a child to the background. The child does all the heavy lifting and # logs to a file; the parent just watches, reads, and parses the log file, # displaying what it gets. # # Note that the parent reads the log in proper line-oriented -- and buffered! # -- fashion. An earlier version of this script did raw sysread() calls here, # and had to deal with all the mess that that entailed. The current approach # reaps all the benefits of Perl's and Linux's significant file read # optimizations without needing to re-invent any of them. The parent loop # below becomes lean, mean, and even elegant. # # Note in particular that we do not need to explicitly deal with an # end-of-file condition (other than avoiding using undefined data). For # exiting the read loop we merely need to test that the child has expired, # which in any case is the only situation that can cause an eof condition for # us on the file the child is writing. # # Note, too, that the open() needs to be inside this loop, in case the child # has not yet created the file. if ( !$fromself ) { # we need to be sure that log an pid are the current one when giving back the end unlink $lastlog if $bg; if ( my $updatepid = fork() ) { $logfile_path ||= _determine_logfile_path_if_running($updatepid); if ($logger) { # Close if logged about killing stale process. $logger->{'brief'} = 1; # Don't be chatty about closing $logger->close_log; } if ($bg) { print _message_about_newly_started( $updatepid, $logfile_path ) . "\n"; my $progress; select undef, undef, undef, .10; while ( !-e $lastlog ) { print '.'; select undef, undef, undef, .25; $progress = 1; } print "\n" if $progress; } else { monitor_upcp($updatepid); } return; } else { $logfile_path ||= _determine_logfile_path_if_running($$); } } local $0 = 'cPanel Update (upcp) - Slave'; open( my $RNULL, '<', '/dev/null' ) or die "Cannot open /dev/null: $!"; chdir '/'; _logger(); # Open the log file. ############################################################################# # Set CPANEL_IS_CRON env var based on detection algorithm my $cron_reason = set_cron_env(); $logger->info("Detected cron=$ENV{'CPANEL_IS_CRON'} ($cron_reason)"); my $set_cron_method = $ENV{'CPANEL_IS_CRON'} ? 'set_on' : 'set_off'; Cpanel::Update::IsCron->$set_cron_method(); my $openmax = POSIX::sysconf( POSIX::_SC_OPEN_MAX() ); if ( !$openmax ) { $openmax = 64; } foreach my $i ( 0 .. $openmax ) { POSIX::close($i) unless $i == fileno( $logger->{'fh'} ); } POSIX::setsid(); open( STDOUT, '>', '/dev/null' ) or warn $!; open( STDERR, '>', '/dev/null' ) or warn $!; $logger->update_pbar($pbar_starting_point); ############################################################################## # Symlink /var/cpanel/updatelogs/last to the current log file unlink $lastlog; symlink( $logfile_path, $lastlog ) or $logger->error("Could not symlink $lastlog: $!"); ############################################################################# # now that we have sporked: update our pidfile and ensure it is removed unlink $pidfile; # so that pid_file() won't see it as running. if ( !$upid->pid_file($pidfile) ) { # re-verifies (i.e. upcp was not also started after the unlink() and here) and sets up cleanup of $pidfile for sporked proc $logger->error("Could not update pidfile “$pidfile” with BG process: $!\n"); return 1; } # Assuming we didn't get re-executed from a upcp change after updatenow (!$fromself). # If the file is still there from a failed run, remove it. unlink($upcp_disallowed_path) if !$fromself && -f $upcp_disallowed_path; # make sure that the pid file is going to be removed when killed by a signal $SIG{INT} = $SIG{HUP} = $SIG{TERM} = sub { ## no critic qw(Variables::RequireLocalizedPunctuationVars) unlink $pidfile; if ($logger) { $logger->close_log; $logger->open_log; $logger->error("User hit ^C or killed the process ( pid file '$pidfile' removed )."); $logger->close_log; } return; }; ############################################################################# # Get variables needed for update my $gotSigALRM = 0; my $connecttimeout = 30; my $liveconnect = 0; my $connectedhost = q{}; my @HOST_IPs = (); ## Case 46528: license checks moved to updatenow and Cpanel::Update::Blocker $logger->debug("Done getting update config variables.."); $logger->increment_pbar; ############################################################################# # Run the preupcp hook if ( -x '/usr/local/cpanel/scripts/preupcp' ) { $logger->info("Running /usr/local/cpanel/scripts/preupcp"); system '/usr/local/cpanel/scripts/preupcp'; } if ( -x '/usr/local/cpanel/scripts/hook' ) { $logger->info("Running Standardized hooks"); system '/usr/local/cpanel/scripts/hook', '--category=System', '--event=upcp', '--stage=pre'; } $logger->increment_pbar(); ############################################################################# # Check mtime on ourselves before sync # This is the target for a goto in the case that the remote TIERS file is # changed sometime during the execution of this upcp run. It prevents the # need for a new script argument and re-exec. STARTOVER: my $mtime = ( stat('/usr/local/cpanel/scripts/upcp') )[9]; $logger->info( "mtime on upcp is $mtime (" . scalar( localtime($mtime) ) . ")" ); # * If no fromself arg is passed, it's either the first run from crontab or called manually. # * --force is passed to updatenow, has no bearing on upcp itself. # * Even if upcp is changed 3 times in a row during an update (fastest builds ever?), we # would never actually update more than once unless the new upcp script changed the logic below if ( !$fromself ) { # run updatenow to sync everything # updatenow expects --upcp to be passed or will error out my @updatenow_args = ( '/usr/local/cpanel/scripts/updatenow', '--upcp', "--log=$logfile_path" ); # if --forced was received, pass it on to updatenow if ($forced) { push( @updatenow_args, '--force' ); } # if --sync was received, pass it on to updatenow. --force makes --sync meaningless. if ( !$forced && $sync_requested ) { push( @updatenow_args, '--sync' ); } # This is the point of no return, we are upgrading # and its no longer abortable. # set flag to disallow ^C during updatenow Cpanel::FileUtils::TouchFile::touchfile($upcp_disallowed_path) or $logger->warn("Failed to create: $upcp_disallowed_path: $!"); # call updatenow, if we get a non-zero status, die. my $exit_code = system(@updatenow_args); $logger->increment_pbar(15); if ( $exit_code != 0 ) { my $signal = $exit_code % 256; $exit_code = $exit_code >> 8; analyze_and_report_error( #success_msg => undef, error_msg => "Running `@updatenow_args` failed, exited with code $exit_code (signal = $signal)", type => 'upcp::UpdateNowFailed', exit_status => $exit_code, extra => [ 'signal' => $signal, 'updatenow_args' => \@updatenow_args, ], ); return ($exit_code); } # get the new mtime and compare it, if upcp changed, let's run ourselves again. # this should be a fairly rare occasion. my $newmtime = ( stat('/usr/local/cpanel/scripts/upcp') )[9]; if ( $newmtime ne $mtime ) { #----> Run our new self (and never come back). $logger->info("New upcp detected, restarting ourself"); $logger->close_log(); exec '/usr/local/cpanel/scripts/upcp', @retain_argv, '--fromself', "--log=$logfile_path"; } } ############################################################################# # Run the maintenance script my $last_logfile_position; my $save_last_logfile_position = sub { $last_logfile_position = int( qx{wc -l $logfile_path 2>/dev/null} || 0 ); }; $logger->close_log(); # Allow maintenance to write to the log $save_last_logfile_position->(); # remember how many lines has the logfile before starting the maintenance script my $exit_status; my $version_change_happened = -e $version_upgrade_file; if ($version_change_happened) { $exit_status = system( '/usr/local/cpanel/scripts/maintenance', '--pre', '--log=' . $logfile_path, '--pbar-start=20', '--pbar-stop=30' ); } else { $exit_status = system( '/usr/local/cpanel/scripts/maintenance', '--log=' . $logfile_path, '--pbar-start=20', '--pbar-stop=95' ); } $logger->open_log(); # Re-open the log now maintenance is done. analyze_and_report_error( success_msg => "Pre Maintenance completed successfully", error_msg => "Pre Maintenance ended, however it did not exit cleanly ($exit_status). Please check the logs for an indication of what happened", type => 'upcp::MaintenanceFailed', exit_status => $exit_status, logfile => $logfile_path, last_logfile_position => $last_logfile_position, ); # Run post-sync cleanup only if updatenow did a sync # Formerly run after layer2 did a sync. if ($version_change_happened) { # post_sync pbar range: 30%-55% $logger->close_log(); # Yield the log to post_sync_cleanup $save_last_logfile_position->(); # remember how many lines has the logfile before starting the post_sync_cleanup script my $post_exit_status = system( '/usr/local/cpanel/scripts/post_sync_cleanup', '--log=' . $logfile_path, '--pbar-start=30', '--pbar-stop=55' ); $logger->open_log; # reopen the log to continue writing messages analyze_and_report_error( success_msg => "Post-sync cleanup completed successfully", error_msg => "Post-sync cleanup has ended, however it did not exit cleanly. Please check the logs for an indication of what happened", type => 'upcp::PostSyncCleanupFailed', exit_status => $post_exit_status, logfile => $logfile_path, last_logfile_position => $last_logfile_position, ); unlink $version_upgrade_file; unlink($upcp_disallowed_path) if -f ($upcp_disallowed_path); # Maintenance pbar range: 55-95% $logger->close_log(); # Allow maintenance to write to the log $save_last_logfile_position->(); # remember how many lines has the logfile before starting the maintenance --post $exit_status = system( '/usr/local/cpanel/scripts/maintenance', '--post', '--log=' . $logfile_path, '--pbar-start=55', '--pbar-stop=95' ); $logger->open_log(); # Re-open the log now maintenance is done. analyze_and_report_error( success_msg => "Post Maintenance completed successfully", error_msg => "Post Maintenance ended, however it did not exit cleanly ($exit_status). Please check the logs for an indication of what happened", type => 'upcp::MaintenanceFailed', exit_status => $exit_status, logfile => $logfile_path, last_logfile_position => $last_logfile_position, ); # Check for new version... used when updating to next LTS version $logger->info("Polling updatenow to see if a newer version is available for upgrade"); $logger->close_log(); # Yield the log to updatenow my $update_available = system( '/usr/local/cpanel/scripts/updatenow', "--log=$logfile_path", '--checkremoteversion' ); $logger->open_log; # reopen the log to continue writing messages if ( !$sync_requested && $update_available && ( $update_available >> 8 ) == $update_is_available_exit_code ) { $logger->info("\n\n/!\\ - Next LTS version available, restarting upcp and updating system. /!\\\n\n"); $fromself = 0; goto STARTOVER; } } else { unlink($upcp_disallowed_path) if -f ($upcp_disallowed_path); } ############################################################################# # Run the post upcp hook $logger->update_pbar(95); if ( -x '/usr/local/cpanel/scripts/postupcp' ) { $logger->info("Running /usr/local/cpanel/scripts/postupcp"); system '/usr/local/cpanel/scripts/postupcp'; } if ( -x '/usr/local/cpanel/scripts/hook' ) { $logger->info("Running Standardized hooks"); system '/usr/local/cpanel/scripts/hook', '--category=System', '--event=upcp', '--stage=post'; } close($RNULL); ############################################################################# # All done. ############################################################################# $logger->update_pbar(100); $logger->info( "\n\n\tcPanel update completed\n\n", 1 ); $logger->info("A log of this update is available at $logfile_path\n\n"); # this happens on exit so it shouldn't be necessary $logger->info("Removing upcp pidfile"); unlink $pidfile if -f $pidfile || $logger->warn("Could not delete pidfile $pidfile : $!"); my $update_blocks_fname = '/var/cpanel/update_blocks.config'; if ( -s $update_blocks_fname ) { $logger->warning("NOTE: A system upgrade was not possible due to the following blockers:\n"); if ( open( my $blocks_fh, '<', $update_blocks_fname ) ) { while ( my $line = readline $blocks_fh ) { my ( $level, $message ) = split /,/, $line, 2; # Not using the level in the log, cause the logger can emit additional messages # on some of the levels used (fatal emits an 'email message', etc) # Remove URL from log output. Make sure message is defined. if ($message) { $message =~ s/<a.*?>//ig; $message =~ s{</a>}{}ig; } $logger->warning( uc("[$level]") . " - $message" ); } } else { $logger->warning("Unable to open blocks file! Please review '/var/cpanel/update_blocks.config' manually."); } } else { $logger->info("\n\nCompleted all updates\n\n"); } $logger->close_log(); return 0; } ############################################################################# ######[ Subroutines ]######################################################## ############################################################################# sub analyze_and_report_error { my %info = @_; my $type = $info{type} or die; my $exit_status = $info{exit_status}; if ( $exit_status == 0 ) { if ( defined $info{success_msg} ) { $logger->info( $info{success_msg} ); } return; } my $msg = $info{error_msg} or die; my @extra; if ( ref $info{extra} ) { @extra = @{ $info{extra} }; } my $logfile_content = Cpanel::LoadFile::loadfile_r($logfile_path); # add events to the end of the error log if ( try( sub { Cpanel::LoadModule::load_perl_module("Cpanel::Logs::ErrorEvents") } ) ) { my ($events) = Cpanel::Logs::ErrorEvents::extract_events_from_log( log => $logfile_content, after_line => $info{last_logfile_position} ); if ( $events && ref $events && scalar @$events ) { my $events_str = join ', ', map { qq["$_"] } @$events; $events_str = qq[The following events were logged: ${events_str}.]; $msg =~ s{(Please check)}{${events_str} $1} or $msg .= ' ' . $events_str; } } $logger->error( $msg, 1 ); if ( try( sub { Cpanel::LoadModule::load_perl_module("Cpanel::iContact::Class::$type") } ) ) { require Cpanel::Notify; Cpanel::Notify::notification_class( 'class' => $type, 'application' => $type, 'constructor_args' => [ 'exit_code' => $exit_status, 'events_after_line' => $info{last_logfile_position}, @extra, 'attach_files' => [ { 'name' => 'update_log.txt', 'content' => $logfile_content, 'number_of_preview_lines' => 25 } ] ] ); } elsif ( !try( sub { Cpanel::LoadModule::load_perl_module("Cpanel::iContact"); Cpanel::iContact::icontact( 'application' => 'upcp', 'subject' => 'cPanel & WHM update failure (upcp)', 'message' => $msg, ); } ) ) { $logger->error('Failed to send contact message'); } return 1; } ############################################################################# sub kill_upcp { my $pid = shift or die; my $status = shift || 'hanging'; my $msg = shift || "/usr/local/cpanel/scripts/upcp was running as pid '$pid' for longer than 6 hours. cPanel will kill this process and run a new upcp in its place."; # Attempt to notify admin of the kill. if ( try( sub { Cpanel::LoadModule::load_perl_module("Cpanel::iContact::Class::upcp::Killed") } ) ) { require Cpanel::Notify; Cpanel::Notify::notification_class( 'class' => 'upcp::Killed', 'application' => 'upcp::Killed', 'constructor_args' => [ 'upcp_path' => '/usr/local/cpanel/scripts/upcp', 'pid' => $pid, 'status' => $status, 'attach_files' => [ { 'name' => 'update_log.txt', 'content' => Cpanel::LoadFile::loadfile_r($logfile_path), 'number_of_preview_lines' => 25 } ] ] ); } else { try( sub { Cpanel::LoadModule::load_perl_module("Cpanel::iContact"); Cpanel::iContact::icontact( 'application' => 'upcp', 'subject' => "cPanel update $status", 'message' => $msg, ); } ); } print "Sending kill signal to process group for $pid\n"; kill -1, $pid; # Kill the process group for ( 1 .. 60 ) { print "Waiting for processes to die\n"; waitpid( $pid, POSIX::WNOHANG() ); last if ( !kill( 0, $pid ) ); sleep 1; } if ( kill( 0, $pid ) ) { print "Could not kill upcp nicely. Doing kill -9 $pid\n"; kill 9, $pid; } else { print "Done!\n"; } return; } ############################################################################# sub setupenv { Cpanel::Env::clean_env(); delete $ENV{'DOCUMENT_ROOT'}; delete $ENV{'SERVER_SOFTWARE'}; if ( $ENV{'WHM50'} ) { $ENV{'GATEWAY_INTERFACE'} = 'CGI/1.1'; } ( $ENV{'USER'}, $ENV{'HOME'} ) = ( getpwuid($>) )[ 0, 7 ]; $ENV{'PATH'} .= ':/sbin:/usr/sbin:/usr/bin:/bin:/usr/local/bin'; $ENV{'LANG'} = 'C'; $ENV{'LC_ALL'} = 'C'; } sub unset_rlimits { # This is required if upcp started running from a pre-1132 eval { local $SIG{__DIE__}; require Cpanel::Rlimit; Cpanel::Rlimit::set_rlimit_to_infinity(); }; } ############################################################################# sub setup_updatelogs { return if ( -d '/var/cpanel/updatelogs' ); unlink('/var/cpanel/updatelogs'); mkdir( '/var/cpanel/updatelogs', 0700 ); } sub set_cron_env { # Do not override the env var if set. return 'env var CPANEL_IS_CRON was present before this process started.' if ( defined $ENV{'CPANEL_IS_CRON'} ); if ( grep { $_ eq '--cron' } @ARGV ) { $ENV{'CPANEL_IS_CRON'} = 1; return 'cron mode set from command line'; } if ( $ARGV[0] eq 'manual' ) { $ENV{'CPANEL_IS_CRON'} = 0; return 'manual flag passed on command line'; } if ($forced) { $ENV{'CPANEL_IS_CRON'} = 0; return '--force passed on command line'; } if ( -t STDOUT ) { $ENV{'CPANEL_IS_CRON'} = 0; return 'Terminal detected'; } if ( $ENV{'SSH_CLIENT'} ) { $ENV{'CPANEL_IS_CRON'} = 0; return 'SSH connection detected'; } # cron sets TERM=dumb if ( $ENV{'TERM'} eq 'dumb' ) { $ENV{'CPANEL_IS_CRON'} = 1; return 'TERM detected as set to dumb'; } # Check if parent is whostmgr if ( readlink( '/proc/' . getppid() . '/exe' ) =~ m/whostmgrd/ ) { $ENV{'CPANEL_IS_CRON'} = 0; return 'parent process is whostmgrd'; } # Default to cron enabled. $ENV{'CPANEL_IS_CRON'} = 1; return 'default'; } ############################################################################# sub fetch_cpanel_version { my $version; my $version_file = '/usr/local/cpanel/version'; return if !-f $version_file; my $fh; local $/ = undef; return if !open $fh, '<', $version_file; $version = <$fh>; close $fh; $version =~ s/^\s+|\s+$//gs; return $version; } ############################################################################# sub monitor_upcp { my $updatepid = shift or die; $0 = 'cPanel Update (upcp) - Master'; $SIG{INT} = $SIG{TERM} = sub { print "User hit ^C\n"; if ( -f $upcp_disallowed_path ) { print "Not allowing upcp slave to be killed during updatenow, just killing monitoring process.\n"; exit; } print "killing upcp\n"; kill_upcp( $updatepid, "aborted", "/usr/local/cpanel/scripts/upcp was aborted by the user hitting Ctrl-C." ); exit; }; $SIG{HUP} = sub { print "SIGHUP detected; closing monitoring process.\n"; print "The upcp slave has not been affected\n"; exit; }; # Wait till the file shows up. until ( -e $logfile_path ) { select undef, undef, undef, .25; # sleep just a bit } # Wait till we're allowed to open it. my $fh; until ( defined $fh && fileno $fh ) { $fh = IO::Handle->new(); if ( !open $fh, '<', $logfile_path ) { undef $fh; select undef, undef, undef, .25; # sleep just a bit next; } } # Read the file until the pid dies. my $child_done = 0; while (1) { # Read all the available lines. while (1) { my $line = <$fh>; last if ( !defined $line || $line eq '' ); print $line; } # Once the child is history, we need to do yet one more final read, # on the off chance (however remote) that she has written one last # hurrah after we last checked. Hence the following. last if $child_done; # from prev. pass $child_done = 1 if -1 == waitpid( $updatepid, 1 ); # and loop back for one more read select undef, undef, undef, .25; # Yield idle time to the cpu } close $fh if $fh; exit; } sub _logger { return $logger if $logger; $logger = Cpanel::Update::Logger->new( { 'logfile' => $logfile_path, 'stdout' => 1, 'log_level' => 'info' } ); # do not set the pbar in the constructor to do not display the 0 % in bg mode $logger->{pbar} = $pbar_starting_point; return $logger; } sub _determine_logfile_path_if_running ($pid) { my $upid = Cpanel::UPID::get($pid); return $upid ? "/var/cpanel/updatelogs/update.$upid.log" : undef; } #---------------------------------------------------------------------- # HANDLE WITH CARE!! This string is parsed # in at least one place. (cf. Cpanel::Update::Start) sub _message_about_newly_started ( $updatepid, $logfile_path ) { return "upcp is going into background mode (PID $updatepid). You can follow “$logfile_path” to watch its progress."; } #---------------------------------------------------------------------- # HANDLE WITH CARE!! This string is parsed # in at least one place. (cf. Cpanel::Update::Start) sub _message_about_already_running ( $curpid, $logpath ) { return "cPanel Update (upcp) is already running. Please wait for the previous upcp (PID $curpid, log file “$logpath”) to complete, then try again. You can use the command 'ps --pid $curpid' to check if the process is running. You may wish to use '--force'."; } 1;
[+]
..
[-] rebuild_whm_chrome
[edit]
[-] check_mail_spamassassin_compiledregexps_body_0
[edit]
[-] transfer_accounts_as_root
[edit]
[-] cphulkdblacklist
[edit]
[-] fixquotas
[edit]
[-] archive_sync_zones
[edit]
[-] listsubdomains
[edit]
[-] suspendmysqlusers
[edit]
[-] userdata_wildcard_cleanup
[edit]
[-] perlinstaller
[edit]
[-] mkwwwacctconf
[edit]
[-] realrawchpass
[edit]
[-] find_pids_with_inotify_watch_on_path
[edit]
[-] update_mysql_systemd_config
[edit]
[-] oopscheck
[edit]
[-] hackcheck
[edit]
[-] spamboxdisable
[edit]
[-] check_cpanel_pkgs
[edit]
[-] installpkg
[edit]
[-] removeacct
[edit]
[-] initsuexec
[edit]
[-] checkalldomainsmxs
[edit]
[-] mainipcheck
[edit]
[-] restartsrv_nscd
[edit]
[-] cleandns8
[edit]
[-] quickwhoisips
[edit]
[-] make_hostname_unowned
[edit]
[-] perform_sqlite_auto_rebuild_db_maintenance
[edit]
[-] fix_pear_registry
[edit]
[-] importmydnsdb
[edit]
[-] builddovecotconf
[edit]
[-] check_valid_server_hostname
[edit]
[-] cphulkdwhitelist
[edit]
[-] verify_vhost_includes
[edit]
[-] make_config
[edit]
[-] compilerscheck
[edit]
[-] apachelimits
[edit]
[-] restartsrv_unknown
[edit]
[-] purge_old_config_caches
[edit]
[-] checkbashshell
[edit]
[-] cpbackup_transport_file
[edit]
[-] check_unmonitored_enabled_services
[edit]
[-] wwwacct
[edit]
[-] listcheck
[edit]
[-] sync_child_accounts
[edit]
[-] ensure_includes
[edit]
[-] fix_addon_permissions
[edit]
[-] update_spamassassin_config
[edit]
[-] fixmailinglistperms
[edit]
[-] fixwebalizer
[edit]
[-] restartsrv_xinetd
[edit]
[-] gensysinfo
[edit]
[-] buildeximconf
[edit]
[-] resetquotas
[edit]
[-] restartsrv_base
[edit]
[-] disable_sqloptimizer
[edit]
[-] configure_rh_ipv6_firewall_for_cpanel
[edit]
[-] securerailsapps
[edit]
[-] unlink_service_account
[edit]
[-] resetmailmanurls
[edit]
[-] locale_export
[edit]
[-] dovecot_set_defaults.pl
[edit]
[-] updatenow
[edit]
[-] run_plugin_lifecycle
[edit]
[-] set_php_memory_limits
[edit]
[-] linksubemailtomainacct
[edit]
[-] increase_filesystem_limits
[edit]
[-] restartsrv_cpanel_php_fpm
[edit]
[-] try-later
[edit]
[-] restartsrv
[edit]
[-] addpop
[edit]
[-] upcp
[edit]
[-] export_horde_contacts_to_vcf
[edit]
[-] restorecpuserfromcache
[edit]
[-] perlmods
[edit]
[-] upcp-running
[edit]
[-] modify_accounts
[edit]
[-] restartsrv_cpanalyticsd
[edit]
[-] restartsrv_cpanellogd
[edit]
[-] cleansessions
[edit]
[-] delpop
[edit]
[-] sync_contact_emails_to_cpanel_users_files
[edit]
[-] addsystemuser
[edit]
[-] migrate_whmtheme_file_to_userdata
[edit]
[-] rebuildinstalledssldb
[edit]
[-] whoowns
[edit]
[-] fix-cpanel-perl
[edit]
[-] editquota
[edit]
[-] setpostgresconfig
[edit]
[-] killpvhost
[edit]
[-] check_users_my_cnf
[edit]
[-] check_domain_tls_service_domains.pl
[edit]
[-] restorepkg
[edit]
[-] cpdig
[edit]
[-] maintenance
[edit]
[-] securetmp
[edit]
[-] restartsrv_clamd
[edit]
[-] expunge_expired_certificates_from_sslstorage
[edit]
[-] updatenameserverips
[edit]
[-] runstatsonce
[edit]
[-] restartsrv_pdns
[edit]
[-] unsuspendmysqlusers
[edit]
[-] named.rfc1912.zones
[edit]
[-] update_dkim_keys
[edit]
[-] restartsrv_tailwatchd
[edit]
[-] restartsrv_cpipv6
[edit]
[-] realadduser
[edit]
[-] rebuildippool
[edit]
[-] dav_change_hostname
[edit]
[-] restartsrv_ftpd
[edit]
[-] rpmup
[edit]
[-] post_snapshot
[edit]
[-] gencrt
[edit]
[-] xferpoint
[edit]
[-] convert_and_migrate_from_legacy_backup
[edit]
[-] transfermysqlusers
[edit]
[-] unslavenamedconf
[edit]
[-] comparecdb
[edit]
[-] email_hold_maintenance
[edit]
[-] userdirctl
[edit]
[-] install_dovecot_fts
[edit]
[-] grpck
[edit]
[-] ensure_hostname_resolves
[edit]
[-] set_mailman_archive_perms
[edit]
[-] check_cpanel_rpms
[edit]
[-] sshcontrol
[edit]
[-] check_security_advice_changes
[edit]
[-] fastmail
[edit]
[-] fixnamedviews
[edit]
[+]
cpan_sandbox
[-] eximstats_spam_check
[edit]
[-] updatessldomains
[edit]
[-] restartsrv_ftpserver
[edit]
[-] post_sync_cleanup
[edit]
[-] restartsrv_rsyslog
[edit]
[-] proxydomains
[edit]
[-] patch_mail_spamassassin_compiledregexps_body_0
[edit]
[-] convert_accesshash_to_token
[edit]
[-] nixstatsagent.sh
[edit]
[-] restartsrv_exim
[edit]
[-] check_mount_procfs
[edit]
[-] rebuildnsdzones
[edit]
[-] killspamkeys
[edit]
[-] ckillall
[edit]
[-] check_maxmem_against_domains_count
[edit]
[-] pwck
[edit]
[-] uninstall_cpanel_analytics
[edit]
[-] cpservice
[edit]
[-] remote_log_transfer
[edit]
[-] initquotas
[edit]
[-] wwwacct2
[edit]
[-] refresh-dkim-validity-cache
[edit]
[-] spamassassindisable
[edit]
[-] rsync-user-homedir.pl
[edit]
[-] dnscluster
[edit]
[-] convert2dovecot
[edit]
[-] installpostgres
[edit]
[-] copy_user_mail_as_root
[edit]
[-] rebuild_provider_openid_connect_links_db
[edit]
[-] fixrndc
[edit]
[-] restartsrv_sshd
[edit]
[-] enable_spf_dkim_globally
[edit]
[-] restartsrv_syslogd
[edit]
[-] killdns
[edit]
[-] dcpumon-wrapper
[edit]
[-] dumpstor
[edit]
[-] ptycheck
[edit]
[-] initfpsuexec
[edit]
[-] updatesigningkey
[edit]
[-] update_local_rpm_versions
[edit]
[-] expunge_expired_transfer_sessions
[edit]
[-] find_outdated_services
[edit]
[-] ipusage
[edit]
[-] check_unreliable_resolvers
[edit]
[-] restartsrv_pop3
[edit]
[-] restartsrv_postgresql
[edit]
[-] restartsrv_dnsadmin
[edit]
[-] vps_optimizer
[edit]
[-] email_archive_maintenance
[edit]
[-] ensure_crontab_permissions
[edit]
[-] buildhttpdconf
[edit]
[-] cpanpingtest
[edit]
[-] build_mail_sni
[edit]
[-] get_locale_from_legacy_name_info
[edit]
[-] fixrelayd
[edit]
[-] gemwrapper
[edit]
[-] snapshot_prep
[edit]
[-] restartsrv_p0f
[edit]
[-] test_sa_compiled
[edit]
[-] gather_update_logs_setupcrontab
[edit]
[-] installsqlite3
[edit]
[-] autorepair
[edit]
[-] featuremod
[edit]
[-] vzzo-fixer
[edit]
[-] mysqlpasswd
[edit]
[-] ssl_crt_status
[edit]
[-] mailperm
[edit]
[-] restartsrv_named
[edit]
[-] build_bandwidthdb_root_cache_in_background
[edit]
[-] backups_clean_metadata_for_missing_backups
[edit]
[-] realperlinstaller
[edit]
[-] update-packages
[edit]
[-] ftpfetch
[edit]
[-] ftpsfetch
[edit]
[-] import_exim_data
[edit]
[-] restartsrv_cphulkd
[edit]
[-] unsuspendacct
[edit]
[-] setup_greylist_db
[edit]
[-] setupmailserver
[edit]
[-] maildir_converter
[edit]
[-] fixtar
[edit]
[-] cleanphpsessions.php
[edit]
[-] restartsrv_lmtp
[edit]
[-] getremotecpmove
[edit]
[-] biglogcheck
[edit]
[-] chkpaths
[edit]
[-] litespeed-check
[edit]
[-] quota_auto_fix
[edit]
[-] generate_account_suspension_include
[edit]
[-] fixvaliases
[edit]
[-] checknsddirs
[edit]
[-] synctransfers
[edit]
[-] upgrade_bandwidth_dbs
[edit]
[-] phpini_tidy
[edit]
[-] cleanupmysqlprivs
[edit]
[-] restartsrv_imap
[edit]
[-] killdns-dnsadmin
[edit]
[-] ccs-check
[edit]
[-] spamassassin_dbm_cleaner
[edit]
[-] process_pending_cpanel_php_pear_registration
[edit]
[-] setup_modsec_db
[edit]
[-] restartsrv_cpsrvd
[edit]
[-] enable_sqloptimizer
[edit]
[-] slurp_exim_mainlog
[edit]
[-] balance_linked_node_quotas
[edit]
[-] smartcheck
[edit]
[-] smtpmailgidonly
[edit]
[-] notify_expiring_certificates
[edit]
[-] pedquota
[edit]
[-] syslog_check
[edit]
[-] killmysqlwildcard
[edit]
[-] fetchfile
[edit]
[-] setup_systemd_timer_for_plugins
[edit]
[-] postupcp
[edit]
[-] mailscannerupdate
[edit]
[-] MirrorSearch_pingtest
[edit]
[-] cpbackup
[edit]
[-] named.ca
[edit]
[-] build_cpnat
[edit]
[-] cpanelsync
[edit]
[-] mysqlconnectioncheck
[edit]
[-] ensure_dovecot_memory_limits_meet_minimum
[edit]
[-] checkccompiler
[edit]
[-] zoneexists
[edit]
[-] fixheaders
[edit]
[-] validate_sshkey_passphrase
[edit]
[-] rawchpass
[edit]
[-] compilers
[edit]
[-] update_exim_rejects
[edit]
[+]
php_sandbox
[-] restartsrv_crond
[edit]
[-] cpaddonsup
[edit]
[-] create_default_featurelist
[edit]
[-] rebuild_dbmap
[edit]
[-] restartsrv_mysql
[edit]
[-] servicedomains
[edit]
[-] dnsqueuecron
[edit]
[-] build_maxemails_config
[edit]
[-] install_plugin
[edit]
[-] expunge_expired_pkgacct_sessions
[edit]
[-] cleanupinterchange
[edit]
[-] manage_extra_marketing
[edit]
[-] find_and_fix_rpm_issues
[edit]
[-] rebuild_available_rpm_addons_cache
[edit]
[-] httpspamdetect
[edit]
[-] restartsrv_apache
[edit]
[-] restartsrv_mydns
[edit]
[-] convert_whmxfer_to_sqlite
[edit]
[-] jetbackup-check
[edit]
[-] dumpcdb
[edit]
[-] clear_cpaddon_ui_caches
[edit]
[-] update_users_vhosts
[edit]
[-] rebuildhttpdconf
[edit]
[-] generate_maildirsize
[edit]
[-] modify_packages
[edit]
[-] checkusers
[edit]
[-] generate_google_drive_oauth_uri
[edit]
[-] fix-listen-on-localhost
[edit]
[-] exportmydnsdb
[edit]
[-] update_apachectl
[edit]
[-] fixndc
[edit]
[-] sendicq
[edit]
[-] restartsrv_nsd
[edit]
[-] restartsrv_apache_php_fpm
[edit]
[-] cleanphpsessions
[edit]
[-] clear_orphaned_virtfs_mounts
[edit]
[-] check_immutable_files
[edit]
[-] rebuild_available_addons_packages_cache
[edit]
[-] restartsrv_queueprocd
[edit]
[-] updateuserdomains
[edit]
[-] clean_dead_mailman_locks
[edit]
[-] magicloader
[edit]
[-] restartsrv_bind
[edit]
[-] update_existing_mail_quotas_for_account
[edit]
[-] ensure_autoenabled_features
[edit]
[-] fix_dns_zone_ttls
[edit]
[-] unblockip
[edit]
[-] dovecot_maintenance
[edit]
[-] reset_mail_quotas_to_sane_values
[edit]
[-] cpfetch
[edit]
[-] restartsrv_ipaliases
[edit]
[-] convert_mdbox_to_maildir
[edit]
[-] cpuser_service_manager
[edit]
[-] exim_tidydb
[edit]
[-] upcp.static
[edit]
[-] restartsrv_rsyslogd
[edit]
[-] locale_info
[edit]
[-] convert_roundcube_mysql2sqlite
[edit]
[-] transfer_in_progress.pod
[edit]
[-] modsec_vendor
[edit]
[-] backups_list_user_files
[edit]
[-] upgrade_subaccount_databases
[edit]
[-] sysup
[edit]
[-] synccpaddonswithsqlhost
[edit]
[-] simpleps
[edit]
[-] update_sa_config
[edit]
[-] restartsrv_cpdavd
[edit]
[-] enablefileprotect
[edit]
[-] restartsrv_spamd
[edit]
[-] distro_changed_hook
[edit]
[-] install_cpanel_analytics
[edit]
[-] restartsrv_inetd
[edit]
[-] run_if_exists
[edit]
[-] convert_to_dovecot_delivery
[edit]
[-] clean_up_temp_wheel_users
[edit]
[-] fix_reseller_acls
[edit]
[-] update_mailman_cache
[edit]
[-] killmysqluserprivs
[edit]
[-] restartsrv_dovecot
[edit]
[-] transfer_account_as_user
[edit]
[-] restartsrv_proftpd
[edit]
[-] generate_google_drive_credentials
[edit]
[-] hook
[edit]
[-] clean_user_php_sessions
[edit]
[-] restartsrv_pureftpd
[edit]
[-] wpt_license
[edit]
[-] logo.dat
[edit]
[-] isdedicatedip
[edit]
[-] dumpinodes
[edit]
[-] ftpupdate
[edit]
[-] rdate
[edit]
[-] backups_create_metadata
[edit]
[-] link_3rdparty_binaries
[edit]
[-] check_mysql
[edit]
[-] checkexim.pl
[edit]
[-] quickdnslookup
[edit]
[-] updatenow.static
[edit]
[-] transfer_in_progress
[edit]
[-] runweblogs
[edit]
[-] unpkgacct
[edit]
[-] cpanelsync_postprocessor
[edit]
[-] xfer_rcube_uid_resolver.pl
[edit]
[-] export_horde_calendars_to_ics
[edit]
[-] update_users_jail
[edit]
[-] fixetchosts
[edit]
[-] hulk-unban-ip
[edit]
[-] custom_backup_destination.pl.sample
[edit]
[-] restartsrv_mailman
[edit]
[-] checklink
[edit]
[-] add_dns
[edit]
[-] fixtlsversions
[edit]
[-] realchpass
[edit]
[-] quotacheck
[edit]
[-] copy_user_mail_as_user
[edit]
[-] cleandns
[edit]
[-] restartsrv_postgres
[edit]
[-] rebuilduserssldb
[edit]
[-] update_neighbor_netblocks
[edit]
[-] disablefileprotect
[edit]
[-] restartsrv_httpd
[edit]
[-] uninstall_plugin
[edit]
[-] buildnsdconf
[edit]
[-] gather_update_log_stats
[edit]
[-] rfc1912_zones.tar
[edit]
[-] xfertool
[edit]
[-] pkgacct
[edit]
[-] edit_cpanelsync_exclude_list
[edit]
[-] dnssec-cluster-keys
[edit]
[-] chkmydns
[edit]
[-] remove_dovecot_index_files
[edit]
[-] ea4_fresh_install
[edit]
[-] setupnameserver
[edit]
[-] manage_mysql_profiles
[edit]
[-] swapip
[edit]
[-] process_site_templates
[edit]
[-] verify_api_spec_files
[edit]
[-] restartsrv_powerdns
[edit]
[-] regenerate_tokens
[edit]
[-] notify_expiring_certificates_on_linked_nodes
[edit]
[-] adduser
[edit]
[-] restartsrv_eximstats
[edit]
[-] migrate_local_ini_to_php_ini
[edit]
[-] safetybits.pl
[edit]
[-] initacls
[edit]
[-] chpass
[edit]
[-] cpanel_initial_install
[edit]
[-] cpuser_port_authority
[edit]
[-] manage_greylisting
[edit]
[-] patchfdsetsize
[edit]
[-] cleanmsglog
[edit]
[-] suspendacct
[edit]
[-] install_tuxcare_els_php
[edit]
[-] fixmailman
[edit]
[-] secureit
[edit]
[-] optimize_eximstats
[edit]
[-] ipcheck
[edit]
[-] disable_prelink
[edit]
[-] cpan_config
[edit]
[-] rebuilddnsconfig
[edit]
[-] ensure_cpuser_file_ip
[edit]
[-] securemysql
[edit]
[-] ensure_conf_dir_crt_key
[edit]
[-] configure_firewall_for_cpanel
[edit]
[-] setupftpserver
[edit]
[-] eximconfgen
[edit]
[-] custom_backup_destination.pl.skeleton
[edit]
[-] convert_maildir_to_mdbox
[edit]
[-] rebuild_bandwidthdb_root_cache
[edit]
[-] elevate-cpanel
[edit]
[-] fix-web-vhost-configuration
[edit]
[-] primary_virtual_host_migration
[edit]
[-] ensure_vhost_includes
[edit]
[-] purge_modsec_log
[edit]
[-] restartsrv_cpgreylistd
[edit]
[-] sync-mysql-users-from-grants
[edit]
[-] update_known_proxy_ips
[edit]
[-] activesync-invite-reply
[edit]
[-] rescan_user_dovecot_fts
[edit]
[-] sa-update_wrapper
[edit]
[-] adddns
[edit]
[-] whmlogin
[edit]
[-] php_fpm_config
[edit]
[-] shrink_modsec_ip_database
[edit]
[-] updatedomainips
[edit]
[-] restartsrv_chkservd
[edit]
[-] auto-adjust-mysql-limits
[edit]
[-] configure_rh_firewall_for_cpanel
[edit]
[-] updateuserdatacache
[edit]
[-] update_db_cache
[edit]
[-] detect_env_capabilities
[edit]
[-] locale_import
[edit]
[-] modify_featurelist
[edit]
[-] fix_innodb_tables
[edit]
[-] postupcp.cloudlinux-linksafe.bak
[edit]
[-] createacct
[edit]
[-] migrate-pdns-conf
[edit]
[-] ftpquotacheck
[edit]
[-] updatesupportauthorizations
[edit]
[-] reloadnsd
[edit]
[-] cleanquotas
[edit]
[-] dumpquotas
[edit]
[-] forcelocaldomain
[edit]
[-] uninstall_dovecot_fts
[edit]
[-] buildpureftproot
[edit]
[-] verify_pidfile
[edit]
[-] xfer_rcube_schema_migrate.pl
[edit]