Files
sub2api-cn-relay-manager/scripts/deploy/deploy_crm_only.sh
phamnazage-jpg 77b7f7f660
Some checks failed
CI / Build & Test (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / Docker Build (push) Has been cancelled
CI / Release (push) Has been cancelled
feat: harden runtime import and frontend verification workflows
2026-06-04 20:02:36 +08:00

221 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
# deploy_crm_only.sh — 把 sub2api-cn-relay-managerCRM 控制面)单进程部署到
# remote43。不起 sub2api host / PG / Redis 容器。
#
# 复用 scripts/deploy/remote43_patched_stack_lib.sh 的 env 渲染 helper。
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
# shellcheck disable=SC1091
source "$ROOT_DIR/scripts/deploy/remote43_patched_stack_lib.sh"
KEY="${KEY:-/home/long/下载/zjsea.pem}"
REMOTE="${REMOTE:-ubuntu@43.155.133.187}"
STACK_NAME="${STACK_NAME:-crm-only-$(date +%Y%m%d)}"
CRM_PORT="${CRM_PORT:-18190}"
CRM_BINARY="${CRM_BINARY:-$ROOT_DIR/server}"
LOCAL_REPO_BUNDLE="${LOCAL_REPO_BUNDLE:-/tmp/${STACK_NAME}-repo.bundle}"
LOCAL_OPERATOR_ENV_FILE="${LOCAL_OPERATOR_ENV_FILE:-/tmp/${STACK_NAME}.env}"
LOCAL_TUNNEL_SCRIPT="${LOCAL_TUNNEL_SCRIPT:-/tmp/${STACK_NAME}.tunnel.sh}"
LOCAL_DEPLOY_DIR="${LOCAL_DEPLOY_DIR:-/tmp/${STACK_NAME}-stage}"
REMOTE_ROOT="${REMOTE_ROOT:-/home/ubuntu/${STACK_NAME}_${CRM_PORT}}"
REMOTE_REPO_ROOT="${REMOTE_REPO_ROOT:-/home/ubuntu/sub2api-cn-relay-manager-git-current}"
REMOTE_REPO_BUNDLE="$REMOTE_ROOT/sub2api-cn-relay-manager.bundle"
REMOTE_CRM_ENV_FILE="$REMOTE_ROOT/.env.crm"
REMOTE_BOOTSTRAP_FILE="$REMOTE_ROOT/bootstrap.sh"
REMOTE_CRM_BINARY="$REMOTE_ROOT/sub2api-cn-relay-manager-server"
REMOTE_CRM_DB_FILE="$REMOTE_ROOT/sub2api-cn-relay-manager.db"
REMOTE_CRM_PID_FILE="$REMOTE_ROOT/crm.pid"
REMOTE_CRM_LOG_FILE="$REMOTE_ROOT/crm.log"
crm_admin_token="${crm_admin_token:-$(remote43_random_hex 24)}"
crm_admin_username="${crm_admin_username:-admin}"
crm_admin_password="${crm_admin_password:-$crm_admin_token}"
DRY_RUN="${DRY_RUN:-0}"
die() { echo "$*" >&2; exit 1; }
require_cmd() { command -v "$1" >/dev/null 2>&1 || die "missing command: $1"; }
run_cmd() {
if [[ "$DRY_RUN" == "1" ]]; then
printf "DRY_RUN:"; printf " %q" "$@"; printf "\n"
return 0
fi
"$@"
}
ssh_remote() { run_cmd ssh -i "$KEY" -o StrictHostKeyChecking=no "$REMOTE" "$@"; }
scp_remote() { run_cmd scp -i "$KEY" -o StrictHostKeyChecking=no "$@"; }
write_local_tunnel_script() {
cat > "$LOCAL_TUNNEL_SCRIPT" <<EOF
#!/usr/bin/env bash
set -euo pipefail
exec ssh -N \\
-L ${CRM_PORT}:127.0.0.1:${CRM_PORT} \\
-i $(printf "%q" "$KEY") \\
-o StrictHostKeyChecking=no \\
$(printf "%q" "$REMOTE")
EOF
chmod +x "$LOCAL_TUNNEL_SCRIPT"
}
write_operator_env() {
remote43_write_env_file "$LOCAL_OPERATOR_ENV_FILE" \
CRM_BASE "http://127.0.0.1:${CRM_PORT}" \
REMOTE_CRM_BASE "http://127.0.0.1:${CRM_PORT}" \
REMOTE_ROOT "$REMOTE_ROOT" \
REMOTE_CRM_ENV_FILE "$REMOTE_CRM_ENV_FILE" \
REMOTE_REPO_ROOT "$REMOTE_REPO_ROOT" \
KEY "$KEY" \
REMOTE "$REMOTE" \
crm_admin_token "$crm_admin_token" \
crm_admin_username "$crm_admin_username" \
crm_admin_password "$crm_admin_password" \
CRM_PORT "$CRM_PORT"
chmod 600 "$LOCAL_OPERATOR_ENV_FILE"
}
render_crm_only_bootstrap() {
local crm_env_q remote_root_q remote_repo_bundle_q
local crm_binary_q crm_db_q crm_pid_q crm_log_q remote_repo_root_q crm_port_q
printf -v crm_env_q "%q" "$REMOTE_CRM_ENV_FILE"
printf -v remote_root_q "%q" "$REMOTE_ROOT"
printf -v remote_repo_bundle_q "%q" "$REMOTE_REPO_BUNDLE"
printf -v crm_binary_q "%q" "$REMOTE_CRM_BINARY"
printf -v crm_db_q "%q" "$REMOTE_CRM_DB_FILE"
printf -v crm_pid_q "%q" "$REMOTE_CRM_PID_FILE"
printf -v crm_log_q "%q" "$REMOTE_CRM_LOG_FILE"
printf -v remote_repo_root_q "%q" "$REMOTE_REPO_ROOT"
printf -v crm_port_q "%q" "$CRM_PORT"
local tmp_bootstrap
tmp_bootstrap="$(mktemp)"
cat > "$tmp_bootstrap" <<'BOOTSTRAP_EOF'
#!/usr/bin/env bash
set -euo pipefail
export REMOTE_ROOT=__REMOTE_ROOT__
export CRM_ENV_FILE=__CRM_ENV_FILE__
export CRM_BINARY=__CRM_BINARY__
export CRM_DB_FILE=__CRM_DB_FILE__
export CRM_PID_FILE=__CRM_PID_FILE__
export CRM_LOG_FILE=__CRM_LOG_FILE__
export REMOTE_REPO_ROOT=__REMOTE_REPO_ROOT__
export REMOTE_REPO_BUNDLE=__REMOTE_REPO_BUNDLE__
export CRM_PORT=__CRM_PORT__
mkdir -p "$REMOTE_ROOT" "$(dirname "$REMOTE_REPO_ROOT")"
chmod 755 "$CRM_BINARY"
if [[ -f "$REMOTE_REPO_BUNDLE" ]]; then
if [[ -d "$REMOTE_REPO_ROOT/.git" ]]; then
git -C "$REMOTE_REPO_ROOT" fetch "$REMOTE_REPO_BUNDLE" main
git -C "$REMOTE_REPO_ROOT" reset --hard FETCH_HEAD
else
rm -rf "$REMOTE_REPO_ROOT"
git clone "$REMOTE_REPO_BUNDLE" "$REMOTE_REPO_ROOT"
git -C "$REMOTE_REPO_ROOT" checkout main
fi
git -C "$REMOTE_REPO_ROOT" config user.name "Remote43 CRM"
git -C "$REMOTE_REPO_ROOT" config user.email "remote43-crm@tksea.top"
fi
if [[ -f "$CRM_PID_FILE" ]]; then
OLD_PID="$(cat "$CRM_PID_FILE")"
if kill "$OLD_PID" >/dev/null 2>&1; then
sleep 1
fi
rm -f "$CRM_PID_FILE"
fi
rm -f "$CRM_DB_FILE" "$CRM_LOG_FILE"
nohup bash -lc 'set -a; source "$CRM_ENV_FILE"; set +a; exec "$CRM_BINARY"' >"$CRM_LOG_FILE" 2>&1 &
echo $! > "$CRM_PID_FILE"
python3 - "$CRM_PORT" <<'PY'
import subprocess, sys, time
url = f"http://127.0.0.1:{sys.argv[1]}/healthz"
for _ in range(30):
r = subprocess.run(["curl", "-fsS", url], text=True, capture_output=True)
if r.returncode == 0 and r.stdout.strip() == "ok":
raise SystemExit(0)
time.sleep(1)
raise SystemExit(f"crm healthz did not become ready on {url}")
PY
printf "crm_base=http://127.0.0.1:%s\n" "$CRM_PORT"
printf "crm_pid_file=%s\n" "$CRM_PID_FILE"
printf "crm_log=%s\n" "$CRM_LOG_FILE"
printf "remote_repo_root=%s\n" "$REMOTE_REPO_ROOT"
BOOTSTRAP_EOF
sed -i -e "s|__REMOTE_ROOT__|$remote_root_q|g" -e "s|__CRM_ENV_FILE__|$crm_env_q|g" -e "s|__CRM_BINARY__|$crm_binary_q|g" -e "s|__CRM_DB_FILE__|$crm_db_q|g" -e "s|__CRM_PID_FILE__|$crm_pid_q|g" -e "s|__CRM_LOG_FILE__|$crm_log_q|g" -e "s|__REMOTE_REPO_ROOT__|$remote_repo_root_q|g" -e "s|__REMOTE_REPO_BUNDLE__|$remote_repo_bundle_q|g" -e "s|__CRM_PORT__|$crm_port_q|g" "$tmp_bootstrap"
cat "$tmp_bootstrap"
rm -f "$tmp_bootstrap"
}
main() {
require_cmd bash curl git python3 ssh scp
remote43_require_file "$KEY" "ssh key"
remote43_require_file "$CRM_BINARY" "crm server binary"
rm -f "$LOCAL_REPO_BUNDLE"
git -C "$ROOT_DIR" bundle create "$LOCAL_REPO_BUNDLE" main
write_local_tunnel_script
write_operator_env
local crm_env_file bootstrap_file
crm_env_file="$(mktemp)"
bootstrap_file="$(mktemp)"
trap "rm -f \"$crm_env_file\" \"$bootstrap_file\"" EXIT
render_remote43_crm_env \
"$CRM_PORT" \
"file:${REMOTE_CRM_DB_FILE}?_foreign_keys=on&_busy_timeout=5000" \
"$crm_admin_token" \
"$REMOTE_REPO_ROOT" \
"$crm_admin_username" \
"$crm_admin_password" > "$crm_env_file"
render_crm_only_bootstrap > "$bootstrap_file"
chmod +x "$bootstrap_file"
mkdir -p "$LOCAL_DEPLOY_DIR"
cp "$crm_env_file" "$LOCAL_DEPLOY_DIR/.env.crm"
cp "$bootstrap_file" "$LOCAL_DEPLOY_DIR/bootstrap.sh"
ssh_remote "mkdir -p $(printf "%q" "$REMOTE_ROOT")
if [[ -f $(printf "%q" "$REMOTE_CRM_PID_FILE") ]]; then
OLDPID=\$(cat $(printf "%q" "$REMOTE_CRM_PID_FILE"))
kill \$OLDPID 2>/dev/null || true
sleep 1
fi
rm -f $(printf "%q" "$REMOTE_CRM_PID_FILE") $(printf "%q" "$REMOTE_CRM_DB_FILE") $(printf "%q" "$REMOTE_CRM_LOG_FILE") $(printf "%q" "$REMOTE_CRM_BINARY")"
scp_remote "$CRM_BINARY" "$REMOTE:$REMOTE_CRM_BINARY"
scp_remote "$LOCAL_REPO_BUNDLE" "$REMOTE:$REMOTE_REPO_BUNDLE"
scp_remote "$crm_env_file" "$REMOTE:$REMOTE_CRM_ENV_FILE"
scp_remote "$bootstrap_file" "$REMOTE:$REMOTE_BOOTSTRAP_FILE"
ssh_remote "bash $(printf "%q" "$REMOTE_BOOTSTRAP_FILE")"
cat <<EOF
crm-only stack prepared
remote crm base: http://127.0.0.1:${CRM_PORT}
remote crm env file: ${REMOTE_CRM_ENV_FILE}
remote crm log: ${REMOTE_CRM_LOG_FILE}
remote repo root: ${REMOTE_REPO_ROOT}
local operator env file: ${LOCAL_OPERATOR_ENV_FILE}
local tunnel script: ${LOCAL_TUNNEL_SCRIPT}
local deploy dir: ${LOCAL_DEPLOY_DIR}
next:
1. 在另一终端运行: ${LOCAL_TUNNEL_SCRIPT}
2. 当前终端执行: set -a; source ${LOCAL_OPERATOR_ENV_FILE}; set +a
3. 验证: curl -fsS http://127.0.0.1:${CRM_PORT}/healthz
curl -fsS -H "Authorization: Bearer \$crm_admin_token" http://127.0.0.1:${CRM_PORT}/api/packs
EOF
}
main "$@"