Files
bluebird/deploy/upgrade.sh
T

93 lines
4.3 KiB
Bash
Executable File

#!/bin/sh
# Upgrade the existing installation, retaining its data and administrator account.
set -eu
PATH=/usr/sbin:/usr/bin:/sbin:/bin
export PATH
umask 077
usage() {
cat <<'HELP'
用法:sudo ./upgrade.sh [--prefix /opt/bluebird] [--access-url URL ...] [--lan-url URL] [--listen IP:端口] [--no-start]
保留当前配置参数、文件、密钥和管理员密码;新增入口与指定监听地址会合并到配置中。
默认停止服务、一致性备份、更新程序及配置、检查后启动。失败时恢复旧程序和配置。
--no-start用于已手动停服的离线升级,升级后暂不启动服务。
HELP
}
die(){ printf '%s\n' "升级失败:$*" >&2;exit 1; }
value(){ [ "$#" -ge 2 ] && [ -n "$2" ] || die "$1缺少参数"; }
prefix=/opt/bluebird
additions=
lan_url=
listen=
no_start=false
while [ "$#" -gt 0 ];do
case "$1" in
--prefix) value "$@";prefix=$2;shift 2 ;;
--access-url) value "$@";case "$2" in *[[:space:]]*) die '访问地址不能含空白' ;;esac;additions="$additions $2";shift 2 ;;
--lan-url) value "$@";lan_url=$2;shift 2 ;;
--listen) value "$@";listen=$2;shift 2 ;;
--no-start) no_start=true;shift ;;
-h|--help) usage;exit 0 ;;
*) die "未知选项:$1" ;;
esac
done
[ "$(id -u)" = 0 ] || die '请使用sudo或root运行'
[ "$(uname -s)" = Linux ] || die '仅支持Linux'
prefix=$(realpath -m -- "$prefix")
[ -x "$prefix/bluebird" ] && [ -f "$prefix/config.toml" ] || die '未找到已有安装,请使用install.sh'
exec 9>"$prefix/.upgrade.lock"
flock -n 9 || die '另一升级进程正在运行'
package_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
[ -x "$package_dir/bluebird" ] && [ -r "$package_dir/ARCH" ] || die '请在新版发布包目录运行'
case "$(cat "$package_dir/ARCH"):$(uname -m)" in amd64:x86_64|arm64:aarch64) ;;*) die '发布包架构与主机不匹配' ;;esac
if [ "$no_start" = false ];then [ -d /run/systemd/system ] && command -v systemctl >/dev/null || die 'systemd未运行,先手动停服再使用--no-start';fi
candidate=$(mktemp "$prefix/.upgrade-config-XXXXXX.toml")
backup=
changed=false
was_active=false
success=false
cleanup(){
rm -f -- "$candidate" "$prefix/bluebird.new"
if [ "$success" = false ];then
if [ "$changed" = true ];then
if [ "$no_start" = false ];then systemctl stop bluebird.service || :;fi
install -o root -g bluebird -m 0750 "$backup/bluebird" "$prefix/bluebird.rollback"
mv -f -- "$prefix/bluebird.rollback" "$prefix/bluebird"
cp -p -- "$backup/config.toml" "$prefix/config.toml"
printf '%s\n' "已恢复旧程序和配置;备份保留在$backup" >&2
fi
if [ "$was_active" = true ] && [ "$no_start" = false ];then systemctl start bluebird.service || :;fi
fi
}
trap cleanup EXIT
trap 'exit 130' INT
trap 'exit 143' TERM HUP
cp -p -- "$prefix/config.toml" "$candidate"
set -- "$package_dir/bluebird" configure-access --config "$candidate"
[ -z "$listen" ] || set -- "$@" --listen "$listen"
[ -z "$lan_url" ] || set -- "$@" --lan-url "$lan_url"
# URLs are separate argv values, never shell code. Globbing is disabled.
set -f
for item in $additions;do set -- "$@" --access-url "$item";done
"$@"
"$package_dir/bluebird" validate-config --config "$candidate"
if [ "$no_start" = false ];then
if systemctl is-active --quiet bluebird.service;then was_active=true;fi
systemctl stop bluebird.service
fi
backup="$prefix/backups/upgrade-$(date -u +%Y%m%dT%H%M%SZ)-$$"
install -d -o bluebird -g bluebird -m 0700 "$backup"
cp -p -- "$prefix/config.toml" "$backup/config.toml"
install -o root -g bluebird -m 0750 "$prefix/bluebird" "$backup/bluebird"
runuser -u bluebird -- "$prefix/bluebird" backup --config "$prefix/config.toml" --output "$backup/data.tar.gz"
# No configuration/data reinitialization; keep all existing administrator hashes.
install -o root -g bluebird -m 0750 "$package_dir/bluebird" "$prefix/bluebird.new"
changed=true
mv -f -- "$prefix/bluebird.new" "$prefix/bluebird"
mv -f -- "$candidate" "$prefix/config.toml"
runuser -u bluebird -- "$prefix/bluebird" check --config "$prefix/config.toml"
if [ "$no_start" = false ];then systemctl start bluebird.service;systemctl is-active --quiet bluebird.service;fi
success=true
printf '%s\n' "升级完成:$prefix" "旧版本、配置及一致性数据备份:$backup"
if [ "$no_start" = true ];then printf '%s\n' '服务尚未启动,请执行:systemctl start bluebird.service';fi