225 lines
6.5 KiB
Bash
Executable File
225 lines
6.5 KiB
Bash
Executable File
#!/bin/bash
|
|
# PlantAI-dev 9000 服务管理脚本
|
|
# 用法: bash manage_plantai.sh {start|stop|restart|status} [--port PORT]
|
|
# 默认端口: 9000
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
if [ -f "$SCRIPT_DIR/.env" ]; then
|
|
set -a
|
|
. "$SCRIPT_DIR/.env"
|
|
set +a
|
|
fi
|
|
|
|
# 解析命令行参数:第一个参数是命令,后面可选 --port / -p
|
|
CMD=""
|
|
WEB_PORT="${PLANTAI_WEB_PORT:-9000}"
|
|
for arg in "$@"; do
|
|
case "$arg" in
|
|
start|stop|restart|status)
|
|
CMD="$arg"
|
|
;;
|
|
--port|-p)
|
|
WEB_PORT=""
|
|
;;
|
|
*)
|
|
if [ -z "$WEB_PORT" ] && [[ "$arg" =~ ^[0-9]+$ ]]; then
|
|
WEB_PORT="$arg"
|
|
elif [ -z "$CMD" ]; then
|
|
echo "错误: 未知命令 '$arg'"
|
|
echo "用法: bash manage_plantai.sh {start|stop|restart|status} [--port PORT]"
|
|
exit 1
|
|
fi
|
|
;;
|
|
esac
|
|
done
|
|
CMD="${CMD:-status}"
|
|
|
|
# Conda 环境:启动脚本内部也依赖这个环境
|
|
CONDA_BASE="${BBAV5_CONDA_BASE:-/home/xia-lab/miniconda3}"
|
|
DEFAULT_ENV="${BBAV5_DEFAULT_ENV:-test4py311}"
|
|
CONDA_ENV="${CONDA_ENV:-$CONDA_BASE/envs/$DEFAULT_ENV}"
|
|
export PATH="$CONDA_ENV/bin:$PATH"
|
|
|
|
# 项目配置(与 .env 和启动脚本保持一致)
|
|
PROJECT_DIR="$SCRIPT_DIR"
|
|
QUEUE_PREFIX="${BBAV5_QUEUE_PREFIX:-plantai_4090_9000}"
|
|
REDIS_URL="${BBAV5_REDIS_URL:-redis://localhost:6379/10}"
|
|
WEB_LOG="/tmp/plantai_${WEB_PORT}.log"
|
|
CELERY_LOG="/tmp/celery_${WEB_PORT}.log"
|
|
|
|
red() { echo -e "\033[31m$*\033[0m"; }
|
|
green(){ echo -e "\033[32m$*\033[0m"; }
|
|
cyan() { echo -e "\033[36m$*\033[0m"; }
|
|
|
|
web_pid_for_port() {
|
|
ss -tlnp 2>/dev/null \
|
|
| grep ":$WEB_PORT " \
|
|
| grep -oP 'pid=\K\d+' \
|
|
| head -n 1 \
|
|
|| true
|
|
}
|
|
|
|
web_process_cwd() {
|
|
readlink -f "/proc/$1/cwd" 2>/dev/null || true
|
|
}
|
|
|
|
web_pid_belongs_to_project() {
|
|
[ "$(web_process_cwd "$1")" = "$PROJECT_DIR" ]
|
|
}
|
|
|
|
status() {
|
|
echo ""
|
|
cyan "=== PlantAI-dev ${WEB_PORT} 服务状态 ==="
|
|
echo ""
|
|
|
|
# Web 服务
|
|
WEB_PID="$(web_pid_for_port)"
|
|
if [ -n "${WEB_PID:-}" ]; then
|
|
WEB_CWD="$(web_process_cwd "$WEB_PID")"
|
|
if web_pid_belongs_to_project "$WEB_PID"; then
|
|
green "[✓] Web 服务运行中 (端口 $WEB_PORT, PID $WEB_PID)"
|
|
else
|
|
red "[!] 端口 $WEB_PORT 被其他项目占用 (PID $WEB_PID, cwd ${WEB_CWD:-未知})"
|
|
fi
|
|
else
|
|
red "[✗] Web 服务未启动 (端口 $WEB_PORT)"
|
|
fi
|
|
|
|
# Redis
|
|
if redis-cli -u "$REDIS_URL" ping > /dev/null 2>&1; then
|
|
green "[✓] Redis 运行中 ($REDIS_URL)"
|
|
else
|
|
red "[✗] Redis 未启动"
|
|
fi
|
|
|
|
# Celery workers
|
|
CELERY_COUNT="$(pgrep -fc "$QUEUE_PREFIX" || true)"
|
|
if [ "$CELERY_COUNT" -gt 0 ]; then
|
|
green "[✓] Celery workers 运行中 (${CELERY_COUNT} 进程, 队列前缀: $QUEUE_PREFIX)"
|
|
echo " Worker 列表:"
|
|
ps aux | grep "$QUEUE_PREFIX" | grep -v grep | grep -oP "queues=\K\S+" | sort | while read q; do
|
|
echo " - $q"
|
|
done
|
|
else
|
|
red "[✗] Celery workers 未启动 (队列前缀: $QUEUE_PREFIX)"
|
|
fi
|
|
echo ""
|
|
}
|
|
|
|
stop() {
|
|
echo ""
|
|
cyan "=== 停止 PlantAI-dev ${WEB_PORT} 服务 ==="
|
|
echo ""
|
|
|
|
# 停止 Web 服务
|
|
WEB_PID="$(web_pid_for_port)"
|
|
if [ -n "${WEB_PID:-}" ]; then
|
|
WEB_CWD="$(web_process_cwd "$WEB_PID")"
|
|
if ! web_pid_belongs_to_project "$WEB_PID"; then
|
|
red "[!] 拒绝停止:端口 $WEB_PORT 属于其他项目 (PID $WEB_PID, cwd ${WEB_CWD:-未知})"
|
|
return 1
|
|
fi
|
|
echo "正在停止 Web 服务 (PID $WEB_PID)..."
|
|
kill "$WEB_PID" 2>/dev/null || true
|
|
sleep 1
|
|
# 仅强制停止仍属于本项目的原进程,避免 PID 复用造成误杀。
|
|
if kill -0 "$WEB_PID" 2>/dev/null && web_pid_belongs_to_project "$WEB_PID"; then
|
|
kill -9 "$WEB_PID" 2>/dev/null || true
|
|
fi
|
|
green "[✓] Web 服务已停止"
|
|
else
|
|
echo "[ ] Web 服务未运行"
|
|
fi
|
|
|
|
# 停止 Celery workers
|
|
CELERY_PIDS=$(pgrep -f "$QUEUE_PREFIX" 2>/dev/null) || true
|
|
if [ -n "${CELERY_PIDS:-}" ]; then
|
|
echo "正在停止 Celery workers..."
|
|
echo "$CELERY_PIDS" | xargs -r kill 2>/dev/null || true
|
|
sleep 2
|
|
# 清理残留
|
|
REMAIN=$(pgrep -f "$QUEUE_PREFIX" 2>/dev/null) || true
|
|
if [ -n "${REMAIN:-}" ]; then
|
|
echo " 强制清理残留进程..."
|
|
echo "$REMAIN" | xargs -r kill -9 2>/dev/null || true
|
|
fi
|
|
green "[✓] Celery workers 已停止"
|
|
else
|
|
echo "[ ] Celery workers 未运行"
|
|
fi
|
|
echo ""
|
|
}
|
|
|
|
start() {
|
|
echo ""
|
|
cyan "=== 启动 PlantAI-dev ${WEB_PORT} 服务 ==="
|
|
echo ""
|
|
|
|
# 检查是否已在运行
|
|
WEB_PID="$(web_pid_for_port)"
|
|
if [ -n "${WEB_PID:-}" ]; then
|
|
WEB_CWD="$(web_process_cwd "$WEB_PID")"
|
|
if web_pid_belongs_to_project "$WEB_PID"; then
|
|
red "[!] 本项目 Web 已在端口 $WEB_PORT 运行 (PID $WEB_PID)"
|
|
else
|
|
red "[!] 端口 $WEB_PORT 被其他项目占用 (PID $WEB_PID, cwd ${WEB_CWD:-未知})"
|
|
fi
|
|
exit 1
|
|
fi
|
|
|
|
if ! redis-cli -u "$REDIS_URL" ping > /dev/null 2>&1; then
|
|
red "[!] Redis 未运行,请先启动 Redis"
|
|
exit 1
|
|
fi
|
|
|
|
cd "$PROJECT_DIR"
|
|
|
|
# 启动 Celery workers
|
|
echo "正在启动 Celery workers..."
|
|
nohup bash start_celery_9000.sh > "$CELERY_LOG" 2>&1 &
|
|
sleep 3
|
|
CELERY_COUNT="$(pgrep -fc "$QUEUE_PREFIX" || true)"
|
|
if [ "$CELERY_COUNT" -gt 0 ]; then
|
|
green " [✓] Celery workers 已启动 (${CELERY_COUNT} 进程)"
|
|
else
|
|
red " [✗] Celery workers 启动失败,查看 $CELERY_LOG"
|
|
fi
|
|
|
|
# 启动 Web 服务
|
|
echo "正在启动 Web 服务..."
|
|
nohup bash start_plantai_9000.sh --port "$WEB_PORT" > "$WEB_LOG" 2>&1 &
|
|
sleep 3
|
|
if ss -tlnp 2>/dev/null | grep -q ":$WEB_PORT"; then
|
|
green " [✓] Web 服务已启动 (http://0.0.0.0:$WEB_PORT)"
|
|
else
|
|
red " [✗] Web 服务启动失败,查看 $WEB_LOG"
|
|
fi
|
|
|
|
# 最终状态
|
|
echo ""
|
|
echo "日志文件:"
|
|
echo " Web: $WEB_LOG"
|
|
echo " Celery: $CELERY_LOG"
|
|
echo " Worker: $PROJECT_DIR/logs/celery_${QUEUE_PREFIX}/"
|
|
echo ""
|
|
}
|
|
|
|
restart() {
|
|
stop
|
|
sleep 1
|
|
start
|
|
}
|
|
|
|
case "$CMD" in
|
|
start) start ;;
|
|
stop) stop ;;
|
|
restart) restart ;;
|
|
status) status ;;
|
|
*)
|
|
echo "用法: bash manage_plantai.sh {start|stop|restart|status} [--port PORT]"
|
|
exit 1
|
|
;;
|
|
esac
|