Files
ARTEX-chixuweihu/start.sh
T
Autumn-27 44156a0a4c feat(update): 页面一键更新 + 守护启动脚本
系统配置页新增「版本与更新」卡片,顶栏版本号旁在有新版时亮出提示胶囊。
更新链路:下载发布包 → 比对 SHA256SUMS → -h 冒烟测试 → 暂存 artex.new
→ 以退出码 75 退出 → 守护脚本重新拉起并完成换装,页面轮询 /api/health
等版本号变化后自动刷新。

新增 start.sh / start.bat 作为正式启动入口,只按退出码决定是否重新拉起
(0 停止 / 75 应用新版 / 其余崩溃退避)。校验、冒烟、换装、回滚全部收在
selfupdate 包里而不写进脚本:这些逻辑在 sh 和 bat 上要写两套,而它们恰恰
最不能出错——换上跑不起来的二进制后守护进程会反复拉起它,只能上机器手工救。
Docker 的 ENTRYPOINT 一并改为该脚本,并由它转发 SIGTERM,否则 docker stop
只发给 PID 1,artex 做不了优雅关闭会被 SIGKILL 硬杀。

失败保护两道闸门互补:无法 exec 由换装前的冒烟挡住,能执行但初始化崩溃
由启动计数兜住(连续 3 次失败自动回滚 artex.old,坏的留作 artex.failed)。

GitHub 查询结果后端缓存 30 分钟(失败 2 分钟)。未认证 API 是每 IP 每小时
60 次,且这 60 次是服务器 IP 上所有用户共用的,顶栏每次整页加载都查一次,
不缓存会很快耗光配额导致真想更新时反而查不动。手动「检查更新」带 force=1
绕过缓存。

安全:只认 GitHub 域名且强制 HTTPS(逐跳校验重定向),发布源写死不可配置;
升级文件挂在可执行文件所在目录而非 CWD(服务化运行时 CWD 可能是 /);
开发构建版本号不可比较,禁用一键更新。

走完整 zip 而非裸二进制,因为现有 Release 的 SHA256SUMS 只覆盖 zip,
这样无需改 CI,也兼容已发布的历史版本。

已知限制:Docker 下只换程序不换镜像(工具链不同步、重建容器会退回镜像
版本);不同步发布包里的 skills/;更新即重启会中断运行中的任务。
2026-09-11 12:39:59 -04:00

83 lines
2.4 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/sh
# ARTEX 守护启动脚本(Linux / macOS / Docker ENTRYPOINT)
#
# 用法:
# ./start.sh 前台运行(Ctrl-C 停止)
# nohup ./start.sh >artex.log 2>&1 & 后台常驻
# ./start.sh -addr :9000 额外参数原样透传给 artex
#
# 它只做一件事:把 artex 跑起来,进程退出后按退出码决定要不要再拉起。
#
# 0 用户正常停止 → 退出循环
# 75 程序请求重启 → 立刻重跑(页面点了"一键更新"或"回滚")
# 其他 崩溃 → 退避后重跑(1→2→4…最多 60 秒)
#
# 刻意不在这里做下载、SHA256 校验或换装:那些逻辑在 sh 和 bat 上要写两套,
# 而它们恰恰是最不能出错的一环——一旦换上跑不起来的二进制,本脚本会忠实地
# 反复拉起它,用户只能上机器手工救。所以校验/换装全部留在 Go 里(selfupdate 包),
# 由 artex 自己在启动时完成,脚本保持傻瓜化。
set -u
cd "$(dirname "$0")" || exit 1
BIN=./artex
[ -x "$BIN" ] || { echo "[artex] 找不到可执行文件 $BIN" >&2; exit 1; }
RESTART_CODE=75
MAX_DELAY=60
child=0
stopping=0
# 转发停止信号给 artex 本体。
#
# Docker 下这是必需的:docker stop 只把 SIGTERM 发给 PID 1(也就是本脚本),
# 不会发给子进程。不转发的话 artex 收不到信号、做不了优雅关闭,10 秒后被 SIGKILL
# 硬杀,正在跑的任务直接断在半路。
forward() {
stopping=1
if [ "$child" -ne 0 ]; then
kill -TERM "$child" 2>/dev/null || true
fi
}
trap forward INT TERM
delay=1
while :; do
"$BIN" "$@" &
child=$!
# 信号会打断 wait 并让它返回 >128。此时子进程其实还在做优雅关闭,
# 必须再 wait 一次才能拿到它真正的退出码。
wait "$child"
code=$?
if [ "$code" -gt 128 ]; then
wait "$child"
code=$?
fi
child=0
if [ "$stopping" -eq 1 ]; then
echo "[artex] 已停止"
exit 0
fi
case "$code" in
0)
echo "[artex] 正常退出"
exit 0
;;
"$RESTART_CODE")
# 更新/回滚已就绪:重跑后 artex 会在启动时完成换装(见 selfupdate.Bootstrap)。
echo "[artex] 请求重启(应用新版本)…"
delay=1
;;
*)
echo "[artex] 异常退出 (code=$code),${delay}s 后重启" >&2
sleep "$delay"
delay=$((delay * 2))
[ "$delay" -gt "$MAX_DELAY" ] && delay=$MAX_DELAY
;;
esac
done