Add single-exchange instance-only deploy menu options.
Manage menu 4/5/6 install OKX/Binance/Gate Flask only without hub or agents; reuse setup_env --only and narrowed PM2 verify. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+6
-1
@@ -24,11 +24,16 @@ bash /opt/crypto_monitor/deploy/manage.sh
|
||||
|
||||
| 选项 | 功能 |
|
||||
|------|------|
|
||||
| **1) 一键部署** | 装系统依赖 + Node/PM2 + venv + 自动生成密钥 + 启动 7 进程 |
|
||||
| **1) 一键部署(全套)** | 装系统依赖 + Node/PM2 + venv + 自动生成密钥 + 启动 7 进程(三所+中控) |
|
||||
| **4) 仅 OKX 实例** | 只部署/启动 `crypto_okx`(不含中控/agent) |
|
||||
| **5) 仅 Binance 实例** | 只部署/启动 `crypto_binance` |
|
||||
| **6) 仅 Gate 实例** | 只部署/启动 `crypto_gate` |
|
||||
| **2) 一键卸载** | 备份 `.env` / `hub_settings.json` → 停 PM2 → 移走目录 |
|
||||
| **3) 更新** | 快速更新 / 依赖更新 / 深度重装 |
|
||||
| **0) 退出** | |
|
||||
|
||||
单所模式仍 clone 整仓到 `/opt/crypto_monitor`(共用 `lib/`),但 `setup_env.sh --only <所>` 只建该所 venv,且 PM2 只起对应 Flask.
|
||||
|
||||
### 部署完成后
|
||||
|
||||
脚本自动验收(PM2 7 进程 + 页面可访问),并提示:
|
||||
|
||||
+123
-24
@@ -330,9 +330,57 @@ pm2_count_online() {
|
||||
is_deployed() {
|
||||
local root="$1"
|
||||
[[ -x "${root}/crypto_monitor_binance/.venv/bin/python" ]] \
|
||||
|| [[ -x "${root}/crypto_monitor_gate/.venv/bin/python" ]] \
|
||||
|| [[ -x "${root}/crypto_monitor_okx/.venv/bin/python" ]] \
|
||||
|| [[ -x "${root}/manual_trading_hub/.venv/bin/python" ]]
|
||||
}
|
||||
|
||||
# 单所实例: key -> 目录 / PM2 名 / 端口 / 展示名
|
||||
exchange_dir() {
|
||||
case "$1" in
|
||||
okx) echo "crypto_monitor_okx" ;;
|
||||
binance) echo "crypto_monitor_binance" ;;
|
||||
gate) echo "crypto_monitor_gate" ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
exchange_pm2_name() {
|
||||
case "$1" in
|
||||
okx) echo "crypto_okx" ;;
|
||||
binance) echo "crypto_binance" ;;
|
||||
gate) echo "crypto_gate" ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
exchange_http_port() {
|
||||
case "$1" in
|
||||
okx) echo "5004" ;;
|
||||
binance) echo "5001" ;;
|
||||
gate) echo "5000" ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
exchange_label() {
|
||||
case "$1" in
|
||||
okx) echo "OKX" ;;
|
||||
binance) echo "Binance" ;;
|
||||
gate) echo "Gate" ;;
|
||||
*) echo "$1" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
normalize_exchange_key() {
|
||||
local k
|
||||
k="$(echo "${1:-}" | tr '[:upper:]' '[:lower:]' | xargs)"
|
||||
case "${k}" in
|
||||
okx|binance|gate) echo "${k}" ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
check_http() {
|
||||
local url="$1"
|
||||
local code
|
||||
@@ -342,37 +390,62 @@ check_http() {
|
||||
|
||||
verify_deployment() {
|
||||
local ip="${1:-$(detect_server_ip)}"
|
||||
local mode="${2:-all}"
|
||||
local ok=1
|
||||
local online total
|
||||
local ex_key=""
|
||||
|
||||
step "部署验收"
|
||||
total="${#PM2_APPS[@]}"
|
||||
online="$(pm2_count_online)"
|
||||
if [[ "${online}" -eq "${total}" ]]; then
|
||||
echo " [✓] PM2 进程 ${online}/${total} online"
|
||||
else
|
||||
echo " [✗] PM2 进程 ${online}/${total} online"
|
||||
ok=0
|
||||
pm2 list 2>/dev/null || true
|
||||
fi
|
||||
|
||||
local checks=(
|
||||
"中控:http://127.0.0.1:5100/"
|
||||
"Binance:http://127.0.0.1:5001/"
|
||||
"Gate:http://127.0.0.1:5000/"
|
||||
"OKX:http://127.0.0.1:5004/"
|
||||
)
|
||||
local item label url
|
||||
for item in "${checks[@]}"; do
|
||||
label="${item%%:*}"
|
||||
url="${item#*:}"
|
||||
if check_http "${url}"; then
|
||||
echo " [✓] ${label} 可访问"
|
||||
if [[ "${mode}" == "all" || -z "${mode}" ]]; then
|
||||
total="${#PM2_APPS[@]}"
|
||||
online="$(pm2_count_online)"
|
||||
if [[ "${online}" -eq "${total}" ]]; then
|
||||
echo " [✓] PM2 进程 ${online}/${total} online"
|
||||
else
|
||||
echo " [✗] ${label} 不可访问 (${url})"
|
||||
echo " [✗] PM2 进程 ${online}/${total} online"
|
||||
ok=0
|
||||
pm2 list 2>/dev/null || true
|
||||
fi
|
||||
local checks=(
|
||||
"中控:http://127.0.0.1:5100/"
|
||||
"Binance:http://127.0.0.1:5001/"
|
||||
"Gate:http://127.0.0.1:5000/"
|
||||
"OKX:http://127.0.0.1:5004/"
|
||||
)
|
||||
local item label url
|
||||
for item in "${checks[@]}"; do
|
||||
label="${item%%:*}"
|
||||
url="${item#*:}"
|
||||
if check_http "${url}"; then
|
||||
echo " [✓] ${label} 可访问"
|
||||
else
|
||||
echo " [✗] ${label} 不可访问 (${url})"
|
||||
ok=0
|
||||
fi
|
||||
done
|
||||
else
|
||||
if ! ex_key="$(normalize_exchange_key "${mode}")"; then
|
||||
echo " [✗] 未知验收模式: ${mode}"
|
||||
return 1
|
||||
fi
|
||||
local pm2_name port label
|
||||
pm2_name="$(exchange_pm2_name "${ex_key}")"
|
||||
port="$(exchange_http_port "${ex_key}")"
|
||||
label="$(exchange_label "${ex_key}")"
|
||||
if pm2_app_exists "${pm2_name}"; then
|
||||
echo " [✓] PM2 ${pm2_name} 已注册"
|
||||
else
|
||||
echo " [✗] PM2 缺少进程 ${pm2_name}"
|
||||
ok=0
|
||||
pm2 list 2>/dev/null || true
|
||||
fi
|
||||
if check_http "http://127.0.0.1:${port}/"; then
|
||||
echo " [✓] ${label} 可访问 (http://127.0.0.1:${port}/)"
|
||||
else
|
||||
echo " [✗] ${label} 不可访问 (http://127.0.0.1:${port}/)"
|
||||
ok=0
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [[ "${ok}" -eq 1 ]]; then
|
||||
echo ""
|
||||
@@ -410,3 +483,29 @@ print_post_install_guide() {
|
||||
═══════════════════════════════════════════
|
||||
EOF
|
||||
}
|
||||
|
||||
print_post_install_guide_instance() {
|
||||
local ex_key="$1"
|
||||
local ip="${2:-$(detect_server_ip)}"
|
||||
local label port
|
||||
label="$(exchange_label "${ex_key}")"
|
||||
port="$(exchange_http_port "${ex_key}")"
|
||||
cat <<EOF
|
||||
|
||||
═══════════════════════════════════════════
|
||||
✅ 单所实例部署完成(不含中控)
|
||||
|
||||
${label}: http://${ip}:${port}
|
||||
|
||||
登录账号: admin
|
||||
登录密码: admin123
|
||||
(请尽快在 env 配置中修改)
|
||||
|
||||
下一步(浏览器):
|
||||
1. ${label} → env 配置 → 填 API、风控、企业微信
|
||||
2. 开启实盘下单 → 保存并重启该实例进程
|
||||
|
||||
说明: 本模式不起中控 / agent;整仓仍在 ${INSTALL_ROOT},仅启动本所 Flask.
|
||||
═══════════════════════════════════════════
|
||||
EOF
|
||||
}
|
||||
|
||||
+81
-11
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
# deploy/lib/install.sh — 一键部署
|
||||
# deploy/lib/install.sh — 一键部署(全套) / 单所仅实例
|
||||
set -e
|
||||
set -u
|
||||
if [ -n "${BASH_VERSION:-}" ]; then
|
||||
@@ -10,6 +10,26 @@ LIB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=common.sh
|
||||
source "${LIB_DIR}/common.sh"
|
||||
|
||||
EXCHANGE=""
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--exchange)
|
||||
EXCHANGE="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
-h|--help)
|
||||
echo "用法: bash deploy/lib/install.sh [--exchange okx|binance|gate]"
|
||||
echo " 无 --exchange: 全套(三所+中控)"
|
||||
echo " 有 --exchange: 仅该所 Flask 实例(不含中控/agent)"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "未知参数: $1" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
install_fresh() {
|
||||
step "克隆仓库"
|
||||
if [[ -d "${INSTALL_ROOT}" ]]; then
|
||||
@@ -45,6 +65,28 @@ run_install_pipeline() {
|
||||
print_post_install_guide "$(detect_server_ip)"
|
||||
}
|
||||
|
||||
run_instance_pipeline() {
|
||||
local ex_key="$1"
|
||||
local dir_name
|
||||
dir_name="$(exchange_dir "${ex_key}")"
|
||||
|
||||
step "单所环境部署 setup_env.sh --only ${ex_key}(不含中控)"
|
||||
bash "${REPO_ROOT}/deploy/setup_env.sh" --only "${ex_key}" --install-system-deps
|
||||
|
||||
step "启动 PM2 仅 ${dir_name}"
|
||||
bash "${REPO_ROOT}/deploy/pm2_start_all.sh" --only "${ex_key}"
|
||||
|
||||
pm2_save_startup
|
||||
local cron_script="${REPO_ROOT}/${dir_name}/scripts/install_backup_cron.sh"
|
||||
if [[ -x "${cron_script}" ]]; then
|
||||
step "安装 ${ex_key} 备份 cron"
|
||||
bash "${cron_script}" || true
|
||||
fi
|
||||
|
||||
verify_deployment "$(detect_server_ip)" "${ex_key}" || true
|
||||
print_post_install_guide_instance "${ex_key}" "$(detect_server_ip)"
|
||||
}
|
||||
|
||||
handle_existing_install() {
|
||||
echo ""
|
||||
echo "检测到已部署安装: ${INSTALL_ROOT}"
|
||||
@@ -72,10 +114,47 @@ handle_existing_install() {
|
||||
esac
|
||||
}
|
||||
|
||||
ensure_repo_ready() {
|
||||
if repo_ready "${INSTALL_ROOT}"; then
|
||||
REPO_ROOT="${INSTALL_ROOT}"
|
||||
elif [[ -n "${REPO_ROOT:-}" ]] && repo_ready "${REPO_ROOT}"; then
|
||||
:
|
||||
else
|
||||
REPO_ROOT=""
|
||||
fi
|
||||
|
||||
if [[ -z "${REPO_ROOT}" ]]; then
|
||||
install_system_packages
|
||||
install_node_pm2
|
||||
install_fresh
|
||||
REPO_ROOT="${INSTALL_ROOT}"
|
||||
else
|
||||
install_system_packages
|
||||
install_node_pm2
|
||||
fi
|
||||
}
|
||||
|
||||
main_install_instance() {
|
||||
local ex_key="$1"
|
||||
require_root
|
||||
require_ubuntu
|
||||
ensure_repo_ready
|
||||
run_instance_pipeline "${ex_key}"
|
||||
}
|
||||
|
||||
main_install() {
|
||||
require_root
|
||||
require_ubuntu
|
||||
|
||||
if [[ -n "${EXCHANGE}" ]]; then
|
||||
local ex_key=""
|
||||
if ! ex_key="$(normalize_exchange_key "${EXCHANGE}")"; then
|
||||
die "无效 --exchange: ${EXCHANGE} (期望 okx|binance|gate)"
|
||||
fi
|
||||
main_install_instance "${ex_key}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if repo_ready "${INSTALL_ROOT}"; then
|
||||
REPO_ROOT="${INSTALL_ROOT}"
|
||||
elif repo_ready "${REPO_ROOT}"; then
|
||||
@@ -89,16 +168,7 @@ main_install() {
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ -z "${REPO_ROOT}" ]]; then
|
||||
install_system_packages
|
||||
install_node_pm2
|
||||
install_fresh
|
||||
REPO_ROOT="${INSTALL_ROOT}"
|
||||
else
|
||||
install_system_packages
|
||||
install_node_pm2
|
||||
fi
|
||||
|
||||
ensure_repo_ready
|
||||
run_install_pipeline
|
||||
}
|
||||
|
||||
|
||||
+15
-3
@@ -105,7 +105,10 @@ show_banner() {
|
||||
}
|
||||
|
||||
show_menu() {
|
||||
echo " 1) 一键部署"
|
||||
echo " 1) 一键部署(全套:三所+中控)"
|
||||
echo " 4) 仅 OKX 实例(不含中控)"
|
||||
echo " 5) 仅 Binance 实例(不含中控)"
|
||||
echo " 6) 仅 Gate 实例(不含中控)"
|
||||
echo " 2) 一键卸载"
|
||||
echo " 3) 更新"
|
||||
echo " 0) 退出"
|
||||
@@ -122,11 +125,20 @@ main_menu() {
|
||||
show_banner
|
||||
show_menu
|
||||
local choice=""
|
||||
cm_read choice "请选择 [0-3]: "
|
||||
cm_read choice "请选择 [0-6]: "
|
||||
case "${choice}" in
|
||||
1)
|
||||
bash "${LIB_DIR}/install.sh"
|
||||
;;
|
||||
4)
|
||||
bash "${LIB_DIR}/install.sh" --exchange okx
|
||||
;;
|
||||
5)
|
||||
bash "${LIB_DIR}/install.sh" --exchange binance
|
||||
;;
|
||||
6)
|
||||
bash "${LIB_DIR}/install.sh" --exchange gate
|
||||
;;
|
||||
2)
|
||||
bash "${LIB_DIR}/uninstall.sh"
|
||||
;;
|
||||
@@ -138,7 +150,7 @@ main_menu() {
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "无效选项,请输入 0-3"
|
||||
echo "无效选项,请输入 0-6"
|
||||
;;
|
||||
esac
|
||||
echo ""
|
||||
|
||||
+45
-5
@@ -2,6 +2,9 @@
|
||||
# 按推荐顺序启动三所 Flask + 中控 hub/三 agent(PM2).
|
||||
# 用法(仓库根或任意目录):
|
||||
# bash deploy/pm2_start_all.sh
|
||||
# bash deploy/pm2_start_all.sh --only okx
|
||||
# bash deploy/pm2_start_all.sh --only binance
|
||||
# bash deploy/pm2_start_all.sh --only gate
|
||||
#
|
||||
# 与 deploy/setup_env.sh 独立:setup_env 只建 venv;本脚本负责 PM2 启动.
|
||||
set -e
|
||||
@@ -12,6 +15,26 @@ fi
|
||||
|
||||
DEPLOY_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "${DEPLOY_DIR}/.." && pwd)"
|
||||
# shellcheck source=lib/common.sh
|
||||
source "${DEPLOY_DIR}/lib/common.sh"
|
||||
|
||||
ONLY="all"
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--only)
|
||||
ONLY="${2:-all}"
|
||||
shift 2
|
||||
;;
|
||||
-h|--help)
|
||||
sed -n '2,10p' "$0" | sed 's/^# \?//'
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "未知参数: $1" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
start_one() {
|
||||
local dir_name="$1"
|
||||
@@ -22,7 +45,14 @@ start_one() {
|
||||
return 0
|
||||
fi
|
||||
echo "==> pm2 start ${dir_name}"
|
||||
(cd "${proj}" && pm2 start ecosystem.config.cjs)
|
||||
# 已存在则 restart,避免重复 start 导致 set -e 退出
|
||||
if (cd "${proj}" && pm2 start ecosystem.config.cjs); then
|
||||
return 0
|
||||
fi
|
||||
echo " (已存在,改为 restart)"
|
||||
(cd "${proj}" && pm2 startOrReload ecosystem.config.cjs --update-env) \
|
||||
|| (cd "${proj}" && pm2 reload ecosystem.config.cjs --update-env) \
|
||||
|| true
|
||||
}
|
||||
|
||||
if ! command -v pm2 >/dev/null 2>&1; then
|
||||
@@ -30,10 +60,20 @@ if ! command -v pm2 >/dev/null 2>&1; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
start_one crypto_monitor_binance
|
||||
start_one crypto_monitor_gate
|
||||
start_one crypto_monitor_okx
|
||||
start_one manual_trading_hub
|
||||
if [[ "${ONLY}" == "all" ]]; then
|
||||
start_one crypto_monitor_binance
|
||||
start_one crypto_monitor_gate
|
||||
start_one crypto_monitor_okx
|
||||
start_one manual_trading_hub
|
||||
else
|
||||
ex_key="$(normalize_exchange_key "${ONLY}" || true)"
|
||||
if [[ -z "${ex_key}" ]]; then
|
||||
echo "未知 --only 值: ${ONLY} (期望 okx|binance|gate|all)" >&2
|
||||
exit 1
|
||||
fi
|
||||
dir_name="$(exchange_dir "${ex_key}")"
|
||||
start_one "${dir_name}"
|
||||
fi
|
||||
|
||||
pm2 save 2>/dev/null || true
|
||||
echo ""
|
||||
|
||||
Reference in New Issue
Block a user