use gocron for scheduling auto-cert job

Improved error handling
This commit is contained in:
0xJacky 2022-07-05 16:37:17 +08:00
parent 1803f1308f
commit 21c6f403ce
6 changed files with 247 additions and 206 deletions

3
go.mod
View file

@ -7,6 +7,7 @@ require (
github.com/gin-contrib/static v0.0.1 github.com/gin-contrib/static v0.0.1
github.com/gin-gonic/gin v1.7.4 github.com/gin-gonic/gin v1.7.4
github.com/go-acme/lego/v4 v4.4.0 github.com/go-acme/lego/v4 v4.4.0
github.com/go-co-op/gocron v1.15.0
github.com/go-playground/locales v0.13.0 github.com/go-playground/locales v0.13.0
github.com/go-playground/universal-translator v0.17.0 github.com/go-playground/universal-translator v0.17.0
github.com/go-playground/validator/v10 v10.4.1 github.com/go-playground/validator/v10 v10.4.1
@ -38,10 +39,12 @@ require (
github.com/miekg/dns v1.1.40 // indirect github.com/miekg/dns v1.1.40 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.1 // indirect github.com/modern-go/reflect2 v1.0.1 // indirect
github.com/robfig/cron/v3 v3.0.1 // indirect
github.com/tklauser/go-sysconf v0.3.7 // indirect github.com/tklauser/go-sysconf v0.3.7 // indirect
github.com/tklauser/numcpus v0.2.3 // indirect github.com/tklauser/numcpus v0.2.3 // indirect
github.com/ugorji/go/codec v1.1.7 // indirect github.com/ugorji/go/codec v1.1.7 // indirect
golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d // indirect golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect
golang.org/x/text v0.3.4 // indirect golang.org/x/text v0.3.4 // indirect
gopkg.in/square/go-jose.v2 v2.5.1 // indirect gopkg.in/square/go-jose.v2 v2.5.1 // indirect

15
go.sum
View file

@ -115,6 +115,8 @@ github.com/go-acme/lego/v4 v4.4.0 h1:uHhU5LpOYQOdp3aDU+XY2bajseu8fuExphTL1Ss6/Fc
github.com/go-acme/lego/v4 v4.4.0/go.mod h1:l3+tFUFZb590dWcqhWZegynUthtaHJbG2fevUpoOOE0= github.com/go-acme/lego/v4 v4.4.0/go.mod h1:l3+tFUFZb590dWcqhWZegynUthtaHJbG2fevUpoOOE0=
github.com/go-chi/chi v4.0.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= github.com/go-chi/chi v4.0.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
github.com/go-cmd/cmd v1.0.5/go.mod h1:y8q8qlK5wQibcw63djSl/ntiHUHXHGdCkPk0j4QeW4s= github.com/go-cmd/cmd v1.0.5/go.mod h1:y8q8qlK5wQibcw63djSl/ntiHUHXHGdCkPk0j4QeW4s=
github.com/go-co-op/gocron v1.15.0 h1:XmiPazahD9aq0/QdK5toCVHfgTXfrZ/s83RpAgzr6SM=
github.com/go-co-op/gocron v1.15.0/go.mod h1:On9zUZTv7FBeuj9D/cdYyAWcPUiLqqAx7nsPHd0EmKM=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
@ -366,6 +368,8 @@ github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDa
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rainycape/memcache v0.0.0-20150622160815-1031fa0ce2f2/go.mod h1:7tZKcyumwBO6qip7RNQ5r77yrssm9bfCowcLEBcU5IA= github.com/rainycape/memcache v0.0.0-20150622160815-1031fa0ce2f2/go.mod h1:7tZKcyumwBO6qip7RNQ5r77yrssm9bfCowcLEBcU5IA=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
@ -406,13 +410,16 @@ github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5q
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.3.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.3.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.5 h1:s5PTfem8p8EbKQOctVV53k6jCJt3UX4IEJzwh+C324Q=
github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tklauser/go-sysconf v0.3.7 h1:HT7h4+536gjqeq1ZIJPgOl1rg1XFatQGVZWp7Py53eg= github.com/tklauser/go-sysconf v0.3.7 h1:HT7h4+536gjqeq1ZIJPgOl1rg1XFatQGVZWp7Py53eg=
github.com/tklauser/go-sysconf v0.3.7/go.mod h1:JZIdXh4RmBvZDBZ41ld2bGxRV3n4daiiqA3skYhAoQ4= github.com/tklauser/go-sysconf v0.3.7/go.mod h1:JZIdXh4RmBvZDBZ41ld2bGxRV3n4daiiqA3skYhAoQ4=
@ -534,8 +541,9 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180622082034-63fc586f45fe/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180622082034-63fc586f45fe/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -707,8 +715,9 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/sqlite v1.1.4 h1:PDzwYE+sI6De2+mxAneV9Xs11+ZyKV6oxD3wDGkaNvM= gorm.io/driver/sqlite v1.1.4 h1:PDzwYE+sI6De2+mxAneV9Xs11+ZyKV6oxD3wDGkaNvM=
gorm.io/driver/sqlite v1.1.4/go.mod h1:mJCeTFr7+crvS+TRnWc5Z3UvwxUN1BGBLMrf5LA9DYw= gorm.io/driver/sqlite v1.1.4/go.mod h1:mJCeTFr7+crvS+TRnWc5Z3UvwxUN1BGBLMrf5LA9DYw=
gorm.io/gorm v1.20.7/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw= gorm.io/gorm v1.20.7/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=

122
main.go
View file

@ -1,74 +1,84 @@
package main package main
import ( import (
"context" "context"
"flag" "flag"
"github.com/0xJacky/Nginx-UI/server/analytic" "github.com/0xJacky/Nginx-UI/server/analytic"
"github.com/0xJacky/Nginx-UI/server/model" "github.com/0xJacky/Nginx-UI/server/model"
"github.com/0xJacky/Nginx-UI/server/router" "github.com/0xJacky/Nginx-UI/server/router"
"github.com/0xJacky/Nginx-UI/server/settings" "github.com/0xJacky/Nginx-UI/server/settings"
"github.com/0xJacky/Nginx-UI/server/tool" "github.com/0xJacky/Nginx-UI/server/tool"
"github.com/0xJacky/Nginx-UI/server/tool/nginx" "github.com/0xJacky/Nginx-UI/server/tool/nginx"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"log" "github.com/go-co-op/gocron"
"mime" "log"
"net/http" "mime"
"os/signal" "net/http"
"syscall" "os/signal"
"time" "syscall"
"time"
) )
func main() { func main() {
// Create context that listens for the interrupt signal from the OS. // Create context that listens for the interrupt signal from the OS.
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer stop() defer stop()
// Hack: fix wrong Content Type of .js file on some OS platforms // Hack: fix wrong Content Type of .js file on some OS platforms
// See https://github.com/golang/go/issues/32350 // See https://github.com/golang/go/issues/32350
_ = mime.AddExtensionType(".js", "text/javascript; charset=utf-8") _ = mime.AddExtensionType(".js", "text/javascript; charset=utf-8")
var confPath string var confPath string
flag.StringVar(&confPath, "config", "app.ini", "Specify the configuration file") flag.StringVar(&confPath, "config", "app.ini", "Specify the configuration file")
flag.Parse() flag.Parse()
gin.SetMode(settings.ServerSettings.RunMode) gin.SetMode(settings.ServerSettings.RunMode)
settings.Init(confPath) settings.Init(confPath)
log.Printf("nginx config dir path: %s", nginx.GetNginxConfPath("")) log.Printf("nginx config dir path: %s", nginx.GetNginxConfPath(""))
if "" != settings.ServerSettings.JwtSecret { if "" != settings.ServerSettings.JwtSecret {
model.Init() model.Init()
go tool.AutoCert()
go analytic.RecordServerAnalytic()
}
srv := &http.Server{ s := gocron.NewScheduler(time.UTC)
Addr: ":" + settings.ServerSettings.HttpPort, job, err := s.Every(1).Hour().SingletonMode().Do(tool.AutoCert)
Handler: router.InitRouter(),
}
// Initializing the server in a goroutine so that if err != nil {
// it won't block the graceful shutdown handling below log.Fatalf("AutoCert Job: %v, Err: %v\n", job, err)
go func() { }
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("listen: %s\n", err)
}
}()
// Listen for the interrupt signal. s.StartAsync()
<-ctx.Done()
// Restore default behavior on the interrupt signal and notify user of shutdown. go analytic.RecordServerAnalytic()
stop() }
log.Println("shutting down gracefully, press Ctrl+C again to force")
// The context is used to inform the server it has 5 seconds to finish srv := &http.Server{
// the request it is currently handling Addr: ":" + settings.ServerSettings.HttpPort,
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) Handler: router.InitRouter(),
defer cancel() }
if err := srv.Shutdown(ctx); err != nil {
log.Fatal("Server forced to shutdown: ", err)
}
log.Println("Server exiting") // Initializing the server in a goroutine so that
// it won't block the graceful shutdown handling below
go func() {
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("listen: %s\n", err)
}
}()
// Listen for the interrupt signal.
<-ctx.Done()
// Restore default behavior on the interrupt signal and notify user of shutdown.
stop()
log.Println("shutting down gracefully, press Ctrl+C again to force")
// The context is used to inform the server it has 5 seconds to finish
// the request it is currently handling
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := srv.Shutdown(ctx); err != nil {
log.Fatal("Server forced to shutdown: ", err)
}
log.Println("Server exiting")
} }

