Files
memind/scripts/install-prod-services.sh
T
John 6d99d762da Add image-designer skill, align billing to DeepSeek ×1, and enrich Plaza demo.
Introduce AI image generation with chat shortcut and agent API, improve MindSpace chat-to-page save resolution, and seed Plaza covers with production deploy scripts.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-16 16:29:19 -07:00

186 lines
5.8 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.
#!/usr/bin/env bash
# 安装 g2.tkmind.cn + plaza.tkmind.cn 生产 LaunchAgent(登录自启 + 崩溃自动重启)
#
# 架构:
# cloudflared → g2 :8090 (Caddy) → Portal :8081
# cloudflared → plaza :3001 (Next.js) → Portal :8081
#
# 用法:pnpm setup:prod-services
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
LOG_DIR="${HOME}/Library/Logs"
PORTAL_PLIST="${HOME}/Library/LaunchAgents/cn.tkmind.memind-portal.plist"
PLAZA_PLIST="${HOME}/Library/LaunchAgents/cn.tkmind.plaza.plist"
G2_LB_PLIST="${HOME}/Library/LaunchAgents/cn.tkmind.g2-lb.plist"
CF_PLIST="${HOME}/Library/LaunchAgents/com.cloudflare.cloudflared.plist"
PORTAL_RUN="${ROOT}/scripts/run-memind-portal-prod.sh"
PLAZA_RUN="${ROOT}/scripts/run-plaza-prod.sh"
CADDYFILE="${ROOT}/scripts/g2-lb.Caddyfile"
UID_NUM="$(id -u)"
GUI="gui/${UID_NUM}"
PATH_ENV="/opt/homebrew/bin:/opt/homebrew/opt/node@22/bin:/usr/local/bin:/usr/bin:/bin"
chmod +x "${PORTAL_RUN}" "${PLAZA_RUN}" "${ROOT}/scripts/install-g2-lb.sh"
mkdir -p "${LOG_DIR}"
cat >"${PORTAL_PLIST}" <<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>cn.tkmind.memind-portal</string>
<key>ProgramArguments</key>
<array>
<string>${PORTAL_RUN}</string>
</array>
<key>WorkingDirectory</key>
<string>${ROOT}</string>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>${PATH_ENV}</string>
</dict>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>ThrottleInterval</key>
<integer>10</integer>
<key>StandardOutPath</key>
<string>${LOG_DIR}/memind-portal.log</string>
<key>StandardErrorPath</key>
<string>${LOG_DIR}/memind-portal.log</string>
</dict>
</plist>
EOF
cat >"${PLAZA_PLIST}" <<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>cn.tkmind.plaza</string>
<key>ProgramArguments</key>
<array>
<string>${PLAZA_RUN}</string>
</array>
<key>WorkingDirectory</key>
<string>${ROOT}</string>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>${PATH_ENV}</string>
</dict>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>ThrottleInterval</key>
<integer>15</integer>
<key>StandardOutPath</key>
<string>${LOG_DIR}/plaza-prod.log</string>
<key>StandardErrorPath</key>
<string>${LOG_DIR}/plaza-prod.log</string>
</dict>
</plist>
EOF
if [[ ! -f "${G2_LB_PLIST}" ]]; then
cat >"${G2_LB_PLIST}" <<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>cn.tkmind.g2-lb</string>
<key>ProgramArguments</key>
<array>
<string>/opt/homebrew/bin/caddy</string>
<string>run</string>
<string>--config</string>
<string>${CADDYFILE}</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>ThrottleInterval</key>
<integer>10</integer>
<key>StandardOutPath</key>
<string>${LOG_DIR}/g2-lb.log</string>
<key>StandardErrorPath</key>
<string>${LOG_DIR}/g2-lb.log</string>
</dict>
</plist>
EOF
fi
install_agent() {
local label="$1"
local plist="$2"
if launchctl print "${GUI}/${label}" >/dev/null 2>&1; then
launchctl bootout "${GUI}/${label}" 2>/dev/null || true
sleep 1
fi
launchctl bootstrap "${GUI}" "${plist}"
launchctl enable "${GUI}/${label}"
launchctl kickstart -k "${GUI}/${label}"
}
echo "==> 释放端口 8081 / 3001(避免与手动进程冲突)…"
for port in 8081 3001; do
lsof -ti "TCP:${port}" -sTCP:LISTEN 2>/dev/null | xargs kill -9 2>/dev/null || true
done
sleep 1
echo "==> 安装 LaunchAgent…"
install_agent "cn.tkmind.memind-portal" "${PORTAL_PLIST}"
sleep 2
install_agent "cn.tkmind.plaza" "${PLAZA_PLIST}"
install_agent "cn.tkmind.g2-lb" "${G2_LB_PLIST}"
if [[ -f "${CF_PLIST}" ]]; then
install_agent "com.cloudflare.cloudflared" "${CF_PLIST}"
else
echo "⚠ 未找到 ${CF_PLIST},请确认 cloudflared LaunchAgent 已配置" >&2
fi
echo "==> 等待服务就绪…"
for _ in $(seq 1 60); do
portal_ok=0
plaza_ok=0
g2_ok=0
curl -sf "http://127.0.0.1:8081/api/status" >/dev/null 2>&1 && portal_ok=1
curl -sf "http://127.0.0.1:3001/plaza" >/dev/null 2>&1 && plaza_ok=1
curl -sf "http://127.0.0.1:8090/api/status" >/dev/null 2>&1 && g2_ok=1
if [[ "${portal_ok}" -eq 1 && "${plaza_ok}" -eq 1 && "${g2_ok}" -eq 1 ]]; then
break
fi
sleep 2
done
echo ""
echo "=== 生产服务状态 ==="
launchctl list | grep -E "cn.tkmind\.(memind-portal|plaza|g2-lb)|com.cloudflare.cloudflared" || true
curl -s -o /dev/null -w "Portal :8081 → %{http_code}\n" "http://127.0.0.1:8081/api/status" || true
curl -s -o /dev/null -w "g2 LB :8090 → %{http_code}\n" "http://127.0.0.1:8090/api/status" || true
curl -s -o /dev/null -w "Plaza :3001 → %{http_code}\n" "http://127.0.0.1:3001/plaza" || true
curl -s -o /dev/null -w "外网 g2 → %{http_code}\n" "https://g2.tkmind.cn/api/status" || true
curl -s -o /dev/null -w "外网 plaza → %{http_code}\n" "https://plaza.tkmind.cn/plaza" || true
echo ""
echo "✅ 生产 LaunchAgent 已安装(登录自启 + KeepAlive"
echo " Portal cn.tkmind.memind-portal → ~/Library/Logs/memind-portal.log"
echo " Plaza cn.tkmind.plaza → ~/Library/Logs/plaza-prod.log"
echo " g2 LB cn.tkmind.g2-lb → ~/Library/Logs/g2-lb.log"
echo " 隧道 com.cloudflare.cloudflared"
echo ""
echo "管理命令:"
echo " launchctl kickstart -k ${GUI}/cn.tkmind.memind-portal"
echo " launchctl kickstart -k ${GUI}/cn.tkmind.plaza"
echo " tail -f ~/Library/Logs/memind-portal.log ~/Library/Logs/plaza-prod.log"