Detect Python/Node/PM2 on deploy (install only if missing); uninstall removes /opt/eth_hedge_sim.
Keep .env and DB backup under /root/backups before deleting the install directory. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+118
-12
@@ -84,22 +84,128 @@ resolve_repo_root() {
|
||||
return 1
|
||||
}
|
||||
|
||||
ensure_system_deps() {
|
||||
step "检查系统依赖"
|
||||
# ---------- 运行时检测(有则跳过,无则安装) ----------
|
||||
|
||||
python_runtime_ok() {
|
||||
command -v python3 >/dev/null 2>&1 || return 1
|
||||
# 能创建 venv 即可;pip 在项目 .venv 内安装
|
||||
python3 -c "import venv" >/dev/null 2>&1 || return 1
|
||||
return 0
|
||||
}
|
||||
|
||||
node_runtime_ok() {
|
||||
command -v node >/dev/null 2>&1 || return 1
|
||||
command -v npm >/dev/null 2>&1 || return 1
|
||||
return 0
|
||||
}
|
||||
|
||||
pm2_runtime_ok() {
|
||||
command -v pm2 >/dev/null 2>&1
|
||||
}
|
||||
|
||||
print_runtime_probe() {
|
||||
echo "环境检测:"
|
||||
if python_runtime_ok; then
|
||||
echo " [OK] Python3 + venv → $(python3 --version 2>&1)"
|
||||
else
|
||||
echo " [缺] Python3 / venv → 将自动安装"
|
||||
fi
|
||||
if node_runtime_ok; then
|
||||
echo " [OK] Node.js + npm → $(node --version 2>&1) / npm $(npm --version 2>&1)"
|
||||
else
|
||||
echo " [缺] Node.js / npm → 将自动安装 Node ${NODE_MAJOR}"
|
||||
fi
|
||||
if pm2_runtime_ok; then
|
||||
echo " [OK] PM2 → $(pm2 -v 2>&1)"
|
||||
else
|
||||
echo " [缺] PM2 → 将自动安装"
|
||||
fi
|
||||
}
|
||||
|
||||
install_python_runtime() {
|
||||
step "安装 Python3 环境 (python3 / venv / pip)"
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
if command -v apt-get >/dev/null 2>&1; then
|
||||
apt-get update -qq
|
||||
apt-get install -y git ca-certificates curl python3 python3-venv python3-pip
|
||||
if ! command -v apt-get >/dev/null 2>&1; then
|
||||
die "非 apt 系统,请手动安装 python3 python3-venv python3-pip"
|
||||
fi
|
||||
if ! command -v node >/dev/null 2>&1; then
|
||||
step "安装 Node.js ${NODE_MAJOR}"
|
||||
curl -fsSL "https://deb.nodesource.com/setup_${NODE_MAJOR}.x" | bash -
|
||||
apt-get install -y nodejs
|
||||
apt-get update -qq
|
||||
apt-get install -y python3 python3-venv python3-pip
|
||||
if ! python_runtime_ok; then
|
||||
die "Python 环境安装后仍不可用,请检查 apt 源"
|
||||
fi
|
||||
if ! command -v pm2 >/dev/null 2>&1; then
|
||||
step "安装 PM2"
|
||||
npm install -g pm2
|
||||
log "Python 已就绪: $(python3 --version 2>&1)"
|
||||
}
|
||||
|
||||
install_node_runtime() {
|
||||
step "安装 Node.js ${NODE_MAJOR}"
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
if ! command -v apt-get >/dev/null 2>&1; then
|
||||
die "非 apt 系统,请手动安装 Node.js ${NODE_MAJOR}+"
|
||||
fi
|
||||
apt-get update -qq
|
||||
apt-get install -y ca-certificates curl
|
||||
curl -fsSL "https://deb.nodesource.com/setup_${NODE_MAJOR}.x" | bash -
|
||||
apt-get install -y nodejs
|
||||
if ! node_runtime_ok; then
|
||||
die "Node.js 安装后仍不可用"
|
||||
fi
|
||||
log "Node 已就绪: $(node --version 2>&1)"
|
||||
}
|
||||
|
||||
install_pm2_runtime() {
|
||||
step "安装 PM2"
|
||||
if ! command -v npm >/dev/null 2>&1; then
|
||||
die "安装 PM2 需要先有 npm"
|
||||
fi
|
||||
npm install -g pm2
|
||||
if ! pm2_runtime_ok; then
|
||||
die "PM2 安装后仍不可用"
|
||||
fi
|
||||
log "PM2 已就绪: $(pm2 -v 2>&1)"
|
||||
}
|
||||
|
||||
ensure_base_packages() {
|
||||
local need=()
|
||||
command -v git >/dev/null 2>&1 || need+=(git)
|
||||
command -v curl >/dev/null 2>&1 || need+=(curl)
|
||||
if [[ ${#need[@]} -eq 0 ]]; then
|
||||
log "基础包 git/curl 已存在,跳过"
|
||||
return 0
|
||||
fi
|
||||
if ! command -v apt-get >/dev/null 2>&1; then
|
||||
die "缺少依赖: ${need[*]},且无 apt-get"
|
||||
fi
|
||||
step "安装基础包: ${need[*]}"
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
apt-get update -qq
|
||||
apt-get install -y ca-certificates "${need[@]}"
|
||||
}
|
||||
|
||||
ensure_system_deps() {
|
||||
step "环境检测 (Python / Node / PM2)"
|
||||
print_runtime_probe
|
||||
ensure_base_packages
|
||||
|
||||
if python_runtime_ok; then
|
||||
log "Python 环境已存在,跳过安装"
|
||||
else
|
||||
install_python_runtime
|
||||
fi
|
||||
|
||||
if node_runtime_ok; then
|
||||
log "Node.js 环境已存在,跳过安装"
|
||||
else
|
||||
install_node_runtime
|
||||
fi
|
||||
|
||||
if pm2_runtime_ok; then
|
||||
log "PM2 已存在,跳过安装"
|
||||
else
|
||||
install_pm2_runtime
|
||||
fi
|
||||
|
||||
step "环境确认"
|
||||
print_runtime_probe
|
||||
}
|
||||
|
||||
pm2_stop_project() {
|
||||
|
||||
@@ -22,6 +22,7 @@ run_pipeline() {
|
||||
|
||||
install_fresh() {
|
||||
require_root
|
||||
step "一键部署 — 环境检测与依赖"
|
||||
ensure_system_deps
|
||||
step "克隆仓库 → ${INSTALL_ROOT}"
|
||||
if [[ -d "${INSTALL_ROOT}" ]]; then
|
||||
@@ -34,6 +35,7 @@ install_fresh() {
|
||||
|
||||
install_repair() {
|
||||
require_root
|
||||
step "修复部署 — 环境检测与依赖"
|
||||
ensure_system_deps
|
||||
if ! REPO_ROOT="$(resolve_repo_root)"; then
|
||||
die "未找到安装目录 ${INSTALL_ROOT}"
|
||||
|
||||
+38
-18
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
# deploy/lib/uninstall.sh — 一键卸载(仅本项目 PM2,不动其它进程)
|
||||
# deploy/lib/uninstall.sh — 一键卸载(仅本项目 PM2,删除 /opt 安装目录)
|
||||
set -e
|
||||
set -u
|
||||
if [ -n "${BASH_VERSION:-}" ]; then
|
||||
@@ -26,22 +26,21 @@ main_uninstall() {
|
||||
echo ""
|
||||
echo "将卸载 比特骆驼自动化对冲系统 (eth_hedge_sim):"
|
||||
echo " - 停止并删除 PM2 进程: ${PM2_APP_NAME}"
|
||||
echo " - 移走目录: ${INSTALL_ROOT}"
|
||||
echo " - 备份 .env 到 ${BACKUP_ROOT}"
|
||||
echo " - 不影响其它 PM2 应用"
|
||||
echo " - 删除安装目录: ${INSTALL_ROOT}"
|
||||
echo " - 备份 .env / 数据库到 ${BACKUP_ROOT}"
|
||||
echo " - 不影响其它 PM2 应用 / 不卸载系统 Python、Node、PM2"
|
||||
echo ""
|
||||
if ! confirm_yes "确认卸载?"; then
|
||||
if ! confirm_yes "确认卸载并删除 ${INSTALL_ROOT}?"; then
|
||||
log "已取消卸载"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local stamp backup_dir removed_dir
|
||||
local stamp backup_dir
|
||||
stamp="$(TZ="${TZ_NAME}" date +%Y%m%d-%H%M%S)"
|
||||
backup_dir="${BACKUP_ROOT}/pre-uninstall-${stamp}"
|
||||
removed_dir="${INSTALL_ROOT}.removed.${stamp}"
|
||||
mkdir -p "${backup_dir}"
|
||||
|
||||
step "备份配置"
|
||||
step "备份配置与数据"
|
||||
if [[ -f "${REPO_ROOT}/.env" ]]; then
|
||||
cp -a "${REPO_ROOT}/.env" "${backup_dir}/.env"
|
||||
fi
|
||||
@@ -51,30 +50,51 @@ main_uninstall() {
|
||||
{
|
||||
echo "created_at=${stamp}"
|
||||
echo "install_root=${INSTALL_ROOT}"
|
||||
echo "removed_dir=${removed_dir}"
|
||||
echo "pm2_app=${PM2_APP_NAME}"
|
||||
echo "action=rm_rf_install_root"
|
||||
} >"${backup_dir}/uninstall.manifest"
|
||||
|
||||
step "停止并移除 PM2 进程 ${PM2_APP_NAME}"
|
||||
pm2_stop_project
|
||||
pm2_delete_project
|
||||
|
||||
step "移走安装目录"
|
||||
step "删除安装目录 ${INSTALL_ROOT}"
|
||||
if [[ -d "${INSTALL_ROOT}" ]]; then
|
||||
mv "${INSTALL_ROOT}" "${removed_dir}"
|
||||
log "已移动: ${INSTALL_ROOT} -> ${removed_dir}"
|
||||
# 安全:只允许删除约定安装路径(默认 /opt/eth_hedge_sim)
|
||||
case "${INSTALL_ROOT}" in
|
||||
/opt/eth_hedge_sim|/opt/eth_hedge_sim/)
|
||||
rm -rf "${INSTALL_ROOT}"
|
||||
log "已删除: ${INSTALL_ROOT}"
|
||||
;;
|
||||
*)
|
||||
if [[ "${ALLOW_UNSAFE_UNINSTALL:-}" == "1" ]]; then
|
||||
rm -rf "${INSTALL_ROOT}"
|
||||
log "已删除(ALLOW_UNSAFE_UNINSTALL=1): ${INSTALL_ROOT}"
|
||||
else
|
||||
die "拒绝删除非默认路径 ${INSTALL_ROOT};若确认,设置 ALLOW_UNSAFE_UNINSTALL=1"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
else
|
||||
log "安装目录不存在,跳过"
|
||||
log "安装目录不存在,跳过删除"
|
||||
fi
|
||||
|
||||
# 清理历史「移走未删」残留
|
||||
local leftover
|
||||
for leftover in /opt/eth_hedge_sim.removed.* /opt/eth_hedge_sim.old.*; do
|
||||
if [[ -e "${leftover}" ]]; then
|
||||
rm -rf "${leftover}"
|
||||
log "已清理残留: ${leftover}"
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "卸载完成."
|
||||
echo " 配置备份: ${backup_dir}"
|
||||
echo " 旧目录: ${removed_dir} (确认无误后可手动 rm -rf)"
|
||||
echo " 配置/数据备份: ${backup_dir}"
|
||||
echo " 安装目录已删除: ${INSTALL_ROOT}"
|
||||
echo ""
|
||||
echo "回滚示例:"
|
||||
echo " mv ${removed_dir} ${INSTALL_ROOT}"
|
||||
echo " bash ${INSTALL_ROOT}/deploy/manage.sh # 选 1 修复环境"
|
||||
echo "重新部署:"
|
||||
echo " curl -fsSL https://git.bz121.com/dekun/eth_hedge_sim/raw/branch/main/deploy/manage.sh | bash"
|
||||
}
|
||||
|
||||
main_uninstall "$@"
|
||||
|
||||
@@ -19,6 +19,8 @@ main_update() {
|
||||
die "安装不完整,请先执行「1) 一键部署」"
|
||||
fi
|
||||
|
||||
step "更新 — 环境检测 (缺则装,有则跳过)"
|
||||
ensure_system_deps
|
||||
step "更新 比特骆驼自动化对冲系统 (git pull + 构建 + pm2 reload)"
|
||||
bash "${REPO_ROOT}/deploy/pull_and_restart.sh"
|
||||
verify_health || true
|
||||
|
||||
@@ -8,6 +8,13 @@ set -euo pipefail
|
||||
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
cd "$ROOT"
|
||||
|
||||
# 有 root 时:检测 Python / Node / PM2,缺则装、有则跳过
|
||||
if [[ -f "$ROOT/deploy/lib/common.sh" ]] && [[ "$(id -u)" -eq 0 ]]; then
|
||||
# shellcheck source=lib/common.sh
|
||||
source "$ROOT/deploy/lib/common.sh"
|
||||
ensure_system_deps
|
||||
fi
|
||||
|
||||
echo "[比特骆驼] pull @ $ROOT"
|
||||
if [[ -d "$ROOT/.git" ]]; then
|
||||
git fetch --all --prune
|
||||
@@ -25,7 +32,13 @@ if [[ ! -f "$ROOT/.env" ]]; then
|
||||
echo "[比特骆驼] wrote .env — please review AUTH_* secrets"
|
||||
fi
|
||||
|
||||
if ! command -v python3 >/dev/null 2>&1; then
|
||||
echo "ERROR: python3 not found. 请用 manage.sh 一键部署自动安装。"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -d "$ROOT/.venv" ]]; then
|
||||
echo "[比特骆驼] create venv"
|
||||
python3 -m venv "$ROOT/.venv"
|
||||
fi
|
||||
# shellcheck disable=SC1091
|
||||
@@ -45,7 +58,10 @@ fi
|
||||
)
|
||||
|
||||
if ! command -v pm2 >/dev/null 2>&1; then
|
||||
echo "[比特骆驼] install pm2"
|
||||
npm install -g pm2
|
||||
else
|
||||
echo "[比特骆驼] pm2 already present, skip install"
|
||||
fi
|
||||
|
||||
# 仅 reload 本项目进程,禁止 pm2 restart all
|
||||
|
||||
Reference in New Issue
Block a user