diff --git a/cmd/start/start.go b/cmd/start/start.go index 9602c5e..3c4aeff 100644 --- a/cmd/start/start.go +++ b/cmd/start/start.go @@ -3,7 +3,11 @@ package start import ( "fmt" "os" + "os/signal" + "syscall" "sysmonitord/internal/config" + "sysmonitord/internal/monitor/detector" + "sysmonitord/internal/monitor/timer" "sysmonitord/internal/monitor/watcher" "sysmonitord/internal/scanner/file" "sysmonitord/internal/scanner/process" @@ -91,7 +95,15 @@ var StartCmd = &cobra.Command{ mon.Start() - logger.Log.Info("系统监控守护服务已启动,正在监控文件系统变化...") + // ====== 启动进程检测定时任务 ====== + procDetector := detector.NewProcessDetector(cfg) + procScheduler := timer.NewScheduler(time.Duration(cfg.Scanner.Process.Interval)*time.Second, procDetector) + procScheduler.Start() + + logger.Log.Info("系统监控守护服务已启动,正在监控系统变化...") + + quit := make(chan os.Signal, 1) + signal.Notify(quit, os.Interrupt, syscall.SIGTERM, syscall.SIGINT) for { select { @@ -110,11 +122,12 @@ var StartCmd = &cobra.Command{ case err := <-mon.Errors(): logger.Log.Error("文件监听错误", zap.Error(err)) - // case <-quit: - // logger.Log.Info("正在停止系统监控守护服务...") - // mon.Stop() - // logger.Log.Info("系统监控守护服务已停止") - // return + case <-quit: + logger.Log.Info("正在停止系统监控守护服务...") + mon.Stop() + procScheduler.Stop() + logger.Log.Info("系统监控守护服务已停止") + return } } diff --git a/config.yaml b/config.yaml index 07ef926..20f7035 100644 --- a/config.yaml +++ b/config.yaml @@ -3,8 +3,8 @@ server: port: 8080 log: - # level: "info" - level: "debug" + level: "info" + # level: "debug" audit: enabled: true @@ -26,6 +26,8 @@ scanner: fast_hash: true fast_hash_size: 100MB fast_hash_chunk: 2MB + process: + interval: 30 # seconds storage: data_dir: "./data" diff --git a/internal/config/config.go b/internal/config/config.go index ed2a306..eef2a10 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -19,14 +19,19 @@ type AuditConfig struct { } type ScannerConfig struct { - File FileScannerConfig `yaml:"file"` - Hash hashConfig `yaml:"hash"` + File FileScannerConfig `yaml:"file"` + Hash hashConfig `yaml:"hash"` + Process ProcessScannerConfig `yaml:"process"` } type hashConfig struct { Algorithm string `yaml:"algorithm"` } +type ProcessScannerConfig struct { + Interval int `yaml:"interval"` +} + type StorageConfig struct { DataDir string `yaml:"data_dir"` ProcessSystemFile string `yaml:"process_system_file"` diff --git a/internal/monitor/detector/detector.go b/internal/monitor/detector/detector.go new file mode 100644 index 0000000..2f76726 --- /dev/null +++ b/internal/monitor/detector/detector.go @@ -0,0 +1,82 @@ +package detector + +import ( + "bufio" + "os" + "path/filepath" + "strings" + "sysmonitord/internal/config" + "sysmonitord/internal/scanner/process" + "sysmonitord/pkg/logger" + + "go.uber.org/zap" +) + +type ProcessDetector struct { + cfg *config.Config + whiteList map[string]string + storagePath string +} + +func NewProcessDetector(cfg *config.Config) *ProcessDetector { + p := &ProcessDetector{ + cfg: cfg, + whiteList: make(map[string]string), + } + + p.loadWhiteList() + return p +} + +func (p *ProcessDetector) loadWhiteList() { + filepath := filepath.Join(p.cfg.Storage.DataDir, p.cfg.Storage.ProcessSystemFile) + file, err := os.Open(filepath) + if err != nil { + logger.Log.Error("[monitor] 加载进程白名单失败", zap.String("file", filepath), zap.Error(err)) + return + } + defer file.Close() + + scanner := bufio.NewScanner(file) + for scanner.Scan() { + line := scanner.Text() + if line == "" || strings.HasPrefix(line, "#") { + continue + } + + parts := strings.Split(line, ":") + if len(parts) >= 3 { + p.whiteList[parts[1]] = parts[2] // name:path:hash + } + } + + logger.Log.Info("[monitor] 进程白名单加载完成", zap.Int("count", len(p.whiteList))) +} + +func (p *ProcessDetector) Run() error { + logger.Log.Info("[monitor] 进程检测已启动") + + currentProcs, err := process.ScanAllProcesses(p.cfg) + if err != nil { + logger.Log.Error("[monitor] 扫描进程失败", zap.Error(err)) + return err + } + + newCount := 0 + for _, proc := range currentProcs { + _, exists := p.whiteList[proc.Path] + if !exists { + logger.Log.Warn("[monitor] 发现新进程", zap.String("name", proc.Name), zap.String("path", proc.Path)) + newCount++ + + // Todo: 处理新进程 + } + } + + logger.Log.Info("[monitor] 进程检测完成", zap.Int("total", len(currentProcs)), zap.Int("new", newCount)) + return nil +} + +func (p *ProcessDetector) Name() string { + return "ProcessMonitor" +} diff --git a/internal/monitor/timer/timer.go b/internal/monitor/timer/timer.go new file mode 100644 index 0000000..f04d15e --- /dev/null +++ b/internal/monitor/timer/timer.go @@ -0,0 +1,64 @@ +package timer + +import ( + "sync" + "sysmonitord/pkg/logger" + "time" + + "go.uber.org/zap" +) + +type Job interface { + Run() error + Name() string +} + +type Scheduler struct { + ticker *time.Ticker + stopCh chan struct{} + job Job + wg sync.WaitGroup + interval time.Duration +} + +func NewScheduler(interval time.Duration, job Job) *Scheduler { + return &Scheduler{ + ticker: time.NewTicker(interval), + stopCh: make(chan struct{}), + job: job, + interval: interval, + } +} + +func (s *Scheduler) Start() { + logger.Log.Info("[monitor] 定时任务已启动", zap.String("job", s.job.Name()), zap.Duration("interval", s.interval)) + + s.wg.Add(1) + go func() { + defer s.wg.Done() + + logger.Log.Info("[monitor] 执行定时任务", zap.String("job", s.job.Name())) + if err := s.job.Run(); err != nil { + logger.Log.Error("[monitor] 定时任务执行失败", zap.String("job", s.job.Name()), zap.Error(err)) + } + + for { + select { + case <-s.ticker.C: + logger.Log.Info("[monitor] 执行定时任务", zap.String("job", s.job.Name())) + if err := s.job.Run(); err != nil { + logger.Log.Error("[monitor] 定时任务执行失败", zap.String("job", s.job.Name()), zap.Error(err)) + } + case <-s.stopCh: + logger.Log.Info("[monitor] 定时任务已停止", zap.String("job", s.job.Name())) + return + } + } + }() +} + +func (s *Scheduler) Stop() { + close(s.stopCh) + s.ticker.Stop() + s.wg.Wait() +}