mirror of
https://github.com/0xJacky/nginx-ui.git
synced 2025-05-11 10:25:52 +02:00
bug fix
This commit is contained in:
parent
ad421905a8
commit
dd6e19657a
162 changed files with 15071 additions and 932 deletions
|
@ -1,104 +1,96 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/0xJacky/Nginx-UI/server/tool"
|
||||
"github.com/dustin/go-humanize"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/mackerelio/go-osstat/cpu"
|
||||
"github.com/mackerelio/go-osstat/loadavg"
|
||||
"github.com/mackerelio/go-osstat/memory"
|
||||
"github.com/mackerelio/go-osstat/uptime"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/shirou/gopsutil/v3/cpu"
|
||||
"github.com/shirou/gopsutil/v3/disk"
|
||||
"github.com/shirou/gopsutil/v3/host"
|
||||
"github.com/shirou/gopsutil/v3/load"
|
||||
"github.com/shirou/gopsutil/v3/mem"
|
||||
"net/http"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/dustin/go-humanize"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
var upGrader = websocket.Upgrader{
|
||||
CheckOrigin: func(r *http.Request) bool {
|
||||
return true
|
||||
},
|
||||
}
|
||||
|
||||
func Analytic(c *gin.Context) {
|
||||
// upgrade http to websocket
|
||||
ws, err := upGrader.Upgrade(c.Writer, c.Request, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var upGrader = websocket.Upgrader{
|
||||
CheckOrigin: func(r *http.Request) bool {
|
||||
return true
|
||||
},
|
||||
}
|
||||
// upgrade http to websocket
|
||||
ws, err := upGrader.Upgrade(c.Writer, c.Request, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer ws.Close()
|
||||
defer ws.Close()
|
||||
|
||||
for {
|
||||
// read
|
||||
mt, message, err := ws.ReadMessage()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
if string(message) == "ping" {
|
||||
response := make(gin.H)
|
||||
|
||||
response := make(gin.H)
|
||||
for {
|
||||
// read
|
||||
mt, message, err := ws.ReadMessage()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
for {
|
||||
|
||||
memoryStat, err := memory.Get()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
response["memory_total"] = humanize.Bytes(memoryStat.Total)
|
||||
response["memory_used"] = humanize.Bytes(memoryStat.Used)
|
||||
response["memory_cached"] = humanize.Bytes(memoryStat.Cached)
|
||||
response["memory_free"] = humanize.Bytes(memoryStat.Free)
|
||||
memoryStat, err := mem.VirtualMemory()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
response["memory_pressure"] = memoryStat.Used * 100 / memoryStat.Total
|
||||
response["memory_total"] = humanize.Bytes(memoryStat.Total)
|
||||
response["memory_used"] = humanize.Bytes(memoryStat.Used)
|
||||
response["memory_cached"] = humanize.Bytes(memoryStat.Cached)
|
||||
response["memory_free"] = humanize.Bytes(memoryStat.Free)
|
||||
|
||||
before, err := cpu.Get()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
time.Sleep(time.Duration(1) * time.Second)
|
||||
after, err := cpu.Get()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
response["memory_pressure"], _ = strconv.ParseFloat(fmt.Sprintf("%.2f", memoryStat.UsedPercent), 64)
|
||||
|
||||
total := float64(after.Total - before.Total)
|
||||
cpuTimesBefore, _ := cpu.Times(false)
|
||||
time.Sleep(1000 * time.Millisecond)
|
||||
cpuTimesAfter, _ := cpu.Times(false)
|
||||
threadNum := runtime.GOMAXPROCS(0)
|
||||
|
||||
response["cpu_user"], _ = strconv.ParseFloat(fmt.Sprintf("%.2f",
|
||||
float64(after.User-before.User)/total*100), 64)
|
||||
cpuUserUsage := (cpuTimesAfter[0].User - cpuTimesBefore[0].User) / (float64(1000*threadNum) / 1000)
|
||||
cpuSystemUsage := (cpuTimesAfter[0].System - cpuTimesBefore[0].System) / (float64(1000*threadNum) / 1000)
|
||||
|
||||
response["cpu_system"], _ = strconv.ParseFloat(fmt.Sprintf("%.2f",
|
||||
float64(after.System-before.System)/total*100), 64)
|
||||
|
||||
response["cpu_idle"], _ = strconv.ParseFloat(fmt.Sprintf("%.2f",
|
||||
float64(after.Idle-before.Idle)/total*100), 64)
|
||||
response["cpu_user"], _ = strconv.ParseFloat(fmt.Sprintf("%.2f",
|
||||
cpuUserUsage*100), 64)
|
||||
|
||||
response["uptime"], _ = uptime.Get()
|
||||
response["uptime"] = response["uptime"].(time.Duration) / time.Second
|
||||
response["loadavg"], _ = loadavg.Get()
|
||||
response["cpu_system"], _ = strconv.ParseFloat(fmt.Sprintf("%.2f",
|
||||
cpuSystemUsage*100), 64)
|
||||
|
||||
used, _total, percentage, err := tool.DiskUsage(".")
|
||||
response["cpu_idle"], _ = strconv.ParseFloat(fmt.Sprintf("%.2f",
|
||||
(1-cpuUserUsage+cpuSystemUsage)*100), 64)
|
||||
|
||||
response["disk_used"] = used
|
||||
response["disk_total"] = _total
|
||||
response["disk_percentage"] = percentage
|
||||
response["uptime"], _ = host.Uptime()
|
||||
response["loadavg"], _ = load.Avg()
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
m, err := json.Marshal(response)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
message = m
|
||||
}
|
||||
// write
|
||||
err = ws.WriteMessage(mt, message)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
diskUsage, _ := disk.Usage(".")
|
||||
|
||||
response["disk_used"] = humanize.Bytes(diskUsage.Used)
|
||||
response["disk_total"] = humanize.Bytes(diskUsage.Total)
|
||||
response["disk_percentage"], _ = strconv.ParseFloat(fmt.Sprintf("%.2f", diskUsage.UsedPercent), 64)
|
||||
|
||||
m, _ := json.Marshal(response)
|
||||
message = m
|
||||
|
||||
// write
|
||||
err = ws.WriteMessage(mt, message)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
time.Sleep(800 * time.Microsecond)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,46 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"log"
|
||||
"net/http"
|
||||
"github.com/gin-gonic/gin"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
ut "github.com/go-playground/universal-translator"
|
||||
val "github.com/go-playground/validator/v10"
|
||||
)
|
||||
|
||||
func ErrorHandler(c *gin.Context, err error) {
|
||||
log.Println(err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"message": err.Error(),
|
||||
})
|
||||
log.Println(err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"message": err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
type ValidError struct {
|
||||
Key string
|
||||
Message string
|
||||
}
|
||||
|
||||
type ValidErrors gin.H
|
||||
|
||||
func BindAndValid(c *gin.Context, v interface{}) (bool, ValidErrors) {
|
||||
errs := make(ValidErrors)
|
||||
err := c.ShouldBind(v)
|
||||
if err != nil {
|
||||
|
||||
v := c.Value("trans")
|
||||
trans, _ := v.(ut.Translator)
|
||||
verrs, ok := err.(val.ValidationErrors)
|
||||
if !ok {
|
||||
return false, errs
|
||||
}
|
||||
|
||||
for key, value := range verrs.Translate(trans) {
|
||||
errs[key] = value
|
||||
}
|
||||
|
||||
return false, errs
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
|
|
@ -1,34 +1,38 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"github.com/0xJacky/Nginx-UI/server/model"
|
||||
"github.com/gin-gonic/gin"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"log"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type LoginUser struct {
|
||||
Name string `json:"name"`
|
||||
Password string `json:"password"`
|
||||
Name string `json:"name" binding:"required,max=255"`
|
||||
Password string `json:"password" binding:"required,max=255"`
|
||||
}
|
||||
|
||||
func Login(c *gin.Context) {
|
||||
var user LoginUser
|
||||
err := c.BindJSON(&user)
|
||||
ok, verrs := BindAndValid(c, &user)
|
||||
if !ok {
|
||||
c.JSON(http.StatusNotAcceptable, gin.H{
|
||||
"errors": verrs,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
u, err := model.GetUser(user.Name)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
c.JSON(http.StatusForbidden, gin.H{
|
||||
"message": "Incorrect name or password",
|
||||
})
|
||||
return
|
||||
}
|
||||
var u model.Auth
|
||||
u, err = model.GetUser(user.Name)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
data := []byte(user.Password)
|
||||
has := md5.Sum(data)
|
||||
md5str := fmt.Sprintf("%x", has) // 将[]byte转成16进制
|
||||
if u.Password != md5str {
|
||||
|
||||
if err = bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(user.Password)); err != nil {
|
||||
c.JSON(http.StatusForbidden, gin.H{
|
||||
"message": "Incorrect name or password",
|
||||
})
|
||||
|
|
|
@ -5,7 +5,8 @@ import (
|
|||
"encoding/json"
|
||||
"github.com/0xJacky/Nginx-UI/server/tool"
|
||||
"github.com/gin-gonic/gin"
|
||||
"io"
|
||||
"github.com/gorilla/websocket"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
|
@ -69,6 +70,11 @@ func CertInfo(c *gin.Context) {
|
|||
|
||||
func IssueCert(c *gin.Context) {
|
||||
domain := c.Param("domain")
|
||||
var upGrader = websocket.Upgrader{
|
||||
CheckOrigin: func(r *http.Request) bool {
|
||||
return true
|
||||
},
|
||||
}
|
||||
|
||||
// upgrade http to websocket
|
||||
ws, err := upGrader.Upgrade(c.Writer, c.Request, nil)
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/server/tool"
|
||||
"github.com/gin-gonic/gin"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"github.com/0xJacky/Nginx-UI/server/tool"
|
||||
"github.com/gin-gonic/gin"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func GetDomains(c *gin.Context) {
|
||||
orderBy := c.Query("order_by")
|
||||
sort := c.DefaultQuery("sort", "desc")
|
||||
orderBy := c.Query("order_by")
|
||||
sort := c.DefaultQuery("sort", "desc")
|
||||
|
||||
mySort := map[string]string{
|
||||
"enabled": "bool",
|
||||
"name": "string",
|
||||
"modify": "time",
|
||||
}
|
||||
mySort := map[string]string{
|
||||
"enabled": "bool",
|
||||
"name": "string",
|
||||
"modify": "time",
|
||||
}
|
||||
|
||||
configFiles, err := ioutil.ReadDir(tool.GetNginxConfPath("sites-available"))
|
||||
|
||||
|
@ -75,7 +75,7 @@ func GetDomain(c *gin.Context) {
|
|||
c.JSON(http.StatusNotFound, gin.H{
|
||||
"message": err.Error(),
|
||||
})
|
||||
return
|
||||
return
|
||||
}
|
||||
ErrorHandler(c, err)
|
||||
return
|
||||
|
@ -83,8 +83,8 @@ func GetDomain(c *gin.Context) {
|
|||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"enabled": enabled,
|
||||
"name": name,
|
||||
"config": string(content),
|
||||
"name": name,
|
||||
"config": string(content),
|
||||
})
|
||||
|
||||
}
|
||||
|
@ -98,34 +98,43 @@ func EditDomain(c *gin.Context) {
|
|||
path := filepath.Join(tool.GetNginxConfPath("sites-available"), name)
|
||||
|
||||
if _, err = os.Stat(path); err == nil {
|
||||
origContent, err = ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
ErrorHandler(c, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if request["content"] != "" && request["content"] != string(origContent) {
|
||||
// model.CreateBackup(path)
|
||||
err := ioutil.WriteFile(path, []byte(request["content"].(string)), 0644)
|
||||
origContent, err = ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
ErrorHandler(c, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := os.Stat(filepath.Join(tool.GetNginxConfPath("sites-enabled"), name)); err == nil {
|
||||
output := tool.ReloadNginx()
|
||||
|
||||
if output != "" {
|
||||
if request["content"] != "" && request["content"] != string(origContent) {
|
||||
// model.CreateBackup(path)
|
||||
err = ioutil.WriteFile(path, []byte(request["content"].(string)), 0644)
|
||||
if err != nil {
|
||||
ErrorHandler(c, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
enabledConfigFilePath := filepath.Join(tool.GetNginxConfPath("sites-enabled"), name)
|
||||
if _, err = os.Stat(enabledConfigFilePath); err == nil {
|
||||
// 测试配置文件,不通过则撤回修改
|
||||
err = tool.TestNginxConf(enabledConfigFilePath)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"message": output,
|
||||
"message": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
output := tool.ReloadNginx()
|
||||
|
||||
if output != "" {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"message": output,
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
GetDomain(c)
|
||||
GetDomain(c)
|
||||
}
|
||||
|
||||
func EnableDomain(c *gin.Context) {
|
||||
|
@ -146,14 +155,24 @@ func EnableDomain(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
output := tool.ReloadNginx()
|
||||
|
||||
if output != "" {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"message": output,
|
||||
})
|
||||
// 测试配置文件,不通过则撤回修改
|
||||
err = tool.TestNginxConf(enabledConfigFilePath)
|
||||
if err != nil {
|
||||
_ = os.Remove(enabledConfigFilePath)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"message": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
output := tool.ReloadNginx()
|
||||
|
||||
if output != "" {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"message": output,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "ok",
|
||||
|
@ -180,19 +199,18 @@ func DisableDomain(c *gin.Context) {
|
|||
output := tool.ReloadNginx()
|
||||
|
||||
if output != "" {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"message": output,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"message": output,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "ok",
|
||||
})
|
||||
}
|
||||
|
||||
func DeleteDomain(c *gin.Context) {
|
||||
func DeleteDomain(c *gin.Context) {
|
||||
var err error
|
||||
name := c.Param("name")
|
||||
availablePath := filepath.Join(tool.GetNginxConfPath("sites-available"), name)
|
||||
|
|
135
server/api/user.go
Normal file
135
server/api/user.go
Normal file
|
@ -0,0 +1,135 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/0xJacky/Nginx-UI/server/model"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/spf13/cast"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func GetUsers(c *gin.Context) {
|
||||
curd := model.NewCurd(&model.Auth{})
|
||||
|
||||
var list []model.Auth
|
||||
err := curd.GetList(&list)
|
||||
|
||||
if err != nil {
|
||||
ErrorHandler(c, err)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"data": list,
|
||||
})
|
||||
}
|
||||
|
||||
func GetUser(c *gin.Context) {
|
||||
curd := model.NewCurd(&model.Auth{})
|
||||
id := c.Param("id")
|
||||
|
||||
var user model.Auth
|
||||
err := curd.First(&user, id)
|
||||
|
||||
if err != nil {
|
||||
ErrorHandler(c, err)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, user)
|
||||
}
|
||||
|
||||
type UserJson struct {
|
||||
Name string `json:"name" binding:"required,max=255"`
|
||||
Password string `json:"password" binding:"max=255"`
|
||||
}
|
||||
|
||||
func AddUser(c *gin.Context) {
|
||||
var json UserJson
|
||||
ok, verrs := BindAndValid(c, &json)
|
||||
if !ok {
|
||||
c.JSON(http.StatusNotAcceptable, gin.H{
|
||||
"errors": verrs,
|
||||
})
|
||||
return
|
||||
}
|
||||
curd := model.NewCurd(&model.Auth{})
|
||||
|
||||
pwd, err := bcrypt.GenerateFromPassword([]byte(json.Password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
ErrorHandler(c, err)
|
||||
return
|
||||
}
|
||||
json.Password = string(pwd)
|
||||
|
||||
user := model.Auth{
|
||||
Name: json.Name,
|
||||
Password: json.Password,
|
||||
}
|
||||
|
||||
err = curd.Add(&user)
|
||||
|
||||
if err != nil {
|
||||
ErrorHandler(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, user)
|
||||
|
||||
}
|
||||
|
||||
func EditUser(c *gin.Context) {
|
||||
var json UserJson
|
||||
ok, verrs := BindAndValid(c, &json)
|
||||
if !ok {
|
||||
c.JSON(http.StatusNotAcceptable, gin.H{
|
||||
"errors": verrs,
|
||||
})
|
||||
}
|
||||
curd := model.NewCurd(&model.Auth{})
|
||||
|
||||
var user, edit model.Auth
|
||||
|
||||
err := curd.First(&user, c.Param("id"))
|
||||
|
||||
if err != nil {
|
||||
ErrorHandler(c, err)
|
||||
return
|
||||
}
|
||||
edit.Name = json.Name
|
||||
|
||||
// 改密码加密
|
||||
if json.Password != "" {
|
||||
var pwd []byte
|
||||
pwd, err = bcrypt.GenerateFromPassword([]byte(json.Password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
ErrorHandler(c, err)
|
||||
return
|
||||
}
|
||||
edit.Password = string(pwd)
|
||||
}
|
||||
|
||||
err = curd.Edit(&user, &edit)
|
||||
|
||||
if err != nil {
|
||||
ErrorHandler(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, user)
|
||||
}
|
||||
|
||||
func DeleteUser(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
|
||||
if cast.ToInt(id) == 1 {
|
||||
ErrorHandler(c, errors.New("不允许删除默认账户"))
|
||||
return
|
||||
}
|
||||
curd := model.NewCurd(&model.Auth{})
|
||||
err := curd.Delete(&model.Auth{}, "id", id)
|
||||
if err != nil {
|
||||
ErrorHandler(c, err)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusNoContent, gin.H{})
|
||||
}
|
|
@ -7,9 +7,13 @@ require (
|
|||
github.com/dustin/go-humanize v1.0.0
|
||||
github.com/gin-gonic/gin v1.7.4
|
||||
github.com/go-acme/lego/v4 v4.4.0
|
||||
github.com/go-playground/universal-translator v0.17.0
|
||||
github.com/go-playground/validator/v10 v10.4.1
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/mackerelio/go-osstat v0.2.0
|
||||
github.com/shirou/gopsutil/v3 v3.21.7
|
||||
github.com/spf13/cast v1.3.1
|
||||
github.com/unknwon/com v1.0.1
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
|
||||
gopkg.in/ini.v1 v1.62.0
|
||||
gorm.io/driver/sqlite v1.1.4
|
||||
gorm.io/gorm v1.21.14
|
||||
|
|
|
@ -44,6 +44,8 @@ github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAE
|
|||
github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87/go.mod h1:iGLljf5n9GjT6kc0HBvyI1nOKnGQbNB66VzSNbK5iks=
|
||||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||
github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA=
|
||||
github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8=
|
||||
github.com/akamai/AkamaiOPEN-edgegrid-golang v1.1.0/go.mod h1:kX6YddBkXqqywAe8c9LyvgTCyFuZCTMF4cRPQhc3Fy8=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
|
@ -118,6 +120,8 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2
|
|||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY=
|
||||
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
|
||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
|
||||
|
@ -261,8 +265,6 @@ github.com/liquidweb/go-lwApi v0.0.0-20190605172801-52a4864d2738/go.mod h1:0sYF9
|
|||
github.com/liquidweb/go-lwApi v0.0.5/go.mod h1:0sYF9rMXb0vlG+4SzdiGMXHheCZxjguMq+Zb4S2BfBs=
|
||||
github.com/liquidweb/liquidweb-cli v0.6.9/go.mod h1:cE1uvQ+x24NGUL75D0QagOFCG8Wdvmwu8aL9TLmA/eQ=
|
||||
github.com/liquidweb/liquidweb-go v1.6.3/go.mod h1:SuXXp+thr28LnjEw18AYtWwIbWMHSUiajPQs8T9c/Rc=
|
||||
github.com/mackerelio/go-osstat v0.2.0 h1:UVn9Am/OOj2Ig0LNNHLqiHeXsZWmMNcMPZ3h+z/8+h8=
|
||||
github.com/mackerelio/go-osstat v0.2.0/go.mod h1:UzRL8dMCCTqG5WdRtsxbuljMpZt9PCAGXqxPst5QtaY=
|
||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||
github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ=
|
||||
|
@ -364,6 +366,8 @@ github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb
|
|||
github.com/sacloud/libsacloud v1.36.2/go.mod h1:P7YAOVmnIn3DKHqCZcUKYUXmSwGBm3yS7IBEjKVSrjg=
|
||||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.7.0.20210127161313-bd30bebeac4f/go.mod h1:CJJ5VAbozOl0yEw7nHB9+7BXTJbIn6h7W+f6Gau5IP8=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/shirou/gopsutil/v3 v3.21.7 h1:PnTqQamUjwEDSgn+nBGu0qSDV/CfvyiR/gwTH3i7HTU=
|
||||
github.com/shirou/gopsutil/v3 v3.21.7/go.mod h1:RGl11Y7XMTQPmHh8F0ayC6haKNBgH4PXMJuTAcMOlz4=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
|
@ -383,6 +387,7 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO
|
|||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/afero v1.4.1/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
|
||||
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
|
@ -402,6 +407,10 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
|||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
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/go.mod h1:JZIdXh4RmBvZDBZ41ld2bGxRV3n4daiiqA3skYhAoQ4=
|
||||
github.com/tklauser/numcpus v0.2.3 h1:nQ0QYpiritP6ViFhrKYsiv6VVxOpum2Gks5GhnJbS/8=
|
||||
github.com/tklauser/numcpus v0.2.3/go.mod h1:vpEPS/JC+oZGGQ/My/vJnNsvMDQL6PwOqt8dsCw5j+E=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/transip/gotransip/v6 v6.2.0/go.mod h1:pQZ36hWWRahCUXkFWlx9Hs711gLd8J4qdgLdRzmtY+g=
|
||||
github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g=
|
||||
|
@ -542,6 +551,7 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
@ -563,8 +573,8 @@ golang.org/x/sys v0.0.0-20200918174421-af09f7315aff/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201110211018-35f3e6cf4a65/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210113181707-4bcb84eeeb78 h1:nVuTkr9L6Bq62qpUqKo/RnZCFfzDBL0bYo6w9OJUqZY=
|
||||
golang.org/x/sys v0.0.0-20210113181707-4bcb84eeeb78/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
|
BIN
server/main
Executable file
BIN
server/main
Executable file
Binary file not shown.
|
@ -1,7 +1,8 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/server/model"
|
||||
"flag"
|
||||
"github.com/0xJacky/Nginx-UI/server/model"
|
||||
"github.com/0xJacky/Nginx-UI/server/router"
|
||||
"github.com/0xJacky/Nginx-UI/server/settings"
|
||||
"github.com/0xJacky/Nginx-UI/server/tool"
|
||||
|
@ -9,11 +10,17 @@ import (
|
|||
)
|
||||
|
||||
func main() {
|
||||
settings.Init()
|
||||
var dbPath string
|
||||
var confPath string
|
||||
flag.StringVar(&confPath, "c", "app.ini", "Specify the conf path to load")
|
||||
flag.StringVar(&dbPath, "d", "database.db", "Specify the database path to load")
|
||||
flag.Parse()
|
||||
|
||||
settings.Init(confPath)
|
||||
|
||||
r := router.InitRouter()
|
||||
|
||||
model.Init()
|
||||
model.Init(dbPath)
|
||||
|
||||
log.Printf("nginx config dir path: %s", tool.GetNginxConfPath(""))
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ type Auth struct {
|
|||
Model
|
||||
|
||||
Name string `json:"name"`
|
||||
Password string `json:"password"`
|
||||
Password string `json:"-"`
|
||||
}
|
||||
|
||||
type AuthToken struct {
|
||||
|
|
38
server/model/curd.go
Normal file
38
server/model/curd.go
Normal file
|
@ -0,0 +1,38 @@
|
|||
package model
|
||||
|
||||
type Curd struct {
|
||||
Model interface{}
|
||||
}
|
||||
|
||||
func NewCurd(Model interface{}) *Curd {
|
||||
return &Curd{Model: Model}
|
||||
}
|
||||
|
||||
func (c *Curd) GetList(dest interface{}) (err error) {
|
||||
err = db.Model(c.Model).Scan(dest).Error
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Curd) First(dest interface{}, conds ...interface{}) (err error) {
|
||||
err = db.Model(c.Model).First(dest, conds).Error
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Curd) Add(value interface{}) (err error) {
|
||||
err = db.Model(c.Model).Create(value).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = db.Find(value).Error
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Curd) Edit(orig interface{}, new interface{}) (err error) {
|
||||
err = db.Model(orig).Updates(new).Error
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Curd) Delete(value interface{}, conds ...interface{}) (err error) {
|
||||
err = db.Model(c.Model).Delete(value, conds).Error
|
||||
return
|
||||
}
|
|
@ -1,20 +1,29 @@
|
|||
package model
|
||||
|
||||
import (
|
||||
"gorm.io/driver/sqlite"
|
||||
"gorm.io/gorm"
|
||||
"log"
|
||||
"gorm.io/driver/sqlite"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/logger"
|
||||
"log"
|
||||
"time"
|
||||
)
|
||||
|
||||
var db *gorm.DB
|
||||
|
||||
type Model struct {
|
||||
gorm.Model
|
||||
ID uint `gorm:"primarykey" json:"id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
DeletedAt *time.Time `gorm:"index" json:"deleted_at"`
|
||||
}
|
||||
|
||||
func Init() {
|
||||
func Init(dbPath string) {
|
||||
var err error
|
||||
db, err = gorm.Open(sqlite.Open("database.db"), &gorm.Config{})
|
||||
|
||||
db, err = gorm.Open(sqlite.Open(dbPath), &gorm.Config{
|
||||
Logger: logger.Default.LogMode(logger.Info),
|
||||
PrepareStmt: true,
|
||||
})
|
||||
log.Println("database.db")
|
||||
|
||||
if err != nil {
|
||||
|
@ -23,11 +32,11 @@ func Init() {
|
|||
|
||||
// Migrate the schema
|
||||
AutoMigrate(&ConfigBackup{})
|
||||
AutoMigrate(&Auth{})
|
||||
AutoMigrate(&AuthToken{})
|
||||
AutoMigrate(&Auth{})
|
||||
AutoMigrate(&AuthToken{})
|
||||
}
|
||||
|
||||
func AutoMigrate(model interface{}) {
|
||||
func AutoMigrate(model interface{}) {
|
||||
err := db.AutoMigrate(model)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
|
|
BIN
server/nginx-ui@linux-amd64
Executable file
BIN
server/nginx-ui@linux-amd64
Executable file
Binary file not shown.
|
@ -47,33 +47,37 @@ func InitRouter() *gin.Engine {
|
|||
"message": "Hello World",
|
||||
})
|
||||
})
|
||||
|
||||
r.GET("/analytic", api.Analytic)
|
||||
r.POST("/login", api.Login)
|
||||
r.DELETE("/logout", api.Logout)
|
||||
|
||||
endpoint := r.Group("/", authRequired())
|
||||
g := r.Group("/", authRequired())
|
||||
{
|
||||
endpoint.GET("domains", api.GetDomains)
|
||||
endpoint.GET("domain/:name", api.GetDomain)
|
||||
endpoint.POST("domain/:name", api.EditDomain)
|
||||
endpoint.POST("domain/:name/enable", api.EnableDomain)
|
||||
endpoint.POST("domain/:name/disable", api.DisableDomain)
|
||||
endpoint.DELETE("domain/:name", api.DeleteDomain)
|
||||
g.GET("/users", api.GetUsers)
|
||||
g.GET("/user/:id", api.GetUser)
|
||||
g.POST("/user", api.AddUser)
|
||||
g.POST("/user/:id", api.EditUser)
|
||||
g.DELETE("/user/:id", api.DeleteUser)
|
||||
|
||||
endpoint.GET("configs", api.GetConfigs)
|
||||
endpoint.GET("config/:name", api.GetConfig)
|
||||
endpoint.POST("config", api.AddConfig)
|
||||
endpoint.POST("config/:name", api.EditConfig)
|
||||
g.GET("domains", api.GetDomains)
|
||||
g.GET("domain/:name", api.GetDomain)
|
||||
g.POST("domain/:name", api.EditDomain)
|
||||
g.POST("domain/:name/enable", api.EnableDomain)
|
||||
g.POST("domain/:name/disable", api.DisableDomain)
|
||||
g.DELETE("domain/:name", api.DeleteDomain)
|
||||
|
||||
endpoint.GET("backups", api.GetFileBackupList)
|
||||
endpoint.GET("backup/:id", api.GetFileBackup)
|
||||
g.GET("configs", api.GetConfigs)
|
||||
g.GET("config/:name", api.GetConfig)
|
||||
g.POST("config", api.AddConfig)
|
||||
g.POST("config/:name", api.EditConfig)
|
||||
|
||||
endpoint.GET("template/:name", api.GetTemplate)
|
||||
g.GET("backups", api.GetFileBackupList)
|
||||
g.GET("backup/:id", api.GetFileBackup)
|
||||
|
||||
endpoint.GET("analytic", api.Analytic)
|
||||
g.GET("template/:name", api.GetTemplate)
|
||||
|
||||
endpoint.GET("cert/issue/:domain", api.IssueCert)
|
||||
endpoint.GET("cert/:domain/info", api.CertInfo)
|
||||
g.GET("cert/issue/:domain", api.IssueCert)
|
||||
g.GET("cert/:domain/info", api.CertInfo)
|
||||
}
|
||||
|
||||
return r
|
||||
|
|
|
@ -8,30 +8,31 @@ import (
|
|||
var Conf *ini.File
|
||||
|
||||
type Server struct {
|
||||
HttpPort string
|
||||
RunMode string
|
||||
WebSocketToken string
|
||||
JwtSecret string
|
||||
HTTPChallengePort string
|
||||
Email string
|
||||
HttpPort string
|
||||
RunMode string
|
||||
WebSocketToken string
|
||||
JwtSecret string
|
||||
HTTPChallengePort string
|
||||
Email string
|
||||
}
|
||||
|
||||
var ServerSettings = &Server{}
|
||||
|
||||
func Init() {
|
||||
var err error
|
||||
Conf, err = ini.Load("app.ini")
|
||||
if err != nil {
|
||||
log.Fatalf("setting.Setup, fail to parse 'app.ini': %v", err)
|
||||
}
|
||||
func Init(confPath string) {
|
||||
var err error
|
||||
|
||||
mapTo("server", ServerSettings)
|
||||
Conf, err = ini.Load(confPath)
|
||||
if err != nil {
|
||||
log.Fatalf("setting.Setup, fail to parse '%s': %v", confPath, err)
|
||||
}
|
||||
|
||||
mapTo("server", ServerSettings)
|
||||
|
||||
}
|
||||
|
||||
func mapTo(section string, v interface{}) {
|
||||
err := Conf.Section(section).MapTo(v)
|
||||
if err != nil {
|
||||
log.Fatalf("Cfg.MapTo %s err: %v", section, err)
|
||||
}
|
||||
err := Conf.Section(section).MapTo(v)
|
||||
if err != nil {
|
||||
log.Fatalf("Cfg.MapTo %s err: %v", section, err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,62 +1,36 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
humanize "github.com/dustin/go-humanize"
|
||||
"github.com/mackerelio/go-osstat/cpu"
|
||||
"github.com/mackerelio/go-osstat/disk"
|
||||
"github.com/mackerelio/go-osstat/memory"
|
||||
"os"
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
"fmt"
|
||||
"github.com/shirou/gopsutil/v3/cpu"
|
||||
"github.com/shirou/gopsutil/v3/disk"
|
||||
"github.com/shirou/gopsutil/v3/load"
|
||||
"github.com/shirou/gopsutil/v3/mem"
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestGetArch(t *testing.T) {
|
||||
fmt.Println("os:", runtime.GOOS)
|
||||
fmt.Println("threads:", runtime.GOMAXPROCS(0))
|
||||
func TestGoPsutil(t *testing.T) {
|
||||
fmt.Println("os:", runtime.GOOS)
|
||||
fmt.Println("threads:", runtime.GOMAXPROCS(0))
|
||||
|
||||
memoryStat, err := memory.Get()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%s\n", err)
|
||||
return
|
||||
}
|
||||
fmt.Println("memory total:", humanize.Bytes(memoryStat.Total))
|
||||
fmt.Println("memory used:", humanize.Bytes(memoryStat.Used))
|
||||
fmt.Println("memory cached:", humanize.Bytes(memoryStat.Cached))
|
||||
fmt.Println("memory free:", humanize.Bytes(memoryStat.Free))
|
||||
v, _ := mem.VirtualMemory()
|
||||
|
||||
before, err := cpu.Get()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
time.Sleep(time.Duration(1) * time.Second)
|
||||
after, err := cpu.Get()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
total := float64(after.Total - before.Total)
|
||||
fmt.Printf("cpu user: %f %%\n", float64(after.User-before.User)/total*100)
|
||||
fmt.Printf("cpu system: %f %%\n", float64(after.System-before.System)/total*100)
|
||||
fmt.Printf("cpu idle: %f %%\n", float64(after.Idle-before.Idle)/total*100)
|
||||
loadAvg, _ := load.Avg()
|
||||
|
||||
err = diskUsage(".")
|
||||
fmt.Println("loadavg", loadAvg.String())
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
func diskUsage(path string) error {
|
||||
di, err := disk.GetInfo(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
percentage := (float64(di.Total-di.Free) / float64(di.Total)) * 100
|
||||
fmt.Printf("%s of %s disk space used (%0.2f%%)\n",
|
||||
humanize.Bytes(di.Total-di.Free),
|
||||
humanize.Bytes(di.Total),
|
||||
percentage,
|
||||
)
|
||||
return nil
|
||||
fmt.Printf("Total: %v, Free:%v, UsedPercent:%f%%\n", v.Total, v.Free, v.UsedPercent)
|
||||
cpuTimesBefore, _ := cpu.Times(false)
|
||||
time.Sleep(1000*time.Millisecond)
|
||||
cpuTimesAfter, _ := cpu.Times(false)
|
||||
threadNum := runtime.GOMAXPROCS(0)
|
||||
fmt.Println(cpuTimesBefore[0].String(), "\n", cpuTimesAfter[0].String())
|
||||
cpuUserUsage := (cpuTimesAfter[0].User - cpuTimesBefore[0].User) / (float64(1000*threadNum) / 1000)
|
||||
cpuSystemUsage := (cpuTimesAfter[0].System - cpuTimesBefore[0].System) / (float64(1000*threadNum) / 1000)
|
||||
fmt.Printf("%.2f, %.2f\n", cpuUserUsage*100, cpuSystemUsage*100)
|
||||
|
||||
diskUsage, _ := disk.Usage(".")
|
||||
fmt.Println(diskUsage.String())
|
||||
}
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
package tool
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/dustin/go-humanize"
|
||||
"github.com/mackerelio/go-osstat/disk"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func DiskUsage(path string) (string, string, float64, error) {
|
||||
di, err := disk.GetInfo(path)
|
||||
if err != nil {
|
||||
return "", "", 0, err
|
||||
}
|
||||
percentage := (float64(di.Total-di.Free) / float64(di.Total)) * 100
|
||||
percentage, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", percentage), 64)
|
||||
return humanize.Bytes(di.Total-di.Free), humanize.Bytes(di.Total),
|
||||
percentage, nil
|
||||
}
|
|
@ -1,37 +1,52 @@
|
|||
package tool
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func ReloadNginx() string {
|
||||
out, err := exec.Command("nginx", "-s", "reload").CombinedOutput()
|
||||
func TestNginxConf(filePath string) error {
|
||||
out, err := exec.Command("nginx", "-t").CombinedOutput()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
output := string(out)
|
||||
log.Println(output)
|
||||
if strings.Contains(output, "failed") {
|
||||
return errors.New(output)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
func ReloadNginx() string {
|
||||
out, err := exec.Command("nginx", "-s", "reload").CombinedOutput()
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
output := string(out)
|
||||
log.Println(output)
|
||||
log.Println(output)
|
||||
|
||||
return output
|
||||
}
|
||||
|
||||
func GetNginxConfPath(dir string) string {
|
||||
out, err := exec.Command("nginx", "-V").CombinedOutput()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
// fmt.Printf("%s\n", out)
|
||||
out, err := exec.Command("nginx", "-V").CombinedOutput()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
// fmt.Printf("%s\n", out)
|
||||
|
||||
r, _ := regexp.Compile("--conf-path=(.*)/(.*.conf)")
|
||||
r, _ := regexp.Compile("--conf-path=(.*)/(.*.conf)")
|
||||
|
||||
confPath := r.FindStringSubmatch(string(out))[1]
|
||||
confPath := r.FindStringSubmatch(string(out))[1]
|
||||
|
||||
// fmt.Println(confPath)
|
||||
// fmt.Println(confPath)
|
||||
|
||||
return filepath.Join(confPath, dir)
|
||||
return filepath.Join(confPath, dir)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue