Proxmox VE 9 正式发布后,不少小伙伴在升级或全新安装后发现,每次登录 Web 管理界面都会弹出”No valid subscription”的提示框。虽然不影响功能使用,但频繁点击确认确实很烦人。今天这篇教程就手把手教你如何彻底去除这个弹窗,并提供一个一键脚本方便日后维护。
一、原理说明
PVE 的订阅弹窗是通过前端 JavaScript 控制的,核心逻辑位于以下文件:
文件中有一个
函数,负责在每次执行需要订阅验证的操作前检查订阅状态。如果检测到未激活订阅,就会调用
弹出警告框。我们的目标就是让这个函数”短路”,直接执行原始命令而跳过订阅检查。
二、方法一:一键命令(快速搞定)
如果你只想快速解决问题,在 PVE 节点的 Shell 中执行以下命令即可:
执行完毕后,按
强制刷新浏览器页面,弹窗即消失。
三、方法二:手动修改(推荐了解原理)
如果你想了解具体改了什么,可以按以下步骤手动操作。
1. 备份原文件
2. 编辑文件
在 nano 中按
搜索
找到函数定义。原函数大约长这样:
Proxmox.Utils.API2Request({
url: '/nodes/localhost/subscription',
method: 'GET',
success: function (response, opts) {
let res = response.result;
if (res === null || res === undefined || !res || res.data.status.toLowerCase() !== 'active') {
Ext.Msg.show({
title: gettext('No valid subscription'),
// ... 弹窗配置
});
} else {
orig_cmd();
}
},
});
}
3. 替换为简化版
将整个函数体替换为以下内容:
orig_cmd();
}
4. 重启服务
然后按
刷新浏览器即可。
四、方法三:一键脚本(更新后自动复用)
考虑到每次
更新
包后,修改都会被覆盖,我整理了一个 Shell 脚本,方便每次更新后一键重新应用。
脚本功能
– 自动备份原文件到
– 智能检测是否已修改过,避免重复操作
– 双重策略:先尝试完整替换函数,失败则回退到条件替换
– 支持一键恢复原始文件
使用方法
将以下脚本保存为
Bash 脚本:
set -euo pipefail
WTK_FILE="/usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js"
BACKUP_DIR="/root/.pve-nag-backups"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
check_root() {
if [[ $EUID -ne 0 ]]; then
echo -e "${RED}错误: 请使用 root 权限运行${NC}"
exit 1
fi
}
backup_original() {
mkdir -p "$BACKUP_DIR"
cp "$WTK_FILE" "$BACKUP_DIR/proxmoxlib.js.bak.$TIMESTAMP"
echo -e "${GREEN}✓ 已备份原文件${NC}"
}
apply_patch() {
python3 - "$WTK_FILE" << 'PYEOF'
import sys
file_path = sys.argv[1]
with open(file_path, 'r') as f:
content = f.read()
old_func = """checked_command: function (orig_cmd) {
Proxmox.Utils.API2Request({
url: '/nodes/localhost/subscription',
method: 'GET',
failure: function (response, opts) {
Ext.Msg.alert(gettext('Error'), response.htmlStatus);
},
success: function (response, opts) {
let res = response.result;
if (
res === null ||
res === undefined ||
!res ||
res.data.status.toLowerCase() !== 'active'
) {
Ext.Msg.show({
title: gettext('No valid subscription'),
icon: Ext.Msg.WARNING,
message: Proxmox.Utils.getNoSubKeyHtml(res.data.url),
buttons: Ext.Msg.OK,
callback: function (btn) {
if (btn !== 'ok') {
return;
}
orig_cmd();
},
});
} else {
orig_cmd();
}
},
});
}"""
new_func = """checked_command: function (orig_cmd) {
orig_cmd();
}"""
if old_func in content:
content = content.replace(old_func, new_func)
with open(file_path, 'w') as f:
f.write(content)
print("PATCH_OK")
else:
print("PATCH_FAIL")
PYEOF
}
apply_fallback() {
sed -i "s/res.data.status.toLowerCase() !== 'active'/false/g" "$WTK_FILE"
echo "PATCH_OK"
}
main() {
echo "========================================"
echo "PVE 9 去除订阅弹窗脚本"
echo "========================================"
check_root
backup_original
result=$(apply_patch)
if [[ "$result" != "PATCH_OK" ]]; then
echo -e "${YELLOW}尝试备用方案...${NC}"
apply_fallback
fi
systemctl restart pveproxy.service
echo -e "${GREEN}✓ 完成!请按 Ctrl+F5 刷新浏览器${NC}"
}
main
赋予执行权限并运行:
sudo bash remove-pve-nag.sh
每次系统更新后如果弹窗又回来了,直接再执行一次即可:
五、如何恢复原始文件
如果你需要恢复,脚本每次运行都会自动备份。找到对应的备份文件后执行:
systemctl restart pveproxy.service
六、注意事项
1. 权限要求:所有操作都需要 root 权限,建议在 PVE 节点的 Shell 中直接执行。
2. 更新覆盖:
包更新后修改会被还原,建议保留脚本文件,更新后重新运行。
3. 浏览器缓存:修改完成后务必按
强制刷新,否则可能仍看到缓存的旧页面。
七、总结
PVE 9 去除订阅弹窗的核心就是修改
中的
函数。无论是直接执行 sed 命令、手动编辑,还是使用我提供的脚本,效果都是一样的。推荐把脚本放在服务器上,每次
后顺手执行一下,一劳永逸。