kiss server monitoring tool with email alerts
go monitoring
at v0.1.0 3.0 kB view raw
1package main 2 3import ( 4 "errors" 5 "fmt" 6 "os" 7 "os/exec" 8 "path" 9 "runtime" 10 "runtime/debug" 11 "strings" 12 13 "github.com/spf13/cobra" 14) 15 16var ( 17 flagConfig = "config" 18 flagDaemon = "daemon" 19 cfgFile string 20 runAsDaemon bool 21) 22 23func main() { 24 homeDir, err := os.UserHomeDir() 25 if err != nil { 26 fmt.Fprintf(os.Stderr, "error getting user home directory: %v", err) 27 os.Exit(1) 28 } 29 30 version, err := getVersion() 31 if err != nil { 32 fmt.Fprintf(os.Stderr, "error getting version: %v", err) 33 version = "unknown" 34 } 35 36 rootCmd := &cobra.Command{ 37 Use: "servmon", 38 Short: "KISS server monitoring tool with email alerts", 39 Version: version, 40 RunE: func(cmd *cobra.Command, args []string) error { 41 runAsDaemon, err := cmd.Flags().GetBool(flagDaemon) 42 if err != nil { 43 return fmt.Errorf("error getting flag %s: %v", flagDaemon, err) 44 } 45 46 if runAsDaemon { 47 pid, err := runAsDaemonProcess() 48 if err != nil { 49 return err 50 } 51 52 cmd.Println("Running as daemon with PID", pid) 53 return nil 54 } 55 56 cfgPath, err := cmd.Flags().GetString(flagConfig) 57 if err != nil { 58 return fmt.Errorf("error getting flag %s: %v", flagConfig, err) 59 } 60 61 if _, err := os.Stat(cfgPath); os.IsNotExist(err) { 62 cfg := defaultConfig() 63 if err := cfg.Save(cfgFile); err != nil { 64 return err 65 } 66 67 cmd.Println("Configuration file generated at", cfgFile) 68 return nil 69 } else if err != nil { 70 return fmt.Errorf("error checking config file: %v", err) 71 } 72 73 cfg, err := loadConfig(cfgPath) 74 if err != nil { 75 return err 76 } 77 78 go monitorCPU(cfg) 79 go monitorMemory(cfg) 80 go monitorDisk(cfg) 81 go monitorHTTP(cfg) 82 83 select {} // keep alive 84 }, 85 } 86 87 rootCmd.CompletionOptions.DisableDefaultCmd = true 88 rootCmd.PersistentFlags().StringVar(&cfgFile, flagConfig, path.Join(homeDir, ".servmon.yaml"), "config file") 89 rootCmd.PersistentFlags().BoolVarP(&runAsDaemon, flagDaemon, "d", false, "run as daemon") 90 91 if err := rootCmd.Execute(); err != nil { 92 fmt.Fprint(os.Stderr, err) 93 os.Exit(1) 94 } 95} 96 97func runAsDaemonProcess() (int, error) { 98 if runtime.GOOS == "linux" || runtime.GOOS == "freebsd" { 99 var args []string 100 for _, a := range os.Args[1:] { 101 if a != "-d" && a != "--daemon" { 102 args = append(args, a) 103 } 104 } 105 106 cmd := exec.Command(os.Args[0], args...) 107 cmd.Stdout = os.NewFile(3, "log.out") 108 cmd.Stderr = os.NewFile(4, "log.err") 109 cmd.Stdin = os.NewFile(3, "log.in") 110 111 if err := cmd.Start(); err != nil { 112 return 0, fmt.Errorf("error starting as daemon: %v", err) 113 } 114 115 pid := cmd.Process.Pid 116 117 // Detach the process 118 err := cmd.Process.Release() 119 if err != nil { 120 return 0, fmt.Errorf("error detaching process: %v", err) 121 } 122 123 return pid, nil 124 } 125 126 return 0, fmt.Errorf("daemon mode is not supported on %s", runtime.GOOS) 127} 128 129func getVersion() (string, error) { 130 version, ok := debug.ReadBuildInfo() 131 if !ok { 132 return "", errors.New("failed to get version") 133 } 134 135 return strings.TrimSpace(version.Main.Version), nil 136}