From 668711eb23d5f009d9933cbc834aac621b7e3d09 Mon Sep 17 00:00:00 2001 From: naiba Date: Mon, 31 Oct 2022 21:54:37 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=80=20`dashboard=20v0.14.6`=20with=20`?= =?UTF-8?q?installer=20v0.11.0`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- cmd/agent/pty/pty_windows.go | 39 ++++++++++------- go.mod | 14 +++---- go.sum | 28 +++++++------ script/install.sh | 29 ++++--------- script/install_en.sh | 29 ++++--------- service/rpc/nezha.go | 7 ++-- service/singleton/alertsentinel.go | 4 +- service/singleton/crontask.go | 6 +-- service/singleton/notification.go | 63 +++++++++++++++++++++++----- service/singleton/servicesentinel.go | 8 ++-- service/singleton/singleton.go | 2 +- 12 files changed, 130 insertions(+), 101 deletions(-) diff --git a/README.md b/README.md index 3deb5c7..38ea871 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@
LOGO designed by 熊大 .

-    +   

:trollface: Nezha Monitoring: Self-hosted, lightweight server and website monitoring and O&M tool.

diff --git a/cmd/agent/pty/pty_windows.go b/cmd/agent/pty/pty_windows.go index 499831a..85d5a51 100644 --- a/cmd/agent/pty/pty_windows.go +++ b/cmd/agent/pty/pty_windows.go @@ -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") } diff --git a/go.mod b/go.mod index 922e962..e3c0499 100644 --- a/go.mod +++ b/go.mod @@ -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 diff --git a/go.sum b/go.sum index cb5ef0d..f0a8d71 100644 --- a/go.sum +++ b/go.sum @@ -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= diff --git a/script/install.sh b/script/install.sh index fff1940..4473578 100755 --- a/script/install.sh +++ b/script/install.sh @@ -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 diff --git a/script/install_en.sh b/script/install_en.sh index 92342dd..41bc7dd 100755 --- a/script/install_en.sh +++ b/script/install_en.sh @@ -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 diff --git a/service/rpc/nezha.go b/service/rpc/nezha.go index 4baeb04..04a73e5 100644 --- a/service/rpc/nezha.go +++ b/service/rpc/nezha.go @@ -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) } // 判断是否是机器重启,如果是机器重启要录入最后记录的流量里面 diff --git a/service/singleton/alertsentinel.go b/service/singleton/alertsentinel.go index eb95fc3..8b30e2e 100644 --- a/service/singleton/alertsentinel.go +++ b/service/singleton/alertsentinel.go @@ -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 } diff --git a/service/singleton/crontask.go b/service/singleton/crontask.go index bf721ea..6a1257e 100644 --- a/service/singleton/crontask.go +++ b/service/singleton/crontask.go @@ -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) } } } diff --git a/service/singleton/notification.go b/service/singleton/notification.go index 18d487a..2b4d047 100644 --- a/service/singleton/notification.go +++ b/service/singleton/notification.go @@ -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 +} diff --git a/service/singleton/servicesentinel.go b/service/singleton/servicesentinel.go index 8ac63e3..239133e 100644 --- a/service/singleton/servicesentinel.go +++ b/service/singleton/servicesentinel.go @@ -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() } diff --git a/service/singleton/singleton.go b/service/singleton/singleton.go index a213b5d..e43acc4 100644 --- a/service/singleton/singleton.go +++ b/service/singleton/singleton.go @@ -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