🚀 dashboard v0.14.6 with installer v0.11.0

This commit is contained in:
naiba 2022-10-31 21:54:37 +08:00
parent 851a3dfe1f
commit 668711eb23
12 changed files with 130 additions and 101 deletions

View File

@ -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.14.5&logo=github&style=for-the-badge">&nbsp;<img src="https://img.shields.io/github/v/release/naiba/nezha?color=brightgreen&label=Agent&style=for-the-badge&logo=github">&nbsp;<img src="https://img.shields.io/github/workflow/status/naiba/nezha/Agent%20release?label=Agent%20CI&logo=github&style=for-the-badge">&nbsp;<img src="https://img.shields.io/badge/Installer-v0.10.7-brightgreen?style=for-the-badge&logo=linux">
<img src="https://img.shields.io/github/workflow/status/naiba/nezha/Dashboard%20image?label=Dash%20v0.14.6&logo=github&style=for-the-badge">&nbsp;<img src="https://img.shields.io/github/v/release/naiba/nezha?color=brightgreen&label=Agent&style=for-the-badge&logo=github">&nbsp;<img src="https://img.shields.io/github/workflow/status/naiba/nezha/Agent%20release?label=Agent%20CI&logo=github&style=for-the-badge">&nbsp;<img src="https://img.shields.io/badge/Installer-v0.11.0-brightgreen?style=for-the-badge&logo=linux">
<br>
<br>
<p>:trollface: <b>Nezha Monitoring: Self-hosted, lightweight server and website monitoring and O&M tool.</b></p>

View File

