Edit File: find_and_fix_rpm_issues
#!/usr/local/cpanel/3rdparty/bin/perl # cpanel - find_and_fix_rpm_issues Copyright 2014 cPanel, Inc. # All rights Reserved. # copyright@cpanel.net http://cpanel.net # This code is subject to the cPanel license. Unauthorized copying is prohibited use strict; package scripts::find_and_fix_rpm_issues; use Cpanel::Usage; use Cpanel::Update::Logger; use Cpanel::Update::Blocker::RPM; use Cpanel::SafeRun::Simple (); our $RPM_DB_DIR = '/var/lib/rpm'; exit( run() ) unless caller(); sub usage { my $prog = $0; print <<USAGE; $0 [--findonly] [--rebuildonly] Detects problems with the rpm database and will rebuild the database if it detects problems. Exits 0 if RPM is working properly, or if we were able to fix it by rebuilding its database. --findonly - Detect and report problems. Do not make any changes. --rebuildonly - Unconditionally rebuild the RPM database. USAGE exit 0; } # NOTE: Return logic throughout the script is reversed so that $? is 0 for # success or 1 for failure. sub run { my $findonly = 0; my $rebuildonly = 0; my $rpm_db_is_good = 1; my $opts = { findonly => \$findonly, rebuildonly => \$rebuildonly, }; Cpanel::Usage::wrap_options( \@ARGV, \&usage, $opts ); my $blocker_logger = Cpanel::Update::Logger->new( { 'stdout' => 1, 'log_level' => 'debug', 'timestamp' => 0 } ); my $rpm_db = Cpanel::Update::Blocker::RPM->new( { 'logger' => $blocker_logger } ); if ( !$rebuildonly ) { my $status; ( $rpm_db_is_good, $status ) = $rpm_db->check_package_system(); if ($rpm_db_is_good) { $rpm_db_is_good = verify_no_duplicate_rpms($blocker_logger); } $blocker_logger->info("find_and_fix_rpm_issues: rpm issues have been found") if !$rpm_db_is_good; } $rpm_db_is_good = 0 if $rebuildonly; if ( !$findonly && !$rpm_db_is_good ) { $blocker_logger->info("find_and_fix_rpm_issues: Performing rpm rebuild"); # A non-zero return from rebuild_rpm_database indicates failure. It just returns $?. rebuild_rpm_database($blocker_logger) && return 1; } return 0; } sub rebuild_rpm_database { my ($logger) = @_; if ( opendir my $dh, $RPM_DB_DIR ) { while ( my $file = readdir $dh ) { next unless $file =~ m{^__db\.[0-9]+$} && -f "$RPM_DB_DIR/$file"; unlink "$RPM_DB_DIR/$file" or do { $logger->info("find_and_fix_rpm_issues: Could not unlink $RPM_DB_DIR/$file: $!"); return 1; }; } closedir $dh; } Cpanel::SafeRun::Simple::saferunallerrors( "/bin/rpm", '-vvv', '--rebuilddb' ); if ( ( $? >> 8 ) > 0 ) { $logger->info("find_and_fix_rpm_issues: Rebuilding the rpm database failed with exit code $?."); return 1; } else { return 0; } } # NOTE: The logic here may not be obvious. # If the system has duplicate RPMs, this function will return 0, indicating a problem. # Otherwise, it will return 1, indicating that it did not detect a problem. # # (That doesn't mean there isn't a problem; it just means we didn't find one.) sub verify_no_duplicate_rpms { my ($logger) = @_; my $results = Cpanel::SafeRun::Simple::saferunallerrors(qw< /bin/rpm -qa --queryformat=%{NAME}-%{VERSION}-%{RELEASE}-%{ARCH}\n >); my @output = sort ( split( /\n/, $results ) ); my %rpm_hash; foreach my $rpm (@output) { next if $rpm =~ m/^kernel/; # It's OK to have duplicate kernel RPMs. if ( exists $rpm_hash{$rpm} ) { return 0; } else { $rpm_hash{$rpm} = 1; } } return 1; } 1;