iOSBuildServer/deploy/install-service.sh
shen 6f4f625c56 Initial commit: iOS Build Server
- FastAPI backend with build queue, WebSocket logs, task management
- Vue 3 frontend with build/config/history views
- Xcode project build automation with IPA export
- Fix: initialize build_dir before try block to ensure cleanup on early failure
2026-06-06 17:42:27 +08:00

146 lines
4.0 KiB
Bash
Executable File

#!/bin/bash
# 安装/卸载 macOS launchd 服务(主服务 + watchdog 健康监测)
# 用法: ./deploy/install-service.sh {install|uninstall}
set -e
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
# 加载 .env
if [ -f "$PROJECT_DIR/.env" ]; then
set -a; source "$PROJECT_DIR/.env"; set +a
fi
PORT="${BACKEND_PORT:-8000}"
VENV_DIR="$PROJECT_DIR/.venv"
LOG_DIR="$PROJECT_DIR/logs"
PLIST_APP="com.readoor.buildserver"
PLIST_WD="com.readoor.buildserver.watchdog"
PLIST_APP_TARGET="$HOME/Library/LaunchAgents/$PLIST_APP.plist"
PLIST_WD_TARGET="$HOME/Library/LaunchAgents/$PLIST_WD.plist"
do_install() {
if [ ! -d "$VENV_DIR" ]; then
echo "请先执行 ./deploy.sh build"
exit 1
fi
if [ ! -d "$PROJECT_DIR/backend/static" ]; then
echo "请先执行 ./deploy.sh build"
exit 1
fi
mkdir -p "$LOG_DIR"
# ---- 主服务 plist ----
cat > "$PLIST_APP_TARGET" <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>$PLIST_APP</string>
<key>ProgramArguments</key>
<array>
<string>$VENV_DIR/bin/python3</string>
<string>-m</string>
<string>uvicorn</string>
<string>backend.main:app</string>
<string>--host</string>
<string>0.0.0.0</string>
<string>--port</string>
<string>$PORT</string>
<string>--workers</string>
<string>1</string>
</array>
<key>WorkingDirectory</key>
<string>$PROJECT_DIR</string>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>$VENV_DIR/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
</dict>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<dict>
<key>SuccessfulExit</key>
<false/>
</dict>
<key>StandardOutPath</key>
<string>$LOG_DIR/server-stdout.log</string>
<key>StandardErrorPath</key>
<string>$LOG_DIR/server-stderr.log</string>
</dict>
</plist>
EOF
# ---- Watchdog plist ----
cat > "$PLIST_WD_TARGET" <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>$PLIST_WD</string>
<key>ProgramArguments</key>
<array>
<string>$PROJECT_DIR/deploy.sh</string>
<string>_watchdog_loop</string>
</array>
<key>WorkingDirectory</key>
<string>$PROJECT_DIR</string>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>$VENV_DIR/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
</dict>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>$LOG_DIR/watchdog-stdout.log</string>
<key>StandardErrorPath</key>
<string>$LOG_DIR/watchdog-stderr.log</string>
</dict>
</plist>
EOF
# 加载服务
launchctl unload "$PLIST_WD_TARGET" 2>/dev/null || true
launchctl unload "$PLIST_APP_TARGET" 2>/dev/null || true
launchctl load "$PLIST_APP_TARGET"
launchctl load "$PLIST_WD_TARGET"
echo "服务已安装并启动"
echo " 主服务: http://localhost:$PORT"
echo " Watchdog: 每 ${WATCHDOG_INTERVAL:-30}s 健康检查,故障自动重启"
echo " 日志目录: $LOG_DIR"
echo ""
echo "卸载命令: $0 uninstall"
}
do_uninstall() {
if [ -f "$PLIST_WD_TARGET" ]; then
launchctl unload "$PLIST_WD_TARGET" 2>/dev/null || true
rm -f "$PLIST_WD_TARGET"
echo "Watchdog 已卸载"
fi
if [ -f "$PLIST_APP_TARGET" ]; then
launchctl unload "$PLIST_APP_TARGET" 2>/dev/null || true
rm -f "$PLIST_APP_TARGET"
echo "主服务已卸载"
fi
}
case "${1:-}" in
install) do_install ;;
uninstall) do_uninstall ;;
*)
echo "用法: $0 {install|uninstall}"
exit 1
;;
esac