View file

@ -1,96 +1,115 @@
package analytic package analytic
import ( import (
"github.com/shirou/gopsutil/v3/cpu" "github.com/go-acme/lego/v4/log"
"github.com/shirou/gopsutil/v3/disk" "github.com/shirou/gopsutil/v3/cpu"
"github.com/shirou/gopsutil/v3/net" "github.com/shirou/gopsutil/v3/disk"
"runtime" "github.com/shirou/gopsutil/v3/net"
"time" "runtime"
"time"
) )
func getTotalDiskIO() (read, write uint64) { func getTotalDiskIO() (read, write uint64) {
diskIOCounters, _ := disk.IOCounters() diskIOCounters, err := disk.IOCounters()
for _, v := range diskIOCounters { if err != nil {
write += v.WriteCount log.Println("getTotalDiskIO: get diskIOCounters err", err)
read += v.ReadCount return
} }
return for _, v := range diskIOCounters {
write += v.WriteCount
read += v.ReadCount
}
return
} }
func recordCpu(now time.Time) { func recordCpu(now time.Time) {
cpuTimesBefore, _ := cpu.Times(false) cpuTimesBefore, err := cpu.Times(false)
time.Sleep(1000 * time.Millisecond) if err != nil {
cpuTimesAfter, _ := cpu.Times(false) log.Println("recordCpu: get cpuTimesBefore err", err)
threadNum := runtime.GOMAXPROCS(0) return
}
time.Sleep(1000 * time.Millisecond)
cpuTimesAfter, err := cpu.Times(false)
if err != nil {
log.Println("recordCpu: get cpuTimesAfter err", err)
return
}
threadNum := runtime.GOMAXPROCS(0)
cpuUserUsage := (cpuTimesAfter[0].User - cpuTimesBefore[0].User) / (float64(1000*threadNum) / 1000) cpuUserUsage := (cpuTimesAfter[0].User - cpuTimesBefore[0].User) / (float64(1000*threadNum) / 1000)
cpuUserUsage *= 100 cpuUserUsage *= 100
cpuSystemUsage := (cpuTimesAfter[0].System - cpuTimesBefore[0].System) / (float64(1000*threadNum) / 1000) cpuSystemUsage := (cpuTimesAfter[0].System - cpuTimesBefore[0].System) / (float64(1000*threadNum) / 1000)
cpuSystemUsage *= 100 cpuSystemUsage *= 100
u := usage{ u := usage{
Time: now, Time: now,
Usage: cpuUserUsage, Usage: cpuUserUsage,
} }
CpuUserRecord = append(CpuUserRecord, u) CpuUserRecord = append(CpuUserRecord, u)
s := usage{ s := usage{
Time: now, Time: now,
Usage: cpuUserUsage + cpuSystemUsage, Usage: cpuUserUsage + cpuSystemUsage,
} }
CpuTotalRecord = append(CpuTotalRecord, s) CpuTotalRecord = append(CpuTotalRecord, s)
if len(CpuUserRecord) > 100 { if len(CpuUserRecord) > 100 {
CpuUserRecord = CpuUserRecord[1:] CpuUserRecord = CpuUserRecord[1:]
} }
if len(CpuTotalRecord) > 100 { if len(CpuTotalRecord) > 100 {
CpuTotalRecord = CpuTotalRecord[1:] CpuTotalRecord = CpuTotalRecord[1:]
} }
} }
func recordNetwork(now time.Time) { func recordNetwork(now time.Time) {
network, _ := net.IOCounters(false) network, err := net.IOCounters(false)
if len(network) == 0 {
return if err != nil {
} log.Println("recordNetwork: get network err", err)
NetRecvRecord = append(NetRecvRecord, usage{ return
Time: now, }
Usage: network[0].BytesRecv - LastNetRecv,
}) if len(network) == 0 {
NetSentRecord = append(NetSentRecord, usage{ return
Time: now, }
Usage: network[0].BytesSent - LastNetSent, NetRecvRecord = append(NetRecvRecord, usage{
}) Time: now,
LastNetRecv = network[0].BytesRecv Usage: network[0].BytesRecv - LastNetRecv,
LastNetSent = network[0].BytesSent })
if len(NetRecvRecord) > 100 { NetSentRecord = append(NetSentRecord, usage{
NetRecvRecord = NetRecvRecord[1:] Time: now,
} Usage: network[0].BytesSent - LastNetSent,
if len(NetSentRecord) > 100 { })
NetSentRecord = NetSentRecord[1:] LastNetRecv = network[0].BytesRecv
} LastNetSent = network[0].BytesSent
if len(NetRecvRecord) > 100 {
NetRecvRecord = NetRecvRecord[1:]
}
if len(NetSentRecord) > 100 {
NetSentRecord = NetSentRecord[1:]
}
} }
func recordDiskIO(now time.Time) { func recordDiskIO(now time.Time) {
readCount, writeCount := getTotalDiskIO() readCount, writeCount := getTotalDiskIO()
DiskReadRecord = append(DiskReadRecord, usage{ DiskReadRecord = append(DiskReadRecord, usage{
Time: now, Time: now,
Usage: readCount - LastDiskReads, Usage: readCount - LastDiskReads,
}) })
DiskWriteRecord = append(DiskWriteRecord, usage{ DiskWriteRecord = append(DiskWriteRecord, usage{
Time: now, Time: now,
Usage: writeCount - LastDiskWrites, Usage: writeCount - LastDiskWrites,
}) })
if len(DiskReadRecord) > 100 { if len(DiskReadRecord) > 100 {
DiskReadRecord = DiskReadRecord[1:] DiskReadRecord = DiskReadRecord[1:]
} }
if len(DiskWriteRecord) > 100 { if len(DiskWriteRecord) > 100 {
DiskWriteRecord = DiskWriteRecord[1:] DiskWriteRecord = DiskWriteRecord[1:]
} }
LastDiskWrites = writeCount LastDiskWrites = writeCount
LastDiskReads = readCount LastDiskReads = readCount
} }

