Files
momentry_core/docs/SERVICE_ADDITION_GUIDE.md
accusys 383201cacd feat: Initial v0.9 release with API Key authentication
## v0.9.20260325_144654

### Features
- API Key Authentication System
- Job Worker System
- V2 Backup Versioning

### Bug Fixes
- get_processor_results_by_job column mapping

Co-authored-by: OpenCode
2026-03-25 14:53:41 +08:00

18 KiB
Raw Blame History

Momentry 服務添加規範 v2.1

項目 內容
建立者 Warren
建立時間 2026-03-16
更新時間 2026-03-24
文件版本 V2.1

版本歷史

版本 日期 目的 操作人 工具/模型
V1.0 2026-03-16 創建文件 Warren OpenCode / MiniMax M2.5
V2.1 2026-03-24 更新 launchctl 命令,使用 bootstrap OpenCode OpenCode / big-pickle

一、概述

本文檔定義在 Momentry 系統中添加新服務的標準流程和規範。

重要原則

  • 使用 launchctl 管理服務,勿使用 brew services
  • 所有服務使用 com.momentry.* 作為 plist Label
  • 數據存放於 /Users/accusys/momentry/ 目錄
  • 每個服務需提供完整的監控腳本
  • 所有服務 Plist 存放於 /Library/LaunchDaemons/
  • 所有服務以 accusys 用戶運行,確保 accusys 可以管理

二、服務運行方式

2.1 運行分類

類型 說明 示例
開機自動運行 電腦開機後立即自動啟動 PostgreSQL, Redis, n8n, Caddy 等核心服務
登入時運行 用戶登入後才啟動 開發工具、臨時服務

當前所有服務:均為開機自動運行

2.2 Plist 存放位置

所有 Momentry 服務統一存放於:

/Library/LaunchDaemons/com.momentry.{service_name}.plist

三、服務命名規範

3.1 Plist 文件命名

com.momentry.{service_name}.plist

示例:

  • com.momentry.redis.plist
  • com.momentry.n8n.main.plist
  • com.momentry.rustdesk.hbbs.plist

3.2 目錄命名

服務相關目錄統一放置於:

/Users/accusys/momentry/
├── var/{service_name}/        # 服務數據
├── etc/{service_name}/       # 服務配置
├── log/{service_name}.log   # 服務日誌 (stdout)
└── log/{service_name}.error.log # 錯誤日誌 (stderr)

四、Plist 文件模板

4.1 標準服務模板

<?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>com.momentry.{service_name}</string>
    
    <key>UserName</key>
    <string>accusys</string>
    
    <key>WorkingDirectory</key>
    <string>/Users/accusys/momentry/var/{service_name}</string>
    
    <key>ProgramArguments</key>
    <array>
        <string>/path/to/executable</string>
        <string>--arg1</string>
        <string>value1</string>
    </array>
    
    <key>EnvironmentVariables</key>
    <dict>
        <key>PATH</key>
        <string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
        <!-- 其他環境變數 -->
    </dict>
    
    <key>RunAtLoad</key>
    <true/>
    
    <key>KeepAlive</key>
    <true/>
    
    <key>StandardOutPath</key>
    <string>/Users/accusys/momentry/log/{service_name}.log</string>
    
    <key>StandardErrorPath</key>
    <string>/Users/accusys/momentry/log/{service_name}.error.log</string>
</dict>
</plist>

4.2 日誌文件規範

每個服務必須創建兩個日誌文件:

文件 說明 路徑
StandardOutPath 標準輸出日誌 /Users/accusys/momentry/log/{service_name}.log
StandardErrorPath 錯誤輸出日誌 /Users/accusys/momentry/log/{service_name}.error.log

創建日誌文件

touch /Users/accusys/momentry/log/{service_name}.log
touch /Users/accusys/momentry/log/{service_name}.error.log
chmod 644 /Users/accusys/momentry/log/{service_name}.log
chmod 644 /Users/accusys/momentry/log/{service_name}.error.log

五、添加服務步驟

步驟 1創建目錄結構

# 創建服務目錄
mkdir -p /Users/accusys/momentry/var/{service_name}
mkdir -p /Users/accusys/momentry/etc/{service_name}

# 創建日誌文件
touch /Users/accusys/momentry/log/{service_name}.log
touch /Users/accusys/momentry/log/{service_name}.error.log

