mirror of
https://github.com/usmannasir/cyberpanel.git
synced 2026-05-06 14:57:19 +02:00
Fix missing /usr/local/CyberCP/bin/python for cron and IncBackups
Add plogical/cyberpanel_python.py with resolve_cyberpanel_python() and ensure_cyberpanel_bin_python_shim() (symlink to system Python when venv binary is absent). Call shim before writing root crontab on install/upgrade, and from IncBackups/IncScheduler.py so existing jobs self-heal. IncBackups views use resolved interpreter for backupUtilities. Upgrade._python_for_manage delegates to resolve_cyberpanel_python().
This commit is contained in:
67
plogical/cyberpanel_python.py
Normal file
67
plogical/cyberpanel_python.py
Normal file
@@ -0,0 +1,67 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Resolve the Python interpreter for CyberPanel CLI and cron jobs.
|
||||
|
||||
Some installs omit /usr/local/CyberCP/bin/python (no venv). We symlink that path
|
||||
to a working interpreter when missing so existing crontab lines keep working.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
|
||||
_CANDIDATES = (
|
||||
"/usr/local/CyberPanel/bin/python",
|
||||
"/usr/local/CyberCP/bin/python",
|
||||
"/usr/bin/python3",
|
||||
"/usr/local/bin/python3",
|
||||
)
|
||||
|
||||
|
||||
def resolve_cyberpanel_python() -> str:
|
||||
"""Return first existing executable candidate, else /usr/bin/python3."""
|
||||
for path in _CANDIDATES:
|
||||
if path == "/usr/local/CyberCP/bin/python":
|
||||
continue
|
||||
if path and os.path.isfile(path) and os.access(path, os.X_OK):
|
||||
return path
|
||||
return "/usr/bin/python3"
|
||||
|
||||
|
||||
def ensure_cyberpanel_bin_python_shim() -> None:
|
||||
"""
|
||||
If /usr/local/CyberCP/bin/python is missing or a broken symlink, replace with
|
||||
symlink to resolve_cyberpanel_python(). Non-destructive for a real venv file.
|
||||
"""
|
||||
bin_dir = "/usr/local/CyberCP/bin"
|
||||
legacy = os.path.join(bin_dir, "python")
|
||||
try:
|
||||
os.makedirs(bin_dir, exist_ok=True)
|
||||
except OSError:
|
||||
return
|
||||
|
||||
if os.path.isfile(legacy) and os.access(legacy, os.X_OK) and not os.path.islink(legacy):
|
||||
return
|
||||
|
||||
if os.path.islink(legacy):
|
||||
real = os.path.realpath(legacy)
|
||||
if os.path.isfile(real) and os.access(real, os.X_OK):
|
||||
return
|
||||
try:
|
||||
os.unlink(legacy)
|
||||
except OSError:
|
||||
return
|
||||
|
||||
if os.path.lexists(legacy):
|
||||
try:
|
||||
os.remove(legacy)
|
||||
except OSError:
|
||||
try:
|
||||
os.unlink(legacy)
|
||||
except OSError:
|
||||
return
|
||||
|
||||
target = resolve_cyberpanel_python()
|
||||
try:
|
||||
os.symlink(target, legacy)
|
||||
except OSError:
|
||||
pass
|
||||
Reference in New Issue
Block a user