From de21c03fc7285bf8e26e5a49fac3d8e2aaf075e4 Mon Sep 17 00:00:00 2001 From: master3395 Date: Mon, 26 Jan 2026 23:21:53 +0100 Subject: [PATCH] Fix MariaDB compat, mysql path, and OpenLiteSpeed binary install MariaDB-server-compat: - Remove MariaDB-server-compat* in main() before any MariaDB install - Use dnf remove then rpm -e --nodeps loop in main(), installMySQL, fix_almalinux9 - Prevents transaction conflicts when installing MariaDB 10.11 mysql command not found: - install_utils.call: detect mysql/mariadb commands, use shell=True and full path - Replace leading mysql/mariadb with /usr/bin/mariadb or /usr/bin/mysql - Fixes FileNotFoundError when changeMYSQLRootPassword runs OpenLiteSpeed: - Create /usr/local/lsws and /usr/local/lsws/bin before installing custom binary - Fixes 'No such file or directory: /usr/local/lsws/bin/openlitespeed' --- install/install.py | 47 +++++++++++++++++++++++++-------- install/install_utils.py | 56 +++++++++------------------------------- 2 files changed, 48 insertions(+), 55 deletions(-) diff --git a/install/install.py b/install/install.py index 45b3254f3..3df2263bc 100644 --- a/install/install.py +++ b/install/install.py @@ -354,11 +354,15 @@ class preFlightsChecks: self.stdOut("Removing conflicting MariaDB compat packages...", 1) try: # Remove MariaDB-server-compat packages that conflict with MariaDB 10.11 - compat_remove_cmd = "dnf remove -y MariaDB-server-compat* 2>/dev/null || rpm -e --nodeps MariaDB-server-compat* 2>/dev/null || true" - subprocess.run(compat_remove_cmd, shell=True, timeout=60) + subprocess.run("dnf remove -y 'MariaDB-server-compat*' 2>/dev/null || true", shell=True, timeout=60) + r = subprocess.run("rpm -qa 2>/dev/null | grep -i MariaDB-server-compat", shell=True, capture_output=True, text=True, timeout=30) + for line in (r.stdout or "").strip().splitlines(): + pkg = (line.strip().split() or [""])[0] + if pkg and "MariaDB-server-compat" in pkg: + subprocess.run(["rpm", "-e", "--nodeps", pkg], timeout=30) self.stdOut("Removed conflicting MariaDB compat packages", 1) except Exception as e: - self.stdOut(f"Warning: Could not remove compat packages: {e}", 0) + self.stdOut("Warning: Could not remove compat packages: " + str(e), 0) # Check if MariaDB is already installed before attempting installation is_installed, installed_version, major_minor = self.checkExistingMariaDB() @@ -1261,6 +1265,13 @@ class preFlightsChecks: self.stdOut("Installing custom binaries...", 1) try: + # Ensure /usr/local/lsws/bin exists (dnf openlitespeed may use different layout) + ols_bin_dir = os.path.dirname(OLS_BINARY_PATH) + os.makedirs(ols_bin_dir, mode=0o755, exist_ok=True) + ols_base = os.path.dirname(ols_bin_dir) + if not os.path.isdir(ols_base): + os.makedirs(ols_base, mode=0o755, exist_ok=True) + # Make binary executable before moving os.chmod(tmp_binary, 0o755) @@ -1804,15 +1815,15 @@ module cyberpanel_ols { # These packages from MariaDB 12.1 can conflict with MariaDB 10.11 self.stdOut("Removing conflicting MariaDB compat packages...", 1) try: - # Remove MariaDB-server-compat packages that conflict with MariaDB 10.11 - compat_remove_cmd = "dnf remove -y MariaDB-server-compat* 2>/dev/null || rpm -e --nodeps MariaDB-server-compat* 2>/dev/null || true" - result = subprocess.run(compat_remove_cmd, shell=True, timeout=60, capture_output=True) - if result.returncode == 0 or "not installed" in result.stdout.decode('utf-8', errors='ignore').lower(): - self.stdOut("Removed conflicting MariaDB compat packages", 1) - else: - self.stdOut("No conflicting compat packages found or already removed", 1) + subprocess.run("dnf remove -y 'MariaDB-server-compat*' 2>/dev/null || true", shell=True, timeout=60) + r = subprocess.run("rpm -qa 2>/dev/null | grep -i MariaDB-server-compat", shell=True, capture_output=True, text=True, timeout=30) + for line in (r.stdout or "").strip().splitlines(): + pkg = (line.strip().split() or [""])[0] + if pkg and "MariaDB-server-compat" in pkg: + subprocess.run(["rpm", "-e", "--nodeps", pkg], timeout=30) + self.stdOut("Removed conflicting MariaDB compat packages", 1) except Exception as e: - self.stdOut(f"Warning: Could not remove compat packages: {e}", 0) + self.stdOut("Warning: Could not remove compat packages: " + str(e), 0) # Check if MariaDB is already installed before setting up repository is_installed, installed_version, major_minor = self.checkExistingMariaDB() @@ -6426,6 +6437,20 @@ def main(): # This must run before Pre_Install_Required_Components tries to install MariaDB checks.disableMariaDB12RepositoryIfNeeded() + # CRITICAL: Remove MariaDB-server-compat* before ANY MariaDB installation + # This package conflicts with MariaDB 10.11 and must be removed early + preFlightsChecks.stdOut("Removing conflicting MariaDB-server-compat packages...", 1) + try: + subprocess.run("dnf remove -y 'MariaDB-server-compat*' 2>/dev/null || true", shell=True, timeout=60) + r = subprocess.run("rpm -qa 2>/dev/null | grep -i MariaDB-server-compat", shell=True, capture_output=True, text=True, timeout=30) + for line in (r.stdout or "").strip().splitlines(): + pkg = (line.strip().split() or [""])[0] + if pkg and "MariaDB-server-compat" in pkg: + subprocess.run(["rpm", "-e", "--nodeps", pkg], timeout=30) + preFlightsChecks.stdOut("MariaDB compat cleanup completed", 1) + except Exception as e: + preFlightsChecks.stdOut("Warning: compat cleanup: " + str(e), 0) + # Ensure MySQL password file is created early to prevent FileNotFoundError checks.ensure_mysql_password_file() diff --git a/install/install_utils.py b/install/install_utils.py index a150e0174..5976ad0e4 100644 --- a/install/install_utils.py +++ b/install/install_utils.py @@ -556,58 +556,26 @@ def call(command, distro, bracket, message, log=0, do_exit=0, code=os.EX_OK, she os._exit(code) return False - # CRITICAL: For mysql/mariadb commands, use shell=True and find the binary path - # This fixes "No such file or directory: 'mysql'" errors + # CRITICAL: For mysql/mariadb commands, always use shell=True and full binary path + # This fixes "No such file or directory: 'mysql'" when run via shlex.split if not shell and ('mysql' in command or 'mariadb' in command): - # Try to find mysql/mariadb binary path - mysql_paths = ['/usr/bin/mysql', '/usr/bin/mariadb', '/usr/local/bin/mysql', '/usr/local/bin/mariadb'] - mysql_found = None - - # Check which mysql binary exists - for path in mysql_paths: - if os.path.exists(path): - mysql_found = path - break - - # If mysql/mariadb is in command but not found, try to use shell=True - if mysql_found is None: - # Try using 'which' to find mysql - try: - which_result = subprocess.run(['which', 'mysql'], capture_output=True, text=True, timeout=5) - if which_result.returncode == 0: - mysql_found = which_result.stdout.strip() - except: - pass - - # If still not found, try mariadb - if mysql_found is None: - try: - which_result = subprocess.run(['which', 'mariadb'], capture_output=True, text=True, timeout=5) - if which_result.returncode == 0: - mysql_found = which_result.stdout.strip() - except: - pass - - # If mysql/mariadb command found, replace it with full path - if mysql_found: - # Replace 'mysql' or 'mariadb' at the start of command with full path - import re - command = re.sub(r'^(mysql|mariadb)\s', f'{mysql_found} ', command) - # Also replace if it's in the middle (e.g., "sudo mysql") - command = re.sub(r'\s(mysql|mariadb)\s', f' {mysql_found} ', command) - command = re.sub(r'\s(mysql|mariadb)$', f' {mysql_found}', command) - - # Use shell=True for mysql commands to handle complex SQL properly + import re + mysql_bin = '/usr/bin/mariadb' if os.path.exists('/usr/bin/mariadb') else '/usr/bin/mysql' + if not os.path.exists(mysql_bin): + mysql_bin = '/usr/bin/mysql' + # Replace only leading "mysql" or "mariadb" (executable), not "mysql" in SQL like "use mysql;" + if re.match(r'^\s*(sudo\s+)?(mysql|mariadb)\s', command): + command = re.sub(r'^(\s*)(?:sudo\s+)?(mysql|mariadb)(\s)', r'\g<1>' + mysql_bin + r'\g<3>', command, count=1) shell = True finalMessage = 'Running: %s' % (message) stdOut(finalMessage, log) count = 0 while True: - if shell == False: - res = subprocess.call(shlex.split(command)) - else: + if shell: res = subprocess.call(command, shell=True) + else: + res = subprocess.call(shlex.split(command)) if resFailed(distro, res): count = count + 1