步驟 2創建 Plist 文件

# 複製模板並編輯
cp /Users/accusys/momentry_core_0.1/momentry_runtime/plist/template.service.plist \
   /Users/accusys/momentry_core_0.1/momentry_runtime/plist/com.momentry.{service_name}.plist

# 編輯 plist 文件
vim /Users/accusys/momentry_core_0.1/momentry_runtime/plist/com.momentry.{service_name}.plist

步驟 3複製到系統 LaunchDaemons

# 複製到 /Library/LaunchDaemons/
sudo cp /Users/accusys/momentry_core_0.1/momentry_runtime/plist/com.momentry.{service_name}.plist \
        /Library/LaunchDaemons/

步驟 4載入服務

# 載入服務
sudo launchctl load /Library/LaunchDaemons/com.momentry.{service_name}.plist

# 驗證服務狀態
launchctl list | grep momentry

步驟 5添加監控

monitor/config/monitor_config.yaml 中添加服務配置:

service:
  services:
    - name: "{service_name}"
      type: "http"  # 或 "process", "tcp"
      port: {port_number}
      host: "localhost"
      check_url: "http://localhost:{port}/health"
      timeout: 5
      enabled: true

步驟 6添加文檔

docs/INSTALL_{SERVICE_NAME}.md 中記錄:

  • 安裝步驟
  • 配置說明
  • 健康檢查命令
  • 故障排除

六、服務分類

按功能分類

類別 服務
資料庫 PostgreSQL, Redis, MariaDB, MongoDB
應用 n8n, Gitea, SFTPGo
網頁 Caddy, PHP-FPM
AI/ML Ollama, Qdrant
遠程 RustDesk

按運行方式分類

運行方式 數量 服務
開機自動運行 15 PostgreSQL, Redis, n8n, Caddy, Gitea, SFTPGo, Ollama, Qdrant, MariaDB, PHP-FPM, RustDesk, MongoDB, Agent
登入時運行 0 (暫無)

七、監控要求

每個服務必須提供:

7.1 健康檢查

monitor/service/health_check.sh 中添加檢查函數:

check_{service_name}() {
    local start=$(date +%s%N)
    if nc -z localhost {port} > /dev/null 2>&1; then
        local end=$(date +%s%N)
        local ms=$(( (end - start) / 1000000 ))
        echo -e "${GREEN}${NC} {service_name} ({port}) - ${ms}ms"
        record_service "{service_name}" "up" "$ms" ""
        return 0
    else
        echo -e "${RED}${NC} {service_name} ({port}) - Down"
        record_service "{service_name}" "down" "0" "Connection failed"
        return 1
    fi
}

7.2 數據庫記錄

-- 添加服務監控記錄函數
record_service() {
    local service=$1
    local status=$2
    local response_time=$3
    local error_msg=$4
    
    psql -U accusys -h localhost -d momentry << EOF
INSERT INTO monitor_services (service_name, service_type, status, response_time_ms, error_message, checked_at)
VALUES ('$service', 'service', '$status', $response_time, '$error_msg', NOW());
EOF
}

八、服務管理命令

8.1 基本操作

# 啟動服務 (使用 launchctl bootstrap)
sudo launchctl bootstrap system /Library/LaunchDaemons/com.momentry.{service}.plist

# 停止服務 (使用 launchctl bootout)
sudo launchctl bootout system/com.momentry.{service}.plist

# 重新載入服務
sudo launchctl bootout system/com.momentry.{service}.plist
sudo launchctl bootstrap system /Library/LaunchDaemons/com.momentry.{service}.plist

# 查看服務狀態
launchctl list | grep com.momentry

# 查看特定服務狀態
launchctl list | grep com.momentry.{service}

# 查看服務日誌
tail -f /Users/accusys/momentry/log/{service}.log
tail -f /Users/accusys/momentry/log/{service}.error.log

8.2 批量管理

# 啟動所有 Momentry 服務
for plist in /Library/LaunchDaemons/com.momentry.*.plist; do
    sudo launchctl bootstrap system "$plist"
done

# 停止所有 Momentry 服務
for svc in $(launchctl list | grep com.momentry | awk '{print $3}'); do
    sudo launchctl bootout system/$svc 2>/dev/null
done

# 查看所有 Momentry 服務狀態
launchctl list | grep com.momentry

