package main import ( "context" "encoding/json" "flag" "fmt" "log" "net/http" "os" "os/signal" "syscall" "time" ) var configPath *string = flag.String("c", "config.json", "path to configuration file") var showVersion *bool = flag.Bool("v", false, "show version") var version string func main() { log.SetFlags(0) flag.Parse() if *showVersion { fmt.Println("httpprocprobed ver.", version, "Copyright (c) 2021-2023 Alexander \"Arav\" Andreev ") os.Exit(0) } conf, err := LoadConfiguration(*configPath) if err != nil { log.Fatalf("Cannot load configuration file: %s\n", err) } router := http.NewServeMux() router.HandleFunc("/processes", AreProcessesUp(&conf.Processes)) srv := &http.Server{ Addr: conf.ListenAddress, Handler: router, ReadTimeout: 5 * time.Second, WriteTimeout: 5 * time.Second, IdleTimeout: 10 * time.Second, } go func() { if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { log.Fatalf("ListenAndServe: %s\n", err) } }() syssignal := make(chan os.Signal, 1) signal.Notify(syssignal, os.Interrupt, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP) log.Printf("httpprocprobed is running on \"%s\".", conf.ListenAddress) for { switch <-syssignal { case os.Interrupt: fallthrough case syscall.SIGINT | syscall.SIGTERM: srv.SetKeepAlivesEnabled(false) if err := srv.Shutdown(context.Background()); err != nil { log.Fatalf("%s\n", err) } log.Println("Server shutted down.") os.Exit(0) case syscall.SIGHUP: newconf, err := LoadConfiguration(*configPath) if err != nil { log.Fatalf("Failed to reload a list of processes from configuration: %s\n", err) } conf.Processes = newconf.Processes log.Println("Successfully reloaded a list of watched processes.") } } } // AreProcessesUp sends back status of watched processes. func AreProcessesUp(processes *[]Process) func(http.ResponseWriter, *http.Request) { return func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodGet { w.WriteHeader(http.StatusMethodNotAllowed) w.Header().Add("Allow", "GET") return } w.Header().Add("Content-Type", "application/json") if err := json.NewEncoder(w).Encode(GetProcessesState(processes)); err != nil { w.WriteHeader(http.StatusInternalServerError) log.Printf("Failed to encode a process list: %s\n", err) } } }