@ -4,7 +4,7 @@ package pty
import (
"fmt"
"io/ioutil"
"io"
"log"
"net/http"
"os"
@ -21,36 +21,47 @@ type Pty struct {
}
func DownloadDependency() {
executablePath, err := getExecutableFilePath()
if err != nil {
fmt.Println("NEZHA>> wintty 获取文件路径失败", err)
return
}
winptyAgentExe := filepath.Join(executablePath, "winpty-agent.exe")
winptyAgentDll := filepath.Join(executablePath, "winpty.dll")
fe, errFe := os.Stat(winptyAgentExe)
fd, errFd := os.Stat(winptyAgentDll)
if errFe == nil && fe.Size() > 300000 && errFd == nil && fd.Size() > 300000 {
return
}
resp, err := http.Get("https://dn-dao-github-mirror.daocloud.io/rprichard/winpty/releases/download/0.4.3/winpty-0.4.3-msvc2015.zip")
if err != nil {
log.Println("wintty 下载失败", err)
log.Println("NEZHA>> wintty 下载失败", err)
return
}
defer resp.Body.Close()
content, err := ioutil.ReadAll(resp.Body)
content, err := io.ReadAll(resp.Body)
if err != nil {
log.Println("wintty 下载失败", err)
log.Println("NEZHA>> wintty 下载失败", err)
return
}
if err := ioutil.WriteFile("./wintty.zip", content, os.FileMode(0777)); err != nil {
log.Println("wintty 写入失败", err)
if err := os.WriteFile("./wintty.zip", content, os.FileMode(0777)); err != nil {
log.Println("NEZHA>> wintty 写入失败", err)
return
}
if err := unzip.New("./wintty.zip", "./wintty").Extract(); err != nil {
fmt.Println("wintty 解压失败", err)
fmt.Println("NEZHA>> wintty 解压失败", err)
return
}
arch := "x64"
if runtime.GOARCH != "amd64" {
arch = "ia32"
}
executablePath, err := getExecutableFilePath()
if err != nil {
fmt.Println("wintty 获取文件路径失败", err)
return
}
os.Rename("./wintty/"+arch+"/bin/winpty-agent.exe", filepath.Join(executablePath, "winpty-agent.exe"))
os.Rename("./wintty/"+arch+"/bin/winpty.dll", filepath.Join(executablePath, "winpty.dll"))
os.Rename("./wintty/"+arch+"/bin/winpty-agent.exe", winptyAgentExe)
os.Rename("./wintty/"+arch+"/bin/winpty.dll", winptyAgentDll)
os.RemoveAll("./wintty")
os.RemoveAll("./wintty.zip")
}

14
go.mod
View File

@ -6,7 +6,7 @@ require (
code.cloudfoundry.org/bytefmt v0.0.0-20211005130812-5bb3c17173e5
code.gitea.io/sdk/gitea v0.15.1
github.com/AlecAivazis/survey/v2 v2.3.6
github.com/BurntSushi/toml v1.2.0
github.com/BurntSushi/toml v1.2.1
github.com/artdarek/go-unzip v1.0.0
github.com/blang/semver v3.5.1+incompatible
github.com/creack/pty v1.1.18
@ -29,10 +29,10 @@ require (
github.com/shirou/gopsutil/v3 v3.22.9
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.13.0
github.com/stretchr/testify v1.8.0
github.com/xanzy/go-gitlab v0.73.1
golang.org/x/crypto v0.0.0-20221012134737-56aed061732a
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783
github.com/stretchr/testify v1.8.1
github.com/xanzy/go-gitlab v0.74.0
golang.org/x/crypto v0.1.0
golang.org/x/oauth2 v0.1.0
golang.org/x/sync v0.1.0
golang.org/x/text v0.4.0
google.golang.org/grpc v1.50.1
@ -87,9 +87,9 @@ require (
github.com/ugorji/go/codec v1.2.7 // indirect
github.com/ulikunitz/xz v0.5.10 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
golang.org/x/net v0.0.0-20221017152216-f25eb7ecb193 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/term v0.0.0-20221017184919-83659145692c // indirect
golang.org/x/term v0.1.0 // indirect
golang.org/x/time v0.1.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221018143404-92eef740a0dc // indirect

28
go.sum
View File

@ -45,8 +45,8 @@ github.com/AlecAivazis/survey/v2 v2.3.6 h1:NvTuVHISgTHEHeBFqt6BHOe4Ny/NwGZr7w+F8
github.com/AlecAivazis/survey/v2 v2.3.6/go.mod h1:4AuI9b7RjAR+G7v9+C4YSlX/YL3K3cWNXgWXOhllqvI=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/toml v1.2.0 h1:Rt8g24XnyGTyglgET/PRUNlrUeu9F5L+7FilkXfZgs0=
github.com/BurntSushi/toml v1.2.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s=
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w=
@ -310,6 +310,7 @@ github.com/spf13/viper v1.13.0 h1:BWSJ/M+f+3nmdz9bxB+bWX28kkALN2ok11D0rSo8EJU=
github.com/spf13/viper v1.13.0/go.mod h1:Icm2xNL3/8uyh/wFuB1jI7TiTNKp8632Nwegu+zgdYw=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
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.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
@ -317,8 +318,9 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
github.com/stretchr/testify v1.6.1/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.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs=
github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
github.com/tcnksm/go-gitconfig v0.1.2 h1:iiDhRitByXAEyjgBqsKi9QU4o2TNtv9kPP3RgPgXBPw=
@ -333,8 +335,8 @@ github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8=
github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/xanzy/go-gitlab v0.73.1 h1:UMagqUZLJdjss1SovIC+kJCH4k2AZWXl58gJd38Y/hI=
github.com/xanzy/go-gitlab v0.73.1/go.mod h1:d/a0vswScO7Agg1CZNz15Ic6SSvBG9vfw8egL99t4kA=
github.com/xanzy/go-gitlab v0.74.0 h1:Ha1cokbjn0PXy6B19t3W324dwM4AOT52fuHr7nERPrc=
github.com/xanzy/go-gitlab v0.74.0/go.mod h1:d/a0vswScO7Agg1CZNz15Ic6SSvBG9vfw8egL99t4kA=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@ -356,8 +358,8 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20221012134737-56aed061732a h1:NmSIgad6KjE6VvHciPZuNRTKxGhlPfD6OA87W/PLkqg=
golang.org/x/crypto v0.0.0-20221012134737-56aed061732a/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU=
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -427,8 +429,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20221017152216-f25eb7ecb193 h1:3Moaxt4TfzNcQH6DWvlYKraN1ozhBXQHcgvXjRGeim0=
golang.org/x/net v0.0.0-20221017152216-f25eb7ecb193/go.mod h1:RpDiru2p0u2F0lLpEoqnP2+7xs0ifAuOcJ442g6GU2s=
golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0=
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -438,8 +440,8 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 h1:nt+Q6cXKz4MosCSpnbMtqiQ8Oz0pxTef2B4Vca2lvfk=
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
golang.org/x/oauth2 v0.1.0 h1:isLCZuhj4v+tYv7eskaN4v/TM+A1begWWgyVJDdl1+Y=
golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -509,8 +511,8 @@ golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY=
golang.org/x/term v0.0.0-20221017184919-83659145692c h1:dveknrit5futqEmXAvd2I1BbZIDhxRijsyWHM86NlcA=
golang.org/x/term v0.0.0-20221017184919-83659145692c/go.mod h1:VTIZ7TEbF0BS9Sv9lPTvGbtW8i4z6GGbJBCM37uMCzY=
golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
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=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

View File

@ -11,7 +11,7 @@ NZ_BASE_PATH="/opt/nezha"
NZ_DASHBOARD_PATH="${NZ_BASE_PATH}/dashboard"
NZ_AGENT_PATH="${NZ_BASE_PATH}/agent"
NZ_AGENT_SERVICE="/etc/systemd/system/nezha-agent.service"
NZ_VERSION="v0.10.7"
NZ_VERSION="v0.11.0"
red='\033[0;31m'
green='\033[0;32m'
@ -177,18 +177,6 @@ install_dashboard() {
echo -e "${green}Docker${plain} 安装成功"
fi
command -v docker-compose >/dev/null 2>&1
if [[ $? != 0 ]]; then
echo -e "正在安装 Docker Compose"
wget -t 2 -T 10 -O /usr/local/bin/docker-compose "https://${GITHUB_URL}/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" >/dev/null 2>&1
if [[ $? != 0 ]]; then
echo -e "${red}下载脚本失败,请检查本机能否连接 ${GITHUB_URL}${plain}"
return 0
fi
chmod +x /usr/local/bin/docker-compose
echo -e "${green}Docker Compose${plain} 安装成功"
fi
modify_dashboard_config 0
if [[ $# == 0 ]]; then
@ -375,9 +363,9 @@ restart_and_update() {
echo -e "> 重启并更新面板"
cd $NZ_DASHBOARD_PATH
docker-compose pull
docker-compose down
docker-compose up -d
docker compose pull
docker compose down
docker compose up -d
if [[ $? == 0 ]]; then
echo -e "${green}哪吒监控 重启成功${plain}"
echo -e "默认管理面板地址:${yellow}域名:站点访问端口${plain}"
@ -393,7 +381,7 @@ restart_and_update() {
start_dashboard() {
echo -e "> 启动面板"
cd $NZ_DASHBOARD_PATH && docker-compose up -d
cd $NZ_DASHBOARD_PATH && docker compose up -d
if [[ $? == 0 ]]; then
echo -e "${green}哪吒监控 启动成功${plain}"
else
@ -408,7 +396,7 @@ start_dashboard() {
stop_dashboard() {
echo -e "> 停止面板"
cd $NZ_DASHBOARD_PATH && docker-compose down
cd $NZ_DASHBOARD_PATH && docker compose down
if [[ $? == 0 ]]; then
echo -e "${green}哪吒监控 停止成功${plain}"
else
@ -423,7 +411,7 @@ stop_dashboard() {
show_dashboard_log() {
echo -e "> 获取面板日志"
cd $NZ_DASHBOARD_PATH && docker-compose logs -f
cd $NZ_DASHBOARD_PATH && docker compose logs -f
if [[ $# == 0 ]]; then
before_show_menu
@ -433,8 +421,7 @@ show_dashboard_log() {
uninstall_dashboard() {
echo -e "> 卸载管理面板"
cd $NZ_DASHBOARD_PATH &&
docker-compose down
cd $NZ_DASHBOARD_PATH && docker compose down
rm -rf $NZ_DASHBOARD_PATH
docker rmi -f ghcr.io/naiba/nezha-dashboard > /dev/null 2>&1
docker rmi -f registry.cn-shanghai.aliyuncs.com/naibahq/nezha-dashboard > /dev/null 2>&1

View File

@ -11,7 +11,7 @@ NZ_BASE_PATH="/opt/nezha"
NZ_DASHBOARD_PATH="${NZ_BASE_PATH}/dashboard"
NZ_AGENT_PATH="${NZ_BASE_PATH}/agent"
NZ_AGENT_SERVICE="/etc/systemd/system/nezha-agent.service"
NZ_VERSION="v0.10.7"
NZ_VERSION="v0.11.0"
red='\033[0;31m'
green='\033[0;32m'
@ -146,18 +146,6 @@ install_dashboard() {
echo -e "${green}Docker${plain} installed successfully"
fi
command -v docker-compose >/dev/null 2>&1
if [[ $? != 0 ]]; then
echo -e "Installing Docker Compose"
wget -t 2 -T 10 -O /usr/local/bin/docker-compose "https://${GITHUB_URL}/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" >/dev/null 2>&1
if [[ $? != 0 ]]; then
echo -e "${red}Script failed to get, please check if the network can link ${GITHUB_URL}${plain}"
return 0
fi
chmod +x /usr/local/bin/docker-compose
echo -e "${green}Docker Compose${plain} installed successfully"
fi
modify_dashboard_config 0
if [[ $# == 0 ]]; then
@ -344,9 +332,9 @@ restart_and_update() {
echo -e "> Restart and Update the Panel"
cd $NZ_DASHBOARD_PATH
docker-compose pull
docker-compose down
docker-compose up -d
docker compose pull
docker compose down
docker compose up -d
if [[ $? == 0 ]]; then
echo -e "${green}Nezha Monitoring Restart Successful${plain}"
echo -e "Default panel address: ${yellow}domain:Site_access_port${plain}"
@ -362,7 +350,7 @@ restart_and_update() {
start_dashboard() {
echo -e "> Start Panel"
cd $NZ_DASHBOARD_PATH && docker-compose up -d
cd $NZ_DASHBOARD_PATH && docker compose up -d
if [[ $? == 0 ]]; then
echo -e "${green}Nezha Monitoring Start Successful${plain}"
else
@ -377,7 +365,7 @@ start_dashboard() {
stop_dashboard() {
echo -e "> Stop Panel"
cd $NZ_DASHBOARD_PATH && docker-compose down
cd $NZ_DASHBOARD_PATH && docker compose down
if [[ $? == 0 ]]; then
echo -e "${green}Nezha Monitoring Stop Successful${plain}"
else
@ -392,7 +380,7 @@ stop_dashboard() {
show_dashboard_log() {
echo -e "> View Panel Log"
cd $NZ_DASHBOARD_PATH && docker-compose logs -f
cd $NZ_DASHBOARD_PATH && docker compose logs -f
if [[ $# == 0 ]]; then
before_show_menu
@ -402,8 +390,7 @@ show_dashboard_log() {
uninstall_dashboard() {
echo -e "> Uninstall Panel"
cd $NZ_DASHBOARD_PATH &&
docker-compose down
cd $NZ_DASHBOARD_PATH && docker compose down
rm -rf $NZ_DASHBOARD_PATH
docker rmi -f ghcr.io/naiba/nezha-dashboard > /dev/null 2>&1
clean_all

View File

@ -39,14 +39,14 @@ func (s *NezhaHandler) ReportTask(c context.Context, r *pb.TaskResult) (*pb.Rece
&i18n.LocalizeConfig{
MessageID: "ScheduledTaskExecutedSuccessfully",
},
), cr.Name, singleton.ServerList[clientID].Name, r.GetData()), false, &curServer)
), cr.Name, singleton.ServerList[clientID].Name, r.GetData()), nil, &curServer)
}
if !r.GetSuccessful() {
singleton.SendNotification(cr.NotificationTag, fmt.Sprintf("[%s] %s, %s\n%s", singleton.Localizer.MustLocalize(
&i18n.LocalizeConfig{
MessageID: "ScheduledTaskExecutedFailed",
},
), cr.Name, singleton.ServerList[clientID].Name, r.GetData()), false, &curServer)
), cr.Name, singleton.ServerList[clientID].Name, r.GetData()), nil, &curServer)
}
singleton.DB.Model(cr).Updates(model.Cron{
LastExecutedAt: time.Now().Add(time.Second * -1 * time.Duration(r.GetDelay())),
@ -117,12 +117,13 @@ func (s *NezhaHandler) ReportSystemInfo(c context.Context, r *pb.Host) (*pb.Rece
singleton.ServerList[clientID].Host.IP != "" &&
host.IP != "" &&
singleton.ServerList[clientID].Host.IP != host.IP {
singleton.SendNotification(singleton.Conf.IPChangeNotificationTag, fmt.Sprintf(
"[%s] %s, %s => %s",
singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{
MessageID: "IPChanged",
}),
singleton.ServerList[clientID].Name, singleton.IPDesensitize(singleton.ServerList[clientID].Host.IP), singleton.IPDesensitize(host.IP)), true)
singleton.ServerList[clientID].Name, singleton.IPDesensitize(singleton.ServerList[clientID].Host.IP), singleton.IPDesensitize(host.IP)), singleton.NotificationMuteLabel.IPChanged(clientID), nil)
}
// 判断是否是机器重启,如果是机器重启要录入最后记录的流量里面

View File

@ -163,7 +163,7 @@ func checkStatus() {
MessageID: "Incident",
}), server.Name, IPDesensitize(server.Host.IP), alert.Name)
go SendTriggerTasks(alert.FailTriggerTasks, curServer.ID)
go SendNotification(alert.NotificationTag, message, true, &curServer)
go SendNotification(alert.NotificationTag, message, NotificationMuteLabel.ServerIncident(server.ID, alert.ID), &curServer)
}
} else {
// 本次通过检查但上一次的状态为失败,则发送恢复通知
@ -172,7 +172,7 @@ func checkStatus() {
MessageID: "Resolved",
}), server.Name, IPDesensitize(server.Host.IP), alert.Name)
go SendTriggerTasks(alert.RecoverTriggerTasks, curServer.ID)
go SendNotification(alert.NotificationTag, message, true, &curServer)
go SendNotification(alert.NotificationTag, message, NotificationMuteLabel.ServerIncidentResolved(server.ID, alert.ID), &curServer)
}
alertsPrevState[alert.ID][server.ID] = _RuleCheckPass
}

View File

@ -60,7 +60,7 @@ func LoadCronTasks() {
// 向注册错误的计划任务所在通知组发送通知
for _, tag := range notificationTagList {
notificationMsgMap[tag].WriteString("] 这些任务将无法正常执行,请进入后点重新修改保存。")
SendNotification(tag, notificationMsgMap[tag].String(), false)
SendNotification(tag, notificationMsgMap[tag].String(), nil)
}
Cron.Start()
}
@ -108,7 +108,7 @@ func CronTrigger(cr model.Cron, triggerServer ...uint64) func() {
// 保存当前服务器状态信息
curServer := model.Server{}
copier.Copy(&curServer, s)
SendNotification(cr.NotificationTag, fmt.Sprintf("[任务失败] %s服务器 %s 离线,无法执行。", cr.Name, s.Name), false, &curServer)
SendNotification(cr.NotificationTag, fmt.Sprintf("[任务失败] %s服务器 %s 离线,无法执行。", cr.Name, s.Name), nil, &curServer)
}
}
return
@ -133,7 +133,7 @@ func CronTrigger(cr model.Cron, triggerServer ...uint64) func() {
// 保存当前服务器状态信息
curServer := model.Server{}
copier.Copy(&curServer, s)
SendNotification(cr.NotificationTag, fmt.Sprintf("[任务失败] %s服务器 %s 离线,无法执行。", cr.Name, s.Name), false, &curServer)
SendNotification(cr.NotificationTag, fmt.Sprintf("[任务失败] %s服务器 %s 离线,无法执行。", cr.Name, s.Name), nil, &curServer)
}
}
}

View File

@ -1,8 +1,9 @@
package singleton
import (
"crypto/md5" // #nosec
"encoding/hex"
// #nosec
"fmt"
"log"
"sync"
"time"
@ -48,7 +49,7 @@ func LoadNotifications() {
func SetDefaultNotificationTagInDB(n *model.Notification) {
n.Tag = "default"
if err := DB.Save(n).Error; err != nil {
log.Println("[ERROR]", err)
log.Println("NEZHA>> SetDefaultNotificationTagInDB 错误: ", err)
}
}
@ -102,12 +103,13 @@ func OnDeleteNotification(id uint64) {
}
// SendNotification 向指定的通知方式组的所有通知方式发送通知
func SendNotification(notificationTag string, desc string, mutable bool, ext ...*model.Server) {
if mutable {
func SendNotification(notificationTag string, desc string, muteLabel *string, ext ...*model.Server) {
if muteLabel != nil {
// 将通知方式组名称加入静音标志
muteLabel := fmt.Sprintf("%s:%s", *muteLabel, notificationTag)
// 通知防骚扰策略
nID := hex.EncodeToString(md5.New().Sum([]byte(desc))) // #nosec
var flag bool
if cacheN, has := Cache.Get(nID); has {
if cacheN, has := Cache.Get(muteLabel); has {
nHistory := cacheN.(NotificationHistory)
// 每次提醒都增加一倍等待时间,最后每天最多提醒一次
if time.Now().After(nHistory.Until) {
@ -118,12 +120,12 @@ func SendNotification(notificationTag string, desc string, mutable bool, ext ...
}
nHistory.Until = time.Now().Add(nHistory.Duration)
// 缓存有效期加 10 分钟
Cache.Set(nID, nHistory, nHistory.Duration+time.Minute*10)
Cache.Set(muteLabel, nHistory, nHistory.Duration+time.Minute*10)
}
} else {
// 新提醒直接通知
flag = true
Cache.Set(nID, NotificationHistory{
Cache.Set(muteLabel, NotificationHistory{
Duration: firstNotificationDelay,
Until: time.Now().Add(firstNotificationDelay),
}, firstNotificationDelay+time.Minute*10)
@ -131,7 +133,7 @@ func SendNotification(notificationTag string, desc string, mutable bool, ext ...
if !flag {
if Conf.Debug {
log.Println("NEZHA>> 静音的重复通知:", desc, mutable)
log.Println("NEZHA>> 静音的重复通知:", desc, muteLabel)
}
return
}
@ -140,7 +142,7 @@ func SendNotification(notificationTag string, desc string, mutable bool, ext ...
notificationsLock.RLock()
defer notificationsLock.RUnlock()
for _, n := range NotificationList[notificationTag] {
log.Println("尝试通知", n.Name)
log.Println("NEZHA>> 尝试通知", n.Name)
}
for _, n := range NotificationList[notificationTag] {
ns := model.NotificationServerBundle{
@ -157,3 +159,42 @@ func SendNotification(notificationTag string, desc string, mutable bool, ext ...
}
}
}
type _NotificationMuteLabel struct{}
var NotificationMuteLabel _NotificationMuteLabel
func (_NotificationMuteLabel) IPChanged(serverId uint64) *string {
label := fmt.Sprintf("bf::ic-%d", serverId)
return &label
}
func (_NotificationMuteLabel) ServerIncident(alertId uint64, serverId uint64) *string {
label := fmt.Sprintf("bf::sei-%d-%d", alertId, serverId)
return &label
}
func (_NotificationMuteLabel) ServerIncidentResolved(alertId uint64, serverId uint64) *string {
label := fmt.Sprintf("bf::seir-%d-%d", alertId, serverId)
return &label
}
func (_NotificationMuteLabel) ServiceLatencyMin(serviceId uint64) *string {
label := fmt.Sprintf("bf::sln-%d", serviceId)
return &label
}
func (_NotificationMuteLabel) ServiceLatencyMax(serviceId uint64) *string {
label := fmt.Sprintf("bf::slm-%d", serviceId)
return &label
}
func (_NotificationMuteLabel) ServiceStateChanged(serviceId uint64) *string {
label := fmt.Sprintf("bf::ssc-%d", serviceId)
return &label
}
func (_NotificationMuteLabel) ServiceSSL(serviceId uint64) *string {
label := fmt.Sprintf("bf::sssl-%d", serviceId)
return &label
}

View File

@ -375,12 +375,12 @@ func (ss *ServiceSentinel) worker() {
if ss.monitors[mh.GetId()].LatencyNotify {
if mh.Delay > ss.monitors[mh.GetId()].MaxLatency {
ServerLock.RLock()
go SendNotification(ss.monitors[mh.GetId()].NotificationTag, fmt.Sprintf("[Latency] %s %2f > %2f, Reporter: %s", ss.monitors[mh.GetId()].Name, mh.Delay, ss.monitors[mh.GetId()].MaxLatency, ServerList[r.Reporter].Name), true)
go SendNotification(ss.monitors[mh.GetId()].NotificationTag, fmt.Sprintf("[Latency] %s %2f > %2f, Reporter: %s", ss.monitors[mh.GetId()].Name, mh.Delay, ss.monitors[mh.GetId()].MaxLatency, ServerList[r.Reporter].Name), NotificationMuteLabel.ServiceLatencyMin(mh.GetId()))
ServerLock.RUnlock()
}
if mh.Delay < ss.monitors[mh.GetId()].MinLatency {
ServerLock.RLock()
go SendNotification(ss.monitors[mh.GetId()].NotificationTag, fmt.Sprintf("[Latency] %s %2f < %2f, Reporter: %s", ss.monitors[mh.GetId()].Name, mh.Delay, ss.monitors[mh.GetId()].MinLatency, ServerList[r.Reporter].Name), true)
go SendNotification(ss.monitors[mh.GetId()].NotificationTag, fmt.Sprintf("[Latency] %s %2f < %2f, Reporter: %s", ss.monitors[mh.GetId()].Name, mh.Delay, ss.monitors[mh.GetId()].MinLatency, ServerList[r.Reporter].Name), NotificationMuteLabel.ServiceLatencyMax(mh.GetId()))
ServerLock.RUnlock()
}
}
@ -393,7 +393,7 @@ func (ss *ServiceSentinel) worker() {
ss.lastStatus[mh.GetId()] = stateCode
if isNeedSendNotification {
ServerLock.RLock()
go SendNotification(ss.monitors[mh.GetId()].NotificationTag, fmt.Sprintf("[%s] %s Reporter: %s, Error: %s", StatusCodeToString(stateCode), ss.monitors[mh.GetId()].Name, ServerList[r.Reporter].Name, mh.Data), true)
go SendNotification(ss.monitors[mh.GetId()].NotificationTag, fmt.Sprintf("[%s] %s Reporter: %s, Error: %s", StatusCodeToString(stateCode), ss.monitors[mh.GetId()].Name, ServerList[r.Reporter].Name, mh.Data), NotificationMuteLabel.ServiceStateChanged(mh.GetId()))
ServerLock.RUnlock()
}
ss.monitorsLock.RUnlock()
@ -438,7 +438,7 @@ func (ss *ServiceSentinel) worker() {
if errMsg != "" {
ss.monitorsLock.RLock()
if ss.monitors[mh.GetId()].Notify {
go SendNotification(ss.monitors[mh.GetId()].NotificationTag, fmt.Sprintf("[SSL] %s %s", ss.monitors[mh.GetId()].Name, errMsg), true)
go SendNotification(ss.monitors[mh.GetId()].NotificationTag, fmt.Sprintf("[SSL] %s %s", ss.monitors[mh.GetId()].Name, errMsg), NotificationMuteLabel.ServiceSSL(mh.GetId()))
}
ss.monitorsLock.RUnlock()
}

View File

@ -12,7 +12,7 @@ import (
"github.com/naiba/nezha/pkg/utils"
)
var Version = "v0.14.5" // !!记得修改 README 中的 badge 版本!!
var Version = "v0.14.6" // !!记得修改 README 中的 badge 版本!!
var (
Conf *model.Config