refactor: 重构初始化逻辑,添加配置加载和运行管理功能

This commit is contained in:
wuko233 2026-03-26 21:15:05 +08:00
parent 31ad2fb41a
commit 26cc907024
4 changed files with 262 additions and 175 deletions

View File

@ -1,29 +1,16 @@
package main package main
import ( import (
"io"
"log" "log"
"os" "os"
"os/signal" "os/signal"
"syscall" "syscall"
"time"
"github.com/wuko233/sysmonitord/internal/config" "github.com/wuko233/sysmonitord/internal/initializer"
"github.com/wuko233/sysmonitord/internal/monitor"
"github.com/wuko233/sysmonitord/internal/network"
"github.com/wuko233/sysmonitord/internal/scanner"
"github.com/wuko233/sysmonitord/internal/whitelist"
"gopkg.in/natefinch/lumberjack.v2"
)
const (
OfficialConfigURL = "http://localhost:8090/api/v1/configs/official.json"
UserConfigURL = "http://localhost:8090/api/v1/configs/user.json"
) )
func main() { func main() {
initializer.InitLogger()
initLogger()
log.Println("==========================================") log.Println("==========================================")
log.Print(` log.Print(`
_ _ _ _ _ _
@ -37,175 +24,29 @@ func main() {
`) `)
log.Println("==========================================") log.Println("==========================================")
// 加载配置 log.Println("[初始化]: 从远程加载配置...")
log.Println("[启动流程] 1/6: 下载远程安全策略配置...") cfgLoader := initializer.NewConfigLoader()
cfgLoader := network.NewConfigLoader()
officialCfg, userCfg, err := cfgLoader.LoadConfigs(network.ConfigUrls{ officialCfg, userCfg, err := cfgLoader.Load(
OfficialConfigUrl: OfficialConfigURL, "http://localhost:8090/api/v1/configs/official.json",
UserConfigUrl: UserConfigURL, "http://localhost:8090/api/v1/configs/user.json",
}) )
if err != nil { if err != nil {
log.Fatalf("[启动错误]下载配置失败: %v", err) log.Fatalf("[错误] 加载配置失败: %v", err)
panic(err)
} }
log.Println("[初始化]: 配置加载成功")
CenterServerURL := determineServerURL(userCfg) runtime := initializer.NewRuntime(*officialCfg, *userCfg)
if err := runtime.Start(); err != nil {
log.Println("[启动流程] 2/6: 初始化白名单判定引擎...") log.Fatalf("[错误] 启动进程失败: %v", err)
wlManager := whitelist.NewManager(officialCfg, userCfg) panic(err)
wlManager.UpdateConfig(officialCfg, userCfg)
log.Println("[启动流程] 3/6: 启动中心服务器连接...")
centerClient := network.NewWSClient(network.ClientConfig{
ServerURL: CenterServerURL,
SendInterval: 1 * time.Second,
BufferSize: 1000,
})
centerClient.Start()
auditUrl := wlManager.GetAuditServerUrl()
if auditUrl == "" {
auditUrl = CenterServerURL
} }
auditClient := network.NewWSClient(network.ClientConfig{
ServerURL: auditUrl,
SendInterval: 1 * time.Second,
BufferSize: 1000,
})
auditClient.Start()
log.Println("[启动流程] 4/6: 启动文件完整性防护...")
var sysScanner *scanner.Scanner
var sysWatcher *scanner.Watcher
var sshMon *monitor.SSHMonitor
var infoMon *monitor.InfoMonitor
scanPaths := determineScanPaths(officialCfg, userCfg)
// 扫盘器
if userCfg.Modules.FileScanner {
sysScanner = scanner.NewScanner(wlManager, centerClient, scanPaths)
sysScanner.Start()
log.Printf("[监控信息] 文件周期扫描器已启动")
}
// 监控器
if userCfg.Modules.FileWatcher {
var err error
sysWatcher, err = scanner.NewWatcher(wlManager, centerClient, scanPaths)
if err != nil {
log.Fatalf("[启动错误] 初始化监控器失败: %v", err)
} else {
sysWatcher.Start()
log.Printf("[监控信息] 文件监控已启动")
}
}
log.Println("[启动流程] 5/6: 启动系统行为监控...")
// SSH监控
if userCfg.Modules.SSHMonitor {
sshAlertChan := make(chan monitor.Alert, 100)
sshMon = monitor.NewSSHMonitor(&userCfg.MonitorConfig.SSHMonitorConfig, sshAlertChan)
go func() {
for alert := range sshAlertChan {
packet := network.NewPacket("SSH_ALERT", alert)
auditClient.SendQueue(packet)
}
}()
go func() {
if err := sshMon.Start(); err != nil {
log.Printf("[监控错误] SSH监控遇到错误: %v", err)
}
log.Printf("[监控信息] SSH监控已启动")
}()
}
// 状态监控
if userCfg.Modules.SystemMonitor {
metricsChan := make(chan monitor.ServerMetrics, 100)
SystemMonitorCfg := &userCfg.MonitorConfig.SystemMonitorConfig
infoMon = monitor.NewInfoMonitor(SystemMonitorCfg, metricsChan)
go func() {
for metrics := range metricsChan {
packet := network.NewPacket("STATUS_UPDATE", metrics)
centerClient.SendQueue(packet)
}
}()
go infoMon.Start()
log.Printf("[监控信息] 系统状态监控已启动")
}
log.Println("[启动流程] 6/6: 系统监控守护进程启动完成!")
stopChan := make(chan os.Signal, 1) stopChan := make(chan os.Signal, 1)
signal.Notify(stopChan, os.Interrupt, syscall.SIGTERM) signal.Notify(stopChan, os.Interrupt, syscall.SIGTERM)
<-stopChan <-stopChan
log.Println("[守护进程] 接收到停止信号,正在关闭...")
if sysWatcher != nil { runtime.Stop()
sysWatcher.Stop()
}
if sysScanner != nil {
sysScanner.Stop()
}
if sshMon != nil {
sshMon.Stop()
}
if infoMon != nil {
infoMon.Stop()
}
if centerClient != nil {
centerClient.Stop()
}
centerClient.Stop()
auditClient.Stop()
log.Println("[守护进程] 已成功停止,安全退出程序。")
}
func determineServerURL(userCfg config.UserConfig) string {
// 服务器地址仅从用户配置获取(符合 ARCHITECTURE.md 规范)
if userCfg.Connection.CenterServerURL != "" {
return userCfg.Connection.CenterServerURL
}
// 默认地址
return "ws://localhost:8090/api/v1/ws"
}
func initLogger() {
log.SetOutput(os.Stdout)
fileLogger := &lumberjack.Logger{
Filename: "/var/log/sysmonitord/sysmonitord.log",
MaxSize: 100, // MB
MaxBackups: 7,
MaxAge: 30, // 天
Compress: true,
}
log.SetOutput(io.MultiWriter(os.Stdout, fileLogger))
}
func determineScanPaths(officialCfg config.OfficialConfig, userCfg config.UserConfig) []string {
// 从用户配置获取扫描路径
if len(userCfg.ScanPaths) > 0 {
return userCfg.ScanPaths
}
// 从官方配置获取扫描路径
if len(officialCfg.ScanPaths) > 0 {
return officialCfg.ScanPaths
}
// 默认扫描路径
return []string{"/bin", "/sbin", "/usr/bin", "/usr/sbin", "/etc", "/tmp", "/home"}
} }

View File

@ -0,0 +1,84 @@
package initializer
import (
"encoding/json"
"fmt"
"io"
"net/http"
"time"
"github.com/wuko233/sysmonitord/internal/config"
)
type ConfigLoader struct {
client *http.Client
}
func NewConfigLoader() *ConfigLoader {
return &ConfigLoader{
client: &http.Client{Timeout: 10 * time.Second},
}
}
func (l *ConfigLoader) Load(officialURL, UserURL string) (*config.OfficialConfig, *config.UserConfig, error) {
var officialCfg config.OfficialConfig
var userCfg config.UserConfig
if err := l.fetchJSON(officialURL, &officialCfg); err != nil {
return nil, nil, fmt.Errorf("加载官方配置失败: %v", err)
}
if err := l.fetchJSON(UserURL, &userCfg); err != nil {
return nil, nil, fmt.Errorf("加载用户配置失败: %v", err)
}
return &officialCfg, &userCfg, nil
}
func (l *ConfigLoader) fetchJSON(url string, target interface{}) error {
resp, err := l.client.Get(url)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("HTTP %s", resp.Status)
}
body, err := io.ReadAll(resp.Body)
if err != nil {
return err
}
return json.Unmarshal(body, target)
}
func determineServerURL(userCfg config.UserConfig) string {
if userCfg.Connection.CenterServerURL != "" {
return userCfg.Connection.CenterServerURL
}
// 默认地址
return "ws://localhost:8090/api/v1/ws"
}
func determineScanPaths(officialCfg config.OfficialConfig, userCfg config.UserConfig) []string {
// 从用户配置获取扫描路径
if len(userCfg.ScanPaths) > 0 {
return userCfg.ScanPaths
}
// 从官方配置获取扫描路径
if len(officialCfg.ScanPaths) > 0 {
return officialCfg.ScanPaths
}
// 默认扫描路径
return []string{"/bin", "/sbin", "/usr/bin", "/usr/sbin", "/etc", "/tmp", "/home"}
}
func determineWatchPaths(official config.OfficialConfig, user config.UserConfig) []string {
// 可复用扫描路径,或从 user.WatchPaths 读取
return determineScanPaths(official, user)
}

