feat: 军事科技每日资讯推送系统 - Docker部署 + 日志系统 + 数据目录重组
This commit is contained in:
@@ -0,0 +1,144 @@
|
||||
#!/usr/bin/env bash
|
||||
# Daily News - 系统服务一键安装
|
||||
# 用法:./scripts/install.sh
|
||||
# 不要用 sudo 直接调用本脚本;脚本会在需要时自行 sudo 提权。
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
|
||||
# ─── 用户检测 ────────────────────────────────────────────────
|
||||
if [[ $EUID -eq 0 ]]; then
|
||||
if [[ -z "${SUDO_USER:-}" ]]; then
|
||||
echo "❌ 请勿直接用 root 运行本脚本,请用普通用户(脚本按需自动提权)"
|
||||
exit 1
|
||||
fi
|
||||
RUN_USER="$SUDO_USER"
|
||||
else
|
||||
RUN_USER="$USER"
|
||||
fi
|
||||
RUN_GROUP="$(id -gn "$RUN_USER")"
|
||||
|
||||
# ─── uv 检测 ─────────────────────────────────────────────────
|
||||
UV_BIN="$(command -v uv || true)"
|
||||
if [[ -z "$UV_BIN" ]]; then
|
||||
echo "❌ 找不到 uv 命令,请先安装:https://docs.astral.sh/uv/"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ─── systemd 检测 ────────────────────────────────────────────
|
||||
if ! command -v systemctl >/dev/null 2>&1; then
|
||||
echo "❌ 系统未检测到 systemctl(非 systemd 系统),本脚本仅支持 systemd Linux"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd "$PROJECT_DIR"
|
||||
|
||||
echo "🚀 Daily News - 系统服务安装"
|
||||
echo "────────────────────────────────────────"
|
||||
echo " 项目目录: $PROJECT_DIR"
|
||||
echo " 运行身份: $RUN_USER:$RUN_GROUP"
|
||||
echo " uv 路径: $UV_BIN"
|
||||
echo "────────────────────────────────────────"
|
||||
echo ""
|
||||
|
||||
# 提前提权一次,后续 sudo 命令直接复用凭据缓存
|
||||
echo "🔐 需要 sudo 权限来写入 /etc/systemd/system/"
|
||||
sudo -v
|
||||
echo ""
|
||||
|
||||
# ─── [1/6] 同步依赖 ──────────────────────────────────────────
|
||||
echo "📦 [1/6] 同步依赖 (uv sync)..."
|
||||
uv sync
|
||||
echo "✓ 依赖已就绪"
|
||||
echo ""
|
||||
|
||||
# ─── [2/6] 验证 .env ────────────────────────────────────────
|
||||
echo "🔐 [2/6] 验证 .env..."
|
||||
if [[ ! -f "$PROJECT_DIR/.env" ]]; then
|
||||
echo "❌ .env 不存在,请先复制 .env.example 并填入 API Key"
|
||||
exit 1
|
||||
fi
|
||||
echo "✓ .env 存在"
|
||||
echo ""
|
||||
|
||||
# ─── [3/6] LLM 健康检查 ─────────────────────────────────────
|
||||
echo "🔍 [3/6] 校验 LLM 接口(仅在此处校验,运行时不再校验)..."
|
||||
if ! uv run python -m src.main check; then
|
||||
echo ""
|
||||
echo "❌ LLM 校验失败,已中止安装"
|
||||
echo "请检查 config.json 中的 llm.baseUrl/model 以及 .env 中的 API Key"
|
||||
exit 1
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# ─── [4/6] 生成单元文件 ─────────────────────────────────────
|
||||
echo "📝 [4/6] 渲染 systemd 单元模板..."
|
||||
STAGE_DIR="$(mktemp -d)"
|
||||
trap 'rm -rf "$STAGE_DIR"' EXIT
|
||||
|
||||
uv run python "$PROJECT_DIR/scripts/_gen_units.py" \
|
||||
--project-dir "$PROJECT_DIR" \
|
||||
--user "$RUN_USER" \
|
||||
--group "$RUN_GROUP" \
|
||||
--uv-bin "$UV_BIN" \
|
||||
--output-dir "$STAGE_DIR"
|
||||
|
||||
# 同时渲染 daily-news 包装脚本(/usr/local/bin/daily-news)
|
||||
sed "s|{{PROJECT_DIR}}|$PROJECT_DIR|g" \
|
||||
"$PROJECT_DIR/scripts/daily-news.tmpl" > "$STAGE_DIR/daily-news"
|
||||
echo " ✓ daily-news"
|
||||
echo ""
|
||||
|
||||
# ─── [5/6] 安装到 systemd ───────────────────────────────────
|
||||
echo "📥 [5/6] 安装到系统..."
|
||||
sudo install -m 644 "$STAGE_DIR/dnews-fetch.service" /etc/systemd/system/
|
||||
sudo install -m 644 "$STAGE_DIR/dnews-fetch.timer" /etc/systemd/system/
|
||||
sudo install -m 644 "$STAGE_DIR/dnews-push.service" /etc/systemd/system/
|
||||
sudo install -m 644 "$STAGE_DIR/dnews-push.timer" /etc/systemd/system/
|
||||
|
||||
# 日志保留策略(journald 命名空间 drop-in)
|
||||
sudo mkdir -p /etc/systemd/journald@dnews.conf.d
|
||||
sudo install -m 644 "$STAGE_DIR/journald-dnews.conf" \
|
||||
/etc/systemd/journald@dnews.conf.d/retention.conf
|
||||
|
||||
# daily-news 包装脚本到系统 PATH
|
||||
sudo install -m 755 "$STAGE_DIR/daily-news" /usr/local/bin/daily-news
|
||||
|
||||
sudo systemctl daemon-reload
|
||||
|
||||
# 命名空间 journald 实例首次会在 fetch/push 首次产出日志时自动拉起;
|
||||
# 若已存在(重装场景),重启以加载新保留策略。
|
||||
sudo systemctl restart systemd-journald@dnews.service 2>/dev/null || true
|
||||
|
||||
echo "✓ 单元文件 + daily-news 包装脚本已安装"
|
||||
echo ""
|
||||
|
||||
# ─── [6/6] 启用并启动 timer ─────────────────────────────────
|
||||
echo "🚦 [6/6] 启用并(重)启动 timer..."
|
||||
# 先 enable 注册开机自启
|
||||
sudo systemctl enable dnews-fetch.timer dnews-push.timer
|
||||
# 再 restart 强制按新单元文件重置内存中的 timer 状态
|
||||
# (enable --now 对已运行的 timer 是 no-op,无法应用新 OnCalendar/OnActiveSec 等改动)
|
||||
sudo systemctl restart dnews-fetch.timer dnews-push.timer
|
||||
echo ""
|
||||
|
||||
# ─── 完成 ───────────────────────────────────────────────────
|
||||
echo "✅ 安装完成!"
|
||||
echo ""
|
||||
echo "下次触发时间:"
|
||||
systemctl list-timers 'dnews-*' --no-pager || true
|
||||
echo ""
|
||||
echo "常用命令(系统 PATH 中可直接调用):"
|
||||
echo " daily-news status 查看状态 + 最近日志"
|
||||
echo " daily-news logs 实时跟随日志"
|
||||
echo " daily-news stop 停止"
|
||||
echo " daily-news start 启动"
|
||||
echo " daily-news restart 重启 timer"
|
||||
echo ""
|
||||
echo "手动立即触发一次任务(不影响下次调度):"
|
||||
echo " sudo systemctl start dnews-fetch.service"
|
||||
echo " sudo systemctl start dnews-push.service"
|
||||
echo ""
|
||||
echo "卸载:$PROJECT_DIR/scripts/uninstall.sh"
|
||||
Reference in New Issue
Block a user