8.2 故障排除

# 檢查服務是否運行
pgrep -f "{service_process_name}"

# 檢查端口是否監聽
lsof -i :{port}

# 檢查錯誤日誌
tail -100 /Users/accusys/momentry/log/{service}.error.log

九、服務備份作業

9.1 備份內容

每個服務需要備份的內容:

類別 路徑 說明
數據 /Users/accusys/momentry/var/{service}/ 服務運行數據
配置 /Users/accusys/momentry/etc/{service}/ 服務配置文件
Plist /Library/LaunchDaemons/com.momentry.{service}.plist 啟動配置
日誌 /Users/accusys/momentry/log/{service}.log 運行日誌

9.2 備份命名規範

格式: {service}_{type}_{YYYYMMDD}_{HHMMSS}[_{suffix}].{ext}

組成部分:

位置 說明 範例
{service} 服務名稱 (小寫) postgresql, redis, n8n
{type} 備份類型 full, db, cfg, data
{YYYYMMDD} 備份日期 20260315
{HHMMSS} 備份時間 (24小時制) 030000
{suffix} 可選標記 incremental, verified
{ext} 檔案擴展名 sql.gz, tar.gz, rdb, zip

類型說明:

類型 說明 包含內容
full 完整備份 數據 + 配置 + 日誌
db 數據庫備份 資料庫導出 (sql, rdb)
cfg 配置備份 配置文件
data 數據備份 var 目錄

範例:

postgresql_db_20260315_030000.sql.gz    # PostgreSQL 完整資料庫 (壓縮)
redis_rdb_20260315_030000.rdb          # Redis RDB 快照
n8n_full_20260315_030000.tar.gz        # n8n 完整備份
mariadb_db_wordpress_20260315_030000.sql.gz  # MariaDB WP 資料庫
gitea_full_20260315_030000.zip         # Gitea 完整備份
qdrant_snapshot_20260315_030000.tar.gz # Qdrant 向量庫
ollama_cfg_20260315_030000.tar.gz      # Ollama 配置
caddy_cfg_20260315_030000.tar.gz       # Caddy 配置

可信斷點標記:

  • 檔名本身即為可信時間點
  • 還原時直接使用檔名中的時間戳
  • 建議配合 backup_registry 資料庫記錄完整元數據

校驗和命名:

postgresql_db_20260315_030000.sql.gz.sha256

9.3 備份腳本

#!/bin/bash
# 標準化備份腳本範本
# 遵循命名規範: {service}_{type}_{YYYYMMDD}_{HHMMSS}.{ext}

set -e

SERVICE_NAME="{service_name}"
BACKUP_TYPE="{type}"  # full, db, cfg, data
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/Users/accusys/momentry/backup/${SERVICE_NAME}"

mkdir -p "$BACKUP_DIR"

# 根據類型執行備份
case "$BACKUP_TYPE" in
    full)
        echo "[$TIMESTAMP] 執行 $SERVICE_NAME 完整備份..."
        tar -czf "$BACKUP_DIR/${SERVICE_NAME}_full_${TIMESTAMP}.tar.gz" \
            /Users/accusys/momentry/var/${SERVICE_NAME}/ \
            /Users/accusys/momentry/etc/${SERVICE_NAME}/ 2>/dev/null
        ;;
    db)
        echo "[$TIMESTAMP] 執行 $SERVICE_NAME 資料庫備份..."
        if [ "$SERVICE_NAME" = "postgresql" ]; then
            pg_dump -U accusys ${SERVICE_NAME} | gzip > \
                "$BACKUP_DIR/${SERVICE_NAME}_db_${TIMESTAMP}.sql.gz"
        elif [ "$SERVICE_NAME" = "mariadb" ]; then
            mysqldump -u root -p --all-databases | gzip > \
                "$BACKUP_DIR/${SERVICE_NAME}_db_${TIMESTAMP}.sql.gz"
        elif [ "$SERVICE_NAME" = "redis" ]; then
            redis-cli -a accusys SAVE
            cp /opt/homebrew/var/db/redis/dump.rdb \
                "$BACKUP_DIR/${SERVICE_NAME}_rdb_${TIMESTAMP}.rdb"
        fi
        ;;
    cfg)
        echo "[$TIMESTAMP] 執行 $SERVICE_NAME 配置備份..."
        tar -czf "$BACKUP_DIR/${SERVICE_NAME}_cfg_${TIMESTAMP}.tar.gz" \
            /Users/accusys/momentry/etc/${SERVICE_NAME}/ 2>/dev/null
        ;;
    data)
        echo "[$TIMESTAMP] 執行 $SERVICE_NAME 數據備份..."
        tar -czf "$BACKUP_DIR/${SERVICE_NAME}_data_${TIMESTAMP}.tar.gz" \
            /Users/accusys/momentry/var/${SERVICE_NAME}/ 2>/dev/null
        ;;
