Files
market_sync/deploy/systemd/deploy.sh
T
gao 8f016f25df chore: baseline — ORM migration + systemd deploy + MCP server + daily check
- ORM migration: models/ops 重构
- deploy: 标准化 systemd timer/service 部署体系
- MCP server: 5 个只读工具(任务/状态/数据集)
- daily check: 数据一致性巡检
- watch: task_watch 后台监控
- kline_daily: 麦蕊优先,时间门禁15:00
- 删除: task_industry_sector, task_sector_features
2026-07-21 16:37:00 +08:00

212 lines
7.1 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.
#!/bin/bash
# market_sync systemd 一键部署脚本
#
# 用途:把 deploy/systemd/units/*.service 和 *.timer 同步到 /etc/systemd/system/
# 并自动启用 timer、处理 worker 服务状态。
#
# 运行:sudo bash deploy/systemd/deploy.sh
# sudo bash deploy/systemd/deploy.sh --yes # 跳过确认
#
# 设计原则:
# - 必须 sudo(写 /etc/systemd/system/ + daemon-reload
# - 幂等:重复运行无副作用
# - 显示 plan → 等待确认 → 执行
# - 失败立即中止,不留半套状态
set -e
PROJECT_ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
REPO_UNITS_DIR="$PROJECT_ROOT/deploy/systemd/units"
ETC_UNITS_DIR="/etc/systemd/system"
SKIP_CONFIRM=false
# ── 0. 前置检查 ─────────────────────────────────────────────────────────────
if [ "$(id -u)" -ne 0 ]; then
echo "❌ 必须 sudo 运行:sudo bash $0"
exit 1
fi
if [ "${1:-}" = "--yes" ]; then
SKIP_CONFIRM=true
fi
if [ ! -d "$REPO_UNITS_DIR" ]; then
echo "❌ repo unit 目录不存在: $REPO_UNITS_DIR"
exit 1
fi
# ── 1. 计算 plan ────────────────────────────────────────────────────────────
declare -a TO_COPY=() # repo→etc 拷贝
declare -a TO_REMOVE=() # etc 中孤儿(repo 已删)
declare -a TO_RESTART_SVC=() # service 文件变了需要 daemon-reload + restart
# repo 中所有 market-sync* unit
mapfile -t REPO_UNITS < <(find "$REPO_UNITS_DIR" -maxdepth 1 -type f \( -name "*.service" -o -name "*.timer" \) -printf '%f\n' | sort)
# /etc 中所有 market-sync* unit
mapfile -t ETC_UNITS < <(find "$ETC_UNITS_DIR" -maxdepth 1 -type f \( -name "market-sync*.service" -o -name "market-sync*.timer" \) -printf '%f\n' | sort 2>/dev/null || true)
# drift 1: repo 有 /etc 没装
for u in "${REPO_UNITS[@]}"; do
if [ ! -f "$ETC_UNITS_DIR/$u" ]; then
TO_COPY+=("$u")
fi
done
# drift 2: 两边都有但内容不一致
for u in "${REPO_UNITS[@]}"; do
if [ -f "$ETC_UNITS_DIR/$u" ]; then
if ! diff -q "$REPO_UNITS_DIR/$u" "$ETC_UNITS_DIR/$u" > /dev/null 2>&1; then
TO_COPY+=("$u")
if [[ "$u" == *.service ]]; then
TO_RESTART_SVC+=("${u%.service}")
fi
fi
fi
done
# drift 3: /etc 有 repo 没维护(孤儿)
for u in "${ETC_UNITS[@]}"; do
found=0
for r in "${REPO_UNITS[@]}"; do
if [ "$r" = "$u" ]; then found=1; break; fi
done
if [ $found -eq 0 ]; then
TO_REMOVE+=("$u")
fi
done
# ── 2. 显示 plan ────────────────────────────────────────────────────────────
echo "============================================================"
echo "market_sync systemd deploy plan"
echo "============================================================"
echo "Repo units dir: $REPO_UNITS_DIR"
echo
echo "Repo units: ${#REPO_UNITS[@]}"
echo "/etc units: ${#ETC_UNITS[@]}"
echo
if [ ${#TO_COPY[@]} -eq 0 ] && [ ${#TO_REMOVE[@]} -eq 0 ]; then
echo "✅ 无 drift 需要修复。"
else
if [ ${#TO_COPY[@]} -gt 0 ]; then
echo "📋 将要拷贝 (${#TO_COPY[@]} 个):"
for u in "${TO_COPY[@]}"; do
echo " cp deploy/systemd/units/$u → /etc/systemd/system/$u"
done
echo
fi
if [ ${#TO_RESTART_SVC[@]} -gt 0 ]; then
echo "🔄 将要处理 service (${#TO_RESTART_SVC[@]} 个):"
for s in "${TO_RESTART_SVC[@]}"; do
echo " systemctl reset-failed $s.service"
done
echo
fi
if [ ${#TO_REMOVE[@]} -gt 0 ]; then
echo "🗑️ 将要删除 etc 中的孤儿 (${#TO_REMOVE[@]} 个):"
for u in "${TO_REMOVE[@]}"; do
echo " rm /etc/systemd/system/$u"
done
echo
fi
fi
# ── 3. 等待确认 ────────────────────────────────────────────────────────────
if [ "$SKIP_CONFIRM" = false ]; then
read -p "确认执行?[y/N] " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo "已取消。"
exit 0
fi
fi
# ── 4. 执行 ─────────────────────────────────────────────────────────────────
echo
echo "=== 执行 ==="
# 4a. cp 漂移的 unit
for u in "${TO_COPY[@]}"; do
cp -v "$REPO_UNITS_DIR/$u" "$ETC_UNITS_DIR/$u"
done
# 4b. 删孤儿
for u in "${TO_REMOVE[@]}"; do
rm -v "$ETC_UNITS_DIR/$u"
done
# 4c. reload systemd
echo
echo "=== systemctl daemon-reload ==="
systemctl daemon-reload
# 4d. 停用并 mask worker 服务(systemd 模式下不需要进程内 scheduler)
if systemctl is-enabled market-sync-worker.service >/dev/null 2>&1 || \
systemctl is-active market-sync-worker.service >/dev/null 2>&1; then
echo "=== 关闭 market-sync-worker.servicesystemd 模式下由 timer 触发任务)==="
systemctl stop market-sync-worker.service || true
systemctl disable market-sync-worker.service || true
systemctl mask market-sync-worker.service || true
fi
# 4e. reset-failed + restart 修改过的 service
for s in "${TO_RESTART_SVC[@]}"; do
if systemctl is-enabled "${s}.service" 2>/dev/null | grep -q enabled; then
systemctl reset-failed "${s}.service" || true
echo " reset-failed ${s}.service (由 timer 自然触发)"
fi
done
# 4f. 启用所有 timer(幂等)
echo
echo "=== 启用 timers ==="
for u in "${REPO_UNITS[@]}"; do
if [[ "$u" == *.timer ]]; then
timer="${u%.timer}"
if ! systemctl is-enabled "${timer}.timer" >/dev/null 2>&1; then
systemctl enable "${timer}.timer"
echo " enable ${timer}.timer"
else
echo " ${timer}.timer 已启用"
fi
fi
done
# ── 5. 验证 ────────────────────────────────────────────────────────────────
echo
echo "=== 验证 ==="
echo "Repo units: ${#REPO_UNITS[@]}"
echo "/etc units: $(find "$ETC_UNITS_DIR" -maxdepth 1 -type f \( -name 'market-sync*.service' -o -name 'market-sync*.timer' \) | wc -l)"
drift_count=0
for u in "${REPO_UNITS[@]}"; do
if [ -f "$ETC_UNITS_DIR/$u" ]; then
if ! diff -q "$REPO_UNITS_DIR/$u" "$ETC_UNITS_DIR/$u" > /dev/null 2>&1; then
echo "$u 仍有 drift"
drift_count=$((drift_count + 1))
fi
else
echo "$u 仍未部署"
drift_count=$((drift_count + 1))
fi
done
# 验证 worker 已被 mask
if systemctl is-enabled market-sync-worker.service 2>/dev/null | grep -q masked; then
echo " ✅ market-sync-worker.service 已 masksystemd 模式下不启用进程内 scheduler"
else
echo " ⚠️ market-sync-worker.service 未被 masksystemd 模式下可能双调度器重叠"
fi
echo
if [ $drift_count -eq 0 ]; then
echo "✅ 所有 unit 已对齐,0 drift"
echo
echo "下一步:跑 .venv/bin/python bin/daily_sync_check.py --report-only 验证"
else
echo "❌ 还有 $drift_count 处 drift,请检查"
exit 1
fi