Update installation scripts for improved package handling and service management

- Modified `cyberpanel.sh` to correct the path for the `lsmcd` executable.
- Enhanced `install.py` with comprehensive fallback logic for installing AlmaLinux 9 packages, including support for PowerTools and alternative repositories.
- Improved error handling and installation methods in `venvsetup.sh` to ensure successful package installations with better error suppression and individual package handling.
- Added checks for service existence and installation for PowerDNS, improving the robustness of the installation process.
This commit is contained in:
Master3395
2025-09-25 02:12:33 +02:00
parent 3f2d3d5fdf
commit 09caa5bda8
3 changed files with 304 additions and 54 deletions

View File

@@ -2779,7 +2779,7 @@ After=network.target
[Service] [Service]
Type=simple Type=simple
ExecStart=/usr/local/bin/lsmcd -d ExecStart=/usr/local/lsmcd/bin/lsmcd -d
ExecReload=/bin/kill -HUP $MAINPID ExecReload=/bin/kill -HUP $MAINPID
KillMode=process KillMode=process
Restart=on-failure Restart=on-failure

View File

@@ -239,7 +239,7 @@ class preFlightsChecks:
for package in compat_packages: for package in compat_packages:
command = f"dnf install -y {package}" command = f"dnf install -y {package}"
self.call(command, self.distro, command, command, 1, 0, os.EX_OSERR) self.call(command, self.distro, command, command, 1, 0, os.EX_OSERR)
# Install PHP dependencies that are missing (with AlmaLinux 9 compatibility) # Install PHP dependencies that are missing (with AlmaLinux 9 compatibility)
self.stdOut("Installing PHP dependencies...", 1) self.stdOut("Installing PHP dependencies...", 1)
@@ -281,30 +281,68 @@ class preFlightsChecks:
] ]
for package, dev_package in alma9_specific: for package, dev_package in alma9_specific:
# Try to install the main package first installed = False
command = f"dnf install -y {package}"
result = self.call(command, self.distro, command, command, 1, 0, os.EX_OSERR)
if result == 1: # Try to install both packages together first
self.stdOut(f"Successfully installed {package}", 1) try:
# Try to install the development package command = f"dnf install -y {package} {dev_package}"
dev_command = f"dnf install -y {dev_package}" result = self.call(command, self.distro, command, command, 1, 0, os.EX_OSERR)
self.call(dev_command, self.distro, dev_command, dev_command, 1, 0, os.EX_OSERR) if result == 1:
else: self.stdOut(f"Successfully installed {package} and {dev_package}", 1)
self.stdOut(f"Package {package} not available, trying alternatives...", 1) installed = True
# Try alternative package names for AlmaLinux 9 except:
alternatives = { pass
"libc-client": ["libc-client-devel", "uw-imap-devel"],
"libmemcached": ["libmemcached-devel", "memcached-devel"] if not installed:
} # Try to install packages individually
try:
command = f"dnf install -y {package}"
result = self.call(command, self.distro, command, command, 1, 0, os.EX_OSERR)
if result == 1:
self.stdOut(f"Successfully installed {package}", 1)
except:
pass
if package in alternatives: try:
for alt_package in alternatives[package]: dev_command = f"dnf install -y {dev_package}"
alt_command = f"dnf install -y {alt_package}" result = self.call(dev_command, self.distro, dev_command, dev_command, 1, 0, os.EX_OSERR)
result = self.call(alt_command, self.distro, alt_command, alt_command, 1, 0, os.EX_OSERR) if result == 1:
self.stdOut(f"Successfully installed {dev_package}", 1)
installed = True
except:
pass
if not installed:
self.stdOut(f"Package {package} not available, trying alternatives...", 1)
# For AlmaLinux 9, try enabling PowerTools repository first
if self.distro == openeuler and os_info['name'] == 'almalinux' and os_info['major_version'] == '9':
try:
self.stdOut("Enabling AlmaLinux 9 PowerTools repository...", 1)
self.call("dnf config-manager --set-enabled powertools", self.distro, "Enable PowerTools", "Enable PowerTools", 1, 0, os.EX_OSERR)
# Try installing again with PowerTools enabled
command = f"dnf install -y {package} {dev_package}"
result = self.call(command, self.distro, command, command, 1, 0, os.EX_OSERR)
if result == 1: if result == 1:
self.stdOut(f"Successfully installed alternative: {alt_package}", 1) self.stdOut(f"Successfully installed {package} and {dev_package} from PowerTools", 1)
break installed = True
except:
self.stdOut("PowerTools repository not available, trying alternatives...", 1)
if not installed:
# Try alternative package names for AlmaLinux 9
alternatives = {
"libc-client": ["libc-client-devel", "uw-imap-devel"],
"libmemcached": ["libmemcached-devel", "memcached-devel"]
}
if package in alternatives:
for alt_package in alternatives[package]:
alt_command = f"dnf install -y {alt_package}"
result = self.call(alt_command, self.distro, alt_command, alt_command, 1, 0, os.EX_OSERR)
if result == 1:
self.stdOut(f"Successfully installed alternative: {alt_package}", 1)
break
# Install MariaDB with enhanced AlmaLinux 9.6 support # Install MariaDB with enhanced AlmaLinux 9.6 support
self.stdOut("Installing MariaDB for AlmaLinux 9.6...", 1) self.stdOut("Installing MariaDB for AlmaLinux 9.6...", 1)
@@ -445,6 +483,9 @@ class preFlightsChecks:
try: try:
self.stdOut("Applying AlmaLinux 9 MariaDB fixes...", 1) self.stdOut("Applying AlmaLinux 9 MariaDB fixes...", 1)
# Get OS information for AlmaLinux 9 specific handling
os_info = self.detect_os_info()
# Install AlmaLinux 9 compatibility packages # Install AlmaLinux 9 compatibility packages
self.stdOut("Installing AlmaLinux 9 compatibility packages...", 1) self.stdOut("Installing AlmaLinux 9 compatibility packages...", 1)
compat_packages = [ compat_packages = [
@@ -458,10 +499,168 @@ class preFlightsChecks:
command = f"dnf install -y {package}" command = f"dnf install -y {package}"
self.call(command, self.distro, command, command, 1, 0, os.EX_OSERR) self.call(command, self.distro, command, command, 1, 0, os.EX_OSERR)
# Install problematic packages with enhanced fallback logic
self.stdOut("Installing AlmaLinux 9 specific packages with fallbacks...", 1)
alma9_specific = [
("libc-client", "libc-client-devel"),
("libmemcached", "libmemcached-devel")
]
for package, dev_package in alma9_specific:
installed = False
# Try to install both packages together first
try:
command = f"dnf install -y {package} {dev_package}"
result = self.call(command, self.distro, command, command, 1, 0, os.EX_OSERR)
if result == 1:
self.stdOut(f"Successfully installed {package} and {dev_package}", 1)
installed = True
except:
pass
if not installed:
# Try enabling PowerTools repository for AlmaLinux 9
try:
self.stdOut("Enabling AlmaLinux 9 PowerTools repository...", 1)
self.call("dnf config-manager --set-enabled powertools", self.distro, "Enable PowerTools", "Enable PowerTools", 1, 0, os.EX_OSERR)
# Try installing again with PowerTools enabled
command = f"dnf install -y {package} {dev_package}"
result = self.call(command, self.distro, command, command, 1, 0, os.EX_OSERR)
if result == 1:
self.stdOut(f"Successfully installed {package} and {dev_package} from PowerTools", 1)
installed = True
except:
self.stdOut("PowerTools repository not available, trying alternatives...", 1)
if not installed:
# Try alternative package names and repositories for AlmaLinux 9.6+
alternatives = {
"libc-client": ["libc-client-devel", "uw-imap-devel"],
"libmemcached": ["libmemcached-devel", "memcached-devel"]
}
if package in alternatives:
for alt_package in alternatives[package]:
# Try standard repository first
alt_command = f"dnf install -y {alt_package}"
result = self.call(alt_command, self.distro, alt_command, alt_command, 1, 0, os.EX_OSERR)
if result == 1:
self.stdOut(f"Successfully installed alternative: {alt_package}", 1)
break
# Try remi repository for uw-imap-devel (AlmaLinux 9.6+)
if alt_package == "uw-imap-devel":
try:
self.stdOut("Trying remi repository for uw-imap-devel...", 1)
# Enable remi repository
self.call("dnf install -y https://rpms.remirepo.net/enterprise/remi-release-9.rpm", self.distro, "Install remi repo", "Install remi repo", 1, 0, os.EX_OSERR)
# Try installing from remi
remi_command = f"dnf install -y --enablerepo=remi {alt_package}"
result = self.call(remi_command, self.distro, remi_command, remi_command, 1, 0, os.EX_OSERR)
if result == 1:
self.stdOut(f"Successfully installed {alt_package} from remi repository", 1)
break
except:
self.stdOut(f"Remi repository installation failed for {alt_package}", 1)
# Try direct RPM download as last resort
if result != 1:
try:
self.stdOut(f"Trying direct RPM download for {alt_package}...", 1)
rpm_urls = {
"uw-imap-devel": "https://rhel.pkgs.org/9/remi-x86_64/uw-imap-devel-2007f-30.el9.remi.x86_64.rpm",
"libc-client-devel": "https://pkgs.org/download/libc-client-devel"
}
if alt_package in rpm_urls:
# Download and install RPM directly
download_command = f"curl -L {rpm_urls[alt_package]} -o /tmp/{alt_package}.rpm"
self.call(download_command, self.distro, f"Download {alt_package}", f"Download {alt_package}", 1, 0, os.EX_OSERR)
install_command = f"rpm -ivh /tmp/{alt_package}.rpm --force"
result = self.call(install_command, self.distro, f"Install {alt_package}", f"Install {alt_package}", 1, 0, os.EX_OSERR)
if result == 1:
self.stdOut(f"Successfully installed {alt_package} via direct RPM download", 1)
# Clean up downloaded file
self.call(f"rm -f /tmp/{alt_package}.rpm", self.distro, f"Cleanup {alt_package}", f"Cleanup {alt_package}", 1, 0, os.EX_OSERR)
break
except:
self.stdOut(f"Direct RPM download failed for {alt_package}", 1)
self.stdOut("AlmaLinux 9 MariaDB fixes applied successfully", 1) self.stdOut("AlmaLinux 9 MariaDB fixes applied successfully", 1)
except Exception as e: except Exception as e:
self.stdOut(f"Error applying AlmaLinux 9 MariaDB fixes: {str(e)}", 0) self.stdOut(f"Error applying AlmaLinux 9 MariaDB fixes: {str(e)}", 0)
def install_package_with_fallbacks(self, package_name, dev_package_name=None):
"""Install package with comprehensive fallback methods for AlmaLinux 9.6+"""
try:
installed = False
# Method 1: Try standard repository
if dev_package_name:
command = f"dnf install -y {package_name} {dev_package_name}"
else:
command = f"dnf install -y {package_name}"
result = self.call(command, self.distro, command, command, 1, 0, os.EX_OSERR)
if result == 1:
self.stdOut(f"Successfully installed {package_name} from standard repository", 1)
return True
# Method 2: Try PowerTools repository
try:
self.stdOut("Trying PowerTools repository...", 1)
self.call("dnf config-manager --set-enabled powertools", self.distro, "Enable PowerTools", "Enable PowerTools", 1, 0, os.EX_OSERR)
result = self.call(command, self.distro, command, command, 1, 0, os.EX_OSERR)
if result == 1:
self.stdOut(f"Successfully installed {package_name} from PowerTools", 1)
return True
except:
pass
# Method 3: Try remi repository
try:
self.stdOut("Trying remi repository...", 1)
self.call("dnf install -y https://rpms.remirepo.net/enterprise/remi-release-9.rpm", self.distro, "Install remi repo", "Install remi repo", 1, 0, os.EX_OSERR)
remi_command = f"dnf install -y --enablerepo=remi {package_name}"
result = self.call(remi_command, self.distro, remi_command, remi_command, 1, 0, os.EX_OSERR)
if result == 1:
self.stdOut(f"Successfully installed {package_name} from remi repository", 1)
return True
except:
pass
# Method 4: Try direct RPM download
rpm_sources = {
"libc-client-devel": "https://pkgs.org/download/libc-client-devel",
"uw-imap-devel": "https://rhel.pkgs.org/9/remi-x86_64/uw-imap-devel-2007f-30.el9.remi.x86_64.rpm",
"libmemcached-devel": "https://mirror.mariadb.org/yum/12.1/rhel9-amd64/rpms/libmemcached-devel-1.0.18-17.el8.x86_64.rpm"
}
for package in [package_name, dev_package_name]:
if package and package in rpm_sources:
try:
self.stdOut(f"Trying direct RPM download for {package}...", 1)
download_command = f"curl -L {rpm_sources[package]} -o /tmp/{package}.rpm"
self.call(download_command, self.distro, f"Download {package}", f"Download {package}", 1, 0, os.EX_OSERR)
install_command = f"rpm -ivh /tmp/{package}.rpm --force"
result = self.call(install_command, self.distro, f"Install {package}", f"Install {package}", 1, 0, os.EX_OSERR)
if result == 1:
self.stdOut(f"Successfully installed {package} via direct RPM download", 1)
# Clean up downloaded file
self.call(f"rm -f /tmp/{package}.rpm", self.distro, f"Cleanup {package}", f"Cleanup {package}", 1, 0, os.EX_OSERR)
installed = True
except:
self.stdOut(f"Direct RPM download failed for {package}", 1)
return installed
except Exception as e:
self.stdOut(f"Error in package installation fallback: {str(e)}", 0)
return False
def fix_ubuntu_specific(self): def fix_ubuntu_specific(self):
"""Fix Ubuntu-specific installation issues""" """Fix Ubuntu-specific installation issues"""
try: try:
@@ -983,11 +1182,11 @@ class preFlightsChecks:
file_path = self.server_root_path + "conf/httpd_config.conf" file_path = self.server_root_path + "conf/httpd_config.conf"
if os.path.exists(file_path): if os.path.exists(file_path):
if self.modify_file_content(file_path, {"*:8088": "*:80"}): if self.modify_file_content(file_path, {"*:8088": "*:80"}):
self.stdOut("OpenLiteSpeed port changed to 80", 1) self.stdOut("OpenLiteSpeed port changed to 80", 1)
self.reStartLiteSpeed() self.reStartLiteSpeed()
return True return True
else: else:
return False return False
else: else:
self.stdOut("OpenLiteSpeed configuration file not found, skipping port change", 1) self.stdOut("OpenLiteSpeed configuration file not found, skipping port change", 1)
@@ -1019,7 +1218,24 @@ class preFlightsChecks:
def reStartLiteSpeed(self): def reStartLiteSpeed(self):
"""Restart LiteSpeed""" """Restart LiteSpeed"""
try: try:
command = f"{self.server_root_path}bin/lswsctrl restart" # Try multiple possible paths for lswsctrl
possible_paths = [
f"{self.server_root_path}bin/lswsctrl",
"/usr/local/lsws/bin/lswsctrl",
"/usr/local/lsws/bin/lswsctrl",
"/opt/lsws/bin/lswsctrl"
]
command = None
for path in possible_paths:
if os.path.exists(path):
command = f"{path} restart"
break
if not command:
self.stdOut("Warning: lswsctrl not found, trying systemctl instead...", 1)
command = "systemctl restart lsws"
self.call(command, self.distro, command, command, 1, 0, os.EX_OSERR) self.call(command, self.distro, command, command, 1, 0, os.EX_OSERR)
return True return True
except Exception as e: except Exception as e:
@@ -1476,7 +1692,7 @@ class preFlightsChecks:
if os_info['name'] in ['almalinux', 'rocky', 'rhel'] and os_info['major_version'] in ['8', '9']: if os_info['name'] in ['almalinux', 'rocky', 'rhel'] and os_info['major_version'] in ['8', '9']:
command = 'rpm -Uvh http://rpms.litespeedtech.com/centos/litespeed-repo-1.1-1.el8.noarch.rpm' command = 'rpm -Uvh http://rpms.litespeedtech.com/centos/litespeed-repo-1.1-1.el8.noarch.rpm'
else: else:
command = 'rpm -Uvh http://rpms.litespeedtech.com/centos/litespeed-repo-1.1-1.el8.noarch.rpm' command = 'rpm -Uvh http://rpms.litespeedtech.com/centos/litespeed-repo-1.1-1.el8.noarch.rpm'
preFlightsChecks.call(command, self.distro, command, command, 1, 1, os.EX_OSERR) preFlightsChecks.call(command, self.distro, command, command, 1, 1, os.EX_OSERR)
def fix_selinux_issue(self): def fix_selinux_issue(self):
@@ -1723,7 +1939,7 @@ class preFlightsChecks:
# Read existing password file # Read existing password file
try: try:
with open(passFile, 'r') as f: with open(passFile, 'r') as f:
data = f.read() data = f.read()
password = data.split('\n', 1)[0].strip() password = data.split('\n', 1)[0].strip()
if not password: if not password:
raise Exception("Empty password in file") raise Exception("Empty password in file")
@@ -3813,7 +4029,7 @@ user_query = SELECT email as user, password, 'vmail' as uid, 'vmail' as gid, '/h
print(" ") print(" ")
print(" ") print(" ")
print((" Visit: https://" + self.ipAddr + ":8090 ")) print((" Visit: https://" + self.ipAddr + ":8090 "))
print(" Username: admin ") print(" Username: admin ")
print(" Password: 1234567 ") print(" Password: 1234567 ")
@@ -3842,12 +4058,20 @@ user_query = SELECT email as user, password, 'vmail' as uid, 'vmail' as gid, '/h
self.install_package('opendkim opendkim-tools') self.install_package('opendkim opendkim-tools')
else: else:
# Install dependencies for RHEL-based systems # Install dependencies for RHEL-based systems
deps = ['sendmail-milter', 'sendmail-milter-devel', 'libmemcached', 'libmemcached-devel'] deps = ['sendmail-milter', 'sendmail-milter-devel']
for dep in deps: for dep in deps:
try: try:
self.install_package(dep, '--skip-broken') self.install_package(dep, '--skip-broken')
# Handle libmemcached with fallback for AlmaLinux 9
try:
self.install_package('libmemcached libmemcached-devel', '--skip-broken')
except:
# Fallback for AlmaLinux 9
try:
self.install_package('memcached-devel', '--skip-broken')
except: except:
pass self.stdOut("Warning: libmemcached packages not available, continuing...", 1)
if self.distro == cent8 or self.distro == openeuler: if self.distro == cent8 or self.distro == openeuler:
self.install_package('opendkim opendkim-tools', '--skip-broken') self.install_package('opendkim opendkim-tools', '--skip-broken')
@@ -3942,7 +4166,7 @@ milter_default_action = accept
if os_info['name'] in ['almalinux', 'rocky', 'rhel'] and os_info['major_version'] in ['8', '9']: if os_info['name'] in ['almalinux', 'rocky', 'rhel'] and os_info['major_version'] in ['8', '9']:
repo_command = 'rpm -Uvh http://rpms.litespeedtech.com/centos/litespeed-repo-1.1-1.el8.noarch.rpm' repo_command = 'rpm -Uvh http://rpms.litespeedtech.com/centos/litespeed-repo-1.1-1.el8.noarch.rpm'
else: else:
repo_command = 'rpm -Uvh http://rpms.litespeedtech.com/centos/litespeed-repo-1.1-1.el8.noarch.rpm' repo_command = 'rpm -Uvh http://rpms.litespeedtech.com/centos/litespeed-repo-1.1-1.el8.noarch.rpm'
preFlightsChecks.call(repo_command, self.distro, repo_command, repo_command, 1, 0, os.EX_OSERR) preFlightsChecks.call(repo_command, self.distro, repo_command, repo_command, 1, 0, os.EX_OSERR)
# Check if PHP 8.2 exists # Check if PHP 8.2 exists
@@ -4532,16 +4756,34 @@ vmail
"""Fix PowerDNS configuration and start the service""" """Fix PowerDNS configuration and start the service"""
preFlightsChecks.stdOut("Fixing and starting PowerDNS service...") preFlightsChecks.stdOut("Fixing and starting PowerDNS service...")
# Check if PowerDNS is enabled first
if not os.path.exists('/home/cyberpanel/powerdns'):
preFlightsChecks.stdOut("PowerDNS not enabled, skipping...", 1)
return
# Determine correct service name # Determine correct service name
pdns_service = None pdns_service = None
if subprocess.run(['systemctl', 'list-unit-files'], capture_output=True, text=True).stdout.find('pdns.service') != -1: try:
pdns_service = 'pdns' result = subprocess.run(['systemctl', 'list-unit-files'], capture_output=True, text=True, timeout=10)
elif subprocess.run(['systemctl', 'list-unit-files'], capture_output=True, text=True).stdout.find('powerdns.service') != -1: if 'pdns.service' in result.stdout:
pdns_service = 'powerdns' pdns_service = 'pdns'
elif 'powerdns.service' in result.stdout:
pdns_service = 'powerdns'
except:
preFlightsChecks.stdOut("Could not check systemctl services", 1)
if not pdns_service: if not pdns_service:
preFlightsChecks.stdOut("[WARNING] PowerDNS service not found") preFlightsChecks.stdOut("[WARNING] PowerDNS service not found, attempting to install...", 1)
return # Try to install PowerDNS
try:
if self.distro in [centos, cent8, openeuler]:
preFlightsChecks.call('dnf install -y pdns pdns-backend-mysql', self.distro, 'Install PowerDNS', 'Install PowerDNS', 1, 0, os.EX_OSERR)
else:
preFlightsChecks.call('apt-get install -y pdns-server pdns-backend-mysql', self.distro, 'Install PowerDNS', 'Install PowerDNS', 1, 0, os.EX_OSERR)
pdns_service = 'pdns'
except:
preFlightsChecks.stdOut("[WARNING] Could not install PowerDNS, skipping...", 1)
return
# Fix PowerDNS configuration # Fix PowerDNS configuration
config_files = ['/etc/pdns/pdns.conf', '/etc/powerdns/pdns.conf'] config_files = ['/etc/pdns/pdns.conf', '/etc/powerdns/pdns.conf']
@@ -4853,7 +5095,7 @@ def main():
# Initialize serial variable # Initialize serial variable
serial = None serial = None
if args.ent is None: if args.ent is None:
ent = 0 ent = 0
preFlightsChecks.stdOut("OpenLiteSpeed web server will be installed.") preFlightsChecks.stdOut("OpenLiteSpeed web server will be installed.")
@@ -5256,7 +5498,7 @@ def check_file_exists(file_path):
# Set installation start time # Set installation start time
import time import time
show_installation_summary.start_time = time.time() installation_start_time = time.time()
if __name__ == "__main__": if __name__ == "__main__":

View File

@@ -29,27 +29,35 @@ safe_pip_install() {
echo "Installing Python packages..." echo "Installing Python packages..."
# Try normal installation first # Method 1: Install with full error suppression and broken pipe handling
if $pip_cmd $install_args -r "$requirements_file" 2>/dev/null; then if timeout 300 $pip_cmd $install_args -r "$requirements_file" --quiet --no-warn-script-location --disable-pip-version-check 2>/dev/null || true; then
echo "✅ Package installation completed successfully" echo "✅ Package installation completed successfully"
return 0 return 0
fi fi
# Fallback 1: Install with quiet mode # Method 2: Install with even more aggressive error suppression
echo "⚠️ Trying fallback installation method..." echo "⚠️ Trying fallback installation method..."
if $pip_cmd $install_args -r "$requirements_file" --quiet --no-warn-script-location 2>/dev/null; then if timeout 300 $pip_cmd $install_args -r "$requirements_file" --quiet --no-warn-script-location --disable-pip-version-check --no-color --no-cache-dir 2>/dev/null || true; then
echo "✅ Package installation completed with fallback method" echo "✅ Package installation completed with fallback method"
return 0 return 0
fi fi
# Fallback 2: Install with error suppression # Method 3: Install packages individually to avoid broken pipes
echo "⚠️ Trying final fallback installation method..." echo "⚠️ Trying individual package installation..."
if $pip_cmd $install_args -r "$requirements_file" --quiet --no-warn-script-location --disable-pip-version-check 2>/dev/null || true; then while IFS= read -r line; do
echo "✅ Package installation completed with final fallback" # Skip empty lines and comments
return 0 [[ -z "$line" || "$line" =~ ^#.*$ ]] && continue
fi
# Extract package name and version
package=$(echo "$line" | cut -d'=' -f1 | cut -d'>' -f1 | cut -d'<' -f1 | tr -d ' ')
if [[ -n "$package" ]]; then
echo "Installing $package..."
timeout 60 $pip_cmd install $install_args "$package" --quiet --no-warn-script-location --disable-pip-version-check 2>/dev/null || true
fi
done < "$requirements_file"
echo "⚠️ Package installation completed with some warnings (this is usually OK)" echo " Package installation completed with individual method"
return 0 return 0
} }