test/main.go
2024-11-16 16:27:05 +08:00

185 lines
4.6 KiB
Go

package main
import (
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"os"
"os/exec"
"path/filepath"
"strings"
"time"
)
// ProcessConfig 进程配置结构体
type ProcessConfig struct {
ProcessName string `json:"process_name"`
FileName string `json:"file_name"` // 文件名
KumaURL string `json:"kuma_url"`
CheckInterval int `json:"check_interval"`
}
// Config 整体配置结构体
type Config struct {
Processes []ProcessConfig `json:"processes"`
}
// ProcessMonitor 进程监控结构体
type ProcessMonitor struct {
config ProcessConfig
httpClient *http.Client
status string
logDir string
}
// NewProcessMonitor 创建新的进程监控
func NewProcessMonitor(config ProcessConfig, logDir string) *ProcessMonitor {
return &ProcessMonitor{
config: config,
httpClient: &http.Client{},
status: "down",
logDir: logDir,
}
}
// LoadConfig 加载配置文件
func LoadConfig(filename string) (*Config, error) {
file, err := os.Open(filename)
if err != nil {
return nil, err
}
defer file.Close()
var config Config
if err := json.NewDecoder(file).Decode(&config); err != nil {
return nil, err
}
return &config, nil
}
// InitLogFile 初始化日志文件
func InitLogFile(logDir string) (*os.File, error) {
if err := os.MkdirAll(logDir, 0755); err != nil {
return nil, fmt.Errorf("failed to create log directory: %v", err)
}
logFile := filepath.Join(logDir, time.Now().Format("2006-01-02")+".log")
file, err := os.OpenFile(logFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666)
if err != nil {
return nil, fmt.Errorf("failed to open log file: %v", err)
}
return file, nil
}
// IsProcessRunning 检查进程是否正在运行
func (pm *ProcessMonitor) IsProcessRunning() bool {
output, err := exec.Command("tasklist").Output()
if err != nil {
log.Printf("Error retrieving process list: %v", err)
return false
}
lines := string(output)
for _, line := range strings.Split(lines, "\n") {
if strings.Contains(line, pm.config.ProcessName) {
// 如果指定了文件名,则检查文件名
if pm.config.FileName == "" || strings.Contains(line, pm.config.FileName) {
return true
}
}
}
return false
}
// PushStatusToKuma 向 Uptime Kuma 推送状态
func (pm *ProcessMonitor) PushStatusToKuma() error {
response, err := pm.httpClient.Get(fmt.Sprintf("%s?status=%s", pm.config.KumaURL, pm.status))
if err != nil {
return err
}
defer response.Body.Close()
log.Printf("Pushed status '%s' for process '%s' fileName '%s' to Uptime Kuma: %s", pm.status, pm.config.ProcessName, pm.config.FileName, response.Status)
return nil
}
// Monitor 监控进程状态
func (pm *ProcessMonitor) Monitor() {
ticker := time.NewTicker(time.Duration(pm.config.CheckInterval) * time.Second)
defer ticker.Stop()
pm.checkAndPushStatus() // 启动时立即检查一次
for {
select {
case <-ticker.C:
pm.checkAndPushStatus()
case <-time.After(24 * time.Hour): // 每天执行日志清理
pm.cleanOldLogs()
}
}
}
// checkAndPushStatus 检查进程状态并推送到 Uptime Kuma
func (pm *ProcessMonitor) checkAndPushStatus() {
pm.status = "down"
if pm.IsProcessRunning() {
pm.status = "up"
}
if err := pm.PushStatusToKuma(); err != nil {
log.Printf("Error pushing status for process '%s' fileName '%s': %v", pm.config.ProcessName, pm.config.FileName, err)
}
}
// cleanOldLogs 清理旧日志
func (pm *ProcessMonitor) cleanOldLogs() {
logFiles, err := os.ReadDir(pm.logDir)
if err != nil {
log.Printf("Error reading log directory: %v", err)
return
}
threshold := time.Now().AddDate(0, 0, -30) // 30天前的日期
for _, logFile := range logFiles {
if logFile.Type().IsRegular() {
if fileInfo, err := logFile.Info(); err == nil {
if fileInfo.ModTime().Before(threshold) {
if err := os.Remove(filepath.Join(pm.logDir, logFile.Name())); err != nil {
log.Printf("Error deleting old log file '%s': %v", logFile.Name(), err)
} else {
log.Printf("Deleted old log file: '%s'", logFile.Name())
}
}
}
}
}
}
func main() {
logDir := "logs"
logFile, err := InitLogFile(logDir)
if err != nil {
log.Fatalf("Error initializing log file: %v\n", err)
}
defer logFile.Close()
// 设置日志同时输出到控制台和文件
multiWriter := io.MultiWriter(logFile, os.Stdout)
log.SetOutput(multiWriter)
config, err := LoadConfig("config.json")
if err != nil {
log.Fatalf("Error loading config: %v", err)
}
// 启动监控
for _, processConfig := range config.Processes {
pm := NewProcessMonitor(processConfig, logDir)
go pm.Monitor()
}
select {} // 阻止主进程退出
}