InPanel 1.2.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- inpanel/__init__.py +29 -0
- inpanel/acme.py +289 -0
- inpanel/aliyuncs.py +269 -0
- inpanel/app.py +514 -0
- inpanel/apt.py +223 -0
- inpanel/base.py +200 -0
- inpanel/config.py +139 -0
- inpanel/data/config.ini +29 -0
- inpanel/data/history +5 -0
- inpanel/data/runlogs.ini +12 -0
- inpanel/data/update_info.ini +4 -0
- inpanel/dnf.py +225 -0
- inpanel/lib/__init__.py +9 -0
- inpanel/lib/async_process.py +98 -0
- inpanel/lib/filelock.py +82 -0
- inpanel/lib/magic.py +233 -0
- inpanel/lib/pxssh.py +310 -0
- inpanel/lib/pyDes.py +867 -0
- inpanel/mod/__init__.py +0 -0
- inpanel/mod/apt.py +316 -0
- inpanel/mod/certificate.py +268 -0
- inpanel/mod/config.py +372 -0
- inpanel/mod/cron.py +315 -0
- inpanel/mod/disk.py +322 -0
- inpanel/mod/dnf.py +239 -0
- inpanel/mod/file.py +722 -0
- inpanel/mod/firewall.py +199 -0
- inpanel/mod/firewall_base.py +137 -0
- inpanel/mod/firewall_firewalld.py +170 -0
- inpanel/mod/firewall_iptables.py +176 -0
- inpanel/mod/firewall_macos.py +213 -0
- inpanel/mod/firewall_ufw.py +128 -0
- inpanel/mod/ftp.py +231 -0
- inpanel/mod/httpd.py +1205 -0
- inpanel/mod/lighttpd.py +26 -0
- inpanel/mod/login.py +98 -0
- inpanel/mod/mysql.py +577 -0
- inpanel/mod/named.py +26 -0
- inpanel/mod/nginx.py +2327 -0
- inpanel/mod/package.py +33 -0
- inpanel/mod/package_apt.py +62 -0
- inpanel/mod/package_base.py +77 -0
- inpanel/mod/package_dnf.py +62 -0
- inpanel/mod/package_map.py +366 -0
- inpanel/mod/package_yum.py +64 -0
- inpanel/mod/php.py +289 -0
- inpanel/mod/process.py +291 -0
- inpanel/mod/proftpd.py +26 -0
- inpanel/mod/pureftpd.py +26 -0
- inpanel/mod/query.py +108 -0
- inpanel/mod/server.py +1319 -0
- inpanel/mod/service.py +262 -0
- inpanel/mod/setting.py +228 -0
- inpanel/mod/shell.py +78 -0
- inpanel/mod/ssh.py +280 -0
- inpanel/mod/system.py +220 -0
- inpanel/mod/task.py +1337 -0
- inpanel/mod/ufw.py +14 -0
- inpanel/mod/user.py +306 -0
- inpanel/mod/vsftpd.py +67 -0
- inpanel/mod/yum.py +243 -0
- inpanel/plugins/__init__.py +10 -0
- inpanel/plugins/__pycache__/__init__.cpython-313.pyc +0 -0
- inpanel/plugins/acme/static/index.html +10 -0
- inpanel/plugins/acme/static/index.js +13 -0
- inpanel/plugins/shadowsocks-libev/__pycache__/info.cpython-313.pyc +0 -0
- inpanel/plugins/shadowsocks-libev/info.py +73 -0
- inpanel/plugins/shadowsocks-libev/static/index.html +70 -0
- inpanel/plugins/shadowsocks-libev/static/index.js +18 -0
- inpanel/public/css/global.css +138 -0
- inpanel/public/favicon.ico +0 -0
- inpanel/public/images/alipay.jpg +0 -0
- inpanel/public/images/loading.gif +0 -0
- inpanel/public/images/weixin.jpg +0 -0
- inpanel/public/index.html +94 -0
- inpanel/public/js/controllers/controllers.js +566 -0
- inpanel/public/js/controllers/database.js +590 -0
- inpanel/public/js/controllers/ecs.js +624 -0
- inpanel/public/js/controllers/file.js +940 -0
- inpanel/public/js/controllers/plugins.js +105 -0
- inpanel/public/js/controllers/service.js +1460 -0
- inpanel/public/js/controllers/site.js +1241 -0
- inpanel/public/js/controllers/utils.js +2319 -0
- inpanel/public/js/core.js +221 -0
- inpanel/public/js/directives.js +784 -0
- inpanel/public/js/filters.js +395 -0
- inpanel/public/js/services.js +257 -0
- inpanel/public/lib/angular/1.0.2/angular-resource.min.js +10 -0
- inpanel/public/lib/angular/1.0.2/angular.min.js +158 -0
- inpanel/public/lib/bootstrap/css/bootstrap-theme.css +587 -0
- inpanel/public/lib/bootstrap/css/bootstrap-theme.css.map +1 -0
- inpanel/public/lib/bootstrap/css/bootstrap-theme.min.css +6 -0
- inpanel/public/lib/bootstrap/css/bootstrap-theme.min.css.map +1 -0
- inpanel/public/lib/bootstrap/css/bootstrap.css +6757 -0
- inpanel/public/lib/bootstrap/css/bootstrap.css.map +1 -0
- inpanel/public/lib/bootstrap/css/bootstrap.min.css +6 -0
- inpanel/public/lib/bootstrap/css/bootstrap.min.css.map +1 -0
- inpanel/public/lib/bootstrap/fonts/glyphicons-halflings-regular.eot +0 -0
- inpanel/public/lib/bootstrap/fonts/glyphicons-halflings-regular.svg +288 -0
- inpanel/public/lib/bootstrap/fonts/glyphicons-halflings-regular.ttf +0 -0
- inpanel/public/lib/bootstrap/fonts/glyphicons-halflings-regular.woff +0 -0
- inpanel/public/lib/bootstrap/fonts/glyphicons-halflings-regular.woff2 +0 -0
- inpanel/public/lib/bootstrap/img/glyphicons-halflings-white.png +0 -0
- inpanel/public/lib/bootstrap/img/glyphicons-halflings.png +0 -0
- inpanel/public/lib/bootstrap/js/bootstrap.js +2377 -0
- inpanel/public/lib/bootstrap/js/bootstrap.min.js +7 -0
- inpanel/public/lib/bootstrap/js/npm.js +13 -0
- inpanel/public/lib/codemirror/codemirror-compressed.js +1 -0
- inpanel/public/lib/codemirror/codemirror.css +173 -0
- inpanel/public/lib/jquery/jquery-1.12.4.min.js +5 -0
- inpanel/public/lib/md5/md5.js +379 -0
- inpanel/public/lib/md5/md5.min.js +1 -0
- inpanel/public/partials/database/index.html +172 -0
- inpanel/public/partials/database/mysql/dbedit.html +462 -0
- inpanel/public/partials/database/mysql/dbnew.html +348 -0
- inpanel/public/partials/database/mysql/useredit.html +310 -0
- inpanel/public/partials/database/mysql/usernew.html +97 -0
- inpanel/public/partials/directives/message.html +20 -0
- inpanel/public/partials/directives/navbar.html +25 -0
- inpanel/public/partials/directives/selector.html +57 -0
- inpanel/public/partials/directives/srvbase.html +72 -0
- inpanel/public/partials/directives/srvext.html +34 -0
- inpanel/public/partials/directives/srvfile.html +23 -0
- inpanel/public/partials/directives/srvinstall.html +34 -0
- inpanel/public/partials/directives/srvlog.html +23 -0
- inpanel/public/partials/directives/srvminiop.html +28 -0
- inpanel/public/partials/directives/srvuninstall.html +38 -0
- inpanel/public/partials/directives/srvupdate.html +30 -0
- inpanel/public/partials/ecs/account.html +156 -0
- inpanel/public/partials/ecs/ecs.html +198 -0
- inpanel/public/partials/ecs/index.html +40 -0
- inpanel/public/partials/ecs/setings.html +459 -0
- inpanel/public/partials/file/file.html +501 -0
- inpanel/public/partials/file/trash.html +95 -0
- inpanel/public/partials/ftp.html +36 -0
- inpanel/public/partials/log.html +83 -0
- inpanel/public/partials/login.html +79 -0
- inpanel/public/partials/logout.html +22 -0
- inpanel/public/partials/main.html +534 -0
- inpanel/public/partials/plugins/index.html +55 -0
- inpanel/public/partials/plugins/plugins.html +13 -0
- inpanel/public/partials/secure.html +13 -0
- inpanel/public/partials/service/apache.html +147 -0
- inpanel/public/partials/service/cron.html +71 -0
- inpanel/public/partials/service/index.html +293 -0
- inpanel/public/partials/service/iptables.html +40 -0
- inpanel/public/partials/service/lighttpd.html +63 -0
- inpanel/public/partials/service/mariadb.html +113 -0
- inpanel/public/partials/service/memcache.html +36 -0
- inpanel/public/partials/service/minio.html +44 -0
- inpanel/public/partials/service/mongodb.html +44 -0
- inpanel/public/partials/service/mysql.html +113 -0
- inpanel/public/partials/service/named.html +61 -0
- inpanel/public/partials/service/nginx.html +296 -0
- inpanel/public/partials/service/ntp.html +40 -0
- inpanel/public/partials/service/php.html +250 -0
- inpanel/public/partials/service/proftpd.html +59 -0
- inpanel/public/partials/service/pureftpd.html +59 -0
- inpanel/public/partials/service/redis.html +40 -0
- inpanel/public/partials/service/samba.html +58 -0
- inpanel/public/partials/service/sendmail.html +40 -0
- inpanel/public/partials/service/ssh.html +186 -0
- inpanel/public/partials/service/tomcat.html +65 -0
- inpanel/public/partials/service/vsftpd.html +195 -0
- inpanel/public/partials/setting.html +299 -0
- inpanel/public/partials/site/apache/site.html +277 -0
- inpanel/public/partials/site/index.html +344 -0
- inpanel/public/partials/site/nginx/site.html +558 -0
- inpanel/public/partials/sorry.html +19 -0
- inpanel/public/partials/storage/autofm.html +103 -0
- inpanel/public/partials/storage/backup.html +42 -0
- inpanel/public/partials/storage/index.html +360 -0
- inpanel/public/partials/storage/migrate.html +93 -0
- inpanel/public/partials/storage/movedata.html +98 -0
- inpanel/public/partials/storage/remote.html +77 -0
- inpanel/public/partials/utils/cron.html +486 -0
- inpanel/public/partials/utils/firewall.html +266 -0
- inpanel/public/partials/utils/index.html +193 -0
- inpanel/public/partials/utils/network.html +118 -0
- inpanel/public/partials/utils/process.html +239 -0
- inpanel/public/partials/utils/repository.html +373 -0
- inpanel/public/partials/utils/shell.html +28 -0
- inpanel/public/partials/utils/ssl.html +319 -0
- inpanel/public/partials/utils/time.html +109 -0
- inpanel/public/partials/utils/user.html +359 -0
- inpanel/public/robots.txt +2 -0
- inpanel/remote.py +109 -0
- inpanel/templates/file/preview.html +34 -0
- inpanel/templates/index.html +93 -0
- inpanel/utils.py +282 -0
- inpanel/web.py +1811 -0
- inpanel/yum.py +756 -0
- inpanel-1.2.1.dist-info/METADATA +399 -0
- inpanel-1.2.1.dist-info/RECORD +198 -0
- inpanel-1.2.1.dist-info/WHEEL +5 -0
- inpanel-1.2.1.dist-info/entry_points.txt +2 -0
- inpanel-1.2.1.dist-info/licenses/LICENSE +30 -0
- inpanel-1.2.1.dist-info/top_level.txt +1 -0
inpanel/mod/package.py
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2020-2026 Jackson Dou
|
|
4
|
+
# All rights reserved.
|
|
5
|
+
#
|
|
6
|
+
# InPanel is distributed under the terms of The New BSD License.
|
|
7
|
+
# The full license can be found in 'LICENSE'.
|
|
8
|
+
'''Module for Package Manager Integration'''
|
|
9
|
+
|
|
10
|
+
from typing import Optional
|
|
11
|
+
|
|
12
|
+
from .package_base import PackageManager
|
|
13
|
+
from .package_yum import YumPM
|
|
14
|
+
from .package_dnf import DnfPM
|
|
15
|
+
from .package_apt import AptPM
|
|
16
|
+
from .package_map import (
|
|
17
|
+
PACKAGE_MAP,
|
|
18
|
+
resolve_package_names,
|
|
19
|
+
is_installed,
|
|
20
|
+
install_if_not_exists,
|
|
21
|
+
parse_search_output,
|
|
22
|
+
parse_list_installed_output,
|
|
23
|
+
parse_info_output
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def get_package_manager() -> Optional[PackageManager]:
|
|
28
|
+
"""工厂函数:根据系统返回对应的包管理器实例"""
|
|
29
|
+
managers = [DnfPM(), YumPM(), AptPM()]
|
|
30
|
+
for mgr in managers:
|
|
31
|
+
if mgr.detect():
|
|
32
|
+
return mgr
|
|
33
|
+
return None
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2019-2026 Jackson Dou
|
|
4
|
+
# All rights reserved.
|
|
5
|
+
#
|
|
6
|
+
# InPanel is distributed under the terms of The New BSD License.
|
|
7
|
+
# The full license can be found in 'LICENSE'.
|
|
8
|
+
|
|
9
|
+
'''Module for APT(Advanced Packaging Tool) Management'''
|
|
10
|
+
|
|
11
|
+
import shutil
|
|
12
|
+
from typing import List, Tuple
|
|
13
|
+
|
|
14
|
+
from .package_base import PackageManager
|
|
15
|
+
from .system import is_debian_family
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class AptPM(PackageManager):
|
|
19
|
+
"""Debian 9-13 / Ubuntu 18.04+ / Linux Mint:apt"""
|
|
20
|
+
|
|
21
|
+
def detect(self) -> bool:
|
|
22
|
+
if not shutil.which("apt"):
|
|
23
|
+
return False
|
|
24
|
+
return is_debian_family()
|
|
25
|
+
|
|
26
|
+
def install(self, packages: List[str], assume_yes: bool = True) -> Tuple[bool, str]:
|
|
27
|
+
cmd = ["apt"]
|
|
28
|
+
if assume_yes:
|
|
29
|
+
cmd.append("-y")
|
|
30
|
+
cmd.extend(["install"] + packages)
|
|
31
|
+
return self._run_cmd(cmd)
|
|
32
|
+
|
|
33
|
+
def remove(self, packages: List[str], assume_yes: bool = True) -> Tuple[bool, str]:
|
|
34
|
+
cmd = ["apt"]
|
|
35
|
+
if assume_yes:
|
|
36
|
+
cmd.append("-y")
|
|
37
|
+
cmd.extend(["remove"] + packages)
|
|
38
|
+
return self._run_cmd(cmd)
|
|
39
|
+
|
|
40
|
+
def refresh(self) -> Tuple[bool, str]:
|
|
41
|
+
return self._run_cmd(["apt", "update"])
|
|
42
|
+
|
|
43
|
+
def search(self, pattern: str) -> Tuple[bool, str]:
|
|
44
|
+
return self._run_cmd(["apt", "search", pattern])
|
|
45
|
+
|
|
46
|
+
def list_installed(self) -> Tuple[bool, str]:
|
|
47
|
+
return self._run_cmd(["dpkg", "-l"])
|
|
48
|
+
|
|
49
|
+
def update(self) -> Tuple[bool, str]:
|
|
50
|
+
return self._run_cmd(["apt", "-y", "upgrade"])
|
|
51
|
+
|
|
52
|
+
def upgrade(self) -> Tuple[bool, str]:
|
|
53
|
+
return self._run_cmd(["apt", "-y", "full-upgrade"])
|
|
54
|
+
|
|
55
|
+
def info(self, package: str) -> Tuple[bool, str]:
|
|
56
|
+
return self._run_cmd(["apt", "show", package])
|
|
57
|
+
|
|
58
|
+
def clean(self) -> Tuple[bool, str]:
|
|
59
|
+
return self._run_cmd(["apt", "clean"])
|
|
60
|
+
|
|
61
|
+
def get_os_type(self) -> str:
|
|
62
|
+
return "debian"
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2020-2026 Jackson Dou
|
|
4
|
+
# All rights reserved.
|
|
5
|
+
#
|
|
6
|
+
# InPanel is distributed under the terms of The New BSD License.
|
|
7
|
+
# The full license can be found in 'LICENSE'.
|
|
8
|
+
'''Module for Package Manager Base Class'''
|
|
9
|
+
|
|
10
|
+
import subprocess
|
|
11
|
+
from abc import ABC, abstractmethod
|
|
12
|
+
from typing import List, Tuple
|
|
13
|
+
|
|
14
|
+
from .system import (
|
|
15
|
+
get_os_family,
|
|
16
|
+
get_os_id,
|
|
17
|
+
get_os_version_major,
|
|
18
|
+
is_rhel_family,
|
|
19
|
+
is_debian_family,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class PackageManager(ABC):
|
|
24
|
+
"""包管理器抽象基类"""
|
|
25
|
+
|
|
26
|
+
@abstractmethod
|
|
27
|
+
def detect(self) -> bool:
|
|
28
|
+
"""检测当前系统是否匹配该包管理器"""
|
|
29
|
+
pass
|
|
30
|
+
|
|
31
|
+
@abstractmethod
|
|
32
|
+
def install(self, packages: List[str], assume_yes: bool = True) -> Tuple[bool, str]:
|
|
33
|
+
"""
|
|
34
|
+
安装包
|
|
35
|
+
:param packages: 包名列表(内部统一用小写)
|
|
36
|
+
:param assume_yes: 是否自动确认(yum/dnf/apt 的 -y 参数)
|
|
37
|
+
:return: (成功?, 输出日志)
|
|
38
|
+
"""
|
|
39
|
+
pass
|
|
40
|
+
|
|
41
|
+
@abstractmethod
|
|
42
|
+
def remove(self, packages: List[str], assume_yes: bool = True) -> Tuple[bool, str]:
|
|
43
|
+
"""卸载包"""
|
|
44
|
+
pass
|
|
45
|
+
|
|
46
|
+
@abstractmethod
|
|
47
|
+
def refresh(self) -> Tuple[bool, str]:
|
|
48
|
+
"""更新包缓存(apt update / yum makecache / dnf makecache)"""
|
|
49
|
+
pass
|
|
50
|
+
|
|
51
|
+
def search(self, pattern: str) -> Tuple[bool, str]:
|
|
52
|
+
"""搜索包"""
|
|
53
|
+
return (False, "Not implemented")
|
|
54
|
+
|
|
55
|
+
def list_installed(self) -> Tuple[bool, str]:
|
|
56
|
+
"""列出已安装包"""
|
|
57
|
+
return (False, "Not implemented")
|
|
58
|
+
|
|
59
|
+
def get_os_type(self) -> str:
|
|
60
|
+
"""返回操作系统类型:rhel 或 debian"""
|
|
61
|
+
return get_os_family()
|
|
62
|
+
|
|
63
|
+
@staticmethod
|
|
64
|
+
def _run_cmd(cmd: List[str]) -> Tuple[bool, str]:
|
|
65
|
+
"""执行 shell 命令并返回结果"""
|
|
66
|
+
try:
|
|
67
|
+
result = subprocess.run(
|
|
68
|
+
cmd,
|
|
69
|
+
stdout=subprocess.PIPE,
|
|
70
|
+
stderr=subprocess.PIPE,
|
|
71
|
+
text=True,
|
|
72
|
+
check=False
|
|
73
|
+
)
|
|
74
|
+
output = result.stdout + result.stderr
|
|
75
|
+
return (result.returncode == 0, output.strip())
|
|
76
|
+
except Exception as e:
|
|
77
|
+
return (False, str(e))
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2020-2026 Jackson Dou
|
|
4
|
+
# All rights reserved.
|
|
5
|
+
#
|
|
6
|
+
# InPanel is distributed under the terms of The New BSD License.
|
|
7
|
+
# The full license can be found in 'LICENSE'.
|
|
8
|
+
'''Module for DNF Package Manager'''
|
|
9
|
+
|
|
10
|
+
import shutil
|
|
11
|
+
from typing import List, Tuple
|
|
12
|
+
|
|
13
|
+
from .package_yum import YumPM
|
|
14
|
+
from .system import get_os_id, get_os_version_major
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class DnfPM(YumPM):
|
|
18
|
+
"""Alma 8-10 / Rocky 8-10 / CentOS 8+ / RHEL 8+ / Fedora:dnf"""
|
|
19
|
+
|
|
20
|
+
def detect(self) -> bool:
|
|
21
|
+
if not shutil.which("dnf"):
|
|
22
|
+
return False
|
|
23
|
+
os_id = get_os_id()
|
|
24
|
+
if os_id == "fedora":
|
|
25
|
+
return True
|
|
26
|
+
version_major = get_os_version_major()
|
|
27
|
+
return version_major >= 8
|
|
28
|
+
|
|
29
|
+
def install(self, packages: List[str], assume_yes: bool = True) -> Tuple[bool, str]:
|
|
30
|
+
cmd = ["dnf"]
|
|
31
|
+
if assume_yes:
|
|
32
|
+
cmd.append("-y")
|
|
33
|
+
cmd.extend(["install"] + packages)
|
|
34
|
+
return self._run_cmd(cmd)
|
|
35
|
+
|
|
36
|
+
def remove(self, packages: List[str], assume_yes: bool = True) -> Tuple[bool, str]:
|
|
37
|
+
cmd = ["dnf"]
|
|
38
|
+
if assume_yes:
|
|
39
|
+
cmd.append("-y")
|
|
40
|
+
cmd.extend(["remove"] + packages)
|
|
41
|
+
return self._run_cmd(cmd)
|
|
42
|
+
|
|
43
|
+
def refresh(self) -> Tuple[bool, str]:
|
|
44
|
+
return self._run_cmd(["dnf", "makecache"])
|
|
45
|
+
|
|
46
|
+
def search(self, pattern: str) -> Tuple[bool, str]:
|
|
47
|
+
return self._run_cmd(["dnf", "search", pattern])
|
|
48
|
+
|
|
49
|
+
def list_installed(self) -> Tuple[bool, str]:
|
|
50
|
+
return self._run_cmd(["dnf", "list", "installed"])
|
|
51
|
+
|
|
52
|
+
def update(self) -> Tuple[bool, str]:
|
|
53
|
+
return self._run_cmd(["dnf", "-y", "update"])
|
|
54
|
+
|
|
55
|
+
def upgrade(self) -> Tuple[bool, str]:
|
|
56
|
+
return self._run_cmd(["dnf", "-y", "upgrade"])
|
|
57
|
+
|
|
58
|
+
def info(self, package: str) -> Tuple[bool, str]:
|
|
59
|
+
return self._run_cmd(["dnf", "info", package])
|
|
60
|
+
|
|
61
|
+
def clean(self) -> Tuple[bool, str]:
|
|
62
|
+
return self._run_cmd(["dnf", "clean", "all"])
|
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2020-2026 Jackson Dou
|
|
4
|
+
# All rights reserved.
|
|
5
|
+
#
|
|
6
|
+
# InPanel is distributed under the terms of The New BSD License.
|
|
7
|
+
# The full license can be found in 'LICENSE'.
|
|
8
|
+
'''Module for Package Name Mapping'''
|
|
9
|
+
|
|
10
|
+
from typing import List, Tuple, Dict
|
|
11
|
+
|
|
12
|
+
PACKAGE_MAP = {
|
|
13
|
+
"nginx": {
|
|
14
|
+
"rhel": "nginx",
|
|
15
|
+
"debian": "nginx"
|
|
16
|
+
},
|
|
17
|
+
"mariadb": {
|
|
18
|
+
"rhel": "mariadb-server",
|
|
19
|
+
"debian": "mariadb-server"
|
|
20
|
+
},
|
|
21
|
+
"mysql": {
|
|
22
|
+
"rhel": "mariadb-server",
|
|
23
|
+
"debian": "default-mysql-server"
|
|
24
|
+
},
|
|
25
|
+
"mysql-community": {
|
|
26
|
+
"rhel": "mysql-community-server",
|
|
27
|
+
"debian": "mysql-server"
|
|
28
|
+
},
|
|
29
|
+
"php": {
|
|
30
|
+
"rhel": "php",
|
|
31
|
+
"debian": "php"
|
|
32
|
+
},
|
|
33
|
+
"php-fpm": {
|
|
34
|
+
"rhel": "php-fpm",
|
|
35
|
+
"debian": "php-fpm"
|
|
36
|
+
},
|
|
37
|
+
"php-cli": {
|
|
38
|
+
"rhel": "php-cli",
|
|
39
|
+
"debian": "php-cli"
|
|
40
|
+
},
|
|
41
|
+
"php-mysql": {
|
|
42
|
+
"rhel": "php-mysqlnd",
|
|
43
|
+
"debian": "php-mysql"
|
|
44
|
+
},
|
|
45
|
+
"php-pdo": {
|
|
46
|
+
"rhel": "php-pdo",
|
|
47
|
+
"debian": "php-pdo"
|
|
48
|
+
},
|
|
49
|
+
"php-mbstring": {
|
|
50
|
+
"rhel": "php-mbstring",
|
|
51
|
+
"debian": "php-mbstring"
|
|
52
|
+
},
|
|
53
|
+
"php-xml": {
|
|
54
|
+
"rhel": "php-xml",
|
|
55
|
+
"debian": "php-xml"
|
|
56
|
+
},
|
|
57
|
+
"php-gd": {
|
|
58
|
+
"rhel": "php-gd",
|
|
59
|
+
"debian": "php-gd"
|
|
60
|
+
},
|
|
61
|
+
"php-curl": {
|
|
62
|
+
"rhel": "php-curl",
|
|
63
|
+
"debian": "php-curl"
|
|
64
|
+
},
|
|
65
|
+
"php-zip": {
|
|
66
|
+
"rhel": "php-zip",
|
|
67
|
+
"debian": "php-zip"
|
|
68
|
+
},
|
|
69
|
+
"php-intl": {
|
|
70
|
+
"rhel": "php-intl",
|
|
71
|
+
"debian": "php-intl"
|
|
72
|
+
},
|
|
73
|
+
"php-redis": {
|
|
74
|
+
"rhel": "php-pecl-redis",
|
|
75
|
+
"debian": "php-redis"
|
|
76
|
+
},
|
|
77
|
+
"php-memcached": {
|
|
78
|
+
"rhel": "php-pecl-memcached",
|
|
79
|
+
"debian": "php-memcached"
|
|
80
|
+
},
|
|
81
|
+
"git": {
|
|
82
|
+
"rhel": "git",
|
|
83
|
+
"debian": "git"
|
|
84
|
+
},
|
|
85
|
+
"wget": {
|
|
86
|
+
"rhel": "wget",
|
|
87
|
+
"debian": "wget"
|
|
88
|
+
},
|
|
89
|
+
"curl": {
|
|
90
|
+
"rhel": "curl",
|
|
91
|
+
"debian": "curl"
|
|
92
|
+
},
|
|
93
|
+
"vim": {
|
|
94
|
+
"rhel": "vim-enhanced",
|
|
95
|
+
"debian": "vim"
|
|
96
|
+
},
|
|
97
|
+
"rsync": {
|
|
98
|
+
"rhel": "rsync",
|
|
99
|
+
"debian": "rsync"
|
|
100
|
+
},
|
|
101
|
+
"net-tools": {
|
|
102
|
+
"rhel": "net-tools",
|
|
103
|
+
"debian": "net-tools"
|
|
104
|
+
},
|
|
105
|
+
"epel-release": {
|
|
106
|
+
"rhel": "epel-release",
|
|
107
|
+
"debian": ""
|
|
108
|
+
},
|
|
109
|
+
"remi-release": {
|
|
110
|
+
"rhel": "remi-release",
|
|
111
|
+
"debian": ""
|
|
112
|
+
},
|
|
113
|
+
"sury-php": {
|
|
114
|
+
"rhel": "",
|
|
115
|
+
"debian": "ca-certificates apt-transport-https software-properties-common"
|
|
116
|
+
},
|
|
117
|
+
"python3": {
|
|
118
|
+
"rhel": "python3",
|
|
119
|
+
"debian": "python3"
|
|
120
|
+
},
|
|
121
|
+
"python3-pip": {
|
|
122
|
+
"rhel": "python3-pip",
|
|
123
|
+
"debian": "python3-pip"
|
|
124
|
+
},
|
|
125
|
+
"python3-devel": {
|
|
126
|
+
"rhel": "python3-devel",
|
|
127
|
+
"debian": "python3-dev"
|
|
128
|
+
},
|
|
129
|
+
"gcc": {
|
|
130
|
+
"rhel": "gcc",
|
|
131
|
+
"debian": "gcc"
|
|
132
|
+
},
|
|
133
|
+
"make": {
|
|
134
|
+
"rhel": "make",
|
|
135
|
+
"debian": "make"
|
|
136
|
+
},
|
|
137
|
+
"cmake": {
|
|
138
|
+
"rhel": "cmake",
|
|
139
|
+
"debian": "cmake"
|
|
140
|
+
},
|
|
141
|
+
"autoconf": {
|
|
142
|
+
"rhel": "autoconf",
|
|
143
|
+
"debian": "autoconf"
|
|
144
|
+
},
|
|
145
|
+
"automake": {
|
|
146
|
+
"rhel": "automake",
|
|
147
|
+
"debian": "automake"
|
|
148
|
+
},
|
|
149
|
+
"libtool": {
|
|
150
|
+
"rhel": "libtool",
|
|
151
|
+
"debian": "libtool"
|
|
152
|
+
},
|
|
153
|
+
"libxslt": {
|
|
154
|
+
"rhel": "libxslt-devel",
|
|
155
|
+
"debian": "libxslt1-dev"
|
|
156
|
+
},
|
|
157
|
+
"libxml2": {
|
|
158
|
+
"rhel": "libxml2-devel",
|
|
159
|
+
"debian": "libxml2-dev"
|
|
160
|
+
},
|
|
161
|
+
"libcurl": {
|
|
162
|
+
"rhel": "libcurl-devel",
|
|
163
|
+
"debian": "libcurl4-openssl-dev"
|
|
164
|
+
},
|
|
165
|
+
"openssl": {
|
|
166
|
+
"rhel": "openssl-devel",
|
|
167
|
+
"debian": "libssl-dev"
|
|
168
|
+
},
|
|
169
|
+
"zlib": {
|
|
170
|
+
"rhel": "zlib-devel",
|
|
171
|
+
"debian": "zlib1g-dev"
|
|
172
|
+
},
|
|
173
|
+
"bzip2": {
|
|
174
|
+
"rhel": "bzip2-devel",
|
|
175
|
+
"debian": "libbz2-dev"
|
|
176
|
+
},
|
|
177
|
+
"libpng": {
|
|
178
|
+
"rhel": "libpng-devel",
|
|
179
|
+
"debian": "libpng-dev"
|
|
180
|
+
},
|
|
181
|
+
"libjpeg": {
|
|
182
|
+
"rhel": "libjpeg-turbo-devel",
|
|
183
|
+
"debian": "libjpeg-dev"
|
|
184
|
+
},
|
|
185
|
+
"freetype": {
|
|
186
|
+
"rhel": "freetype-devel",
|
|
187
|
+
"debian": "libfreetype6-dev"
|
|
188
|
+
},
|
|
189
|
+
"GeoIP": {
|
|
190
|
+
"rhel": "GeoIP-devel",
|
|
191
|
+
"debian": "libgeoip-dev"
|
|
192
|
+
},
|
|
193
|
+
"gd": {
|
|
194
|
+
"rhel": "gd-devel",
|
|
195
|
+
"debian": "libgd-dev"
|
|
196
|
+
},
|
|
197
|
+
"icu": {
|
|
198
|
+
"rhel": "icu-devel",
|
|
199
|
+
"debian": "libicu-dev"
|
|
200
|
+
},
|
|
201
|
+
"sqlite": {
|
|
202
|
+
"rhel": "sqlite-devel",
|
|
203
|
+
"debian": "libsqlite3-dev"
|
|
204
|
+
},
|
|
205
|
+
"postgresql": {
|
|
206
|
+
"rhel": "postgresql-server",
|
|
207
|
+
"debian": "postgresql"
|
|
208
|
+
},
|
|
209
|
+
"mongodb": {
|
|
210
|
+
"rhel": "mongodb-server",
|
|
211
|
+
"debian": "mongodb"
|
|
212
|
+
},
|
|
213
|
+
"redis": {
|
|
214
|
+
"rhel": "redis",
|
|
215
|
+
"debian": "redis-server"
|
|
216
|
+
},
|
|
217
|
+
"memcached": {
|
|
218
|
+
"rhel": "memcached",
|
|
219
|
+
"debian": "memcached"
|
|
220
|
+
},
|
|
221
|
+
"nodejs": {
|
|
222
|
+
"rhel": "nodejs",
|
|
223
|
+
"debian": "nodejs"
|
|
224
|
+
},
|
|
225
|
+
"npm": {
|
|
226
|
+
"rhel": "npm",
|
|
227
|
+
"debian": "npm"
|
|
228
|
+
},
|
|
229
|
+
"certbot": {
|
|
230
|
+
"rhel": "certbot",
|
|
231
|
+
"debian": "certbot"
|
|
232
|
+
},
|
|
233
|
+
"fail2ban": {
|
|
234
|
+
"rhel": "fail2ban",
|
|
235
|
+
"debian": "fail2ban"
|
|
236
|
+
},
|
|
237
|
+
"htop": {
|
|
238
|
+
"rhel": "htop",
|
|
239
|
+
"debian": "htop"
|
|
240
|
+
},
|
|
241
|
+
"ncdu": {
|
|
242
|
+
"rhel": "ncdu",
|
|
243
|
+
"debian": "ncdu"
|
|
244
|
+
},
|
|
245
|
+
"screen": {
|
|
246
|
+
"rhel": "screen",
|
|
247
|
+
"debian": "screen"
|
|
248
|
+
},
|
|
249
|
+
"tmux": {
|
|
250
|
+
"rhel": "tmux",
|
|
251
|
+
"debian": "tmux"
|
|
252
|
+
},
|
|
253
|
+
"ntp": {
|
|
254
|
+
"rhel": "chrony",
|
|
255
|
+
"debian": "chrony"
|
|
256
|
+
},
|
|
257
|
+
"firewalld": {
|
|
258
|
+
"rhel": "firewalld",
|
|
259
|
+
"debian": "ufw"
|
|
260
|
+
},
|
|
261
|
+
"iptables": {
|
|
262
|
+
"rhel": "iptables-services",
|
|
263
|
+
"debian": "iptables"
|
|
264
|
+
},
|
|
265
|
+
"logrotate": {
|
|
266
|
+
"rhel": "logrotate",
|
|
267
|
+
"debian": "logrotate"
|
|
268
|
+
},
|
|
269
|
+
"cron": {
|
|
270
|
+
"rhel": "cronie",
|
|
271
|
+
"debian": "cron"
|
|
272
|
+
},
|
|
273
|
+
"openssh": {
|
|
274
|
+
"rhel": "openssh-server",
|
|
275
|
+
"debian": "openssh-server"
|
|
276
|
+
},
|
|
277
|
+
"sshd": {
|
|
278
|
+
"rhel": "openssh-server",
|
|
279
|
+
"debian": "openssh-server"
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def resolve_package_names(pm, base_names: List[str]) -> List[str]:
|
|
285
|
+
"""根据包管理器类型解析实际包名"""
|
|
286
|
+
os_type = pm.get_os_type()
|
|
287
|
+
resolved = []
|
|
288
|
+
for name in base_names:
|
|
289
|
+
if name in PACKAGE_MAP and os_type in PACKAGE_MAP[name]:
|
|
290
|
+
pkg_name = PACKAGE_MAP[name][os_type]
|
|
291
|
+
if pkg_name:
|
|
292
|
+
resolved.append(pkg_name)
|
|
293
|
+
else:
|
|
294
|
+
resolved.append(name)
|
|
295
|
+
return resolved
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
def is_installed(pm, package: str) -> bool:
|
|
299
|
+
"""检查包是否已安装"""
|
|
300
|
+
success, output = pm.list_installed()
|
|
301
|
+
if not success:
|
|
302
|
+
return False
|
|
303
|
+
package = package.lower()
|
|
304
|
+
for line in output.split('\n'):
|
|
305
|
+
if package in line.lower():
|
|
306
|
+
return True
|
|
307
|
+
return False
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
def install_if_not_exists(pm, packages: List[str]) -> Tuple[bool, str]:
|
|
311
|
+
"""只安装未安装的包"""
|
|
312
|
+
resolved = resolve_package_names(pm, packages)
|
|
313
|
+
to_install = []
|
|
314
|
+
for pkg in resolved:
|
|
315
|
+
if not is_installed(pm, pkg):
|
|
316
|
+
to_install.append(pkg)
|
|
317
|
+
if not to_install:
|
|
318
|
+
return (True, "All packages already installed")
|
|
319
|
+
return pm.install(to_install)
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
def parse_search_output(output: str) -> List[Dict]:
|
|
323
|
+
"""解析搜索命令输出,返回包列表"""
|
|
324
|
+
packages = []
|
|
325
|
+
lines = output.split('\n')
|
|
326
|
+
for line in lines:
|
|
327
|
+
if not line.strip():
|
|
328
|
+
continue
|
|
329
|
+
parts = line.split()
|
|
330
|
+
if len(parts) >= 2:
|
|
331
|
+
pkg_name = parts[0]
|
|
332
|
+
description = ' '.join(parts[1:]) if len(parts) > 1 else ''
|
|
333
|
+
packages.append({'name': pkg_name, 'description': description})
|
|
334
|
+
return packages
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
def parse_list_installed_output(output: str) -> List[Dict]:
|
|
338
|
+
"""解析已安装包列表输出"""
|
|
339
|
+
packages = []
|
|
340
|
+
lines = output.split('\n')
|
|
341
|
+
for line in lines:
|
|
342
|
+
if not line.strip():
|
|
343
|
+
continue
|
|
344
|
+
if line.startswith('Desired=') or line.startswith('+++') or line.startswith('ii ') or line.startswith('Installed'):
|
|
345
|
+
parts = line.split()
|
|
346
|
+
if len(parts) >= 2:
|
|
347
|
+
if line.startswith('ii '):
|
|
348
|
+
pkg_name = parts[1]
|
|
349
|
+
version = parts[2] if len(parts) > 2 else ''
|
|
350
|
+
elif line.startswith('Installed'):
|
|
351
|
+
continue
|
|
352
|
+
else:
|
|
353
|
+
continue
|
|
354
|
+
packages.append({'name': pkg_name, 'version': version})
|
|
355
|
+
return packages
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
def parse_info_output(output: str) -> dict:
|
|
359
|
+
"""解析包信息输出"""
|
|
360
|
+
info = {}
|
|
361
|
+
lines = output.split('\n')
|
|
362
|
+
for line in lines:
|
|
363
|
+
if ':' in line:
|
|
364
|
+
key, value = line.split(':', 1)
|
|
365
|
+
info[key.strip()] = value.strip()
|
|
366
|
+
return info
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2020-2026 Jackson Dou
|
|
4
|
+
# All rights reserved.
|
|
5
|
+
#
|
|
6
|
+
# InPanel is distributed under the terms of The New BSD License.
|
|
7
|
+
# The full license can be found in 'LICENSE'.
|
|
8
|
+
'''Module for YUM Package Manager'''
|
|
9
|
+
|
|
10
|
+
import shutil
|
|
11
|
+
from typing import List, Tuple
|
|
12
|
+
|
|
13
|
+
from .package_base import PackageManager
|
|
14
|
+
from .system import is_rhel_family, get_os_version_major
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class YumPM(PackageManager):
|
|
18
|
+
"""CentOS 7 及以下 / RHEL 7 及以下:yum"""
|
|
19
|
+
|
|
20
|
+
def detect(self) -> bool:
|
|
21
|
+
if not shutil.which("yum"):
|
|
22
|
+
return False
|
|
23
|
+
if not is_rhel_family():
|
|
24
|
+
return False
|
|
25
|
+
if shutil.which("dnf"):
|
|
26
|
+
version_major = get_os_version_major()
|
|
27
|
+
return version_major == 7
|
|
28
|
+
version_major = get_os_version_major()
|
|
29
|
+
return version_major in (5, 6, 7) or version_major == 0
|
|
30
|
+
|
|
31
|
+
def install(self, packages: List[str], assume_yes: bool = True) -> Tuple[bool, str]:
|
|
32
|
+
cmd = ["yum"]
|
|
33
|
+
if assume_yes:
|
|
34
|
+
cmd.append("-y")
|
|
35
|
+
cmd.extend(["install"] + packages)
|
|
36
|
+
return self._run_cmd(cmd)
|
|
37
|
+
|
|
38
|
+
def remove(self, packages: List[str], assume_yes: bool = True) -> Tuple[bool, str]:
|
|
39
|
+
cmd = ["yum"]
|
|
40
|
+
if assume_yes:
|
|
41
|
+
cmd.append("-y")
|
|
42
|
+
cmd.extend(["remove"] + packages)
|
|
43
|
+
return self._run_cmd(cmd)
|
|
44
|
+
|
|
45
|
+
def refresh(self) -> Tuple[bool, str]:
|
|
46
|
+
return self._run_cmd(["yum", "makecache"])
|
|
47
|
+
|
|
48
|
+
def search(self, pattern: str) -> Tuple[bool, str]:
|
|
49
|
+
return self._run_cmd(["yum", "search", pattern])
|
|
50
|
+
|
|
51
|
+
def list_installed(self) -> Tuple[bool, str]:
|
|
52
|
+
return self._run_cmd(["yum", "list", "installed"])
|
|
53
|
+
|
|
54
|
+
def update(self) -> Tuple[bool, str]:
|
|
55
|
+
return self._run_cmd(["yum", "-y", "update"])
|
|
56
|
+
|
|
57
|
+
def upgrade(self) -> Tuple[bool, str]:
|
|
58
|
+
return self._run_cmd(["yum", "-y", "upgrade"])
|
|
59
|
+
|
|
60
|
+
def info(self, package: str) -> Tuple[bool, str]:
|
|
61
|
+
return self._run_cmd(["yum", "info", package])
|
|
62
|
+
|
|
63
|
+
def clean(self) -> Tuple[bool, str]:
|
|
64
|
+
return self._run_cmd(["yum", "clean", "all"])
|