diff --git a/app/console/commands/monitoring.go b/app/console/commands/monitoring.go index 44b0bf90..adfb0334 100644 --- a/app/console/commands/monitoring.go +++ b/app/console/commands/monitoring.go @@ -44,14 +44,9 @@ func (receiver *Monitoring) Handle(ctx console.Context) error { return nil } - info, err := helpers.GetMonitoringInfo() - if err != nil { - facades.Log().Errorf("[面板] 系统监控失败: %s", err.Error()) - color.Redf("[面板] 系统监控失败: %s", err.Error()) - return nil - } + info := helpers.GetMonitoringInfo() - err = facades.Orm().Query().Create(&models.Monitor{ + err := facades.Orm().Query().Create(&models.Monitor{ Info: info, }) if err != nil { diff --git a/app/console/commands/panel.go b/app/console/commands/panel.go index 75274933..f4679e20 100644 --- a/app/console/commands/panel.go +++ b/app/console/commands/panel.go @@ -97,12 +97,14 @@ func (receiver *Panel) Handle(ctx console.Context) error { return nil } + color.Greenln("用户名: " + user.Username) + color.Greenln("密码: " + password) + nginxConf, err := os.ReadFile("/www/server/nginx/conf/nginx.conf") if err != nil { color.Redln("获取面板端口失败,请检查Nginx主配置文件") return nil } - match := regexp.MustCompile(`listen\s+(\d+)`).FindStringSubmatch(string(nginxConf)) if len(match) < 2 { color.Redln("获取面板端口失败,请检查Nginx主配置文件") @@ -110,8 +112,6 @@ func (receiver *Panel) Handle(ctx console.Context) error { } port := match[1] - color.Greenln("用户名: " + user.Username) - color.Greenln("密码: " + password) color.Greenln("面板端口: " + port) case "getPort": diff --git a/app/http/controllers/helpers.go b/app/http/controllers/helpers.go index 5c02dcb2..59302750 100644 --- a/app/http/controllers/helpers.go +++ b/app/http/controllers/helpers.go @@ -2,7 +2,7 @@ package controllers import "github.com/goravel/framework/contracts/http" -func Success(ctx http.Context, data http.Json) { +func Success(ctx http.Context, data any) { ctx.Response().Success().Json(http.Json{ "code": 0, "message": "success", diff --git a/app/http/controllers/info_controller.go b/app/http/controllers/info_controller.go index 09c61b0e..63648a82 100644 --- a/app/http/controllers/info_controller.go +++ b/app/http/controllers/info_controller.go @@ -1,12 +1,22 @@ package controllers import ( + "fmt" + "github.com/goravel/framework/contracts/http" "github.com/goravel/framework/facades" "panel/app/models" + "panel/packages/helpers" ) +type MenuItem struct { + Name string `json:"name"` + Title string `json:"title"` + Icon string `json:"icon"` + Jump string `json:"jump"` +} + type InfoController struct { //Dependent services } @@ -30,3 +40,42 @@ func (r *InfoController) Name(ctx http.Context) { "name": setting.Value, }) } + +func (r *InfoController) Menu(ctx http.Context) { + Success(ctx, []MenuItem{ + {Name: "home", Title: "主页", Icon: "layui-icon-home", Jump: "/"}, + {Name: "website", Title: "网站管理", Icon: "layui-icon-website", Jump: "website/list"}, + {Name: "monitor", Title: "资源监控", Icon: "layui-icon-chart-screen", Jump: "monitor"}, + {Name: "safe", Title: "系统安全", Icon: "layui-icon-auz", Jump: "safe"}, + {Name: "file", Title: "文件管理", Icon: "layui-icon-file", Jump: "file"}, + {Name: "cron", Title: "计划任务", Icon: "layui-icon-date", Jump: "cron"}, + {Name: "plugin", Title: "插件中心", Icon: "layui-icon-app", Jump: "plugin"}, + {Name: "setting", Title: "面板设置", Icon: "layui-icon-set", Jump: "setting"}, + }) +} + +func (r *InfoController) HomePlugins(ctx http.Context) { + var plugins []models.Plugin + err := facades.Orm().Query().Where("show", 1).Find(&plugins) + if err != nil { + facades.Log().Error("[面板][InfoController] 查询首页插件失败 ", err) + Error(ctx, http.StatusInternalServerError, "系统内部错误") + return + } + + Success(ctx, plugins) +} + +func (r *InfoController) NowMonitor(ctx http.Context) { + Success(ctx, helpers.GetMonitoringInfo()) +} + +func (r *InfoController) SystemInfo(ctx http.Context) { + monitorInfo := helpers.GetMonitoringInfo() + + Success(ctx, http.Json{ + "os_name": monitorInfo.Host.Platform + " " + monitorInfo.Host.PlatformVersion, + "uptime": fmt.Sprintf("%.2f", float64(monitorInfo.Host.Uptime)/86400), + "panel_version": facades.Config().GetString("panel.version"), + }) +} diff --git a/app/http/controllers/task_controller.go b/app/http/controllers/task_controller.go new file mode 100644 index 00000000..a5c3693a --- /dev/null +++ b/app/http/controllers/task_controller.go @@ -0,0 +1,32 @@ +package controllers + +import ( + "github.com/goravel/framework/contracts/http" + "github.com/goravel/framework/facades" + "panel/app/models" +) + +type TaskController struct { + //Dependent services +} + +func NewTaskController() *TaskController { + return &TaskController{ + //Inject services + } +} + +func (r *TaskController) Status(ctx http.Context) { + var task models.Task + err := facades.Orm().Query().Where("status", models.TaskStatusWaiting).OrWhere("status", models.TaskStatusRunning).FirstOrFail(&task) + if err == nil { + Success(ctx, http.Json{ + "task": true, + }) + return + } + + Success(ctx, http.Json{ + "task": false, + }) +} diff --git a/app/http/middleware/jwt.go b/app/http/middleware/jwt.go index d3041257..f6e2f991 100644 --- a/app/http/middleware/jwt.go +++ b/app/http/middleware/jwt.go @@ -13,7 +13,7 @@ import ( // Jwt 确保通过 JWT 鉴权 func Jwt() http.Middleware { return func(ctx http.Context) { - token := ctx.Request().Header("Authorization", "") + token := ctx.Request().Input("access_token", "") if len(token) == 0 { ctx.Request().AbortWithStatusJson(http.StatusUnauthorized, http.Json{ "code": 401, diff --git a/config/panel.go b/config/panel.go new file mode 100644 index 00000000..22badb6e --- /dev/null +++ b/config/panel.go @@ -0,0 +1,13 @@ +package config + +import ( + "github.com/goravel/framework/facades" +) + +func init() { + config := facades.Config() + config.Add("panel", map[string]any{ + "name": "耗子Linux面板", + "version": "2.0.0", + }) +} diff --git a/go.mod b/go.mod index 375dad0e..a3f14a61 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,14 @@ module panel go 1.18 require ( - github.com/goravel/framework v1.12.3-0.20230622070736-f7260a71f319 - google.golang.org/grpc v1.56.0 + github.com/gertd/go-pluralize v0.2.1 + github.com/gin-contrib/static v0.0.1 + github.com/gookit/color v1.5.3 + github.com/goravel/framework v1.12.3 + github.com/iancoleman/strcase v0.2.0 + github.com/mojocn/base64Captcha v1.3.5 + github.com/spf13/cast v1.5.1 + github.com/stretchr/testify v1.8.4 ) require ( @@ -39,12 +45,11 @@ require ( github.com/dustin/go-humanize v1.0.1 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/gabriel-vasile/mimetype v1.4.2 // indirect - github.com/gertd/go-pluralize v0.2.1 // indirect github.com/gin-contrib/sse v0.1.0 // indirect - github.com/gin-contrib/static v0.0.1 // indirect github.com/gin-gonic/gin v1.9.1 // indirect github.com/glebarez/go-sqlite v1.21.1 // indirect github.com/glebarez/sqlite v1.8.0 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.14.1 // indirect @@ -71,7 +76,6 @@ require ( github.com/google/wire v0.5.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect github.com/googleapis/gax-go/v2 v2.8.0 // indirect - github.com/gookit/color v1.5.3 // indirect github.com/gookit/filter v1.1.4 // indirect github.com/gookit/goutil v0.5.15 // indirect github.com/gookit/validate v1.4.6 // indirect @@ -81,7 +85,6 @@ require ( github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/hcl v1.0.0 // indirect - github.com/iancoleman/strcase v0.2.0 // indirect github.com/imdario/mergo v0.3.13 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect @@ -104,7 +107,6 @@ require ( github.com/moby/term v0.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/mojocn/base64Captcha v1.3.5 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.0.2 // indirect github.com/opencontainers/runc v1.1.5 // indirect @@ -117,21 +119,20 @@ require ( github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect - github.com/rs/cors v1.9.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/spf13/afero v1.9.5 // indirect - github.com/spf13/cast v1.5.1 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.16.0 // indirect github.com/streadway/amqp v1.0.0 // indirect github.com/stretchr/objx v0.5.0 // indirect - github.com/stretchr/testify v1.8.4 // indirect github.com/subosito/gotenv v1.4.2 // indirect + github.com/tklauser/go-sysconf v0.3.11 // indirect + github.com/tklauser/numcpus v0.6.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.11 // indirect - github.com/unrolled/secure v1.13.0 // indirect github.com/urfave/cli/v2 v2.25.6 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect github.com/xdg-go/scram v1.1.1 // indirect @@ -142,6 +143,7 @@ require ( github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect + github.com/yusufpapurcu/wmi v1.2.3 // indirect go.mongodb.org/mongo-driver v1.7.5 // indirect go.opencensus.io v0.24.0 // indirect go.uber.org/atomic v1.11.0 // indirect @@ -160,6 +162,7 @@ require ( google.golang.org/genproto v0.0.0-20230525234025-438c736192d0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20230525234020-1aefcd67740a // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect + google.golang.org/grpc v1.56.0 // indirect google.golang.org/protobuf v1.30.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index 12c6e84a..53e0fe99 100644 --- a/go.sum +++ b/go.sum @@ -172,6 +172,8 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= @@ -181,8 +183,6 @@ github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= -github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js= -github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/go-playground/validator/v10 v10.14.1 h1:9c50NUPC30zyuKprjL3vNZ0m5oG+jU0zvx4AqHGnv4k= github.com/go-playground/validator/v10 v10.14.1/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg= @@ -346,10 +346,8 @@ github.com/goravel/file-rotatelogs v0.0.0-20211215053220-2ab31dd9575c h1:obhFK91 github.com/goravel/file-rotatelogs v0.0.0-20211215053220-2ab31dd9575c/go.mod h1:YSWsLXlG16u5CWFaXNZHhEQD10+NwF3xfgDV816OwLE= github.com/goravel/file-rotatelogs/v2 v2.4.1 h1:ogkeIFcTHSBRUBpZYiyJbpul8hkVXxHPuDbOaP78O1M= github.com/goravel/file-rotatelogs/v2 v2.4.1/go.mod h1:euk9qr52WrzM8ICs1hecFcR4CZ/ZZOPdacHfvHgbOf0= -github.com/goravel/framework v1.12.2 h1:2d+RQEVzcky6ff6LxlcPvnAj0tZPc0Y4yQAXQk88+nA= -github.com/goravel/framework v1.12.2/go.mod h1:96GRS8270PKLfJU9zrrLE7XKlp20S2TJ9RB337jBMy4= -github.com/goravel/framework v1.12.3-0.20230622070736-f7260a71f319 h1:xs7YlSAXdSJs0olT59PBwwj+3Rn5nTKASgNc+GUqsV8= -github.com/goravel/framework v1.12.3-0.20230622070736-f7260a71f319/go.mod h1:96GRS8270PKLfJU9zrrLE7XKlp20S2TJ9RB337jBMy4= +github.com/goravel/framework v1.12.3 h1:gGP+7fV7qAoBVh6zz8C4caQX9Vs8XTmqSJdMa/S9BsI= +github.com/goravel/framework v1.12.3/go.mod h1:96GRS8270PKLfJU9zrrLE7XKlp20S2TJ9RB337jBMy4= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= @@ -522,11 +520,12 @@ github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rs/cors v1.9.0 h1:l9HGsTsHJcvW14Nk7J9KFz8bzeAWXn3CG6bgt7LsrAE= -github.com/rs/cors v1.9.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= +github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= +github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= @@ -574,6 +573,10 @@ github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG github.com/tebeka/strftime v0.1.3/go.mod h1:7wJm3dZlpr4l/oVK0t1HYIc4rMzQ2XJlOMIUJUJH6XQ= github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM= +github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI= +github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms= +github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= @@ -581,7 +584,6 @@ github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLY github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/unrolled/secure v1.13.0 h1:sdr3Phw2+f8Px8HE5sd1EHdj1aV3yUwed/uZXChLFsk= -github.com/unrolled/secure v1.13.0/go.mod h1:BmF5hyM6tXczk3MpQkFf1hpKSRqCyhqcbiQtiAF7+40= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli/v2 v2.25.6 h1:yuSkgDSZfH3L1CjF2/5fNNg2KbM47pY2EvjBq4ESQnU= @@ -617,6 +619,8 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= +github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.mongodb.org/mongo-driver v1.4.6/go.mod h1:WcMNYLx/IlOxLe6JRJiv2uXuCz6zBLndR4SoGjYphSc= go.mongodb.org/mongo-driver v1.7.5 h1:ny3p0reEpgsR2cfA5cjgwFZg3Cv/ofFh/8jbhGtz9VI= go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng= @@ -791,6 +795,7 @@ golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/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= golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -839,6 +844,7 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/packages/helpers/helpers.go b/packages/helpers/helpers.go index 07f07e2b..e03727ff 100644 --- a/packages/helpers/helpers.go +++ b/packages/helpers/helpers.go @@ -2,21 +2,23 @@ package helpers import ( - "bufio" - "bytes" "crypto/md5" "crypto/rand" "fmt" "io" "os" - "os/exec" "reflect" - "regexp" - "sort" - "strconv" "strings" "time" "unicode/utf8" + + "github.com/shirou/gopsutil/cpu" + "github.com/shirou/gopsutil/disk" + "github.com/shirou/gopsutil/host" + "github.com/shirou/gopsutil/load" + "github.com/shirou/gopsutil/mem" + "github.com/shirou/gopsutil/net" + "github.com/shirou/gopsutil/process" ) // Empty 类似于 PHP 的 empty() 函数 @@ -104,182 +106,43 @@ func Cut(begin, end, str string) string { return string([]rune(str)[b : b+e]) } -// GetNetInfo 获取网络统计信息 -func GetNetInfo() (uint64, uint64) { - file, err := os.Open("/proc/net/dev") - if err != nil { - panic(err) - } - defer file.Close() - - scanner := bufio.NewScanner(file) - allRs := make(map[string][]string) - lineNumber := 0 - - for scanner.Scan() { - lineNumber++ - if lineNumber < 3 { - continue - } - - line := strings.TrimSpace(scanner.Text()) - line = strings.Replace(line, ":", " ", -1) - re := regexp.MustCompile("[ ]+") - line = re.ReplaceAllString(line, " ") - arr := strings.Split(line, " ") - - if len(arr) > 0 && arr[0] != "" { - allRs[arr[0]+strconv.Itoa(lineNumber)] = []string{arr[0], arr[1], arr[9]} - } - } - - var keys []string - for key := range allRs { - keys = append(keys, key) - } - sort.Strings(keys) - - tx := uint64(0) - rx := uint64(0) - - for _, key := range keys { - if strings.Contains(key, "lo") { - continue - } - val := allRs[key] - txValue, err := strconv.ParseUint(val[2], 10, 64) - if err == nil { - tx += txValue - } - rxValue, err := strconv.ParseUint(val[1], 10, 64) - if err == nil { - rx += rxValue - } - } - - return tx, rx -} - // MonitoringInfo 监控信息 type MonitoringInfo struct { - CpuUse float64 `json:"cpu_use"` - Uptime float64 `json:"uptime"` - UptimePercent float64 `json:"uptime_percent"` - MemTotal float64 `json:"mem_total"` - MemUse float64 `json:"mem_use"` - MemUsePercent float64 `json:"mem_use_percent"` - SwapTotal float64 `json:"swap_total"` - SwapUse float64 `json:"swap_use"` - SwapUsePercent float64 `json:"swap_use_percent"` - NetTx uint64 `json:"net_tx"` - NetRx uint64 `json:"net_rx"` + Cpus []cpu.InfoStat `json:"cpus"` + Percent []float64 `json:"percent"` + Load *load.AvgStat `json:"load"` + Host *host.InfoStat `json:"host"` + Mem *mem.VirtualMemoryStat `json:"mem"` + Swap *mem.SwapMemoryStat `json:"swap"` + Net []net.IOCountersStat `json:"net"` + Disk map[string]disk.IOCountersStat `json:"disk"` + Process []*process.Process `json:"process"` } // GetMonitoringInfo 获取监控数据 -func GetMonitoringInfo() (MonitoringInfo, error) { +func GetMonitoringInfo() MonitoringInfo { var res MonitoringInfo + res.Cpus, _ = cpu.Info() + res.Percent, _ = cpu.Percent(time.Second, false) + res.Load, _ = load.Avg() + res.Host, _ = host.Info() + res.Mem, _ = mem.VirtualMemory() + res.Swap, _ = mem.SwapMemory() + res.Net, _ = net.IOCounters(true) + res.Disk, _ = disk.IOCounters() + res.Process, _ = process.Processes() - // 网络流量 - netTx1, netRx1 := GetNetInfo() - time.Sleep(time.Second) - netTx2, netRx2 := GetNetInfo() - res.NetTx = netTx2 - netTx1 - res.NetRx = netRx2 - netRx1 - - // CPU 信息 - cpuInfoRaw, err := os.ReadFile("/proc/cpuinfo") - if err != nil { - return MonitoringInfo{}, err - } - physicalArr := make(map[string]struct{}) - var siblingsSum float64 - var re = regexp.MustCompile(`\d+\.\d+`) - uptimeOutput, err := exec.Command("uptime").Output() - if err != nil { - return MonitoringInfo{}, err - } - uptimeValues := re.FindAllString(string(uptimeOutput), -1) - uptime1, _ := strconv.ParseFloat(uptimeValues[0], 64) - res.Uptime = uptime1 - processors := bytes.Split(cpuInfoRaw, []byte("\nprocessor")) - rePhysical := regexp.MustCompile(`physical id\s*:\s(.*)`) - reSiblings := regexp.MustCompile(`siblings\s*:\s(.*)`) - for _, v := range processors { - physical := rePhysical.FindSubmatch(v) - siblings := reSiblings.FindSubmatch(v) - if len(physical) > 1 { - pid := string(physical[1]) - if _, found := physicalArr[pid]; !found { - if len(siblings) > 1 { - siblingsValue, _ := strconv.ParseFloat(string(siblings[1]), 64) - siblingsSum += siblingsValue - } - physicalArr[pid] = struct{}{} - } - } - } - - // CPU 使用率 - cpuUse := 0.1 - psOutput, err := exec.Command("ps", "aux").Output() - if err != nil { - return MonitoringInfo{}, err - } - cpuRaw := strings.Split(string(psOutput), "\n") - pid := os.Getpid() - for _, v := range cpuRaw { - v = strings.TrimSpace(v) - v = regexp.MustCompile(`\s+`).ReplaceAllString(v, " ") - values := strings.Split(v, " ") - if len(values) > 2 { - p, _ := strconv.Atoi(values[1]) - if p == pid { - continue - } - cpu, _ := strconv.ParseFloat(values[2], 64) - cpuUse += cpu - } - } - cpuUse = cpuUse / siblingsSum - if cpuUse > 100 { - cpuUse = 100 - } - res.CpuUse = cpuUse - - // 内存使用率 - freeOutput, err := exec.Command("free", "-m").Output() - if err != nil { - return MonitoringInfo{}, err - } - memRaw := strings.Split(string(freeOutput), "\n") - var memList, swapList string - for _, v := range memRaw { - if strings.Contains(v, "Mem") { - memList = regexp.MustCompile(`\s+`).ReplaceAllString(v, " ") - } else if strings.Contains(v, "Swap") { - swapList = regexp.MustCompile(`\s+`).ReplaceAllString(v, " ") - } - } - memArr := strings.Split(memList, " ") - swapArr := strings.Split(swapList, " ") - memTotal, _ := strconv.ParseFloat(memArr[1], 64) - swapTotal, _ := strconv.ParseFloat(swapArr[1], 64) - memUse, _ := strconv.ParseFloat(memArr[2], 64) - swapUse, _ := strconv.ParseFloat(swapArr[2], 64) - memUseP := (memUse / memTotal) * 100 - swapUseP := (swapUse / swapTotal) * 100 - uptime1P := uptime1 * 10 - if uptime1P > 100 { - uptime1P = 100 - } - - res.MemTotal = memTotal - res.MemUse = memUse - res.MemUsePercent = memUseP - res.SwapTotal = swapTotal - res.SwapUse = swapUse - res.SwapUsePercent = swapUseP - res.UptimePercent = uptime1P - - return res, nil + return res +} + +// IsDebian 判断是否是 Debian 系统 +func IsDebian() bool { + _, err := os.Stat("/etc/debian_version") + return err == nil +} + +// IsRHEL 判断是否是 RHEL 系统 +func IsRHEL() bool { + _, err := os.Stat("/etc/redhat-release") + return err == nil } diff --git a/packages/str/str.go b/packages/str/str.go index 00b6f86e..c25b7e4c 100644 --- a/packages/str/str.go +++ b/packages/str/str.go @@ -30,3 +30,12 @@ func Camel(s string) string { func LowerCamel(s string) string { return strcase.ToLowerCamel(s) } + +func ContainsString(arr []string, str string) bool { + for _, s := range arr { + if s == str { + return true + } + } + return false +} diff --git a/public/index.html b/public/index.html index e69afcd5..d0ece897 100644 --- a/public/index.html +++ b/public/index.html @@ -40,19 +40,19 @@ @@ -162,119 +156,134 @@ Date: 2022-11-30 diff --git a/public/res/views/layout.html b/public/res/views/layout.html index 6befe8d8..68d43477 100644 --- a/public/res/views/layout.html +++ b/public/res/views/layout.html @@ -4,7 +4,7 @@