View file

@ -1,75 +1,73 @@
package api package api
import ( import (
"github.com/0xJacky/Nginx-UI/server/model" "github.com/0xJacky/Nginx-UI/server/model"
"github.com/0xJacky/Nginx-UI/server/settings" "github.com/0xJacky/Nginx-UI/server/settings"
"github.com/0xJacky/Nginx-UI/server/tool" "github.com/gin-gonic/gin"
"github.com/gin-gonic/gin" "github.com/google/uuid"
"github.com/google/uuid" "golang.org/x/crypto/bcrypt"
"golang.org/x/crypto/bcrypt" "net/http"
"net/http"
) )
func installLockStatus() bool { func installLockStatus() bool {
return "" != settings.ServerSettings.JwtSecret return "" != settings.ServerSettings.JwtSecret
} }
func InstallLockCheck(c *gin.Context) { func InstallLockCheck(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{ c.JSON(http.StatusOK, gin.H{
"lock": installLockStatus(), "lock": installLockStatus(),
}) })
} }
type InstallJson struct { type InstallJson struct {
Email string `json:"email" binding:"required,email"` Email string `json:"email" binding:"required,email"`
Username string `json:"username" binding:"required,max=255"` Username string `json:"username" binding:"required,max=255"`
Password string `json:"password" binding:"required,max=255"` Password string `json:"password" binding:"required,max=255"`
Database string `json:"database"` Database string `json:"database"`
} }
func InstallNginxUI(c *gin.Context) { func InstallNginxUI(c *gin.Context) {
// 安装过就别访问了 // 安装过就别访问了
if installLockStatus() { if installLockStatus() {
c.JSON(http.StatusForbidden, gin.H{ c.JSON(http.StatusForbidden, gin.H{
"message": "installed", "message": "installed",
}) })
return return
} }
var json InstallJson var json InstallJson
ok := BindAndValid(c, &json) ok := BindAndValid(c, &json)
if !ok { if !ok {
return return
} }
settings.ServerSettings.JwtSecret = uuid.New().String() settings.ServerSettings.JwtSecret = uuid.New().String()
settings.ServerSettings.Email = json.Email settings.ServerSettings.Email = json.Email
if "" != json.Database { if "" != json.Database {
settings.ServerSettings.Database = json.Database settings.ServerSettings.Database = json.Database
} }
settings.ReflectFrom() settings.ReflectFrom()
err := settings.Save() err := settings.Save()
if err != nil { if err != nil {
ErrHandler(c, err) ErrHandler(c, err)
return return
} }
// Init model and auto cert // Init model
model.Init() model.Init()
go tool.AutoCert()
curd := model.NewCurd(&model.Auth{}) curd := model.NewCurd(&model.Auth{})
pwd, _ := bcrypt.GenerateFromPassword([]byte(json.Password), bcrypt.DefaultCost) pwd, _ := bcrypt.GenerateFromPassword([]byte(json.Password), bcrypt.DefaultCost)
err = curd.Add(&model.Auth{ err = curd.Add(&model.Auth{
Name: json.Username, Name: json.Username,
Password: string(pwd), Password: string(pwd),
}) })
if err != nil { if err != nil {
ErrHandler(c, err) ErrHandler(c, err)
return return
} }
c.JSON(http.StatusOK, gin.H{ c.JSON(http.StatusOK, gin.H{
"message": "ok", "message": "ok",
}) })
} }