esac

# 生成校驗和
if [ -f "$BACKUP_DIR/${SERVICE_NAME}_${BACKUP_TYPE}_${TIMESTAMP}"* ]; then
    sha256sum "$BACKUP_DIR/${SERVICE_NAME}_${BACKUP_TYPE}_${TIMESTAMP}"* > \
        "$BACKUP_DIR/${SERVICE_NAME}_${BACKUP_TYPE}_${TIMESTAMP}.sha256"
fi

# 清理舊備份 (保留 30 天)
find "$BACKUP_DIR" -name "*_${TIMESTAMP%%_*}_*.tar.gz" -mtime +30 -delete 2>/dev/null
find "$BACKUP_DIR" -name "*_${TIMESTAMP%%_*}_*.sql.gz" -mtime +30 -delete 2>/dev/null
find "$BACKUP_DIR" -name "*_${TIMESTAMP%%_*}_*.rdb" -mtime +30 -delete 2>/dev/null
find "$BACKUP_DIR" -name "*.sha256" -mtime +30 -delete 2>/dev/null

echo "備份完成: ${SERVICE_NAME}_${BACKUP_TYPE}_${TIMESTAMP}"

9.4 備份排程

建議使用 cron 進行自動備份:

# 編輯 crontab
crontab -e

# 添加備份任務 (每天凌晨 3 點)
0 3 * * * /Users/accusys/momentry/scripts/backup_{service}.sh >> /Users/accusys/momentry/log/backup.log 2>&1

# 每週日凌晨 3 點執行完整備份
0 3 * * 0 /Users/accusys/momentry/scripts/backup_{service}.sh full >> /Users/accusys/momentry/log/backup.log 2>&1

9.5 備份驗證

# 查看備份列表 (按時間排序)
ls -lt /Users/accusys/momentry/backup/{service}/

