diff --git a/.goreleaser.yml b/.goreleaser.yml
index b9496b4..ce40f07 100644
--- a/.goreleaser.yml
+++ b/.goreleaser.yml
@@ -26,14 +26,13 @@ builds:
binary: nezha-agent
universal_binaries:
- name_template: "nezha-agent"
- replace: true
+ replace: false
checksum:
name_template: "checksums.txt"
snapshot:
name_template: "nezha-agent"
archives:
- name_template: "nezha-agent_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}{{ if .Mips }}_{{ .Mips }}{{ end }}"
- allow_different_binary_count: true
files:
- none*
changelog:
diff --git a/README.md b/README.md
index c20930e..ee6648a 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
LOGO designed by 熊大 .
-
+
:trollface: 哪吒监控 一站式轻监控轻运维系统。支持系统状态、HTTP(SSL 证书变更、即将到期、到期)、TCP、Ping 监控报警,计划任务和在线终端。
@@ -45,7 +45,8 @@ _\* 使用 WatchTower 可以自动更新面板,Windows 终端可以使用 nssm
- `--report-delay` 系统信息上报的间隔,默认为 1 秒,可以设置为 3 来进一步降低 agent 端系统资源占用(配置区间 1-4)
- `--skip-conn` 不监控连接数,机场/连接密集型机器推荐设置,不然比较占 CPU([shirou/gopsutil/issues#220](https://github.com/shirou/gopsutil/issues/220))
- `--skip-procs` 不监控进程数,也可以降低 agent 占用
-- `--disable-auto-update` 禁止 Agent 自动更新(安全特性)
+- `--disable-auto-update` 禁止 **自动更新** Agent(安全特性)
+- `--disable-force-update` 禁止 **强制更新** Agent(安全特性)
- `--disable-command-execute` 禁止在 Agent 机器上执行定时任务、打开在线终端(安全特性)
## 功能说明
diff --git a/cmd/agent/main.go b/cmd/agent/main.go
index d5c0579..ecb77b1 100644
--- a/cmd/agent/main.go
+++ b/cmd/agent/main.go
@@ -32,6 +32,7 @@ type AgentConfig struct {
SkipConnectionCount bool
SkipProcsCount bool
DisableAutoUpdate bool
+ DisableForceUpdate bool
DisableCommandExecute bool
Debug bool
Server string
@@ -78,6 +79,7 @@ func main() {
flag.BoolVar(&agentConf.SkipProcsCount, "skip-procs", false, "不监控进程数")
flag.BoolVar(&agentConf.DisableCommandExecute, "disable-command-execute", false, "禁止在此机器上执行命令")
flag.BoolVar(&agentConf.DisableAutoUpdate, "disable-auto-update", false, "禁用自动升级")
+ flag.BoolVar(&agentConf.DisableForceUpdate, "disable-force-update", false, "禁用强制升级")
flag.Parse()
if agentConf.ClientSecret == "" {
@@ -114,7 +116,7 @@ func run() {
time.Sleep(time.Minute * 20)
updateCh <- struct{}{}
}()
- doSelfUpdate()
+ doSelfUpdate(false)
}()
}
}()
@@ -236,8 +238,11 @@ func reportState() {
}
}
-func doSelfUpdate() {
- v := semver.MustParse(version)
+func doSelfUpdate(donNotUseLocalVersion bool) {
+ v := semver.MustParse("0.1.0")
+ if !donNotUseLocalVersion {
+ v = semver.MustParse(version)
+ }
println("检查更新:", v)
latest, err := selfupdate.UpdateSelf(v, "naiba/nezha")
if err != nil {
@@ -250,7 +255,7 @@ func doSelfUpdate() {
}
func handleUpgradeTask(task *pb.Task, result *pb.TaskResult) {
- doSelfUpdate()
+ doSelfUpdate(true)
}
func handleTcpPingTask(task *pb.Task, result *pb.TaskResult) {
diff --git a/cmd/dashboard/controller/controller.go b/cmd/dashboard/controller/controller.go
index da84af9..4bc7def 100644
--- a/cmd/dashboard/controller/controller.go
+++ b/cmd/dashboard/controller/controller.go
@@ -4,6 +4,7 @@ import (
"fmt"
"html/template"
"net/http"
+ "strconv"
"strings"
"sync"
"time"
@@ -28,6 +29,9 @@ func ServeWeb(port uint) *http.Server {
"tf": func(t time.Time) string {
return t.Format("2006年1月2号 15:04:05")
},
+ "len": func(slice []interface{}) string {
+ return strconv.Itoa(len(slice))
+ },
"safe": func(s string) template.HTML {
return template.HTML(s) // #nosec
},
diff --git a/cmd/dashboard/controller/member_api.go b/cmd/dashboard/controller/member_api.go
index 5abb35e..f68e684 100644
--- a/cmd/dashboard/controller/member_api.go
+++ b/cmd/dashboard/controller/member_api.go
@@ -1,6 +1,7 @@
package controller
import (
+ "bytes"
"encoding/json"
"errors"
"fmt"
@@ -14,6 +15,7 @@ import (
"github.com/naiba/nezha/model"
"github.com/naiba/nezha/pkg/mygin"
"github.com/naiba/nezha/pkg/utils"
+ "github.com/naiba/nezha/proto"
"github.com/naiba/nezha/service/dao"
)
@@ -36,6 +38,7 @@ func (ma *memberAPI) serve() {
mr.POST("/monitor", ma.addOrEditMonitor)
mr.POST("/cron", ma.addOrEditCron)
mr.GET("/cron/:id/manual", ma.manualTrigger)
+ mr.POST("/force-update", ma.forceUpdate)
mr.POST("/notification", ma.addOrEditNotification)
mr.POST("/alert-rule", ma.addOrEditAlertRule)
mr.POST("/setting", ma.updateSetting)
@@ -322,6 +325,41 @@ func (ma *memberAPI) manualTrigger(c *gin.Context) {
})
}
+func (ma *memberAPI) forceUpdate(c *gin.Context) {
+ var forceUpdateServers []uint64
+ if err := c.ShouldBindJSON(&forceUpdateServers); err != nil {
+ c.JSON(http.StatusOK, model.Response{
+ Code: http.StatusBadRequest,
+ Message: err.Error(),
+ })
+ return
+ }
+
+ var executeResult bytes.Buffer
+
+ for i := 0; i < len(forceUpdateServers); i++ {
+ dao.ServerLock.RLock()
+ server := dao.ServerList[forceUpdateServers[i]]
+ dao.ServerLock.RUnlock()
+ if server != nil && server.TaskStream != nil {
+ if err := server.TaskStream.Send(&proto.Task{
+ Type: model.TaskTypeUpgrade,
+ }); err != nil {
+ executeResult.WriteString(fmt.Sprintf("%d 下发指令失败 %+v
", forceUpdateServers[i], err))
+ } else {
+ executeResult.WriteString(fmt.Sprintf("%d 下发指令成功
", forceUpdateServers[i]))
+ }
+ } else {
+ executeResult.WriteString(fmt.Sprintf("%d 离线
", forceUpdateServers[i]))
+ }
+ }
+
+ c.JSON(http.StatusOK, model.Response{
+ Code: http.StatusOK,
+ Message: executeResult.String(),
+ })
+}
+
type notificationForm struct {
ID uint64
Name string
diff --git a/go.mod b/go.mod
index 8cc6e39..1422801 100644
--- a/go.mod
+++ b/go.mod
@@ -23,14 +23,13 @@ require (
github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/pkg/errors v0.9.1 // indirect
github.com/robfig/cron/v3 v3.0.1
- github.com/shirou/gopsutil/v3 v3.21.8
+ github.com/shirou/gopsutil/v3 v3.21.10
github.com/spf13/pflag v1.0.3
github.com/spf13/viper v1.7.1
github.com/stretchr/testify v1.7.0
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6 // indirect
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43
- golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 // indirect
google.golang.org/grpc v1.33.1
google.golang.org/protobuf v1.25.0
gopkg.in/yaml.v2 v2.2.8
diff --git a/go.sum b/go.sum
index b03b7c9..f31182c 100644
--- a/go.sum
+++ b/go.sum
@@ -94,8 +94,9 @@ 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-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-ping/ping v0.0.0-20210407214646-e4e642a95741 h1:b0sLP++Tsle+s57tqg5sUk1/OQsC6yMCciVeqNzOcwU=
github.com/go-ping/ping v0.0.0-20210407214646-e4e642a95741/go.mod h1:35JbSyV/BYqHwwRA6Zr1uVDm1637YlNOU61wI797NPI=
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
@@ -144,8 +145,9 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
+github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
@@ -225,6 +227,8 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
+github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
+github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
@@ -290,8 +294,8 @@ github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6So
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
-github.com/shirou/gopsutil/v3 v3.21.8 h1:nKct+uP0TV8DjjNiHanKf8SAuub+GNsbrOtM9Nl9biA=
-github.com/shirou/gopsutil/v3 v3.21.8/go.mod h1:YWp/H8Qs5fVmf17v7JNZzA0mPJ+mS2e9JdiUF9LlKzQ=
+github.com/shirou/gopsutil/v3 v3.21.10 h1:flTg1DrnV/UVrBqjLgVgDJzx6lf+91rC64/dBHmO2IA=
+github.com/shirou/gopsutil/v3 v3.21.10/go.mod h1:t75NhzCZ/dYyPQjyQmrAYP6c8+LCdFANeBMdLPCNnew=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
@@ -470,8 +474,8 @@ golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 h1:foEbQz/B0Oz6YIqu/69kfXPYeFQAuuMYFkjaqXzl5Wo=
-golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211013075003-97ac67df715c h1:taxlMj0D/1sOAuv/CbSD+MMDof2vbyPTqz5FNYKpXt8=
+golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
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=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
diff --git a/resource/template/dashboard/server.html b/resource/template/dashboard/server.html
index 1fc31e1..3b27046 100644
--- a/resource/template/dashboard/server.html
+++ b/resource/template/dashboard/server.html
@@ -8,11 +8,15 @@
+