Files
AskaEth 5139945bfe
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
feat(channels): 非消息事件接入(notice 归一化 + 传入前审查,fail-safe 静默)与入站脱敏帧日志/日志轮转
- notice:adapter 归一化 seam + 结构化分类 + 净化(ANSI/控制/零宽/双向字符、200 runes 截断)
  + fail-safe 写死为「静默」(未装配审查/超时/失败 ⇒ 仅登记、不驱动 loop)
- 身份面零改动:notice 发送者恒 RoleSystem + SenderID=system
- 复用策略四的同一个审查模型(Options.Review),未另造第二套
- 入站帧脱敏 DEBUG(post_type/message_type/sub_type/self_id/user_id/sender_id/group_id/段类型/at 目标)
- ctrl.bat 启动前归档轮转(保留 20 份)+ bash 侧改追加(不再重启即截断)
2026-10-05 11:55:05 +08:00

144 lines
4.4 KiB
Bash
Raw Permalink 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
# Cyrene v2 本地一键控制:启动 / 重启 / 终止 后台 cyrene 进程。
#
# 用法:
# bash scripts/ctrl.sh # 启动(默认)
# bash scripts/ctrl.sh start # 启动
# bash scripts/ctrl.sh restart # 重启
# bash scripts/ctrl.sh stop # 终止
# bash scripts/ctrl.sh status # 查看状态
#
# 说明:
# - 管理单个 cyrene 后端进程(单二进制)。llama-server / PG 若需一并管理,
# 可另用 docker / scripts/dev-up.sh。
# - cyrene 在仓库根下运行(读 .env 的 PORT / DATA_DIR 等),日志**追加**写 ~/cy.log
# (重启不清空历史;Windows 侧 scripts\ctrl.bat 因 Start-Process 无法追加,改为
# 按时间戳归档,见该脚本的注释)。
# - 用 setsid + nohup 脱离进程组,避免终端/后台 shell 超时误杀。
set -euo pipefail
REPO="$(cd "$(dirname "$0")/.." && pwd)"
APP_BIN="$HOME/apps/cyrene/cyrene"
PID_FILE="$HOME/.cyrene.pid"
LOG_FILE="$HOME/cy.log"
# 端口优先读 .env 的 PORT(用户可改),找不到才回退 10080
GW_PORT="$(grep -E '^PORT=' "$REPO/.env" 2>/dev/null | head -1 | cut -d= -f2)"
GW_PORT="${GW_PORT:-10080}"
HEALTH_URL="http://127.0.0.1:$GW_PORT/api/v1/health"
# 读取进程 PID:先看 PID 文件,没有则从监听端口探测(能识别外部已起的 cyrene)
read_pid() {
# 1) PID 文件优先
if [ -f "$PID_FILE" ]; then
local pid
pid="$(cat "$PID_FILE" 2>/dev/null)"
if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
echo "$pid"
return 0
fi
fi
# 2) 端口探测兜底(ss 找监听 GW_PORT 的 cyrene 进程)
local p
p="$(ss -tlnp 2>/dev/null | grep ":$GW_PORT" | grep -oE 'pid=[0-9]+' | head -1 | sed -E 's/[^0-9]//g')"
if [ -n "$p" ] && kill -0 "$p" 2>/dev/null; then
echo "$p"
return 0
fi
return 1
}
is_running() {
read_pid >/dev/null 2>&1
}
# 健康检查:进程在 + HTTP 200
healthy() {
read_pid >/dev/null 2>&1 && curl -s --max-time 2 "$HEALTH_URL" >/dev/null 2>&1
}
start() {
if is_running; then
echo "cyrene 已在运行 (PID $(read_pid)),跳过。用 restart 重启。"
return 0
fi
[ -x "$APP_BIN" ] || { echo "未找到二进制 $APP_BIN,请先 go build"; return 1; }
echo "启动 cyrene → $APP_BIN (端口 $GW_PORT)"
# setsid 只脱离会话,但 cyrene 仍是本 bash 的后台 job;脚本退出时 bash 会等待
# 它结束,导致 restart 命令"挂起超时"。disown 把它从作业表剔除,脚本立即返回。
# 日志**追加**(>>)而不是覆盖(>):重启不再截断上一轮日志——排障证据必须能跨重启
# 留存(「日志重启即清空」曾让一个线上问题无从取证)。
cd "$REPO" || return 1
setsid nohup "$APP_BIN" >> "$LOG_FILE" 2>&1 < /dev/null &
disown
# 等待健康
local i
for i in $(seq 1 20); do
sleep 0.5
if healthy; then
echo "已启动: http://localhost:$GW_PORT (日志 $LOG_FILE)"
return 0
fi
done
echo "启动后 ${GW_PORT} 未就绪,请查看日志 $LOG_FILE"
return 1
}
stop() {
local pid
if read_pid >/dev/null 2>&1; then
pid="$(read_pid)"
kill "$pid" 2>/dev/null || true
echo "已发送终止信号 → PID $pid"
local i
for i in $(seq 1 20); do
sleep 0.4
kill -0 "$pid" 2>/dev/null || { echo "已退出"; rm -f "$PID_FILE"; return 0; }
done
echo "进程未在 8s 内退出,强制 kill -9"
kill -9 "$pid" 2>/dev/null || true
rm -f "$PID_FILE"
else
echo "cyrene 未在运行(无 PID 文件或进程已退出)"
rm -f "$PID_FILE"
fi
}
restart() {
echo "重启 cyrene…"
stop
sleep 1
start
}
status() {
if healthy; then
echo "cyrene: 运行中 (PID $(read_pid)) · 端口 $GW_PORT · health ok"
elif is_running; then
echo "cyrene: 进程在 (PID $(read_pid)) 但 health 未就绪 ($HEALTH_URL)"
else
echo "cyrene: 未运行"
fi
}
usage() {
echo "用法: bash scripts/ctrl.sh [start|stop|restart|status] (无参 = start)"
}
# start 成功后把探测到的 PID 写入文件,供后续 stop 精确管理
record_pid() {
if healthy; then
local p
p="$(ss -tlnp 2>/dev/null | grep ":$GW_PORT" | grep -oE 'pid=[0-9]+' | head -1 | sed -E 's/[^0-9]//g')"
[ -n "$p" ] && echo "$p" > "$PID_FILE"
fi
}
case "${1:-start}" in
start) start; record_pid ;;
restart) restart; record_pid ;;
stop) stop ;;
status) status ;;
*) usage; exit 1 ;;
esac