fix: verify service health after installation
TallyNote release / linux-x64 (push) Successful in 7m7s

This commit is contained in:
Qiufeng
2026-09-02 12:14:18 +08:00
parent 5dcf9d0f61
commit 37ffc27ff5
7 changed files with 136 additions and 21 deletions
+70 -1
View File
@@ -60,6 +60,10 @@ INSTALL_BACKUP_DIR=''
INSTALL_WAS_ACTIVE=0
INSTALL_PATH_WAS_ACTIVE=0
INSTALL_UPDATE_WAS_ACTIVE=0
INSTALL_WAS_ENABLED=0
INSTALL_PATH_WAS_ENABLED=0
INSTALL_UPDATE_WAS_ENABLED=0
INSTALL_SYSTEMD_TOUCHED=0
DATA_DIR_TEMP_ROOT=0
DATA_DIR_ORIGINAL_OWNER=''
@@ -218,6 +222,24 @@ check_requested_port() {
esac
}
wait_for_service_health() {
local host=$1 port=$2 health_host health_url attempt
health_host=$host
case "$health_host" in
0.0.0.0) health_host=127.0.0.1 ;;
::) health_host=::1 ;;
esac
if [[ "$health_host" == *:* && "$health_host" != \[* ]]; then health_host="[$health_host]"; fi
health_url="http://${health_host}:${port}/health"
for attempt in 1 2 3 4 5 6 7 8 9 10 11 12; do
if curl --proto '=http' --connect-timeout 2 --max-time 3 --fail --silent "$health_url" >/dev/null 2>&1; then
return 0
fi
(( attempt < 12 )) && sleep 1
done
return 1
}
has_network_environment() {
[[ -n "${TALLYNOTE_HOST+x}" || -n "${TALLYNOTE_PORT+x}" || -n "${TALLYNOTE_PUBLIC_ORIGIN+x}" || -n "${TALLYNOTE_ALLOW_INSECURE_HTTP+x}" ]]
}
@@ -770,6 +792,17 @@ stop_existing_services() {
# Stop the path trigger first so it cannot launch the privileged updater while
# the data tree is being repaired.
for unit in tallynote-update.path tallynote-update.service tallynote.service; do
case "$unit" in
tallynote.service)
if systemctl is-enabled --quiet "$unit"; then INSTALL_WAS_ENABLED=1; fi
;;
tallynote-update.path)
if systemctl is-enabled --quiet "$unit"; then INSTALL_PATH_WAS_ENABLED=1; fi
;;
tallynote-update.service)
if systemctl is-enabled --quiet "$unit"; then INSTALL_UPDATE_WAS_ENABLED=1; fi
;;
esac
if systemctl is-active --quiet "$unit"; then
case "$unit" in
tallynote.service) INSTALL_WAS_ACTIVE=1 ;;
@@ -783,6 +816,17 @@ stop_existing_services() {
rollback_install_if_needed() {
local result=$? rollback_tmp
if (( INSTALL_COMMITTED == 0 && INSTALL_SYSTEMD_TOUCHED == 1 )) && command -v systemctl >/dev/null 2>&1; then
# The failed install may have started units that were inactive before the
# attempt. Stop them before restoring files so systemd never keeps running
# code from a release directory that rollback is about to remove.
for unit in tallynote-update.path tallynote-update.service tallynote.service; do
systemctl stop "$unit" >/dev/null 2>&1 || true
done
if (( INSTALL_WAS_ENABLED == 0 )); then systemctl disable tallynote.service >/dev/null 2>&1 || true; fi
if (( INSTALL_PATH_WAS_ENABLED == 0 )); then systemctl disable tallynote-update.path >/dev/null 2>&1 || true; fi
if (( INSTALL_UPDATE_WAS_ENABLED == 0 )); then systemctl disable tallynote-update.service >/dev/null 2>&1 || true; fi
fi
if (( INSTALL_SWITCHED == 1 && INSTALL_COMMITTED == 0 )); then
if [[ -n "$INSTALL_PREVIOUS_TARGET" && -d "$INSTALL_PREVIOUS_TARGET" ]]; then
rollback_tmp="$PREFIX/.current-rollback-$$-${RANDOM}.tmp"
@@ -821,6 +865,7 @@ rollback_install_if_needed() {
done
fi
if command -v systemctl >/dev/null 2>&1; then
if (( INSTALL_SYSTEMD_TOUCHED == 1 )); then systemctl daemon-reload >/dev/null 2>&1 || true; fi
if (( INSTALL_WAS_ACTIVE == 1 )); then systemctl start tallynote.service 2>/dev/null || true; fi
if (( INSTALL_UPDATE_WAS_ACTIVE == 1 )); then systemctl start tallynote-update.service 2>/dev/null || true; fi
if (( INSTALL_PATH_WAS_ACTIVE == 1 )); then systemctl start tallynote-update.path 2>/dev/null || true; fi
@@ -1038,7 +1083,10 @@ validate_existing_env() {
install_release() {
local archive=$1 version=$2 tmp release_dir current_tmp=''
tmp=$(mktemp -d)
trap 'rm -rf "$tmp" "$current_tmp" 2>/dev/null || true' RETURN
# RETURN traps survive the function that installs them. Clear the trap from
# inside its first invocation so a later function cannot evaluate the local
# temporary path after it has gone out of scope under `set -u`.
trap 'trap - RETURN; if [[ -n "${tmp-}" ]]; then rm -rf -- "$tmp" 2>/dev/null || true; fi; if [[ -n "${current_tmp-}" ]]; then rm -f -- "$current_tmp" 2>/dev/null || true; fi' RETURN
safe_extract "$archive" "$tmp/unpacked"
normalize_release_tree "$tmp/unpacked"
[[ -d "$tmp/unpacked/dist" ]] || die 'release archive must contain dist/ at its root'
@@ -1364,7 +1412,28 @@ main() {
chown root:root "$CONFIG_DIR/tallynote.env"
chmod 640 "$CONFIG_DIR/tallynote.env"
systemctl daemon-reload
INSTALL_SYSTEMD_TOUCHED=1
systemctl enable --now tallynote.service tallynote-update.path
local health_host health_port
health_host=$(read_env_value "$CONFIG_DIR/tallynote.env" TALLYNOTE_HOST 2>/dev/null || true)
health_port=$(read_env_value "$CONFIG_DIR/tallynote.env" TALLYNOTE_PORT 2>/dev/null || true)
health_host=${health_host:-$INSTALL_HOST}
health_port=${health_port:-$INSTALL_PORT}
stage "检查本机健康接口(${health_host}:${health_port})"
if ! wait_for_service_health "$health_host" "$health_port"; then
log "本机健康检查失败:http://${health_host}:${health_port}/health"
systemctl status tallynote.service --no-pager -l || true
if command -v journalctl >/dev/null 2>&1; then
journalctl -u tallynote.service -n 30 --no-pager || true
fi
die 'TallyNote 服务未通过健康检查;安装未完成,请根据上面的 systemd 日志修复后重试'
fi
stage_done '本机健康检查通过,服务正在监听'
if [[ "$health_host" == 127.0.0.1 || "$health_host" == localhost || "$health_host" == ::1 ]]; then
log '当前监听仅限本机;公网或其他设备无法直接访问,请重新安装并选择 0.0.0.0,或配置 HTTPS 反向代理'
else
log '当前监听已绑定非本机地址;若外部仍无法连接,请检查云安全组、主机防火墙和公网 IP/NAT'
fi
stage_done 'TallyNote 服务已启用并启动'
stage '清理旧版本并完成安装'
prune_releases