refactor: 重构初始化逻辑,添加配置加载和运行管理功能
This commit is contained in:
parent
31ad2fb41a
commit
26cc907024
|
|
@ -1,29 +1,16 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"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"
|
||||
"gopkg.in/natefinch/lumberjack.v2"
|
||||
)
|
||||
|
||||
const (
|
||||
OfficialConfigURL = "http://localhost:8090/api/v1/configs/official.json"
|
||||
UserConfigURL = "http://localhost:8090/api/v1/configs/user.json"
|
||||
"github.com/wuko233/sysmonitord/internal/initializer"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
initLogger()
|
||||
initializer.InitLogger()
|
||||
log.Println("==========================================")
|
||||
log.Print(`
|
||||
_ _ _
|
||||
|
|
@ -37,175 +24,29 @@ func main() {
|
|||
`)
|
||||
log.Println("==========================================")
|
||||
|
||||
// 加载配置
|
||||
log.Println("[启动流程] 1/6: 下载远程安全策略配置...")
|
||||
cfgLoader := network.NewConfigLoader()
|
||||
log.Println("[初始化]: 从远程加载配置...")
|
||||
cfgLoader := initializer.NewConfigLoader()
|
||||
|
||||
officialCfg, userCfg, err := cfgLoader.LoadConfigs(network.ConfigUrls{
|
||||
OfficialConfigUrl: OfficialConfigURL,
|
||||
UserConfigUrl: UserConfigURL,
|
||||
})
|
||||
officialCfg, userCfg, err := cfgLoader.Load(
|
||||
"http://localhost:8090/api/v1/configs/official.json",
|
||||
"http://localhost:8090/api/v1/configs/user.json",
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("[启动错误]下载配置失败: %v", err)
|
||||
log.Fatalf("[错误] 加载配置失败: %v", err)
|
||||
panic(err)
|
||||
}
|
||||
log.Println("[初始化]: 配置加载成功")
|
||||
|
||||
CenterServerURL := determineServerURL(userCfg)
|
||||
|
||||
log.Println("[启动流程] 2/6: 初始化白名单判定引擎...")
|
||||
wlManager := whitelist.NewManager(officialCfg, userCfg)
|
||||
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
|
||||
runtime := initializer.NewRuntime(*officialCfg, *userCfg)
|
||||
if err := runtime.Start(); err != nil {
|
||||
log.Fatalf("[错误] 启动进程失败: %v", err)
|
||||
panic(err)
|
||||
}
|
||||
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)
|
||||
signal.Notify(stopChan, os.Interrupt, syscall.SIGTERM)
|
||||
<-stopChan
|
||||
log.Println("[守护进程] 接收到停止信号,正在关闭...")
|
||||
|
||||
if sysWatcher != nil {
|
||||
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"}
|
||||
runtime.Stop()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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))
|
||||
}
|
||||
|
|
@ -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("[进程] 已成功停止,安全退出程序。")
|
||||
}
|
||||
Reference in New Issue
Block a user