631 lines
17 KiB
Bash
Executable File
631 lines
17 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -e
|
|
|
|
# Sanguo Mail 系统管理脚本
|
|
# 支持启动、停止、配置、健康检查等操作
|
|
|
|
# 颜色定义
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m'
|
|
|
|
# 日志函数
|
|
log() {
|
|
local level="$1"
|
|
local message="$2"
|
|
local color
|
|
|
|
case "$level" in
|
|
"error") color="$RED" ;;
|
|
"warning") color="$YELLOW" ;;
|
|
"info") color="$BLUE" ;;
|
|
"success") color="$GREEN" ;;
|
|
*) color="$NC" ;;
|
|
esac
|
|
|
|
local timestamp=$(date +"%Y-%m-%d %H:%M:%S")
|
|
local level_uppercase=$(echo "$level" | tr '[:lower:]' '[:upper:]')
|
|
|
|
echo -e "${color}[${timestamp}] [${level_uppercase}] ${message}${NC}"
|
|
}
|
|
|
|
# 配置常量
|
|
PROJECT_ROOT="/Users/chufeng/.openclaw/sanguo_projects/sanguo_quant_live"
|
|
MAIL_PROJECT_DIR="$PROJECT_ROOT/mail"
|
|
SCRIPTS_DIR="$PROJECT_ROOT/scripts"
|
|
|
|
# 检查节点是否在线
|
|
check_node() {
|
|
log "info" "检查节点连接..."
|
|
openclaw nodes list >/dev/null 2>&1
|
|
if [ $? -eq 0 ]; then
|
|
log "success" "节点连接正常"
|
|
else
|
|
log "error" "节点连接失败,请确保 OpenClaw 服务正在运行"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# 获取服务配置
|
|
get_config() {
|
|
local config_file="$SCRIPTS_DIR/config.json"
|
|
if [ -f "$config_file" ]; then
|
|
cat "$config_file"
|
|
else
|
|
cat << 'EOF'
|
|
{
|
|
"server": {
|
|
"port": 18888,
|
|
"host": "0.0.0.0",
|
|
"timeout": 30000
|
|
},
|
|
"api": {
|
|
"baseUrl": "http://127.0.0.1:18888",
|
|
"timeout": 10000
|
|
},
|
|
"mailSystem": {
|
|
"rootPath": "/Users/chufeng/.openclaw/sanguo_projects/sanguo_quant_live",
|
|
"teamName": "sanguo-quant"
|
|
},
|
|
"autoCheck": {
|
|
"interval": 60,
|
|
"enabled": true
|
|
}
|
|
}
|
|
EOF
|
|
fi
|
|
}
|
|
|
|
# 设置配置
|
|
set_config() {
|
|
local config_file="$SCRIPTS_DIR/config.json"
|
|
local config=$(get_config)
|
|
local key="$1"
|
|
local value="$2"
|
|
|
|
if [ -z "$key" ] || [ -z "$value" ]; then
|
|
log "error" "设置配置需要提供配置项和值"
|
|
log "usage" "使用方法: $0 config set <key> <value>"
|
|
exit 1
|
|
fi
|
|
|
|
log "info" "正在设置 $key = $value"
|
|
|
|
if [ -f "$config_file" ]; then
|
|
jq ".${key} = \"${value}\"" "$config_file" > "${config_file}.tmp" && mv "${config_file}.tmp" "$config_file"
|
|
else
|
|
local default_config=$(get_config | jq ".${key} = \"${value}\"")
|
|
echo "$default_config" > "$config_file"
|
|
fi
|
|
|
|
log "success" "配置已更新"
|
|
log "info" "重启服务使配置生效"
|
|
}
|
|
|
|
# 启动服务
|
|
start_server() {
|
|
log "info" "正在启动 Sanguo Mail 服务..."
|
|
|
|
# 检查项目是否已安装
|
|
if [ ! -d "$PROJECT_ROOT" ]; then
|
|
log "error" "项目根目录不存在: $PROJECT_ROOT"
|
|
exit 1
|
|
fi
|
|
|
|
# 检查依赖
|
|
if [ ! -d "$PROJECT_ROOT/node_modules" ]; then
|
|
log "info" "依赖未安装,正在安装..."
|
|
install_deps
|
|
fi
|
|
|
|
# 检查邮件系统初始化
|
|
if [ ! -d "$PROJECT_ROOT/mail/sanguo-quant/inboxes" ] || [ ! -f "$PROJECT_ROOT/mail/sanguo-quant/team.json" ]; then
|
|
log "info" "邮件系统未初始化,正在初始化..."
|
|
init_system
|
|
fi
|
|
|
|
# 启动服务
|
|
log "info" "正在启动邮件服务进程..."
|
|
node "$SCRIPTS_DIR/server.js" > "$SCRIPTS_DIR/mail-service.log" 2>&1 &
|
|
local PID=$!
|
|
|
|
# 保存 PID
|
|
echo "$PID" > "$SCRIPTS_DIR/mail.pid"
|
|
|
|
# 等待服务启动
|
|
log "info" "等待服务启动..."
|
|
sleep 2
|
|
|
|
# 检查服务是否正在运行
|
|
if ps -p "$PID" > /dev/null 2>&1; then
|
|
log "success" "服务启动成功,PID: $PID"
|
|
log "success" "服务日志: $SCRIPTS_DIR/mail-service.log"
|
|
log "success" "访问地址: http://127.0.0.1:18888"
|
|
else
|
|
log "error" "服务启动失败"
|
|
if [ -f "$SCRIPTS_DIR/mail-service.log" ]; then
|
|
log "error" "错误日志: $(head -20 "$SCRIPTS_DIR/mail-service.log")"
|
|
fi
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# 停止服务
|
|
stop_server() {
|
|
local PID_FILE="$SCRIPTS_DIR/mail.pid"
|
|
|
|
if [ -f "$PID_FILE" ]; then
|
|
local PID=$(cat "$PID_FILE")
|
|
|
|
log "info" "正在停止服务,PID: $PID"
|
|
|
|
if ps -p "$PID" > /dev/null 2>&1; then
|
|
kill "$PID"
|
|
log "success" "服务已停止"
|
|
else
|
|
log "warning" "服务已停止 (PID $PID 不存在)"
|
|
fi
|
|
|
|
rm -f "$PID_FILE"
|
|
else
|
|
log "warning" "服务 PID 文件不存在,可能服务未运行"
|
|
|
|
# 尝试查找并停止进程
|
|
local PROCESS=$(ps aux | grep "node $SCRIPTS_DIR/server.js" | grep -v grep | awk '{print $2}')
|
|
if [ -n "$PROCESS" ]; then
|
|
log "info" "找到服务进程,PID: $PROCESS"
|
|
kill "$PROCESS"
|
|
log "success" "服务已停止"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# 查看服务状态
|
|
status() {
|
|
log "info" "=== 系统状态 ==="
|
|
|
|
# 检查项目根目录
|
|
if [ -d "$PROJECT_ROOT" ]; then
|
|
log "success" "项目根目录存在: $PROJECT_ROOT"
|
|
else
|
|
log "error" "项目根目录不存在: $PROJECT_ROOT"
|
|
fi
|
|
|
|
# 检查邮件系统目录
|
|
MAIL_DIR="$PROJECT_ROOT/mail/sanguo-quant"
|
|
|
|
if [ -d "$MAIL_DIR" ]; then
|
|
log "success" "邮件系统目录存在: $MAIL_DIR"
|
|
else
|
|
log "warning" "邮件系统目录不存在: $MAIL_DIR"
|
|
fi
|
|
|
|
# 检查收件箱
|
|
if [ -d "$MAIL_DIR/inboxes" ]; then
|
|
log "success" "收件箱目录存在: $MAIL_DIR/inboxes"
|
|
|
|
# 统计收件箱文件数量
|
|
local inbox_count=$(ls -1 "$MAIL_DIR/inboxes"/*.json 2>/dev/null | wc -l)
|
|
log "success" "收件箱数量: $inbox_count"
|
|
else
|
|
log "warning" "收件箱目录不存在: $MAIL_DIR/inboxes"
|
|
fi
|
|
|
|
# 检查成员配置
|
|
TEAM_CONFIG="$MAIL_DIR/team.json"
|
|
|
|
if [ -f "$TEAM_CONFIG" ]; then
|
|
log "success" "团队配置文件存在: $TEAM_CONFIG"
|
|
|
|
# 统计团队成员数量
|
|
local member_count=$(jq '.members | length' "$TEAM_CONFIG" 2>/dev/null || echo 0)
|
|
log "success" "团队成员数量: $member_count"
|
|
else
|
|
log "warning" "团队配置文件不存在: $TEAM_CONFIG"
|
|
fi
|
|
|
|
# 检查服务状态
|
|
if [ -f "$SCRIPTS_DIR/mail.pid" ]; then
|
|
local PID=$(cat "$SCRIPTS_DIR/mail.pid")
|
|
|
|
if ps -p "$PID" > /dev/null 2>&1; then
|
|
log "success" "服务正在运行,PID: $PID"
|
|
else
|
|
log "warning" "PID 文件存在,但进程未运行"
|
|
rm -f "$SCRIPTS_DIR/mail.pid"
|
|
fi
|
|
else
|
|
log "warning" "服务未运行"
|
|
fi
|
|
}
|
|
|
|
# 查看日志
|
|
logs() {
|
|
local LOG_FILE="$SCRIPTS_DIR/mail-service.log"
|
|
|
|
if [ ! -f "$LOG_FILE" ]; then
|
|
log "error" "日志文件不存在: $LOG_FILE"
|
|
exit 1
|
|
fi
|
|
|
|
if [ -z "$2" ]; then
|
|
tail -f "$LOG_FILE"
|
|
else
|
|
log "info" "显示最后 $2 行日志"
|
|
tail -"$2" "$LOG_FILE"
|
|
fi
|
|
}
|
|
|
|
# 健康检查
|
|
check_health() {
|
|
log "info" "正在进行健康检查..."
|
|
|
|
local ERROR_COUNT=0
|
|
local WARNING_COUNT=0
|
|
|
|
# 检查依赖
|
|
if [ ! -d "$PROJECT_ROOT/node_modules" ]; then
|
|
log "error" "依赖未安装"
|
|
ERROR_COUNT=$((ERROR_COUNT + 1))
|
|
else
|
|
log "success" "依赖已安装"
|
|
fi
|
|
|
|
# 检查邮件系统初始化
|
|
if [ ! -d "$PROJECT_ROOT/mail/sanguo-quant/inboxes" ] || [ ! -f "$PROJECT_ROOT/mail/sanguo-quant/team.json" ]; then
|
|
log "warning" "邮件系统未初始化"
|
|
WARNING_COUNT=$((WARNING_COUNT + 1))
|
|
else
|
|
log "success" "邮件系统已初始化"
|
|
fi
|
|
|
|
# 检查服务状态
|
|
if [ -f "$SCRIPTS_DIR/mail.pid" ]; then
|
|
local PID=$(cat "$SCRIPTS_DIR/mail.pid")
|
|
|
|
if ps -p "$PID" > /dev/null 2>&1; then
|
|
log "success" "服务正在运行,PID: $PID"
|
|
else
|
|
log "error" "PID 文件存在,但进程未运行"
|
|
ERROR_COUNT=$((ERROR_COUNT + 1))
|
|
fi
|
|
else
|
|
log "warning" "服务未运行"
|
|
WARNING_COUNT=$((WARNING_COUNT + 1))
|
|
fi
|
|
|
|
log "info" "=== 健康检查结果 ==="
|
|
log "success" "成功项: $((4 - ERROR_COUNT - WARNING_COUNT))"
|
|
|
|
if [ "$WARNING_COUNT" -gt 0 ]; then
|
|
log "warning" "警告项: $WARNING_COUNT"
|
|
fi
|
|
|
|
if [ "$ERROR_COUNT" -gt 0 ]; then
|
|
log "error" "错误项: $ERROR_COUNT"
|
|
exit 1
|
|
fi
|
|
|
|
log "success" "系统健康状况良好"
|
|
}
|
|
|
|
# 检查安全配置
|
|
check_security() {
|
|
if [ ! -f "/Users/chufeng/.openclaw/config/security.json" ]; then
|
|
log "warning" "安全配置文件未找到,使用默认策略"
|
|
return 0
|
|
fi
|
|
|
|
local security_level=$(jq -r '.security_level' "/Users/chufeng/.openclaw/config/security.json")
|
|
log "info" "当前安全级别: $security_level"
|
|
|
|
if [ "$security_level" != "full" ]; then
|
|
log "warning" "安全级别不是 full,可能会影响邮件系统功能"
|
|
fi
|
|
}
|
|
|
|
# 列出配置
|
|
list_config() {
|
|
log "info" "=== 当前配置 ==="
|
|
log "info" "项目根目录: $PROJECT_ROOT"
|
|
log "info" "邮件系统目录: $MAIL_PROJECT_DIR"
|
|
log "info" "脚本目录: $SCRIPTS_DIR"
|
|
|
|
# 显示配置文件内容
|
|
if [ -f "$SCRIPTS_DIR/config.json" ]; then
|
|
log "info" "配置文件内容:"
|
|
cat "$SCRIPTS_DIR/config.json"
|
|
else
|
|
log "warning" "配置文件未找到,使用默认值"
|
|
fi
|
|
}
|
|
|
|
# 启动邮件检查服务
|
|
watch_mail() {
|
|
log "info" "正在启动邮件检查服务..."
|
|
|
|
local interval=${2:-60}
|
|
|
|
log "info" "邮件检查间隔: $interval 秒"
|
|
|
|
# 创建检查脚本
|
|
cat > "$SCRIPTS_DIR/auto-check-mail.js" << 'EOF'
|
|
import { SanguoMailbox } from '/Users/chufeng/.openclaw/sanguo_projects/sanguo_mail/dist/index.js';
|
|
import { join } from 'path';
|
|
|
|
const CONFIG = {
|
|
rootPath: '/Users/chufeng/.openclaw/sanguo_projects/sanguo_quant_live',
|
|
teamName: 'sanguo-quant'
|
|
};
|
|
|
|
async function checkMail() {
|
|
const mailbox = new SanguoMailbox(CONFIG);
|
|
await mailbox.initTeam();
|
|
|
|
const unreadMessages = await mailbox.listUnread('jiangwei');
|
|
if (unreadMessages.length > 0) {
|
|
console.log(`发现 ${unreadMessages.length} 条未读消息`);
|
|
unreadMessages.forEach((msg, index) => {
|
|
console.log(`[${index + 1}] 来自 ${msg.from} - ${msg.text.substring(0, 50)}${msg.text.length > 50 ? '...' : ''}`);
|
|
});
|
|
|
|
await Promise.all(unreadMessages.map((msg, index) =>
|
|
mailbox.markAsReadByIndex('jiangwei', index)
|
|
));
|
|
console.log('所有未读消息已标记为已读');
|
|
}
|
|
}
|
|
|
|
async function startAutoCheck(intervalSeconds) {
|
|
console.log(`邮件检查服务已启动,检查间隔: ${intervalSeconds} 秒`);
|
|
|
|
checkMail();
|
|
|
|
setInterval(checkMail, intervalSeconds * 1000);
|
|
}
|
|
|
|
startAutoCheck(parseInt(process.argv[2]) || 60);
|
|
EOF
|
|
|
|
chmod +x "$SCRIPTS_DIR/auto-check-mail.js"
|
|
|
|
# 启动服务
|
|
log "info" "正在启动邮件检查服务..."
|
|
|
|
node "$SCRIPTS_DIR/auto-check-mail.js" "$interval" > "$SCRIPTS_DIR/auto-check-mail.log" 2>&1 &
|
|
local PID=$!
|
|
|
|
log "success" "邮件检查服务启动成功,PID: $PID"
|
|
log "success" "检查日志: $SCRIPTS_DIR/auto-check-mail.log"
|
|
log "success" "检查间隔: $interval 秒"
|
|
}
|
|
|
|
# 停止邮件检查服务
|
|
stop_watch_mail() {
|
|
local WATCH_PID=$(ps aux | grep "node $SCRIPTS_DIR/auto-check-mail.js" | grep -v grep | awk '{print $2}')
|
|
|
|
if [ -n "$WATCH_PID" ]; then
|
|
log "info" "正在停止邮件检查服务,PID: $WATCH_PID"
|
|
kill "$WATCH_PID"
|
|
log "success" "邮件检查服务已停止"
|
|
else
|
|
log "warning" "邮件检查服务未运行"
|
|
fi
|
|
}
|
|
|
|
# 显示使用说明
|
|
show_usage() {
|
|
log "info" "Sanguo Mail 系统管理脚本"
|
|
log "info" "使用方法: $0 <命令> [参数]"
|
|
log "info" ""
|
|
log "info" "可用命令:"
|
|
log "info" " init 初始化系统"
|
|
log " start 启动服务"
|
|
log " stop 停止服务"
|
|
log " restart 重启服务"
|
|
log " status 显示系统状态"
|
|
log " logs [行数] 显示服务日志"
|
|
log " config [set <配置项> <值>] 设置/查看配置"
|
|
log " install 安装项目依赖"
|
|
log " check 健康检查"
|
|
log " list 列出所有命令"
|
|
log " watch [间隔] 启动邮件检查服务"
|
|
log " stop-watch 停止邮件检查服务"
|
|
log " test 测试邮件发送和接收"
|
|
log " help 显示此帮助信息"
|
|
}
|
|
|
|
# 显示可用命令列表
|
|
list_commands() {
|
|
log "info" "可用命令:"
|
|
log "info" " init 初始化系统"
|
|
log "info" " start 启动服务"
|
|
log "info" " stop 停止服务"
|
|
log "info" " restart 重启服务"
|
|
log "info" " status 显示系统状态"
|
|
log "info" " logs [行数] 显示服务日志"
|
|
log "info" " config [set <配置项> <值>] 设置/查看配置"
|
|
log "info" " install 安装项目依赖"
|
|
log "info" " check 健康检查"
|
|
log "info" " list 列出所有命令"
|
|
log "info" " watch [间隔] 启动邮件检查服务"
|
|
log "info" " stop-watch 停止邮件检查服务"
|
|
log "info" " test 测试邮件发送和接收"
|
|
log "info" " help 显示此帮助信息"
|
|
}
|
|
|
|
# 测试邮件发送
|
|
test_send_mail() {
|
|
log "info" "正在测试邮件发送..."
|
|
|
|
cat > "$SCRIPTS_DIR/test-send.js" << 'EOF'
|
|
import { SanguoMailbox } from '/Users/chufeng/.openclaw/sanguo_projects/sanguo_mail/dist/index.js';
|
|
|
|
const CONFIG = {
|
|
rootPath: '/Users/chufeng/.openclaw/sanguo_projects/sanguo_quant_live',
|
|
teamName: 'sanguo-quant'
|
|
};
|
|
|
|
async function testSendMail() {
|
|
const mailbox = new SanguoMailbox(CONFIG);
|
|
await mailbox.initTeam();
|
|
|
|
await mailbox.sendMessage('zhangfei', {
|
|
from: 'pangtong',
|
|
to: 'zhangfei',
|
|
text: '测试消息:发送一条测试邮件',
|
|
type: 'text'
|
|
});
|
|
|
|
console.log('测试邮件发送成功');
|
|
}
|
|
|
|
testSendMail();
|
|
EOF
|
|
|
|
chmod +x "$SCRIPTS_DIR/test-send.js"
|
|
node "$SCRIPTS_DIR/test-send.js"
|
|
|
|
log "success" "测试邮件发送成功"
|
|
}
|
|
|
|
# 测试邮件接收
|
|
test_receive_mail() {
|
|
log "info" "正在测试邮件接收..."
|
|
|
|
cat > "$SCRIPTS_DIR/test-receive.js" << 'EOF'
|
|
import { SanguoMailbox } from '/Users/chufeng/.openclaw/sanguo_projects/sanguo_mail/dist/index.js';
|
|
|
|
const CONFIG = {
|
|
rootPath: '/Users/chufeng/.openclaw/sanguo_projects/sanguo_quant_live',
|
|
teamName: 'sanguo-quant'
|
|
};
|
|
|
|
async function testReceiveMail() {
|
|
const mailbox = new SanguoMailbox(CONFIG);
|
|
await mailbox.initTeam();
|
|
|
|
const unread = await mailbox.listUnread('zhangfei');
|
|
|
|
if (unread.length === 0) {
|
|
console.log('没有未读邮件');
|
|
return;
|
|
}
|
|
|
|
console.log(`发现 ${unread.length} 条未读邮件`);
|
|
|
|
for (let i = 0; i < unread.length; i++) {
|
|
const msg = unread[i];
|
|
console.log(`[${i + 1}] ${msg.from} - ${msg.text}`);
|
|
console.log(`类型: ${msg.type}`);
|
|
console.log(`时间: ${msg.timestamp}`);
|
|
console.log('');
|
|
}
|
|
}
|
|
|
|
testReceiveMail();
|
|
EOF
|
|
|
|
chmod +x "$SCRIPTS_DIR/test-receive.js"
|
|
node "$SCRIPTS_DIR/test-receive.js"
|
|
|
|
log "success" "测试邮件接收成功"
|
|
}
|
|
|
|
# 测试功能
|
|
run_test() {
|
|
log "info" "正在运行 Sanguo Mail 系统测试..."
|
|
|
|
# 初始化系统(如果未初始化)
|
|
if [ ! -d "$PROJECT_ROOT/mail/sanguo-quant/inboxes" ] || [ ! -f "$PROJECT_ROOT/mail/sanguo-quant/team.json" ]; then
|
|
log "info" "邮件系统未初始化,正在初始化..."
|
|
init_system
|
|
fi
|
|
|
|
# 测试邮件发送
|
|
test_send_mail
|
|
|
|
# 测试邮件接收
|
|
test_receive_mail
|
|
}
|
|
|
|
# 主命令处理
|
|
case "${1:-}" in
|
|
"init" | "setup" )
|
|
init_system
|
|
;;
|
|
|
|
"start" | "up" )
|
|
start_server
|
|
;;
|
|
|
|
"stop" | "down" )
|
|
stop_server
|
|
;;
|
|
|
|
"restart" )
|
|
stop_server
|
|
sleep 2
|
|
start_server
|
|
;;
|
|
|
|
"watch" )
|
|
watch_mail "$@"
|
|
;;
|
|
|
|
"stop-watch" )
|
|
stop_watch_mail
|
|
;;
|
|
|
|
"status" )
|
|
status
|
|
;;
|
|
|
|
"logs" )
|
|
logs "$@"
|
|
;;
|
|
|
|
"config" )
|
|
if [ -z "$2" ]; then
|
|
list_config
|
|
elif [ "$2" = "set" ]; then
|
|
set_config "${3:-}" "${4:-}"
|
|
else
|
|
log "error" "配置命令无效"
|
|
log "usage" "使用方法: $0 config [set <key> <value>]"
|
|
fi
|
|
;;
|
|
|
|
"install" )
|
|
install_deps
|
|
;;
|
|
|
|
"check" )
|
|
check_health
|
|
;;
|
|
|
|
"list" )
|
|
list_commands
|
|
;;
|
|
|
|
"test" )
|
|
run_test
|
|
;;
|
|
|
|
"help" )
|
|
show_usage
|
|
;;
|
|
|
|
"" )
|
|
show_usage
|
|
;;
|
|
|
|
* )
|
|
log "warning" "未知命令: $1"
|
|
show_usage
|
|
exit 1
|
|
;;
|
|
esac
|