# 驗證備份完整性
# 1. 檢查校驗和
sha256sum -c /Users/accusys/momentry/backup/{service}/*.sha256

# 2. 驗證 tar 壓縮
tar -tzf /Users/accusys/momentry/backup/{service}/{service}_full_20260315_030000.tar.gz

# 3. 驗證 SQL 備份
zcat /Users/accusys/momentry/backup/{service}/{service}_db_20260315_030000.sql.gz | head -5

# 驗證備份完整性
tar -tzf /Users/accusys/momentry/backup/{service}/{service}_var_20260315.tar.gz

十、服務完整刪除作業

10.1 刪除前確認

警告:此操作不可逆,請確保已完成備份!

  • 確認服務已停止運行
  • 確認數據已備份
  • 確認無其他服務依賴此服務

10.2 刪除步驟

步驟 1停止服務

# 停止服務
sudo launchctl unload /Library/LaunchDaemons/com.momentry.{service}.plist

# 驗證服務已停止
launchctl list | grep momentry.{service}

步驟 2刪除 Plist

# 刪除系統 Plist
sudo rm /Library/LaunchDaemons/com.momentry.{service}.plist

# 刪除專案 Plist
rm /Users/accusys/momentry_core_0.1/momentry_runtime/plist/com.momentry.{service}.plist

步驟 3刪除數據和配置

# 刪除數據目錄
sudo rm -rf /Users/accusys/momentry/var/{service}/

# 刪除配置目錄
sudo rm -rf /Users/accusys/momentry/etc/{service}/

# 刪除日誌
rm -f /Users/accusys/momentry/log/{service}.log
rm -f /Users/accusys/momentry/log/{service}.error.log

步驟 4清理監控配置

# 從監控配置中移除服務
vim /Users/accusys/momentry_core_0.1/monitor/config/monitor_config.yaml
# 刪除該服務的監控配置

# 從監控腳本中移除
vim /Users/accusys/momentry_core_0.1/monitor/service/health_check.sh
# 移除該服務的檢查函數

步驟 5清理監控數據可選

# 保留歷史數據還是刪除?
# 刪除監控數據
psql -U accusys -h localhost -d momentry -c "
DELETE FROM monitor_services WHERE service_name = '{service}';
"

10.3 驗證刪除

# 確認服務已停止
launchctl list | grep momentry.{service}

# 確認目錄已刪除
ls /Users/accusys/momentry/var/{service}/ 2>/dev/null || echo "已刪除"

# 確認 Plist 已刪除
ls /Library/LaunchDaemons/com.momentry.{service}.plist 2>/dev/null || echo "已刪除"

10.4 完整刪除腳本

#!/bin/bash
SERVICE_NAME="{service_name}"

echo "========== 服務完整刪除 =========="
echo "服務: $SERVICE_NAME"
echo "警告:此操作不可逆!"
read -p "確認繼續 (yes/no): " confirm

if [ "$confirm" != "yes" ]; then
    echo "取消刪除"
    exit 0
fi

# 停止服務
echo "[1/6] 停止服務..."
sudo launchctl unload /Library/LaunchDaemons/com.momentry.${SERVICE_NAME}.plist 2>/dev/null

# 刪除 Plist
echo "[2/6] 刪除 Plist..."
sudo rm -f /Library/LaunchDaemons/com.momentry.${SERVICE_NAME}.plist
rm -f /Users/accusys/momentry_core_0.1/momentry_runtime/plist/com.momentry.${SERVICE_NAME}.plist

# 刪除數據
echo "[3/6] 刪除數據..."
sudo rm -rf /Users/accusys/momentry/var/${SERVICE_NAME}/

# 刪除配置
echo "[4/6] 刪除配置..."
sudo rm -rf /Users/accusys/momentry/etc/${SERVICE_NAME}/

# 刪除日誌
echo "[5/6] 刪除日誌..."
rm -f /Users/accusys/momentry/log/${SERVICE_NAME}.log
rm -f /Users/accusys/momentry/log/${SERVICE_NAME}.error.log

# 清理監控數據
echo "[6/6] 清理監控數據..."
psql -U accusys -h localhost -d momentry -c "
    DELETE FROM monitor_services WHERE service_name = '${SERVICE_NAME}';
" 2>/dev/null

echo "========== 刪除完成 =========="

十一、檢查清單

添加新服務時,請確認以下項目:

  • 創建服務目錄 (var/, etc/)
  • 配置日誌文件 (.log + .error.log)
  • 創建 plist 文件UserName 設為 accusys
  • 複製到 /Library/LaunchDaemons/
  • 使用 launchctl 載入服務
  • 驗證服務運行
  • 添加監控配置
  • 測試監控腳本
  • 創建安裝文檔
  • 更新 SERVICES.md 服務清單
  • 更新 MOMENTRY_INTEGRATION_GUIDE.md

十二、模板文件

Plist 模板位置

/Users/accusys/momentry_core_0.1/momentry_runtime/plist/
├── template.service.plist      # 服務模板
├── com.momentry.redis.plist  # 服務示例
└── com.momentry.n8n.main.plist  # 複雜服務示例

創建模板命令

# 創建服務模板
cat > /Users/accusys/momentry_core_0.1/momentry_runtime/plist/template.service.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>com.momentry.SERVICE_NAME</string>
    <key>UserName</key>
    <string>accusys</string>
    <key>WorkingDirectory</key>
    <string>/Users/accusys/momentry/var/SERVICE_NAME</string>
    <key>ProgramArguments</key>
    <array>
        <string>/path/to/executable</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <true/>
    <key>StandardOutPath</key>
    <string>/Users/accusys/momentry/log/SERVICE_NAME.log</string>
    <key>StandardErrorPath</key>
    <string>/Users/accusys/momentry/log/SERVICE_NAME.error.log</string>
</dict>
</plist>
EOF

十一、版本歷史

版本 日期 內容
1.0 2026-03-15 初始版本
2.0 2026-03-15 統一 Plist 位置、移除 root/用戶區分、加入運行方式分類
2.1 2026-03-15 新增服務備份作業、服務完整刪除作業
2.1 2026-03-24 更新 launchctl 命令,使用 bootstrap/bootout 替代 load/unload