OpenWrt / ImmortalWrt 专属:Passwall 自动更新管理脚本部署指南
在日常维护 OpenWrt 或 ImmortalWrt 路由器时,手动检查并更新 Passwall 插件是一件繁琐的工作。此外,由于系统自带的 wget 在处理 GitHub 重定向链接时存在缺陷,经常会导致下载的安装包文件名变成乱码,从而引起安装失败。
为了解决这些痛点,本文提供了一款专为 OpenWrt/ImmortalWrt 环境打造的 Passwall 自动更新与管理脚本。该脚本带有可视化交互菜单,支持全自动版本匹配、一键配置定时更新、运行状态监控以及脚本自卸载功能。
✨ 核心特性
- 🤖 智能环境自适应: 自动检测系统主版本(支持
22.03、23.05-24.10及最新的25.12+分支),自动匹配.ipk(opkg) 或.apk(apk) 包管理器。 - 🔗 原生文件名解析: 完美解决 GitHub Release 链接重定向导致的下载乱码问题,确保安装包名称原汁原味。
- 🎛️ 交互式管理面板: 告别繁杂的命令行,提供清晰的数字菜单供日常维护使用。
- ⏱️ 零感定时更新: 一键将更新任务写入系统 Cron 计划,每天凌晨自动静默比对 GitHub 最新版本并完成升级。
- 🧹 纯净无残留: 脚本内置自卸载选项,一键清理定时任务、运行日志及脚本文件本身,绝不制造系统垃圾。
🚀 部署步骤
第一步:创建并写入脚本
通过 SSH 登录到你的路由器终端,直接复制并执行以下整段命令。这会自动在 /root 目录下创建脚本文件并赋予运行权限:
Bash
cat << 'EOF' > /root/pw_autoupdate.sh
#!/bin/sh
# ================= 基础变量 =================
SCRIPT_PATH="/root/pw_autoupdate.sh"
LOG_FILE="/tmp/passwall_update.log"
CRON_CMD="30 4 * * * $SCRIPT_PATH auto >> $LOG_FILE 2>&1"
# ================= 核心更新逻辑 =================
do_update() {
echo "--------------------------------------"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 开始执行自动检测更新..."
. /etc/openwrt_release 2>/dev/null
SYS_VER="${DISTRIB_RELEASE:-}"
if command -v apk >/dev/null 2>&1 && [ ! -x "/bin/opkg" ]; then
PKG_TYPE="apk"
MATCH_PREFIX="25.12+"
elif echo "$SYS_VER" | grep -qE '^2[5-9]\.|SNAPSHOT'; then
PKG_TYPE="apk"
MATCH_PREFIX="25.12+"
elif echo "$SYS_VER" | grep -qE '^22\.03|^21\.|^19\.|^18\.'; then
PKG_TYPE="ipk"
MATCH_PREFIX="22.03"
else
PKG_TYPE="ipk"
MATCH_PREFIX="23.05-24.10"
fi
LOCAL_VER=""
if [ "$PKG_TYPE" = "apk" ]; then
LOCAL_VER=$(apk list -I "luci-app-passwall" 2>/dev/null | awk -F'-' '{print $(NF-1)}')
else
LOCAL_VER=$(opkg list-installed luci-app-passwall 2>/dev/null | awk '{print $3}')
fi
API_URL="https://api.github.com/repos/Openwrt-Passwall/openwrt-passwall/releases/latest"
RELEASE_DATA=$(curl -s "$API_URL" || wget -qO- "$API_URL")
if [ -z "$RELEASE_DATA" ]; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [-] 无法连接 GitHub API,终止本次更新。"
return 1
fi
REMOTE_VER=$(echo "$RELEASE_DATA" | grep '"tag_name":' | head -n 1 | sed -E 's/.*"tag_name": *"([^"]+)".*/\1/')
if [ -n "$LOCAL_VER" ] && echo "$LOCAL_VER" | grep -q "${REMOTE_VER%%-*}"; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [✓] 当前版本 ($LOCAL_VER) 已是最新 ($REMOTE_VER),跳过更新。"
return 0
fi
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [*] 发现新版本 $REMOTE_VER,开始下载..."
URL_APP=$(echo "$RELEASE_DATA" | grep -o "https://[^\"]*${MATCH_PREFIX}[^\"]*luci-app-passwall[^\"]*\.${PKG_TYPE}" | head -n 1)
URL_I18N=$(echo "$RELEASE_DATA" | grep -o "https://[^\"]*${MATCH_PREFIX}[^\"]*luci-i18n-passwall-zh-cn[^\"]*\.${PKG_TYPE}" | head -n 1)
if [ -z "$URL_APP" ] || [ -z "$URL_I18N" ]; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [-] 未找到匹配 ${MATCH_PREFIX} 的 .${PKG_TYPE} 更新包。"
return 1
fi
TMP_DIR="/tmp/pw_tmp_dir"
mkdir -p "$TMP_DIR" && cd "$TMP_DIR" || return 1
FILE_APP=$(basename "$URL_APP")
FILE_I18N=$(basename "$URL_I18N")
wget -q -O "$FILE_APP" "$URL_APP"
wget -q -O "$FILE_I18N" "$URL_I18N"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [*] 下载完成,开始静默安装..."
if [ "$PKG_TYPE" = "apk" ]; then
apk add --allow-untrusted *."$PKG_TYPE" >/dev/null 2>&1
else
opkg update >/dev/null 2>&1
opkg install *."$PKG_TYPE" --force-depends >/dev/null 2>&1
fi
rm -rf "$TMP_DIR"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [✓] 新版本更新流程执行完毕!"
}
# ================= 静默运行模式 (供计划任务调用) =================
if [ "$1" = "auto" ]; then
do_update
exit 0
fi
# ================= 交互菜单模式 =================
pause() {
echo ""
printf "按【回车键】返回主菜单..."
read -r DUMMY
}
install_cron() {
clear
echo "======================================"
echo " 安装定时自动更新任务"
echo "======================================"
if grep -q "$SCRIPT_PATH auto" /etc/crontabs/root 2>/dev/null; then
echo "[!] 定时任务已存在,无需重复安装。"
else
echo "$CRON_CMD" >> /etc/crontabs/root
/etc/init.d/cron restart
echo "[✓] 已成功添加定时任务:每天凌晨 4:30 自动检查并更新。"
fi
pause
}
uninstall_script() {
clear
echo "======================================"
echo " 卸载本管理脚本及定时任务"
echo "======================================"
echo "⚠️ 警告:此操作将彻底删除【自动更新脚本】及相关定时任务。"
echo "(不用担心,您已安装的 Passwall 插件主体不会受到任何影响)"
printf "确认要删除本脚本吗?(y/n): "
read -r confirm
if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then
if [ -f "/etc/crontabs/root" ]; then
sed -i "|$SCRIPT_PATH auto|d" /etc/crontabs/root
/etc/init.d/cron restart
fi
rm -f "$LOG_FILE"
echo "[✓] 定时任务和历史日志已清理干净。"
echo "[✓] 脚本本体即将自我删除。退出面板。"
rm -f "$SCRIPT_PATH"
exit 0
else
echo "[-] 已取消卸载。"
pause
fi
}
check_status() {
clear
echo "======================================"
echo " 自动更新任务运行状态"
echo "======================================"
echo "1. 【后台定时任务】:"
if grep -q "$SCRIPT_PATH auto" /etc/crontabs/root 2>/dev/null; then
echo " 🟢 运行中 (设定为每天凌晨 4:30 自动执行)"
else
echo " 🔴 未启用 (如需启用,请在主菜单选择 1 进行安装)"
fi
echo ""
echo "2. 【当前插件版本】:"
if command -v apk >/dev/null 2>&1 && [ ! -x "/bin/opkg" ]; then
apk list -I "luci-app-passwall" 2>/dev/null || echo " 未检测到安装包"
else
opkg list-installed luci-app-passwall 2>/dev/null || echo " 未检测到安装包"
fi
pause
}
view_logs() {
clear
echo "======================================"
echo " 自动更新执行日志"
echo "======================================"
if [ -f "$LOG_FILE" ]; then
tail -n 30 "$LOG_FILE"
else
echo "[-] 暂无日志记录 (计划任务尚未触发或已被清理)。"
fi
pause
}
manual_run() {
clear
echo "======================================"
echo " 立即手动执行一次检查更新"
echo "======================================"
do_update
pause
}
while true; do
clear
echo "======================================"
echo " Passwall 自动更新管理工具 v3.0"
echo "======================================"
echo " 1. ⏱️ 开启自动更新 (每天凌晨 4:30)"
echo " 2. 🗑️ 卸载本脚本 (彻底清理定时任务)"
echo " 3. 🩺 查看任务运行状态"
echo " 4. 📋 查看自动执行日志"
echo " 5. 🚀 立即检查并更新 (测试用)"
echo " 0. 退出管理面板"
echo "======================================"
printf "请输入对应数字 [0-5]: "
read choice
case "$choice" in
1) install_cron ;;
2) uninstall_script ;;
3) check_status ;;
4) view_logs ;;
5) manual_run ;;
0) clear; exit 0 ;;
*) echo "[-] 输入无效。"; sleep 1 ;;
esac
done
EOF
chmod +x /root/pw_autoupdate.sh
第二步:唤出交互面板
代码写入完成后,随时可以通过以下命令启动可视化管理面板:
Bash
/root/pw_autoupdate.sh
🛠️ 面板功能说明
- 选项 1(开启自动更新): 选择后,脚本会自动将执行命令写入系统的 Cron 计划。每天凌晨
4:30,系统会在后台静默完成版本比对和安装,全程无需人工干预。 - 选项 3 & 4(状态与日志查看): 方便排查网络环境是否正常,你可以查阅最近一次后台自动更新的详细执行日志。
- 选项 5(立即检查并更新): 若不想等待凌晨的计划任务,也可以随时通过此选项立刻拉取最新版本。
- 选项 2(卸载本脚本): 若不再需要自动更新功能,此选项会自动清除 Cron 任务、清空执行日志,并销毁脚本文件自身,实现无痕卸载(不会影响已安装的 Passwall 插件主体)。
💡 提示: 确保路由器的网络环境可以正常访问 GitHub API,否则脚本在获取最新版本信息时可能会提示连接失败。