Fix CRLF in deploy shell scripts so Ubuntu bash can run updates.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-26 22:07:44 +08:00
parent 8813fd3e37
commit bffbdafbfc
5 changed files with 545 additions and 545 deletions
+156 -156
View File
@@ -1,156 +1,156 @@
#!/usr/bin/env bash
# deploy/lib/common.sh — 比特骆驼自动化对冲系统 部署公共函数
# 目标系统: Ubuntu 22.04 LTS
set -e
set -u
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}"
BACKUP_ROOT="${BACKUP_ROOT:-/root/backups/eth_hedge_sim}"
TZ_NAME="${EHS_TZ:-Asia/Shanghai}"
NODE_MAJOR="${NODE_MAJOR:-20}"
PM2_APP_NAME="${PM2_APP_NAME:-eth-hedge-api}"
API_PORT="${API_PORT:-5155}"
LIB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
DEPLOY_DIR="$(cd "${LIB_DIR}/.." && pwd)"
REPO_ROOT="$(cd "${DEPLOY_DIR}/.." && pwd)"
log() { printf '[%s] %s\n' "$(TZ="${TZ_NAME}" date '+%Y-%m-%d %H:%M:%S')" "$*"; }
step() { echo ""; log "==> $*"; }
die() {
echo "错误: $*" >&2
exit 1
}
require_root() {
if [[ "$(id -u)" -ne 0 ]]; then
die "请使用 root 执行(推荐: sudo -i 后运行)"
fi
}
detect_server_ip() {
local ip=""
if command -v hostname >/dev/null 2>&1; then
ip="$(hostname -I 2>/dev/null | awk '{print $1}')"
fi
if [[ -z "${ip}" ]]; then
ip="127.0.0.1"
fi
echo "${ip}"
}
# curl|bash 时 stdin 可能是管道,交互从 /dev/tty 读
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}"
}
confirm_yes() {
local msg="$1"
local ans=""
cm_read ans "${msg} [y/N] "
[[ "${ans}" == [yY] || "${ans}" == [yY][eE][sS] ]]
}
repo_ready() {
[[ -f "${1}/deploy/manage.sh" && -f "${1}/deploy/pull_and_restart.sh" ]]
}
resolve_repo_root() {
if repo_ready "${INSTALL_ROOT}"; then
echo "${INSTALL_ROOT}"
return 0
fi
if [[ -n "${REPO_ROOT:-}" ]] && repo_ready "${REPO_ROOT}"; then
echo "${REPO_ROOT}"
return 0
fi
return 1
}
ensure_system_deps() {
step "检查系统依赖"
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
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
fi
if ! command -v pm2 >/dev/null 2>&1; then
step "安装 PM2"
npm install -g pm2
fi
}
pm2_stop_project() {
if command -v pm2 >/dev/null 2>&1; then
pm2 stop "${PM2_APP_NAME}" 2>/dev/null || true
fi
}
pm2_delete_project() {
if command -v pm2 >/dev/null 2>&1; then
pm2 delete "${PM2_APP_NAME}" 2>/dev/null || true
pm2 save 2>/dev/null || true
fi
}
pm2_save_startup() {
if command -v pm2 >/dev/null 2>&1; then
pm2 save 2>/dev/null || true
pm2 startup systemd -u root --hp /root 2>/dev/null || true
fi
}
verify_health() {
local port="${1:-${API_PORT}}"
local url="http://127.0.0.1:${port}/health"
step "健康检查 ${url}"
local i
for i in 1 2 3 4 5 6 7 8 9 10; do
if curl -fsS "${url}" >/dev/null 2>&1; then
log "health OK"
curl -fsS "${url}" || true
echo ""
return 0
fi
sleep 1
done
log "警告: health 暂未就绪,请稍后检查 pm2 logs ${PM2_APP_NAME}"
return 1
}
print_post_install_guide() {
local ip
ip="$(detect_server_ip)"
echo ""
echo "══════════════════════════════════════"
echo " 比特骆驼自动化对冲系统 部署完成"
echo " 目录: ${INSTALL_ROOT}"
echo " 本机: http://${ip}:${API_PORT}/health"
echo " 进程: pm2 status → ${PM2_APP_NAME}"
echo " 管理: bash ${INSTALL_ROOT}/deploy/manage.sh"
echo " 配置: ${INSTALL_ROOT}/.env"
echo "══════════════════════════════════════"
echo ""
}
#!/usr/bin/env bash
# deploy/lib/common.sh — 比特骆驼自动化对冲系统 部署公共函数
# 目标系统: Ubuntu 22.04 LTS
set -e
set -u
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}"
BACKUP_ROOT="${BACKUP_ROOT:-/root/backups/eth_hedge_sim}"
TZ_NAME="${EHS_TZ:-Asia/Shanghai}"
NODE_MAJOR="${NODE_MAJOR:-20}"
PM2_APP_NAME="${PM2_APP_NAME:-eth-hedge-api}"
API_PORT="${API_PORT:-5155}"
LIB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
DEPLOY_DIR="$(cd "${LIB_DIR}/.." && pwd)"
REPO_ROOT="$(cd "${DEPLOY_DIR}/.." && pwd)"
log() { printf '[%s] %s\n' "$(TZ="${TZ_NAME}" date '+%Y-%m-%d %H:%M:%S')" "$*"; }
step() { echo ""; log "==> $*"; }
die() {
echo "错误: $*" >&2
exit 1
}
require_root() {
if [[ "$(id -u)" -ne 0 ]]; then
die "请使用 root 执行(推荐: sudo -i 后运行)"
fi
}
detect_server_ip() {
local ip=""
if command -v hostname >/dev/null 2>&1; then
ip="$(hostname -I 2>/dev/null | awk '{print $1}')"
fi
if [[ -z "${ip}" ]]; then
ip="127.0.0.1"
fi
echo "${ip}"
}
# curl|bash 时 stdin 可能是管道,交互从 /dev/tty 读
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}"
}
confirm_yes() {
local msg="$1"
local ans=""
cm_read ans "${msg} [y/N] "
[[ "${ans}" == [yY] || "${ans}" == [yY][eE][sS] ]]
}
repo_ready() {
[[ -f "${1}/deploy/manage.sh" && -f "${1}/deploy/pull_and_restart.sh" ]]
}
resolve_repo_root() {
if repo_ready "${INSTALL_ROOT}"; then
echo "${INSTALL_ROOT}"
return 0
fi
if [[ -n "${REPO_ROOT:-}" ]] && repo_ready "${REPO_ROOT}"; then
echo "${REPO_ROOT}"
return 0
fi
return 1
}
ensure_system_deps() {
step "检查系统依赖"
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
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
fi
if ! command -v pm2 >/dev/null 2>&1; then
step "安装 PM2"
npm install -g pm2
fi
}
pm2_stop_project() {
if command -v pm2 >/dev/null 2>&1; then
pm2 stop "${PM2_APP_NAME}" 2>/dev/null || true
fi
}
pm2_delete_project() {
if command -v pm2 >/dev/null 2>&1; then
pm2 delete "${PM2_APP_NAME}" 2>/dev/null || true
pm2 save 2>/dev/null || true
fi
}
pm2_save_startup() {
if command -v pm2 >/dev/null 2>&1; then
pm2 save 2>/dev/null || true
pm2 startup systemd -u root --hp /root 2>/dev/null || true
fi
}
verify_health() {
local port="${1:-${API_PORT}}"
local url="http://127.0.0.1:${port}/health"
step "健康检查 ${url}"
local i
for i in 1 2 3 4 5 6 7 8 9 10; do
if curl -fsS "${url}" >/dev/null 2>&1; then
log "health OK"
curl -fsS "${url}" || true
echo ""
return 0
fi
sleep 1
done
log "警告: health 暂未就绪,请稍后检查 pm2 logs ${PM2_APP_NAME}"
return 1
}
print_post_install_guide() {
local ip
ip="$(detect_server_ip)"
echo ""
echo "══════════════════════════════════════"
echo " 比特骆驼自动化对冲系统 部署完成"
echo " 目录: ${INSTALL_ROOT}"
echo " 本机: http://${ip}:${API_PORT}/health"
echo " 进程: pm2 status → ${PM2_APP_NAME}"
echo " 管理: bash ${INSTALL_ROOT}/deploy/manage.sh"
echo " 配置: ${INSTALL_ROOT}/.env"
echo "══════════════════════════════════════"
echo ""
}
+80 -80
View File
@@ -1,80 +1,80 @@
#!/usr/bin/env bash
# deploy/lib/uninstall.sh — 一键卸载(仅本项目 PM2,不动其它进程)
set -e
set -u
if [ -n "${BASH_VERSION:-}" ]; then
set -o pipefail
fi
LIB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=common.sh
source "${LIB_DIR}/common.sh"
main_uninstall() {
require_root
local root=""
if ! root="$(resolve_repo_root)"; then
if [[ -d "${INSTALL_ROOT}" ]]; then
root="${INSTALL_ROOT}"
else
die "未找到安装目录 ${INSTALL_ROOT}"
fi
fi
REPO_ROOT="${root}"
echo ""
echo "将卸载 比特骆驼自动化对冲系统 (eth_hedge_sim):"
echo " - 停止并删除 PM2 进程: ${PM2_APP_NAME}"
echo " - 移走目录: ${INSTALL_ROOT}"
echo " - 备份 .env 到 ${BACKUP_ROOT}"
echo " - 不影响其它 PM2 应用"
echo ""
if ! confirm_yes "确认卸载?"; then
log "已取消卸载"
return 0
fi
local stamp backup_dir removed_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 "备份配置"
if [[ -f "${REPO_ROOT}/.env" ]]; then
cp -a "${REPO_ROOT}/.env" "${backup_dir}/.env"
fi
if [[ -d "${REPO_ROOT}/backend/data" ]]; then
cp -a "${REPO_ROOT}/backend/data" "${backup_dir}/data" 2>/dev/null || true
fi
{
echo "created_at=${stamp}"
echo "install_root=${INSTALL_ROOT}"
echo "removed_dir=${removed_dir}"
echo "pm2_app=${PM2_APP_NAME}"
} >"${backup_dir}/uninstall.manifest"
step "停止并移除 PM2 进程 ${PM2_APP_NAME}"
pm2_stop_project
pm2_delete_project
step "移走安装目录"
if [[ -d "${INSTALL_ROOT}" ]]; then
mv "${INSTALL_ROOT}" "${removed_dir}"
log "已移动: ${INSTALL_ROOT} -> ${removed_dir}"
else
log "安装目录不存在,跳过"
fi
echo ""
echo "卸载完成."
echo " 配置备份: ${backup_dir}"
echo " 旧目录: ${removed_dir} (确认无误后可手动 rm -rf)"
echo ""
echo "回滚示例:"
echo " mv ${removed_dir} ${INSTALL_ROOT}"
echo " bash ${INSTALL_ROOT}/deploy/manage.sh # 选 1 修复环境"
}
main_uninstall "$@"
#!/usr/bin/env bash
# deploy/lib/uninstall.sh — 一键卸载(仅本项目 PM2,不动其它进程)
set -e
set -u
if [ -n "${BASH_VERSION:-}" ]; then
set -o pipefail
fi
LIB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=common.sh
source "${LIB_DIR}/common.sh"
main_uninstall() {
require_root
local root=""
if ! root="$(resolve_repo_root)"; then
if [[ -d "${INSTALL_ROOT}" ]]; then
root="${INSTALL_ROOT}"
else
die "未找到安装目录 ${INSTALL_ROOT}"
fi
fi
REPO_ROOT="${root}"
echo ""
echo "将卸载 比特骆驼自动化对冲系统 (eth_hedge_sim):"
echo " - 停止并删除 PM2 进程: ${PM2_APP_NAME}"
echo " - 移走目录: ${INSTALL_ROOT}"
echo " - 备份 .env 到 ${BACKUP_ROOT}"
echo " - 不影响其它 PM2 应用"
echo ""
if ! confirm_yes "确认卸载?"; then
log "已取消卸载"
return 0
fi
local stamp backup_dir removed_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 "备份配置"
if [[ -f "${REPO_ROOT}/.env" ]]; then
cp -a "${REPO_ROOT}/.env" "${backup_dir}/.env"
fi
if [[ -d "${REPO_ROOT}/backend/data" ]]; then
cp -a "${REPO_ROOT}/backend/data" "${backup_dir}/data" 2>/dev/null || true
fi
{
echo "created_at=${stamp}"
echo "install_root=${INSTALL_ROOT}"
echo "removed_dir=${removed_dir}"
echo "pm2_app=${PM2_APP_NAME}"
} >"${backup_dir}/uninstall.manifest"
step "停止并移除 PM2 进程 ${PM2_APP_NAME}"
pm2_stop_project
pm2_delete_project
step "移走安装目录"
if [[ -d "${INSTALL_ROOT}" ]]; then
mv "${INSTALL_ROOT}" "${removed_dir}"
log "已移动: ${INSTALL_ROOT} -> ${removed_dir}"
else
log "安装目录不存在,跳过"
fi
echo ""
echo "卸载完成."
echo " 配置备份: ${backup_dir}"
echo " 旧目录: ${removed_dir} (确认无误后可手动 rm -rf)"
echo ""
echo "回滚示例:"
echo " mv ${removed_dir} ${INSTALL_ROOT}"
echo " bash ${INSTALL_ROOT}/deploy/manage.sh # 选 1 修复环境"
}
main_uninstall "$@"
+29 -29
View File
@@ -1,29 +1,29 @@
#!/usr/bin/env bash
# deploy/lib/update.sh — 更新(仅 git pull,禁止 scp
set -e
set -u
if [ -n "${BASH_VERSION:-}" ]; then
set -o pipefail
fi
LIB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=common.sh
source "${LIB_DIR}/common.sh"
main_update() {
require_root
if ! REPO_ROOT="$(resolve_repo_root)"; then
die "未找到安装目录 ${INSTALL_ROOT},请先执行「1) 一键部署」"
fi
if ! repo_ready "${REPO_ROOT}"; then
die "安装不完整,请先执行「1) 一键部署」"
fi
step "更新 比特骆驼自动化对冲系统 (git pull + 构建 + pm2 reload)"
bash "${REPO_ROOT}/deploy/pull_and_restart.sh"
verify_health || true
echo ""
log "更新完成"
}
main_update "$@"
#!/usr/bin/env bash
# deploy/lib/update.sh — 更新(仅 git pull,禁止 scp
set -e
set -u
if [ -n "${BASH_VERSION:-}" ]; then
set -o pipefail
fi
LIB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=common.sh
source "${LIB_DIR}/common.sh"
main_update() {
require_root
if ! REPO_ROOT="$(resolve_repo_root)"; then
die "未找到安装目录 ${INSTALL_ROOT},请先执行「1) 一键部署」"
fi
if ! repo_ready "${REPO_ROOT}"; then
die "安装不完整,请先执行「1) 一键部署」"
fi
step "更新 比特骆驼自动化对冲系统 (git pull + 构建 + pm2 reload)"
bash "${REPO_ROOT}/deploy/pull_and_restart.sh"
verify_health || true
echo ""
log "更新完成"
}
main_update "$@"