[scanner] 实现文件扫描与储存

This commit is contained in:
wuko233 2026-04-01 09:06:56 +08:00
parent 7b8a3535d0
commit 92b8ae9648
6 changed files with 183 additions and 0 deletions

View File

@ -4,10 +4,12 @@ import (
"fmt" "fmt"
"os" "os"
"sysmonitord/internal/config" "sysmonitord/internal/config"
"sysmonitord/internal/scanner/file"
"sysmonitord/internal/scanner/hash" "sysmonitord/internal/scanner/hash"
"sysmonitord/internal/scanner/process" "sysmonitord/internal/scanner/process"
"sysmonitord/internal/storage" "sysmonitord/internal/storage"
"sysmonitord/pkg/logger" "sysmonitord/pkg/logger"
"time"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"go.uber.org/zap" "go.uber.org/zap"
@ -42,6 +44,8 @@ var StartCmd = &cobra.Command{
FileSystemFile: cfg.Storage.FileSystemFile, FileSystemFile: cfg.Storage.FileSystemFile,
} }
// ====== 进程扫描和存储 ======
procs, err := process.ScanAllProcesses(hashCfg) procs, err := process.ScanAllProcesses(hashCfg)
if err != nil { if err != nil {
logger.Log.Error("扫描进程失败", zap.Error(err)) logger.Log.Error("扫描进程失败", zap.Error(err))
@ -67,5 +71,36 @@ var StartCmd = &cobra.Command{
zap.Stringer("data", p), zap.Stringer("data", p),
) )
} }
// ====== 文件扫描和存储 ======
logger.Log.Info("正在扫描文件系统...")
startTime := time.Now()
fileCfg := &config.FileScannerConfig{
IncludePaths: cfg.Scanner.File.IncludePaths,
ExcludePaths: cfg.Scanner.File.ExcludePaths,
FastHash: cfg.Scanner.File.FastHash,
FastHashSize: cfg.Scanner.File.FastHashSize,
FastHashChunk: cfg.Scanner.File.FastHashChunk,
}
fileScanner := file.NewScanner(fileCfg)
files, err := fileScanner.Scan()
if err != nil {
logger.Log.Error("扫描文件系统失败", zap.Error(err))
os.Exit(1)
} else {
if err := storage.SaveFileSystem(files, storageCfg.DataDir, storageCfg.FileSystemFile); err != nil {
logger.Log.Error("保存文件系统白名单失败", zap.Error(err))
os.Exit(1)
}
}
duration := time.Since(startTime)
logger.Log.Info("文件系统扫描完成",
zap.Int("文件数量", len(files)),
zap.Duration("扫描耗时", duration),
)
}, },
} }

View File

@ -10,6 +10,8 @@ audit:
scanner: scanner:
file: file:
include_paths:
- /home
exclude_paths: exclude_paths:
- /proc - /proc
- /sys - /sys

View File

@ -350,6 +350,8 @@ audit:
# 扫描配置 # 扫描配置
scanner: scanner:
file: file:
include_paths:
- /
exclude_paths: exclude_paths:
- /proc/ - /proc/
- /sys/ - /sys/

View File