View file

@ -44,28 +44,30 @@ func (u *MyUser) GetPrivateKey() crypto.PrivateKey {
} }
func AutoCert() { func AutoCert() {
for { defer func() {
log.Println("[AutoCert] Start") if err := recover(); err != nil {
autoCertList := model.GetAutoCertList() log.Println("[AutoCert] Recover", err)
for i := range autoCertList { }
domain := autoCertList[i].Domain }()
key, err := GetCertInfo(domain) log.Println("[AutoCert] Start")
if err != nil { autoCertList := model.GetAutoCertList()
log.Println("GetCertInfo Err", err) for i := range autoCertList {
// 获取证书信息失败,本次跳过 domain := autoCertList[i].Domain
continue key, err := GetCertInfo(domain)
} if err != nil {
// 未到一个月 log.Println("GetCertInfo Err", err)
if time.Now().Before(key.NotBefore.AddDate(0, 1, 0)) { // 获取证书信息失败,本次跳过
continue continue
} }
// 过一个月了,重新申请证书 // 未到一个月
err = IssueCert(domain) if time.Now().Before(key.NotBefore.AddDate(0, 1, 0)) {
if err != nil { continue
log.Println(err) }
} // 过一个月了,重新申请证书
err = IssueCert(domain)
if err != nil {
log.Println(err)
} }
time.Sleep(1 * time.Hour)
} }
} }