fix: preserve updater across systemd restart

This commit is contained in:
Qiufeng
2026-08-04 22:31:20 +08:00
parent abba079dde
commit 3bf0d1e0e6
4 changed files with 34 additions and 21 deletions
+11 -11
View File
@@ -111,7 +111,7 @@ PostgreSQL-only 正式构建:
```bash
cd oa-backend
./gradlew clean bootJar -PreleaseVersion=0.3.6 -PproductionBuild=true
./gradlew clean bootJar -PreleaseVersion=0.3.7 -PproductionBuild=true
```
正式 JAR 必须包含 PostgreSQL 驱动,并且不得包含 `sqlite-jdbc``hibernate-community-dialects`
@@ -214,18 +214,18 @@ curl -fsSL https://git.example.com/awaioi/ERP/raw/branch/main/install.sh \
set -e
tmp="$(mktemp)"
trap 'rm -f -- "$tmp"' EXIT
curl -fsSL http://38.76.196.225:10099/awaioi/ERP/raw/tag/v0.3.6/install.sh -o "$tmp"
printf '%s %s\n' '76917da519895bec815bb5492b12f0894e8cff26d6754cb9b2569b45e52ed83c' "$tmp" | sha256sum -c -
curl -fsSL http://38.76.196.225:10099/awaioi/ERP/raw/tag/v0.3.7/install.sh -o "$tmp"
printf '%s %s\n' '88328b3086ece360d3c05d4a22bee06b03ed3639a454c1fe7b9c04b1da80a980' "$tmp" | sha256sum -c -
sudo -E bash "$tmp" \
--gitea-url http://38.76.196.225:10099 \
--repository awaioi/ERP \
--version 0.3.6 \
--version 0.3.7 \
--public-url http://38.76.196.225:8091 \
--allow-insecure
)
```
只有 `v0.3.6` Release 发布后这条命令才可下载安装包。固定 tag 和 SHA-256 只用于保护当前 HTTP 引导脚本不被传输途中篡改;Release 资产仍会继续执行 Ed25519 和 SHA-256 双重校验。HTTP 会暴露请求、Release 元数据和可能使用的访问令牌,不得作为长期生产方案。
只有 `v0.3.7` Release 发布后这条命令才可下载安装包。固定 tag 和 SHA-256 只用于保护当前 HTTP 引导脚本不被传输途中篡改;Release 资产仍会继续执行 Ed25519 和 SHA-256 双重校验。HTTP 会暴露请求、Release 元数据和可能使用的访问令牌,不得作为长期生产方案。
### 完整卸载后重装
@@ -236,7 +236,7 @@ curl -fsSL https://git.example.com/awaioi/ERP/raw/branch/main/install.sh \
set -e
tmp="$(mktemp)"
trap 'rm -f -- "$tmp"' EXIT
curl -fsSL http://38.76.196.225:10099/awaioi/ERP/raw/tag/v0.3.6/uninstall.sh -o "$tmp"
curl -fsSL http://38.76.196.225:10099/awaioi/ERP/raw/tag/v0.3.7/uninstall.sh -o "$tmp"
printf '%s %s\n' '98c56fed2fd4d01874e4ab5a1a4f3ec42ec3e29b315ffd87385a95488d587546' "$tmp" | sha256sum -c -
sudo -E bash "$tmp" --purge-database --yes
)
@@ -301,13 +301,13 @@ location / {
4. 校验 `manifest.json` 中的版本、`database=postgresql``rollbackCompatible=true`
5. 可选执行 `pg_dump`,将新版本写入独立目录。
6. 原子切换 `current` 符号链接,并停止旧 Java 进程。
7. systemd/launchd 拉起新版本,更新助手等待新的 PID 和 `/api/oa/health`
7. systemd/launchd 拉起新版本,更新助手等待新的 PID 和 `/api/oa/health`Linux unit 使用 `KillMode=process`,确保更新助手不会随旧 Java 进程一起被 systemd 清理
8. 新版本不健康时切回上一链接,终止故障进程并再次验证旧版本健康状态。
同一安装目录使用操作系统文件锁,不能并发执行两个更新任务。也可以手工触发:
```bash
/opt/kaidi-erp/current/bin/erp-update install 0.3.6
/opt/kaidi-erp/current/bin/erp-update install 0.3.7
```
应用回滚不等于数据库回滚。包含不可逆 Flyway 迁移的版本必须先保证旧应用仍兼容新结构,并建议在安装配置中启用:
@@ -348,8 +348,8 @@ base64 < ~/.config/kaidi-erp/release-signing-key.pem | tr -d '\n'
```bash
git switch main
git pull --ff-only origin main
git tag -a v0.3.6 -m 'Kaidi ERP v0.3.6'
git push origin v0.3.6
git tag -a v0.3.7 -m 'Kaidi ERP v0.3.7'
git push origin v0.3.7
```
发布完成后必须确认 Release 页面存在四个资产,并使用仓库中的 `distribution/release-public-key.pem` 验证签名。私钥与该公钥不匹配时打包脚本会直接失败。
@@ -358,7 +358,7 @@ git push origin v0.3.6
```bash
ERP_RELEASE_PRIVATE_KEY_FILE="$HOME/.config/kaidi-erp/release-signing-key.pem" \
bash scripts/package-release.sh 0.3.6
bash scripts/package-release.sh 0.3.7
```
## 配置参考
+12 -10
View File
@@ -24,11 +24,13 @@ Gitea Actions runner 需要预装 Java 17 或更高版本、Node.js/npm、Python
base64 < ~/.config/kaidi-erp/release-signing-key.pem | tr -d '\n'
```
发布稳定版本:
发布稳定版本(先确认发布提交已经同步到 `main``dev`
```bash
git tag v0.3.6
git push origin v0.3.6
git switch main
git pull --ff-only origin main
git tag -a v0.3.7 -m 'Kaidi ERP v0.3.7'
git push origin v0.3.7
```
## 首次安装
@@ -52,17 +54,17 @@ Linux 生产服务要求主机使用 systemd;没有 systemd 的容器、WSL
当前 `http://38.76.196.225:10099` 仅用于开发测试,安装器必须同时传入 `--allow-insecure`。在没有 HTTPS 的情况下,必须从固定 tag 下载引导脚本并验证本版本记录的 SHA-256,禁止把可变的 `main` 分支脚本直接管道给 root。HTTP 仍会暴露请求、Release 元数据和 Gitea token,不应作为生产部署方式。
当前 `v0.3.6` 安装命令:
当前 `v0.3.7` 安装命令:
```bash
(
set -e
tmp="$(mktemp)"
trap 'rm -f -- "$tmp"' EXIT
curl -fsSL http://38.76.196.225:10099/awaioi/ERP/raw/tag/v0.3.6/install.sh -o "$tmp"
printf '%s %s\n' '76917da519895bec815bb5492b12f0894e8cff26d6754cb9b2569b45e52ed83c' "$tmp" | sha256sum -c -
curl -fsSL http://38.76.196.225:10099/awaioi/ERP/raw/tag/v0.3.7/install.sh -o "$tmp"
printf '%s %s\n' '88328b3086ece360d3c05d4a22bee06b03ed3639a454c1fe7b9c04b1da80a980' "$tmp" | sha256sum -c -
sudo -E bash "$tmp" --gitea-url http://38.76.196.225:10099 \
--repository awaioi/ERP --version 0.3.6 \
--repository awaioi/ERP --version 0.3.7 \
--public-url http://38.76.196.225:8091 --allow-insecure
)
```
@@ -74,7 +76,7 @@ Linux 生产服务要求主机使用 systemd;没有 systemd 的容器、WSL
set -e
tmp="$(mktemp)"
trap 'rm -f -- "$tmp"' EXIT
curl -fsSL http://38.76.196.225:10099/awaioi/ERP/raw/tag/v0.3.6/uninstall.sh -o "$tmp"
curl -fsSL http://38.76.196.225:10099/awaioi/ERP/raw/tag/v0.3.7/uninstall.sh -o "$tmp"
printf '%s %s\n' '98c56fed2fd4d01874e4ab5a1a4f3ec42ec3e29b315ffd87385a95488d587546' "$tmp" | sha256sum -c -
sudo -E bash "$tmp" --purge-database --yes
)
@@ -93,13 +95,13 @@ Linux 生产服务要求主机使用 systemd;没有 systemd 的容器、WSL
1. 下载正式归档、`SHA256SUMS` 和签名并验证 Ed25519/SHA-256;独立安装器资产只在首次安装使用。
2. 拒绝路径穿越、符号链接和结构不完整的安装包。
3. 可选执行 `pg_dump`,再写入独立版本目录。
4. 原子切换 `current` 链接并终止旧进程,由 systemd 或 launchd 拉起新版本。
4. 原子切换 `current` 链接并终止旧进程,由 systemd 或 launchd 拉起新版本Linux unit 使用 `KillMode=process`,让更新助手继续执行健康检查和必要的回滚
5. 等待健康检查;失败时切回上一版本并再次验证健康状态。
更新过程使用操作系统文件锁,同一安装目录同时只允许一个更新任务。手动触发可执行:
```bash
/opt/kaidi-erp/current/bin/erp-update install 0.3.6
/opt/kaidi-erp/current/bin/erp-update install 0.3.7
```
在线更新依赖安装器注册的 systemd 或 launchd 服务来拉起新旧版本。使用 `--no-service` 时后台更新默认关闭;如由其他进程管理器接管,须先确认它会在 ERP 进程退出后自动重启,再手工启用 `OA_UPDATE_ENABLED=true`。健康检查默认最多等待 120 秒、每 2 秒轮询一次,可分别通过 `ERP_UPDATE_HEALTH_TIMEOUT_SECONDS``ERP_UPDATE_HEALTH_POLL_SECONDS` 调整。
+3
View File
@@ -435,6 +435,8 @@ start_service() {
fi
if [[ "$PLATFORM" == "linux" ]]; then
# The updater shares this service cgroup and must outlive the Java process
# to verify the restarted release and roll back a failed health check.
cat > /etc/systemd/system/kaidi-erp.service <<EOF
[Unit]
Description=Kaidi ERP
@@ -443,6 +445,7 @@ Wants=network-online.target
[Service]
Type=simple
KillMode=process
User=$ERP_USER
Group=$ERP_GROUP
Environment="ERP_INSTALL_ROOT=$INSTALL_ROOT"
+8
View File
@@ -593,6 +593,13 @@ test_systemd_unit_uses_compatible_protection() (
! grep -Fq 'ProtectSystem=strict' "$PROJECT_ROOT/install.sh"
)
test_systemd_unit_preserves_update_helper_during_restart() (
local unit
unit="$(sed -n '/^ cat > \/etc\/systemd\/system\/kaidi-erp.service/,/^ systemctl daemon-reload/p' "$PROJECT_ROOT/install.sh")"
grep -Fqx 'KillMode=process' <<< "$unit"
! grep -Fq 'KillMode=control-group' <<< "$unit"
)
test_systemd_unit_uses_unquoted_legacy_paths() (
local unit
unit="$(sed -n '/^ cat > \/etc\/systemd\/system\/kaidi-erp.service/,/^ systemctl daemon-reload/p' "$PROJECT_ROOT/install.sh")"
@@ -771,6 +778,7 @@ run_test 'installer moves database setup to the web wizard' test_installer_moves
run_test 'installer requires an explicit Gitea URL' test_installer_requires_explicit_gitea_url
run_test 'Linux production install requires systemd' test_linux_service_preflight_requires_systemd
run_test 'systemd unit uses compatible protection' test_systemd_unit_uses_compatible_protection
run_test 'systemd unit preserves update helper during restart' test_systemd_unit_preserves_update_helper_during_restart
run_test 'systemd unit uses unquoted legacy paths' test_systemd_unit_uses_unquoted_legacy_paths
run_test 'uninstaller purges database before removing files' test_uninstaller_purges_database_before_removing_files
run_test 'uninstaller rejects unsafe paths' test_uninstaller_rejects_unsafe_paths