95 lines
2.4 KiB
Go
95 lines
2.4 KiB
Go
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 <me@arav.su>")
|
|
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)
|
|
}
|
|
}
|
|
}
|