Files
height_manager/.cozeproj/scripts/dev_run.sh
jaystar 28c4d7b3b4 feat: 实现减脂体重管理App完整功能
- 实现拍照识别食物功能(集成大语言模型视觉能力)
- 实现智能对话功能(集成大语言模型流式输出)
- 实现食物记录和卡路里管理功能
- 实现体重记录和统计功能
- 实现健康数据管理页面
- 配置数据库表结构(用户、食物记录、体重记录)
- 实现Express后端API路由
- 配置Tab导航和前端页面
- 采用健康运动配色方案
2026-02-02 15:17:50 +08:00

229 lines
7.2 KiB
Bash
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.
ROOT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
PREVIEW_DIR="${COZE_PREVIEW_DIR:-/source/preview}"
LOG_DIR="${COZE_LOG_DIR:-$ROOT_DIR/logs}"
LOG_FILE="$LOG_DIR/app.log"
mkdir -p "$LOG_DIR"
# ==================== 配置项 ====================
# Server 服务配置
SERVER_HOST="0.0.0.0"
SERVER_PORT="9091"
# Expo 项目配置
EXPO_HOST="0.0.0.0"
EXPO_DIR="expo"
EXPO_PORT="5000"
WEB_URL="${COZE_PROJECT_DOMAIN_DEFAULT:-http://127.0.0.1:${SERVER_PORT}}"
ASSUME_YES="1"
EXPO_PUBLIC_BACKEND_BASE_URL="${EXPO_PUBLIC_BACKEND_BASE_URL:-$WEB_URL}"
EXPO_PUBLIC_COZE_PROJECT_ID="${COZE_PROJECT_ID:-}"
EXPO_PACKAGER_PROXY_URL="${EXPO_PUBLIC_BACKEND_BASE_URL}"
export EXPO_PUBLIC_BACKEND_BASE_URL EXPO_PACKAGER_PROXY_URL EXPO_PUBLIC_COZE_PROJECT_ID
# 运行时变量(为避免 set -u 的未绑定错误,预置为空)
SERVER_PID=""
EXPO_PID=""
# ==================== 工具函数 ====================
check_command() {
if ! command -v "$1" &> /dev/null; then
echo "error:命令 $1 未找到,请先安装"
fi
}
while [ $# -gt 0 ]; do
case "$1" in
-y|--yes)
ASSUME_YES="1"
shift
;;
*)
shift
;;
esac
done
is_port_free() {
! lsof -iTCP:"$1" -sTCP:LISTEN >/dev/null 2>&1
}
choose_next_free_port() {
local start=$1
local p=$start
while ! is_port_free "$p"; do
p=$((p+1))
done
echo "$p"
}
ensure_port() {
local var_name=$1
local port_val=$2
if is_port_free "$port_val"; then
echo "端口未占用:$port_val"
eval "$var_name=$port_val"
else
echo "端口已占用:$port_val"
local choice
if [ "$ASSUME_YES" = "1" ]; then choice="Y"; else read -r -p "是否关闭该端口的进程?[Y/n] " choice || choice="Y"; fi
if [ -z "$choice" ] || [ "$choice" = "y" ] || [ "$choice" = "Y" ]; then
if command -v lsof &> /dev/null; then
local pids
pids=$(lsof -t -i tcp:"$port_val" -sTCP:LISTEN 2>/dev/null || true)
if [ -n "$pids" ]; then
echo "正在关闭进程:$pids"
kill -9 $pids 2>/dev/null || echo "关闭进程失败:$pids"
eval "$var_name=$port_val"
else
echo "未获取到占用该端口的进程"
eval "$var_name=$port_val"
fi
else
echo "缺少 lsof无法自动关闭进程"
eval "$var_name=$port_val"
fi
else
local new_port
new_port=$(choose_next_free_port "$port_val")
info "使用新的端口:$new_port"
eval "$var_name=$new_port"
fi
fi
}
pipe_to_log() {
local source="${1:-CLIENT}"
local raw_log="${2:-}"
local line timestamp ts msg record
while IFS= read -r line || [ -n "$line" ]; do
if [ -n "$raw_log" ]; then
echo "$line" >> "$raw_log"
fi
line=$(echo "[$source] $line" | sed 's/\x1b\[[0-9;]*[a-zA-Z]//g; s/\x1b\[[0-9;]*m//g')
msg="${line}"
echo "$msg"
done
}
wait_port_connectable() {
local host=$1 port=$2 retries=${3:-10}
for _ in $(seq 1 "$retries"); do
nc -z -w 1 "$host" "$port" >/dev/null 2>&1 && return 0
sleep 1
done
return 1
}
start_expo() {
local offline="${1:-0}"
pushd "$ROOT_DIR/client"
if [ "$offline" = "1" ]; then
( EXPO_OFFLINE=1 EXPO_NO_DEPENDENCY_VALIDATION=1 EXPO_PUBLIC_BACKEND_BASE_URL="$EXPO_PUBLIC_BACKEND_BASE_URL" EXPO_PACKAGER_PROXY_URL="$EXPO_PACKAGER_PROXY_URL" EXPO_PUBLIC_COZE_PROJECT_ID="$EXPO_PUBLIC_COZE_PROJECT_ID" \
nohup npx expo start --clear --port "$EXPO_PORT" 2>&1 | pipe_to_log "CLIENT" "$ROOT_DIR/logs/client.log" ) &
else
( EXPO_NO_DEPENDENCY_VALIDATION=1 EXPO_PUBLIC_BACKEND_BASE_URL="$EXPO_PUBLIC_BACKEND_BASE_URL" EXPO_PACKAGER_PROXY_URL="$EXPO_PACKAGER_PROXY_URL" EXPO_PUBLIC_COZE_PROJECT_ID="$EXPO_PUBLIC_COZE_PROJECT_ID" \
nohup npx expo start --clear --port "$EXPO_PORT" 2>&1 | pipe_to_log "CLIENT" "$ROOT_DIR/logs/client.log" ) &
fi
EXPO_PID=$!
disown $EXPO_PID 2>/dev/null || true
popd
}
detect_expo_fetch_failed() {
local timeout="${1:-8}"
local waited=0
local log_file="$ROOT_DIR/logs/client.log"
while [ "$waited" -lt "$timeout" ]; do
if [ -f "$log_file" ] && grep -q "TypeError: fetch failed" "$log_file" 2>/dev/null; then
return 0
fi
sleep 1
waited=$((waited+1))
done
return 1
}
# ==================== 前置检查 ====================
# 关掉nginx进程
ps -ef | grep nginx | grep -v grep | awk '{print $2}' | xargs -r kill -9
echo "检查根目录 pre_install.py"
if [ -f "$PREVIEW_DIR/pre_install.py" ]; then
echo "执行python $PREVIEW_DIR/pre_install.py"
python "$PREVIEW_DIR/pre_install.py" || echo "pre_install.py 执行失败"
fi
echo "检查根目录 post_install.py"
if [ -f "$PREVIEW_DIR/post_install.py" ]; then
echo "执行python $PREVIEW_DIR/post_install.py"
python "$PREVIEW_DIR/post_install.py" || echo "post_install.py 执行失败"
fi
echo "==================== 开始启动 ===================="
echo "开始执行服务启动脚本start_dev.sh..."
echo "正在检查依赖命令和目录是否存在..."
# 检查核心命令
check_command "npm"
check_command "pnpm"
check_command "lsof"
check_command "bash"
echo "准备日志目录:$ROOT_DIR/logs"
mkdir -p "$ROOT_DIR/logs"
# 端口占用预检查与处理
ensure_port SERVER_PORT "$SERVER_PORT"
ensure_port EXPO_PORT "$EXPO_PORT"
echo "==================== 启动 server 服务 ===================="
echo "正在执行pnpm run dev (server)"
( pushd "$ROOT_DIR/server" > /dev/null && SERVER_PORT="$SERVER_PORT" nohup pnpm run dev; popd > /dev/null ) &
SERVER_PID=$!
disown $SERVER_PID 2>/dev/null || true
if [ -z "${SERVER_PID}" ]; then
echo "无法获取 server 后台进程 PID"
fi
echo "server 服务已启动,进程 ID${SERVER_PID:-unknown}"
echo "==================== 启动 Expo 项目 ===================="
echo "开始启动 Expo 服务,端口 ${EXPO_PORT}"
start_expo 0
if detect_expo_fetch_failed 8; then
echo "Expo 启动检测到网络错误TypeError: fetch failed启用离线模式重试"
if [ -n "${EXPO_PID}" ]; then kill -9 "$EXPO_PID" 2>/dev/null || true; fi
: > "$ROOT_DIR/logs/client.log"
start_expo 1
fi
# 输出以下环境变量,确保 Expo 项目能正确连接到 Server 服务
echo "Expo 环境变量配置:"
echo "EXPO_PUBLIC_BACKEND_BASE_URL=${EXPO_PUBLIC_BACKEND_BASE_URL}"
echo "EXPO_PACKAGER_PROXY_URL=${EXPO_PACKAGER_PROXY_URL}"
echo "EXPO_PUBLIC_COZE_PROJECT_ID=${EXPO_PUBLIC_COZE_PROJECT_ID}"
if [ -z "${EXPO_PID}" ]; then
echo "无法获取 Expo 后台进程 PID"
fi
echo "所有服务已启动。Server PID: ${SERVER_PID}, Expo PID: ${EXPO_PID}"
echo "检查 Server 服务端口:$SERVER_HOST:$SERVER_PORT"
if wait_port_connectable "$SERVER_HOST" "$SERVER_PORT" 10 2; then
echo "端口可连接:$SERVER_HOST:$SERVER_PORT"
else
echo "端口不可连接:$SERVER_HOST:$SERVER_PORT 10 次)"
fi
echo "检查 Expo 服务端口:$EXPO_HOST:$EXPO_PORT"
if wait_port_connectable "$EXPO_HOST" "$EXPO_PORT" 10 2; then
echo "端口可连接:$EXPO_HOST:$EXPO_PORT"
else
echo "端口不可连接:$EXPO_HOST:$EXPO_PORT(已尝试 10 次)"
fi
echo "服务端口检查完成"
echo "检查根目录 post_run.py"
if [ -f "$ROOT_DIR/post_run.py" ]; then
echo "启动检查中"
python "$ROOT_DIR/post_run.py" --port "$EXPO_PORT" || echo "post_run.py 执行失败"
echo "启动检查结束"
fi
echo "==================== 服务启动完成 ===================="