#!/bin/bash # 微信读书数据看板 - 服务启动脚本 # 用法: # ./start_server.sh 启动服务(前台运行) # ./start_server.sh daemon 后台守护进程方式启动 # ./start_server.sh stop 停止服务 # ./start_server.sh restart 重启服务 # ./start_server.sh status 查看状态 PROJECT_DIR="$(cd "$(dirname "$0")" && pwd)" if [ -x "$PROJECT_DIR/.venv/bin/python" ]; then DEFAULT_PYTHON="$PROJECT_DIR/.venv/bin/python" else DEFAULT_PYTHON="$(command -v python3 || command -v python)" fi PYTHON="${PYTHON:-$DEFAULT_PYTHON}" PID_FILE="$PROJECT_DIR/.server.pid" LOG_FILE="/tmp/weread_server.log" # 默认从 8080 启动;也可通过 PORT 或 WEREAD_PORT 指定端口 PORT="${PORT:-${WEREAD_PORT:-8080}}" cd "$PROJECT_DIR" || exit 1 is_running() { if [ -f "$PID_FILE" ]; then local pid=$(cat "$PID_FILE") if kill -0 "$pid" 2>/dev/null; then return 0 fi fi return 1 } get_pid() { if [ -f "$PID_FILE" ]; then local pid=$(cat "$PID_FILE") if kill -0 "$pid" 2>/dev/null; then echo "$pid" return fi fi return 0 } find_free_port() { while lsof -iTCP:"$PORT" -sTCP:LISTEN -t >/dev/null 2>&1; do PORT=$((PORT + 1)) done } get_running_port() { local pid=$(get_pid) local running_port if [ -n "$pid" ]; then running_port=$(lsof -Pan -p "$pid" -iTCP -sTCP:LISTEN 2>/dev/null \ | awk 'NR > 1 {print $9}' \ | sed -E 's/.*:([0-9]+)$/\1/' \ | head -1) fi echo "${running_port:-$PORT}" } stop_server() { if is_running; then local pid=$(get_pid) echo "停止服务 (PID: $pid)..." kill "$pid" 2>/dev/null sleep 1 if kill -0 "$pid" 2>/dev/null; then kill -9 "$pid" 2>/dev/null fi rm -f "$PID_FILE" echo "已停止" else echo "服务未运行" fi } start_foreground() { if is_running; then local running_port=$(get_running_port) echo "服务已在运行 (PID: $(get_pid), 端口: $running_port)" echo "访问地址: http://127.0.0.1:$running_port" exit 1 fi if [ -z "$PYTHON" ]; then echo "未找到可用的 Python 解释器" exit 1 fi echo "启动服务(前台模式,端口: $PORT)..." echo "访问地址: http://127.0.0.1:$PORT" PORT="$PORT" WEREAD_PORT="$PORT" exec "$PYTHON" app.py } start_daemon() { if [ ! -f "$PID_FILE" ]; then find_free_port fi if is_running; then local running_port=$(get_running_port) echo "服务已在运行 (PID: $(get_pid), 端口: $running_port)" echo "访问地址: http://127.0.0.1:$running_port" exit 1 fi if [ -z "$PYTHON" ]; then echo "未找到可用的 Python 解释器" exit 1 fi echo "启动服务(后台守护模式,端口: $PORT)..." PORT="$PORT" WEREAD_PORT="$PORT" nohup "$PYTHON" app.py > "$LOG_FILE" 2>&1 & local pid=$! echo "$pid" > "$PID_FILE" sleep 2 if kill -0 "$pid" 2>/dev/null; then echo "服务已启动 (PID: $pid)" echo "端口: $PORT" echo "访问地址: http://127.0.0.1:$PORT" echo "日志: $LOG_FILE" else echo "启动失败,请查看日志: $LOG_FILE" cat "$LOG_FILE" rm -f "$PID_FILE" exit 1 fi } show_status() { if is_running; then local pid=$(get_pid) echo "✅ 服务运行中 (PID: $pid)" echo " 端口: $PORT" echo " 日志: $LOG_FILE" else echo "❌ 服务未运行" fi } case "${1:-start}" in start) start_foreground ;; daemon) start_daemon ;; stop) stop_server ;; restart) stop_server; sleep 1; start_daemon ;; status) show_status ;; *) echo "用法: $0 {start|daemon|stop|restart|status}"; exit 1 ;; esac