@ -33,6 +33,7 @@ type StorageConfig struct {
} }
type FileScannerConfig struct { type FileScannerConfig struct {
IncludePaths []string `yaml:"include_paths"`
ExcludePaths []string `yaml:"exclude_paths"` ExcludePaths []string `yaml:"exclude_paths"`
FastHash bool `yaml:"fast_hash"` FastHash bool `yaml:"fast_hash"`
FastHashSizeRaw string `yaml:"fast_hash_size"` FastHashSizeRaw string `yaml:"fast_hash_size"`

View File

@ -0,0 +1,107 @@
package file
import (
"fmt"
"io/fs"
"os"
"path/filepath"
"strings"
"sysmonitord/internal/config"
"sysmonitord/internal/scanner/hash"
"sysmonitord/pkg/logger"
"go.uber.org/zap"
)
type FileInfo struct {
Path string
Hash string
ModTime int64
Size int64
}
type Scanner struct {
cfg *config.FileScannerConfig
}
func NewScanner(cfg *config.FileScannerConfig) *Scanner {
return &Scanner{
cfg: cfg,
}
}
func (s *Scanner) Scan() ([]FileInfo, error) {
targetPaths := s.cfg.IncludePaths
if len(targetPaths) == 0 {
targetPaths = []string{"/"}
}
var allFiles []FileInfo
for _, root := range targetPaths {
if _, err := os.Stat(root); os.IsNotExist(err) {
continue
}
logger.Log.Info("[scan]正在扫描文件系统", zap.String("root", root))
err := filepath.WalkDir(root, s.WalkFunc(&allFiles))
if err != nil {
logger.Log.Error("[scan]扫描文件系统时发生错误", zap.String("root", root), zap.Error(err))
}
}
return allFiles, nil
}
func (s *Scanner) WalkFunc(result *[]FileInfo) fs.WalkDirFunc {
return func(path string, d fs.DirEntry, err error) error {
if err != nil {
logger.Log.Debug("[scan]跳过路径", zap.String("path", path), zap.Error(err))
return fs.SkipDir
}
if d.IsDir() {
return nil
}
for _, exclude := range s.cfg.ExcludePaths {
if strings.HasPrefix(path, exclude) {
logger.Log.Debug("[scan]跳过路径", zap.String("path", path), zap.String("reason", "匹配排除路径"))
return fs.SkipDir
}
}
info, err := d.Info()
if err != nil {
logger.Log.Debug("[scan]无法获取文件信息", zap.String("path", path), zap.Error(err))
return nil
}
if info.Size() != 0 {
hash, err := hash.SHA256(path, &hash.Config{
UseFastHash: s.cfg.FastHash,
Threshold: s.cfg.FastHashSize,
ChunkSize: s.cfg.FastHashChunk,
})
if err != nil {
logger.Log.Debug("[scan]无法计算文件哈希", zap.String("path", path), zap.Error(err))
return nil
}
*result = append(*result, FileInfo{
Path: path,
Hash: hash,
ModTime: info.ModTime().Unix(),
Size: info.Size(),
})
}
return nil
}
}
func (f FileInfo) String() string {
return fmt.Sprintf("%s:%s", f.Path, f.Hash)
}

View File

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"os" "os"
"path/filepath" "path/filepath"
"sysmonitord/internal/scanner/file"
"sysmonitord/internal/scanner/process" "sysmonitord/internal/scanner/process"
"sysmonitord/pkg/logger" "sysmonitord/pkg/logger"
"time" "time"
@ -60,3 +61,38 @@ func SaveProcessSystem(proc []process.ProcessInfo, dataDir string, processSystem
return nil return nil
} }
func SaveFileSystem(files []file.FileInfo, dataDir string, fileSystemFile string) error {
filePath := filepath.Join(dataDir, fileSystemFile)
file, err := os.Create(filePath) // 覆盖
if err != nil {
return fmt.Errorf("[storage]无法创建储存文件系统文件%s: %w", filePath, err)
}
defer file.Close()
writer := bufio.NewWriter(file)
currentTime := time.Now().Format("2006-01-02 15:04:05")
header := fmt.Sprintf("# 文件系统白名单 - 生成时间: %s\n", currentTime)
if _, err := writer.WriteString(header); err != nil {
return err
}
for _, f := range files {
line := fmt.Sprintf("%v\n", f)
if _, err := writer.WriteString(line); err != nil {
return err
}
}
if err := writer.Flush(); err != nil {
return err
}
logger.Log.Info("[storage]文件系统白名单保存成功",
zap.String("file", filePath),
zap.Int("file_count", len(files)),
)
return nil
}