View File

@ -0,0 +1,22 @@
package initializer
import (
"io"
"log"
"os"
"gopkg.in/natefinch/lumberjack.v2"
)
func InitLogger() {
log.SetOutput(os.Stdout)
fileLogger := &lumberjack.Logger{
Filename: "/var/log/sysmonitord/sysmonitord.log",
MaxSize: 100, // MB
MaxBackups: 7,
MaxAge: 30, // 天
Compress: true,
}
log.SetOutput(io.MultiWriter(os.Stdout, fileLogger))
}

View File

@ -0,0 +1,140 @@
package initializer
import (
"log"
"time"
"github.com/wuko233/sysmonitord/internal/config"
"github.com/wuko233/sysmonitord/internal/monitor"
"github.com/wuko233/sysmonitord/internal/network"
"github.com/wuko233/sysmonitord/internal/scanner"
"github.com/wuko233/sysmonitord/internal/whitelist"
)
type Runtime struct {
officialCfg config.OfficialConfig
userCfg config.UserConfig
centerCil *network.WSClient
auditCil *network.WSClient
scanner *scanner.Scanner
watcher *scanner.Watcher
sshMon *monitor.SSHMonitor
infoMon *monitor.InfoMonitor
}
func NewRuntime(official config.OfficialConfig, user config.UserConfig) *Runtime {
return &Runtime{
officialCfg: official,
userCfg: user,
}
}
func (r *Runtime) Start() error {
// 初始化白名单引擎
log.Println("[初始化]: 初始化白名单判定引擎...")
wlManager := whitelist.NewManager(r.officialCfg, r.userCfg)
// WebSocket客户端
log.Println("[初始化]: 启动中心服务器连接...")
centerURL := determineServerURL(r.userCfg)
r.centerCil = network.NewWSClient(network.ClientConfig{
ServerURL: centerURL,
SendInterval: 1 * time.Second,
BufferSize: 1000,
})
r.centerCil.Start()
auditURL := wlManager.GetAuditServerUrl()
if auditURL == "" {
auditURL = centerURL
}
r.auditCil = network.NewWSClient(network.ClientConfig{
ServerURL: auditURL,
SendInterval: 1 * time.Second,
BufferSize: 1000,
})
r.auditCil.Start()
// 文件扫描器
if r.userCfg.Modules.FileScanner {
r.scanner = scanner.NewScanner(wlManager, r.centerCil, determineScanPaths(r.officialCfg, r.userCfg))
r.scanner.Start()
log.Printf("[初始化]: 文件周期扫描器已启动")
}
// 文件监控器
if r.userCfg.Modules.FileWatcher {
var err error
r.watcher, err = scanner.NewWatcher(wlManager, r.centerCil, determineWatchPaths(r.officialCfg, r.userCfg))
if err != nil {
return err
}
r.watcher.Start()
log.Printf("[初始化]: 文件监控已启动")
}
// SSH监控器
if r.userCfg.Modules.SSHMonitor {
sshAlertChan := make(chan monitor.Alert, 100)
r.sshMon = monitor.NewSSHMonitor(&r.userCfg.MonitorConfig.SSHMonitorConfig, sshAlertChan)
go func() {
for alert := range sshAlertChan {
packet := network.NewPacket("SSH_ALERT", alert)
r.auditCil.SendQueue(packet)
}
}()
go func() {
if err := r.sshMon.Start(); err != nil {
log.Printf("[错误] SSH监控遇到错误: %v", err)
}
log.Printf("[初始化] SSH监控已启动")
}()
}
// 系统信息监控器
if r.userCfg.Modules.SystemMonitor {
metricsChan := make(chan monitor.ServerMetrics, 100)
SystemMonitorCfg := &r.userCfg.MonitorConfig.SystemMonitorConfig
r.infoMon = monitor.NewInfoMonitor(SystemMonitorCfg, metricsChan)
go func() {
for metrics := range metricsChan {
packet := network.NewPacket("STATUS_UPDATE", metrics)
r.centerCil.SendQueue(packet)
}
}()
go r.infoMon.Start()
log.Printf("[初始化] 系统状态监控已启动")
}
return nil
}
func (r *Runtime) Stop() {
log.Println("[进程]接收到停止信号,正在关闭...")
if r.watcher != nil {
r.watcher.Stop()
}
if r.scanner != nil {
r.scanner.Stop()
}
if r.sshMon != nil {
r.sshMon.Stop()
}
if r.infoMon != nil {
r.infoMon.Stop()
}
if r.centerCil != nil {
r.centerCil.Stop()
}
if r.auditCil != nil {
r.auditCil.Stop()
}
log.Println("[进程] 已成功停止,安全退出程序。")
}