• v1.3.33 ace8dc8b5c

    zhangpu released this 2026-06-01 14:09:29 +08:00 | -2 commits to main since this release

    [1.3.21] - 2026-06-07

    🐛 修复(端到端续测发现)

    • api/cron/run 同步调用 run_security_update 锁 5+ 分钟:apt-get upgrade 可能跑 1-10 分钟不返回,让用户点 cron/run 后整个面板无响应。修法:走任务流,跟 /api/security/update 一样返回 task_id。
    • run_security_update 第二步裸调 apt-get upgrade 无 sudo:dpkg lock 是 root 拥有,tpanel 调裸调永远 Permission denied。修法:加 sudo。
    • api_ssl_apply 写 /etc/nginx/sites-available 失败:v1.3.11 只改 system.py,ssl_manager.py:apply_letsencrypt 还是 with open(conf_path, 'w') 裸调。修法:写 /tmp + sudo mv。
    • api_ssl_apply 清理软链裸调 os.remove 失败:同上。修法:sudo rm -f。
    • certbot 裸调 写 /var/log/letsencrypt 失败:certbot 要 root。修法:加 sudo + sudoers 加 /usr/bin/certbot。

    ✨ 新增

    • api/settings PUT 同步写 sqlite settings(v1.3.19 候选):之前 PUT 写 tpanel.conf JSON 文件,但 get_panel_domain() 从 sqlite settings 表读,两者不同步→ 改 panel_domain 后 check_panel_domain 永远不生效。修法:PUT 时双写。

    [1.3.20] - 2026-06-07

    🐛 修复

    • file_manager.chmod_file 权限值不识别(mode & 0o777 判断太严):前端传 755 实际是十进制 755 ≠ 0o755,列表里没有。修法:接受 755/644 字符串,转成 0o755/0o644。

    [1.3.19] - 2026-06-07

    🐛 修复

    • api/settings PUT 双重存储 bug:put 写 tpanel.conf,get_panel_domain 读 sqlite settings,两边对不上。修法:PUT 时双写。

    [1.3.18] - 2026-06-07

    ✨ 新增

    • api/auth/change-password 改管理员密码 API(v1.3.18 新增):POST 接口,验证旧密码 + bcrypt 新密码 + 写 security_log。表单中密码 < 6 位拒绝。改完所有现存 token 仍然有效(不重生成),用户需重新登录。

    [1.3.17] - 2026-06-07

    🐛 修复(103.233.254.197 端到端测试发现)

    • api_backups_create 用 conn3.lastrowid 报 AttributeError:v1.3.10 时代遗留——应该用 cur3.lastrowid(Cursor 对象才有 lastrowid,Connection 没有)。结果返回 500 但备份实际成功。
    • api_backups_restore 报 PermissionError:tpanel 用户用 shutil.copy2 覆盖 root 拥有的文件失败。修法:先 sudo mv site_path site_path.bak.<ts>,再解压到临时目录,sudo mv 回来,sudo chown 给站点用户。
    • restore_backup 用 time.time() 没 import time:上一条修复引入的新 bug。补 import time。
    • /api/cron/run 命名误导:实际是「安全更新 + SSL 续期」不是跑 cron job。前端调用时要注意。

    ⚠️ 已知未实现(v1.3.18 候选)

    • 改密码 API 不存在:api/auth/change-password 报 405。代码里没实现。
    • 文件 API path 语义模糊:site_path 已含 /public,path 参数不该再含 public。需要在 install-test 或文档里明示。

    [1.3.16] - 2026-06-07

    🐛 修复(103.233.254.197 真实建站发现)

    • write_nginx_config 写 fastcgi_pass unix:127.0.0.1:9000 错语法 → 新建站点全 502:
      • v1.3.8 时代把 fpm_sock 从 unix socket 改成了 TCP 127.0.0.1:9000
      • 但 nginx 模板里写死 fastcgi_pass unix:{fpm_sock},拼接后变成 unix:127.0.0.1:9000(语法错)
      • 修法:模板改 fastcgi_pass {fpm_sock}(直接拼 IP:port)
      • 所有已建站点的 conf 需手动 sed -i 's|fastcgi_pass unix:127.0.0.1:9000|fastcgi_pass 127.0.0.1:9000|' /etc/nginx/sites-enabled/<domain>.conf

    ✨ 新增

    • tpanel-push.py 远程推送工具(v1.3.15+) + install.sh 加 detect + docs 同步

    [1.3.15] - 2026-06-07

    🐛 修复(103.233.254.197 真实装机发现)

    • write_nginx_config 写 /etc/nginx/sites-available 失败 → PermissionError:v1.3.11 只改了 system.py 里的 chown/nginx -s reload,「写 conf」这段是用 with open(conf_path, 'w') 不是 _run() 所以 static-check 没扫到。新建站点必 500。
    • remove_nginx_config 删 /etc/nginx/sites-{available,enabled}/.conf 失败:同上,os.remove 裸调。
    • sudoers 漏 /usr/bin/mv / rm / ln / tee / cp / mkdir / dpkg:v1.3.14 补了 useradd/nginx/systemctl,但没考虑 write_nginx_config 改成 sudo mv 后需要 mv 授权。
    • DEBIAN_FRONTEND=noninteractive 被 sudo 拒绝 setenv:api_phpmyadmin_install 用 ['sudo', 'DEBIAN_FRONTEND=noninteractive', 'apt-get', ...],sudo 默认不允许设置环境变量,apt 装 phpmyadmin 会问交互。修法:改用 apt-get -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--force-confnew(无需设环境变量)。
    • api_security_update 用 sudo bash -c 'apt-get update -y && apt-get upgrade -y':bash 不在 sudoers 授权里,apt-get update 会要密码。修法:拆成两 步只调 apt-get(后续可以加 upgrade cron)。

    ✨ 新增

    • tpanel-push.py 远程推送工具(v1.3.15 开发用):本地文件 base64 后通过 SSH stdin 推到 VPS,自动验证 md5

    [1.3.14] - 2026-06-07

    🐛 修复

    • ssl_manager.py 裸调 nginx -t / nginx -s reload(static-check 发现):v1.3.11 只改了 system.py 里的 nginx 调用,ssl_manager.py 漏改。新装机器走 SSL 申请路径时也会要密码。

    ✨ 新增

    • tpanel-static-check.py 静态分析工具(v1.3.14 核心):
      • 扫双向闭环:系统调用 vs sudoers 授权、前端 API vs 后端路由、import 模块存在性、版本号一致性
      • 不靠真装机就能抱 80% 装完才暴露的 bug
      • 在本机上跑:python3 tpanel-static-check.py /path/to/source/
      • 5 节检查:1. 高危命令 _run 裸调 / 2. sudoers 双向闭环 / 3. 前端 API 路由 / 4. import 模块存在 / 5. 版本号一致性 / 6. Nginx 端口 / 7. on_complete 钩子函数存在 / 8. phpMyAdmin 反代路径探测 / 9. Nginx SSE location / 10. sudoers !requiretty
      • 凑够以上 10 项检查后,v1.3.14 在 static-check 下 0 CRITICAL 过
      • 提供 run-static-check.sh 入口脚本,发布前必跑

    [1.3.13] - 2026-06-07

    ✨ 新增

    • tpanel-install-test.sh 装完自检脚本:
      • 6 节自检:系统基本 / sudoers NOPASSWD / Nginx SSE 配置 / phpmyadmin 反代 / 端到端 API / 服务健康
      • 覆盖 v1.3.10~v1.3.12 三轮所有「装完才暴露」的问题
      • 在干净容器里能 sudo bash tpanel-install-test.sh --with-install 跑完整 install + 自检
      • 装完同一台机器直接跑:3 分钟出报告,错哪一项明说 + 修哪的脚本

    🐛 修复

    • sudo NOPASSWD 没生效 → sudo: a terminal is required to read the password(用户装机实测发现):v1.3.11 硬编码 /usr/sbin/useradd 等路径,但不同发行版路径不同(Debian minimal 可能是 /sbin/useradd、CentOS 是 /usr/sbin/useradd),且某些镜像有 Defaults requiretty 全局设置,后台 systemd 服务调用 sudo 会被挡住要密码。
    • 修法(v1.3.13+):
      • install.sh 用 command -v 动态探测 useradd/userdel/usermod/chown/chmod/nginx/systemctl 真实路径
      • sudoers 文件开头加 Defaults:tpanel !requiretty 关键声明
      • 加 visudo -c -f 语法验证(v1.3.13 之前完全没验证)
      • 加 NOPASSWD 实跑测试:装完立刻 sudo -u tpanel sudo -n useradd ... 试一次,失败时 warn 提示用户
      • 提供 tpanel-fix-sudo.sh 紧急补丁脚本,老用户一键修复

    [1.3.12] - 2026-06-07

    🐛 修复

    • 软件安装 / 安全更新 SSE 流 “连接断开”(用户全新装机实测发现):apt install/upgrade 静默 30s+ 是常态,phpMyAdmin 装 1-3 分钟也是常态,Nginx 默认 proxy_read_timeout 60s 会在静默期到点后主动断开代理,浏览器 EventSource 看到 连接断开。
    • 修法(v1.3.12+):
      • install.sh 的 Nginx 站点配置为 /api/tasks/<id>/stream 加专用 location:proxy_read_timeout 1800s + proxy_send_timeout 1800s + proxy_buffering off + proxy_cache off + X-Accel-Buffering: no,后端 SSE 循环上限 30 分钟
      • 提供 tpanel-fix-sse.sh 紧急补丁脚本,老用户可一键修复(不动 tpanel 服务,只 reload nginx)

    [1.3.11] - 2026-06-07

    🐛 修复

    • 新建站点提示 useradd: Permission denied + cannot lock /etc/passwd(用户全新装机实测发现):v1.3.10 的 install.sh 只为 mysql 授权了 sudoers(/etc/sudoers.d/tpanel-mysql),但 system.py 中 useradd / userdel / chown / chmod / nginx -s reload 全是裸调,tpanel 用户根本没权限。新建站点第一步创建系统用户就 100% 失败。
    • 修法(v1.3.11+):
      • install.sh 新增 /etc/sudoers.d/tpanel-admin,授权 NOPASSWD 跑 useradd/userdel/usermod/chown/chmod/nginx/systemctl(/usr/sbin/ + /usr/bin/ 都列上,Debian/CentOS 路径不同)
      • system.py 全面加 sudo 前缀:create_site_user / delete_site_user / set_site_permissions / write_nginx_config(nginx -t + reload)/ remove_nginx_config(reload)/ nginx_stop / nginx_start / 系统安全更新(apt-get update)
      • systemctl is-active 保持裸调(查询不需要 root)

    [1.3.10] - 2026-06-07

    🐛 修复

    • phpMyAdmin 装完无反代 → 点 🐘 永远 confirm 死循环:v1.3.10 装完 phpMyAdmin 后没有自动写 Nginx 8443 反代配置,导致 /api/phpmyadmin/status 永远返回 nginx_ok=false,前端 setTimeout(..., 1000) 跳走再调 status 又触发 confirm。

    ✨ 新增

    • task_manager.create_task 支持 on_complete 钩子(v1.3.10 新机制)
      • 签名:on_complete(task_id, status),任务结束(success/failed)后回调
      • 用途:实现"装完 X 自动配 Y"的联动
      • 异常路径也会调用,让钩子自己判断
    • task_manager.setup_phpmyadmin_nginx()(v1.3.10 新增)
      • 自动探测 phpMyAdmin 实际路径(/usr/share/phpmyadmin 或 /usr/share/phpmyadmin/htdocs)
      • 写 /etc/nginx/sites-enabled/phpmyadmin.conf(用 sudo mv 临时文件,安全)
      • 包含安全加固(屏蔽 /libraries、/setup/frames、/sql)
      • nginx -t 验证 + systemctl reload nginx(失败 fallback 到 restart)
      • 失败时把错误追加到任务日志
      • 成功时打印 setup_phpmyadmin_nginx: 成功 - ... 到任务日志
    • api_phpmyadmin_install 接入 on_complete:装完 apt 自动调 setup_phpmyadmin_nginx
    • api_phpmyadmin_status 多维检查:installed = sw_installed AND files_exist AND nginx_ok,返回详细字段方便排查
    • 前端 _pollPhpMyAdminReady(maxSeconds):装完轮询 status 直到 nginx_ok=true(最多 30s),超时提示用户

    [1.3.22] - 2026-06-08

    修复

    • 手机端登录后看不到左侧导航(v1.3.21 时代的 mobile bug):
      • 根因:CSS @media (max-width: 768px) 直接把 .sidebar 设成 display: none,没有任何打开方式。
      • 修法:
        • 移动端侧边栏改成 fixed + translateX(-100%) 默认隐藏在屏幕外
        • 加 .sidebar.open 类切到 translateX(0) 滑出
        • topbar-left 加 ☰ 汉堡按钮(仅 < 769px 显示)
        • 加 .sidebar-backdrop 黑色半透明遮罩(仅 < 769px 显示),点遮罩关闭
        • 新增 toggleSidebar() / closeSidebar() JS 函数
        • setupNav 切页时自动 closeSidebar()(移动端体验)
        • 顺带:topbar 在移动端 padding 收紧、h1 字号缩小、隐藏非必要按钮
      • 验证:Python/JS 语法过;zip 魔数 50 4b 03 04 验过;md5=c85eed59376080dfd7bef4d6c8c1fc47

    [1.3.23] - 2026-06-08

    修复

    • phpMyAdmin 登录 URL 错用 127.0.0.1(用户实测发现):
      • 现象:🐘 按钮点开后跳到 http://127.0.0.1:8443/,从手机/外网根本访问不到
      • 根因:api_phpmyadmin_status 用 socket.gethostbyname(socket.gethostname()) 拿"本机 IP",但大多数 VPS 上 hostname 没在 /etc/hosts 里映射到公网 IP,所以拿到的就是 127.0.0.1
      • 修法(host 取值优先级):
        1. 优先用 get_panel_domain()(用户配置的 panel_domain)
        2. fallback 用 request.host 拆出的 hostname(用户当前怎么访问面板就用什么)
        3. 最后才用本机非 loopback IP / 127.0.0.1
      • 顺带:前端 confirm 文案从"IP 直访"改成"面板当前访问地址"
    • 验证:Python/JS 语法过;逻辑路径走查 3 个分支

    [1.3.24] - 2026-06-08

    修复

    • SSL 证书申请 403 / "Some challenges have failed"(用户实测发现):
      • 现象:申请 zhangpu.tech SSL 失败,certbot 报 status: 403
      • 根因(隐藏很深):
        • create_site 里 site_user = domain.replace('.', '_') → 建站目录叫 zhangpu_tech
        • 但 ssl_manager.apply_letsencrypt 硬编码 site_path = f'/opt/tpanel/sites/{domain}/public'(用原域名 zhangpu.tech)
        • certbot 写 challenge 到 zhangpu.tech/public/.well-known/...(那个目录是空的)
        • nginx root 指向 zhangpu_tech/public(下划线版)
        • LE 服务器拉 http://zhangpu.tech/.well-known/... 时,nginx 找的是下划线目录 → 404/403
      • 修法:新增 _get_real_site_path(domain, site_id) 查 sqlite 拿 sites.site_path 真实值;apply_letsencrypt / deploy_ssl 都改用它;找不到时 fallback 硬编码路径
    • 验证:Python 语法过;md5=2e1906c95a09882bacfb615c9b169bbc

    [1.3.25] - 2026-06-08

    修复

    • SSL 申请返回"证书文件未生成"(用户实测发现):
      • 现象:v1.3.24 修复了 .well-known 路径错误,certbot 实际申请成功了(/etc/letsencrypt/live/zhangpu.tech/ 有证书),但 TPanel 报"证书文件未生成"
      • 根因:apply_letsencrypt 给 certbot 传了 --cert-path /opt/tpanel/ssl/zhangpu.tech/fullchain.pem,但 certbot 不完全遵守这些参数(写到默认位置),TPanel 去 /opt/tpanel/ssl/ 检查时找不到
      • 修法 1(certbot 命令):去掉 --cert-path / --key-path / --chain-path,让 certbot 写默认位置 /etc/letsencrypt/live/<domain>/
      • 修法 2(cert_path 取值):apply_letsencrypt / deploy_ssl 都改为从 /etc/letsencrypt/live/<domain>/fullchain.pem 读
    • 新增:SSL 申请进度框(用户要求):
      • 旧版:apply_letsencrypt 同步执行 certbot,30 秒后超时只看到"证书文件未生成"
      • 新版:api_ssl_apply 走 create_task 任务流,前端用 runTaskWithProgress 弹 SSE 进度框
      • 任务命令是 bash 多步脚本:准备 .well-known → 调 certbot → 写部署标记
      • 完成后用 on_complete 钩子自动调 deploy_ssl 写 nginx 443 配置
      • 任务类型: ssl_apply,target: <domain>,避免同域名并发
    • 验证:Python/JS 语法过;md5 校验过

    [1.3.26] - 2026-06-08

    新增

    • 创建站点页面:站点类型选择(用户要求):
      • 新增下拉框"站点类型",选项:
        • 🌐 PHP 动态网站(需要 PHP-FPM)(默认)
        • 📄 纯静态页面(HTML / CSS / JS,不需 PHP)
      • 选静态时自动隐藏 PHP 版本下拉
    • 后端支持 type=static:
      • 不创建 index.php,改写一个好看的 index.html 欢迎页(带"站点已就绪"卡片 + TPanel 链接)
      • nginx 模板跳过 location ~ \.php$ 块(pure static,PHP-FPM 反代关掉)
      • 模板里 index index.html;(不放 index.php 在前)
      • try_files 改成 $uri $uri/ =404;(不再 fallback 到 index.php)
    • DB schema 升级:
      • sites 表加 site_type TEXT DEFAULT 'php' 列(幂等 ALTER,老站点全为 'php')
      • INSERT 语句更新
    • 验证:Python/JS 语法过;md5 校验过

    [1.3.27] - 2026-06-08

    修复

    • 软件市场点安装 → "❌ 连接断开"(用户实测发现):
      • 现象:点 PHP 安装按钮,进度框弹出但立刻提示"❌ 连接断开"
      • 根因 1(致命):/api/tasks/<id>/stream SSE 鉴权返回 401
        • require_auth 只看 Authorization header
        • 浏览器原生 EventSource 不支持自定义 header,只能通过 query string 传 token
        • 前端在 ?token=xxx 传了,但后端不读,401
        • 401 触发 EventSource onerror,前端提示"连接断开"
      • 根因 2(环境问题):VPS 上 dpkg 处于 broken 状态(之前中断过)
        • 日志里看到 E: dpkg was interrupted, you must manually run 'sudo dpkg --configure -a'
        • 所有 apt install 任务都秒失败,task log 立刻有内容 → 任务"成功失败" → 进度框关闭 → 用户看到"连接断开"
      • 修法 1:require_auth 兼容 ?token=(header 优先,query string 兜底)
      • 修法 2:install.sh 第 1 步依赖前加 dpkg --configure -a(幂等:本来健康就几行输出)
      • 现场修复:已在 VPS 上跑过 sudo dpkg --configure -a,状态恢复
    • 验证:Python/JS 语法过;SSE 401 问题将因 require_auth 兼容 query string 而消失

    [1.3.28] - 2026-06-08

    新增

    • 添加 Sury PHP 第三方源(用户要求):
      • 现象:Debian 12 默认只能装 PHP 8.2,老版本(5.6/7.0/7.4/8.0/8.1)和新版(8.3/8.4)都装不了
      • 修法:新增 POST /api/system/add-sury-php 端点,走任务流:
        1. 装 lsb-release / ca-certificates / curl
        2. 下载 https://packages.sury.org/debsuryorg-archive-keyring.deb GPG keyring
        3. dpkg -i 装 keyring
        4. 写 /etc/apt/sources.list.d/php.list(用 signed-by 信任新 keyring)
        5. apt update(30-90s)
      • 幂等检查:源文件已存在就报错不再跑;同类型任务防并发
      • 前端软件市场页面:右上角加"➕ 添加 Sury PHP 源"按钮,走同样的 SSE 进度框
    • 加完后:PHP 5.6 / 7.0 / 7.4 / 8.0 / 8.1 / 8.3 / 8.4 都能装
    • 验证:Python/JS 语法过

    [1.3.29] - 2026-06-08

    新增

    • 多 PHP 版本 FPM 端口隔离(用户要求):
      • 旧问题:所有 PHP-FPM 都硬编码 127.0.0.1:9000,多版本并存时只能最后启动的抢到端口
      • 修法:
        1. 端口映射 get_php_fpm_port(php_version):
          • PHP 5.6 → 9056
          • PHP 7.0 → 9070
          • PHP 7.4 → 9074
          • PHP 8.0 → 9080
          • PHP 8.1 → 9081
          • PHP 8.2 → 9000(保持向后兼容老 conf)
          • PHP 8.3 → 9083
          • PHP 8.4 → 9084
        2. write_nginx_config 根据 php_version 写对应端口的 fastcgi_pass
        3. setup_php_fpm_listen(php_version) 新函数:备份 www.conf → 改 listen → enable → restart → 验证监听
        4. api_software_install 装 PHP 时用 on_complete 钩子自动调 setup_php_fpm_listen
        5. 新端点 POST /api/system/rewrite-all-nginx 批量重写所有站点 conf(按 db 当前 php_version 字段用对应端口)
    • 验证:Python 语法过;端口映射 8 个版本全部正确

    [1.3.30] - 2026-06-08

    修复

    • 后台页面背景默认黑色 → 改成白色(用户要求):
      • 把默认主题从深色(#0a0e1a)改成浅色(#f8fafc),文本从浅灰改成深色
      • 侧边栏保持深色 #0f172a(保证白色背景下的对比度)
      • 顶栏用新变量 --topbar-bg(亮色:白;暗色:深色)
      • topbar 背景从 var(--sidebar-bg) 改到 var(--topbar-bg, var(--card))(向后兼容)
    • 右上角加主题切换按钮(用户要求):
      • topbar-right 加 🌙/☀️ 按钮
      • JS:toggleTheme() 切 :root.dark class + 写 localStorage + 切换图标
      • initTheme() 页面加载时读 localStorage 恢复偏好
      • mobile 端 .topbar-right .topbar-btn:not(.red) 之前会隐藏所有非红按钮,新增例外 #themeToggle 在 mobile 仍可见
    • static-check.py 升级 v2.0(用户要求):
      • 新增 4 项检查(11-14),覆盖 v1.3.29 时代新出现的"双向闭环"模式:
        • 11. PHP-FPM 端口三向闭环:get_php_fpm_port / write_nginx_config / setup_php_fpm_listen / import 关系
        • 12. 裸调 with open(/etc/...) 写系统目录:扫所有 py 文件,命中即 CRITICAL
        • 13. on_complete 钩子函数必须定义:过滤 None / on_complete 关键字
        • 14. 多 PHP 版本 listen 端口冲突:从 catalog 抓所有版本,模拟跑端口映射
      • 修 3 个误报:on_complete=hook 跳过关键字;端口提取过滤空 ".";新加 defaultdict import
      • 跑出新 bug:catalog 缺 php8.4,已补全
      • 跑 v1.3.30 源码:14 项检查全过(0 CRITICAL)

    [1.3.31] - 2026-06-09

    修复

    • 左侧边栏背景改白色(用户要求):
      • 新增 sidebar 专属颜色变量:--sidebar-bg / --sidebar-text / --sidebar-text-dim / --sidebar-hover / --sidebar-border
      • 亮色主题:白底深字
      • 暗色主题(点 🌙):保持原深色(#0f172a)
      • 配套:mobile .hamburger-btn:hover 修原 rgba(255,255,255,0.05) 在白底看不见的 bug
      • install.sh 升级 v1.3.31
    • 教训:「用户想用就行」与「自动解耦」——直接用变量 + 暗色主题兜底,最简洁

    [1.3.32] - 2026-06-09

    修复

    • v1.3.31 发布失败,deploy 脚本没真跑(SSH 拦截 + 用户没察觉)
    • 侧边栏强制白色 !important 保险(与主题变量解耦):
      • .sidebar 写死 background: #ffffff !important
      • .sidebar-logo span / .nav-item / .nav-section / .sidebar-footer .version 全部 !important
      • 暗色主题下 sidebar 保持白色——用户既定的「白」最重要
    • 清理 :root / :root.dark 里 5 个新增的 sidebar 变量(用不上了)

    [1.3.33] - 2026-06-09

    修复

    • CPU 型号显示 "Unknown CPU" bug(用户装机实测发现,v1.3.10 时代就有的隐藏 bug):
      • 根因:backend/system.py:388 _run("lscpu | grep 'Model name' | head -1") 缺 shell=True
      • 默认 shell=False + 字符串命令 → cmd.split() 拆成 ["lscpu", "|", "grep", ...] 当成 lscpu 的参数列表,lscpu 不知道怎么处理,返回空 → 走到兜底 Unknown CPU
      • 单跑 lscpu | grep ... 命令能拿到的,但 _run 调不行
      • 修法:补 shell=True
      • 验证:VPS 实测 Intel(R) Xeon(R) Platinum 8255C CPU @ 2.50GHz ✅
    • 教训:所有带 | / && / ; 的 _run 字符串参数,必须显式 shell=True,要么改用列表参数
    Downloads