mirror of
https://github.com/nezhahq/nezha.git
synced 2025-01-22 12:48:14 -05:00
✨ 批量更新 Agent
This commit is contained in:
parent
f0e0867a3d
commit
58d17b69a1
@ -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:
|
||||
|
@ -4,7 +4,7 @@
|
||||
<br>
|
||||
<small><i>LOGO designed by <a href="https://xio.ng" target="_blank">熊大</a> .</i></small>
|
||||
<br><br>
|
||||
<img src="https://img.shields.io/github/workflow/status/naiba/nezha/Dashboard%20image?label=Dash%20v0.10.6&logo=github&style=for-the-badge"> <img src="https://img.shields.io/github/v/release/naiba/nezha?color=brightgreen&label=Agent&style=for-the-badge&logo=github"> <img src="https://img.shields.io/github/workflow/status/naiba/nezha/Agent%20release?label=Agent%20CI&logo=github&style=for-the-badge"> <img src="https://img.shields.io/badge/Installer-v0.7.1-brightgreen?style=for-the-badge&logo=linux">
|
||||
<img src="https://img.shields.io/github/workflow/status/naiba/nezha/Dashboard%20image?label=Dash%20v0.10.7&logo=github&style=for-the-badge"> <img src="https://img.shields.io/github/v/release/naiba/nezha?color=brightgreen&label=Agent&style=for-the-badge&logo=github"> <img src="https://img.shields.io/github/workflow/status/naiba/nezha/Agent%20release?label=Agent%20CI&logo=github&style=for-the-badge"> <img src="https://img.shields.io/badge/Installer-v0.7.1-brightgreen?style=for-the-badge&logo=linux">
|
||||
<br>
|
||||
<br>
|
||||
<p>:trollface: <b>哪吒监控</b> 一站式轻监控轻运维系统。支持系统状态、HTTP(SSL 证书变更、即将到期、到期)、TCP、Ping 监控报警,计划任务和在线终端。</p>
|
||||
@ -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 机器上执行定时任务、打开在线终端(安全特性)
|
||||
|
||||
## 功能说明
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
},
|
||||
|
@ -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<br/>", forceUpdateServers[i], err))
|
||||
} else {
|
||||
executeResult.WriteString(fmt.Sprintf("%d 下发指令成功<br/>", forceUpdateServers[i]))
|
||||
}
|
||||
} else {
|
||||
executeResult.WriteString(fmt.Sprintf("%d 离线<br/>", forceUpdateServers[i]))
|
||||
}
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, model.Response{
|
||||
Code: http.StatusOK,
|
||||
Message: executeResult.String(),
|
||||
})
|
||||
}
|
||||
|
||||
type notificationForm struct {
|
||||
ID uint64
|
||||
Name string
|
||||
|
3
go.mod
3
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
|
||||
|
16
go.sum
16
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=
|
||||
|
@ -8,11 +8,15 @@
|
||||
<button class="ui right labeled nezha-primary-btn icon button" onclick="addOrEditServer()"><i
|
||||
class="add icon"></i> 添加主机
|
||||
</button>
|
||||
<button class="ui right labeled nezha-primary-btn icon button" onclick="forceUpdate()"><i
|
||||
class="arrow alternate circle up outline icon"></i> 强制更新
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<table class="ui very basic table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><button onclick="checkAllServer()" class="ui mini nezha-primary-btn button">全选</button></th>
|
||||
<th>ID(排序)</th>
|
||||
<th>名称</th>
|
||||
<th>分组</th>
|
||||
@ -27,6 +31,7 @@
|
||||
<tbody>
|
||||
{{range $server := .Servers}}
|
||||
<tr>
|
||||
<td><input type="checkbox" class="nezha-servers" value="{{$server.ID}}" /></td>
|
||||
<td>{{$server.ID}}({{$server.DisplayIndex}})</td>
|
||||
<td>{{$server.Name}}</td>
|
||||
<td>{{$server.Tag}}</td>
|
||||
@ -72,5 +77,57 @@
|
||||
<script src="https://cdn.jsdelivr.net/npm/clipboard@2.0.8/dist/clipboard.min.js"></script>
|
||||
<script>
|
||||
var clipboard = new ClipboardJS('.ui.icon.green.mini.button');
|
||||
const checkBoxList = document.querySelectorAll('tbody > tr > td > input.nezha-servers[type=checkbox]')
|
||||
function checkAllServer() {
|
||||
checkBoxList.forEach(cb => {
|
||||
cb.checked = true
|
||||
})
|
||||
}
|
||||
function forceUpdate() {
|
||||
const servers = []
|
||||
checkBoxList.forEach(cb => {
|
||||
if (cb.checked) {
|
||||
servers.push(parseInt(cb.value))
|
||||
}
|
||||
})
|
||||
if (servers.length == 0) {
|
||||
$.suiAlert({
|
||||
title: '当前没有选中的服务器',
|
||||
description: '',
|
||||
type: 'warning',
|
||||
time: '2',
|
||||
position: 'top-center',
|
||||
});
|
||||
return
|
||||
}
|
||||
$.post('/api/force-update', JSON.stringify(servers))
|
||||
.then((resp) => {
|
||||
if (resp.code == 200) {
|
||||
$.suiAlert({
|
||||
title: '执行结果',
|
||||
description: resp.message,
|
||||
type: 'success',
|
||||
time: '3',
|
||||
position: 'top-center',
|
||||
});
|
||||
} else {
|
||||
$.suiAlert({
|
||||
title: '',
|
||||
description: resp.message,
|
||||
type: 'error',
|
||||
time: '3',
|
||||
position: 'top-center',
|
||||
});
|
||||
}
|
||||
}).catch(err => {
|
||||
$.suiAlert({
|
||||
title: '',
|
||||
description: err,
|
||||
type: 'error',
|
||||
time: '3',
|
||||
position: 'top-center',
|
||||
});
|
||||
})
|
||||
}
|
||||
</script>
|
||||
{{end}}
|
@ -13,7 +13,7 @@ import (
|
||||
pb "github.com/naiba/nezha/proto"
|
||||
)
|
||||
|
||||
var Version = "v0.10.6" // !!记得修改 README 中的 badge 版本!!
|
||||
var Version = "v0.10.7" // !!记得修改 README 中的 badge 版本!!
|
||||
|
||||
var (
|
||||
Conf *model.Config
|
||||
|
Loading…
Reference in New Issue
Block a user