Files
eth_hedge_sim/deploy/manage.sh
T
dekun da5eb4c18c Add Fleet control plane and split manage.sh deploy menu.
Strategy nodes gain fleet token APIs; control/ app for local ops; manage.sh offers strategy vs control one-click deploy.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-30 10:46:40 +08:00

268 lines
7.9 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.
#!/usr/bin/env bash
# 比特骆驼自动化对冲系统 部署管理器(工程 eth_hedge_sim
# 部署环境: Ubuntu 22.04 LTS
#
# 新服务器(免克隆):
# curl -fsSL https://git.bz121.com/dekun/eth_hedge_sim/raw/branch/main/deploy/manage.sh | bash
#
# 已安装:
# bash /opt/eth_hedge_sim/deploy/manage.sh
#
set -e
if [ -n "${BASH_VERSION:-}" ]; then
set -o pipefail
fi
INSTALL_ROOT="${INSTALL_ROOT:-/opt/eth_hedge_sim}"
GIT_URL="${GIT_URL:-https://git.bz121.com/dekun/eth_hedge_sim.git}"
GIT_BRANCH="${GIT_BRANCH:-main}"
# curl | bash 时脚本从 stdin 执行,BASH_SOURCE[0] 为空;须先安全探测再 set -u
_script_src="${BASH_SOURCE[0]:-}"
if [[ -n "${_script_src}" && -f "${_script_src}" ]]; then
DEPLOY_DIR="$(cd "$(dirname "${_script_src}")" && pwd)"
REPO_ROOT="$(cd "${DEPLOY_DIR}/.." && pwd)"
LIB_DIR="${DEPLOY_DIR}/lib"
else
DEPLOY_DIR=""
REPO_ROOT=""
LIB_DIR=""
fi
unset _script_src
set -u
repo_ready() {
[[ -f "${1}/deploy/manage.sh" && -f "${1}/deploy/pull_and_restart.sh" && -d "${1}/deploy/lib" ]]
}
ensure_git_cli() {
if command -v git >/dev/null 2>&1; then
return 0
fi
if command -v apt-get >/dev/null 2>&1; then
export DEBIAN_FRONTEND=noninteractive
# 新机常撞 unattended-upgrades 占锁;最多等 10 分钟
local waited=0
while pgrep -x unattended-upgr >/dev/null 2>&1 \
|| pgrep -x apt-get >/dev/null 2>&1 \
|| pgrep -x apt >/dev/null 2>&1 \
|| pgrep -x dpkg >/dev/null 2>&1 \
|| { command -v fuser >/dev/null 2>&1 && fuser /var/lib/dpkg/lock-frontend >/dev/null 2>&1; }; do
if [[ "${waited}" -eq 0 ]]; then
echo "等待 apt 锁释放(unattended-upgrades)…"
fi
if [[ "${waited}" -ge 600 ]]; then
echo "错误: 等待 apt 锁超时,请稍后再试" >&2
exit 1
fi
sleep 5
waited=$((waited + 5))
done
apt-get update -qq
apt-get install -y git ca-certificates curl
else
echo "错误: 未找到 git" >&2
exit 1
fi
}
sync_repo_if_present() {
local root="$1"
if [[ -d "${root}/.git" ]] && command -v git >/dev/null 2>&1; then
git -C "${root}" fetch --all --prune 2>/dev/null || true
git -C "${root}" checkout "${GIT_BRANCH}" 2>/dev/null || true
git -C "${root}" pull --ff-only origin "${GIT_BRANCH}" 2>/dev/null \
|| git -C "${root}" pull --ff-only 2>/dev/null \
|| true
fi
}
# 旧目录已存在但缺 manage.sh:尽量 git pull / 修复后切到仓库内脚本
heal_existing_install() {
local root="$1"
echo "检测到已有目录但缺少管理脚本: ${root}"
echo "尝试同步最新代码…"
ensure_git_cli
if [[ -d "${root}/.git" ]]; then
sync_repo_if_present "${root}"
if repo_ready "${root}"; then
echo "同步成功,切换到仓库内 manage.sh"
exec bash "${root}/deploy/manage.sh" "$@" </dev/tty
fi
echo "git pull 后仍不完整,尝试强制对齐 origin/${GIT_BRANCH}"
git -C "${root}" fetch origin "${GIT_BRANCH}" || true
git -C "${root}" reset --hard "origin/${GIT_BRANCH}" || true
if repo_ready "${root}"; then
echo "对齐成功,切换到仓库内 manage.sh"
exec bash "${root}/deploy/manage.sh" "$@" </dev/tty
fi
fi
# 无 .git 或仍不可用:备份 .env/data 后重新 clone
echo "将备份配置并重新克隆到 ${root}"
local stamp backup_dir
stamp="$(date +%Y%m%d-%H%M%S)"
backup_dir="/root/backups/eth_hedge_sim/heal-${stamp}"
mkdir -p "${backup_dir}"
[[ -f "${root}/.env" ]] && cp -a "${root}/.env" "${backup_dir}/.env"
[[ -d "${root}/backend/data" ]] && cp -a "${root}/backend/data" "${backup_dir}/data" || true
echo "备份目录: ${backup_dir}"
local removed="${root}.old.${stamp}"
mv "${root}" "${removed}"
echo "旧目录已移至: ${removed}"
mkdir -p "$(dirname "${root}")"
git clone -b "${GIT_BRANCH}" "${GIT_URL}" "${root}"
if [[ -f "${backup_dir}/.env" ]]; then
cp -a "${backup_dir}/.env" "${root}/.env"
echo "已恢复 .env"
fi
if [[ -d "${backup_dir}/data" ]]; then
mkdir -p "${root}/backend"
cp -a "${backup_dir}/data" "${root}/backend/data"
echo "已恢复 backend/data"
fi
exec bash "${root}/deploy/manage.sh" "$@" </dev/tty
}
bootstrap_repo() {
if repo_ready "${INSTALL_ROOT}"; then
REPO_ROOT="${INSTALL_ROOT}"
DEPLOY_DIR="${REPO_ROOT}/deploy"
LIB_DIR="${DEPLOY_DIR}/lib"
sync_repo_if_present "${REPO_ROOT}"
# pull 后可能才有 lib,再校验一次
if ! repo_ready "${REPO_ROOT}"; then
heal_existing_install "${INSTALL_ROOT}" "$@"
fi
return 0
fi
if [[ -n "${REPO_ROOT}" ]] && repo_ready "${REPO_ROOT}"; then
DEPLOY_DIR="${REPO_ROOT}/deploy"
LIB_DIR="${DEPLOY_DIR}/lib"
return 0
fi
# 目录在,但还是旧版(你当前的情况)
if [[ -d "${INSTALL_ROOT}" ]]; then
if [[ "$(id -u)" -ne 0 ]]; then
echo "错误: 请使用 root 执行" >&2
exit 1
fi
heal_existing_install "${INSTALL_ROOT}" "$@"
fi
echo "比特骆驼自动化对冲系统 部署管理器 — 首次自举"
echo "将克隆到: ${INSTALL_ROOT}"
if [[ "$(id -u)" -ne 0 ]]; then
echo "错误: 请使用 root 执行" >&2
exit 1
fi
ensure_git_cli
mkdir -p "$(dirname "${INSTALL_ROOT}")"
git clone -b "${GIT_BRANCH}" "${GIT_URL}" "${INSTALL_ROOT}"
# clone 后用仓库内脚本 + 终端 stdin(管道已 EOF)
exec bash "${INSTALL_ROOT}/deploy/manage.sh" "$@" </dev/tty
}
show_banner() {
local path
path="${INSTALL_ROOT}"
if [[ -n "${REPO_ROOT}" ]] && repo_ready "${REPO_ROOT}"; then
path="${REPO_ROOT}"
fi
echo ""
echo "╔══════════════════════════════════════╗"
echo "║ 比特骆驼自动化对冲系统 部署管理器 ║"
echo "║ 路径: ${path}"
echo "╚══════════════════════════════════════╝"
echo ""
}
show_menu() {
echo " 1) 一键部署策略机"
echo " 2) 一键部署中控机"
echo " 3) 一键卸载"
echo " 4) 更新策略机"
echo " 5) 更新中控机"
echo " 0) 退出"
echo ""
}
# 交互读入(兼容 curl|bash
cm_read() {
local __var="$1"
local __prompt="${2:-}"
local __line=""
if [[ -n "${__prompt}" ]]; then
printf '%s' "${__prompt}" >/dev/tty 2>/dev/null || printf '%s' "${__prompt}"
fi
if [[ -r /dev/tty ]]; then
IFS= read -r __line </dev/tty || true
else
IFS= read -r __line || true
fi
printf -v "${__var}" '%s' "${__line}"
}
# 中控:依赖已齐 + 仓库在位后跑 control/deploy/update.sh
deploy_control_node() {
require_root
if ! REPO_ROOT="$(resolve_repo_root)"; then
die "未找到安装目录 ${INSTALL_ROOT},请先执行「1) 一键部署策略机」或完成仓库自举"
fi
if [[ ! -f "${REPO_ROOT}/control/deploy/update.sh" ]]; then
die "缺少 control/deploy/update.sh,请先 git pull 更新仓库"
fi
step "一键部署中控机 — 环境检测 (缺则装,有则跳过)"
ensure_system_deps
step "部署中控 (git pull + 构建 + pm2 eth-hedge-control)"
bash "${REPO_ROOT}/control/deploy/update.sh"
echo ""
log "中控部署完成 → http://<本机IP>:5160 默认账号 admin / admin123"
}
main_menu() {
bootstrap_repo
# shellcheck source=lib/common.sh
source "${LIB_DIR}/common.sh"
REPO_ROOT="$(resolve_repo_root || echo "${INSTALL_ROOT}")"
while true; do
show_banner
show_menu
local choice=""
cm_read choice "请选择 [0-5]: "
case "${choice}" in
1)
bash "${LIB_DIR}/install.sh"
;;
2)
deploy_control_node
;;
3)
bash "${LIB_DIR}/uninstall.sh"
;;
4)
bash "${LIB_DIR}/update.sh"
;;
5)
deploy_control_node
;;
0)
echo "再见."
exit 0
;;
*)
echo "无效选项,请输入 0-5"
;;
esac
echo ""
cm_read _ "按 Enter 返回菜单..."
done
}
main_menu "$@"