Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
9c25540e15 | ||
|
a9d521cada | ||
|
60bfb4cb65 | ||
|
9e730cc2cb | ||
|
08d9d14161 | ||
|
9b6d8ad0f2 | ||
|
bd0d355bd6 | ||
|
40ae067f99 | ||
|
11c29d14ad | ||
|
f4b7483807 | ||
|
3d6edd602c | ||
|
2590815a6c | ||
|
c20dfdc7a3 | ||
|
96c3fd433f |
8
.dockerignore
Normal file
8
.dockerignore
Normal file
@ -0,0 +1,8 @@
|
||||
.git
|
||||
.gitignore
|
||||
docker-compose.yml
|
||||
Dockerfile
|
||||
Dockerfile.dev
|
||||
|
||||
|
||||
data/*
|
22
.github/workflows/release.yml
vendored
22
.github/workflows/release.yml
vendored
@ -17,7 +17,7 @@ jobs:
|
||||
goarch: s390x
|
||||
- goos: linux
|
||||
goarch: arm64
|
||||
|
||||
|
||||
name: Build artifacts
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
@ -44,12 +44,12 @@ jobs:
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.23.x"
|
||||
|
||||
|
||||
- name: Build
|
||||
uses: goreleaser/goreleaser-action@v6
|
||||
with:
|
||||
distribution: goreleaser
|
||||
version: '~> v2'
|
||||
version: "~> v2"
|
||||
args: build --single-target --clean --skip=validate
|
||||
|
||||
- name: Upload artifacts
|
||||
@ -72,12 +72,12 @@ jobs:
|
||||
|
||||
- name: Archive and compress binaries
|
||||
run: |
|
||||
for file in assets/*/*/*; do
|
||||
if [ -f "$file" ]; then
|
||||
chmod +x "$file"
|
||||
export fileWithoutExt=${file%.*}
|
||||
zip -jr "$fileWithoutExt.zip" "$file"
|
||||
fi
|
||||
find assets/*/*/* -type f | while read -r file; do
|
||||
chmod +x $file
|
||||
dir=$(dirname "$file")
|
||||
filename=$(basename "$file")
|
||||
fileWithoutExt="${filename%.*}"
|
||||
zip -jr "$dir/$fileWithoutExt.zip" "$file"
|
||||
done
|
||||
|
||||
- name: Release
|
||||
@ -113,7 +113,7 @@ jobs:
|
||||
name: Release Docker images
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
@ -130,7 +130,7 @@ jobs:
|
||||
export TAG_NAME=$(echo ${GITHUB_REF#refs/tags/})
|
||||
echo "tag=$TAG_NAME" >> $GITHUB_OUTPUT
|
||||
id: extract_branch
|
||||
|
||||
|
||||
- name: Log into GHCR
|
||||
uses: docker/login-action@master
|
||||
with:
|
||||
|
1
.github/workflows/sync-release.yml
vendored
1
.github/workflows/sync-release.yml
vendored
@ -6,6 +6,7 @@ on:
|
||||
jobs:
|
||||
sync-release-to-gitee:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
env:
|
||||
GITEE_TOKEN: ${{ secrets.GITEE_TOKEN }}
|
||||
steps:
|
||||
|
63
Dockerfile.dev
Normal file
63
Dockerfile.dev
Normal file
@ -0,0 +1,63 @@
|
||||
# Use build arguments for Go version and architecture
|
||||
ARG GO_VERSION=1.22
|
||||
ARG BUILDARCH=amd64
|
||||
|
||||
# Stage 1: Builder Stage
|
||||
# FROM golang:${GO_VERSION}-alpine AS builder
|
||||
FROM crazymax/xgo:${GO_VERSION} AS builder
|
||||
|
||||
# Set up working directory
|
||||
WORKDIR /app
|
||||
|
||||
# Step 1: Copy the source code
|
||||
COPY . .
|
||||
|
||||
# use --mount=type=cache,target=/go/pkg/mod to cache the go mod
|
||||
# Step 2: Download dependencies
|
||||
RUN --mount=type=cache,target=/go/pkg/mod \
|
||||
go mod tidy && go mod download
|
||||
|
||||
# Step 3: Build the Go application with CGO enabled and specified ldflags
|
||||
RUN --mount=type=cache,target=/go/pkg/mod \
|
||||
CGO_ENABLED=1 GOOS=linux go build -a \
|
||||
-ldflags "-s -w --extldflags '-static -fpic'" \
|
||||
-installsuffix cgo -o dashboard cmd/dashboard/main.go
|
||||
|
||||
|
||||
# Stage 2: Create the final image
|
||||
FROM alpine:latest
|
||||
|
||||
ARG COUNTRY
|
||||
# Install required tools without caching index to minimize image size
|
||||
RUN if [ "$COUNTRY" = "CN" ] ; then \
|
||||
echo "It is in China, updating the repositories"; \
|
||||
sed -i 's#https\?://dl-cdn.alpinelinux.org/alpine#https://mirrors.tuna.tsinghua.edu.cn/alpine#g' /etc/apk/repositories; \
|
||||
fi && \
|
||||
apk update && apk add --no-cache tzdata && \
|
||||
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
|
||||
echo 'Asia/Shanghai' >/etc/timezone && \
|
||||
rm -rf /var/cache/apk/* && \
|
||||
mkdir -p /dashboard/data
|
||||
|
||||
|
||||
# Copy the entrypoint script and ensure it is executable
|
||||
COPY ./script/entrypoint.sh /entrypoint.sh
|
||||
|
||||
# Set up the entrypoint script
|
||||
RUN chmod +x /entrypoint.sh
|
||||
|
||||
WORKDIR /dashboard
|
||||
|
||||
# Copy the statically linked binary from the builder stage
|
||||
COPY --from=builder /app/dashboard ./app
|
||||
# Copy the configuration file and the resource directory
|
||||
COPY ./script/config.yaml ./data/config.yaml
|
||||
COPY ./resource ./resource
|
||||
|
||||
|
||||
# Set up volume and expose ports
|
||||
VOLUME ["/dashboard/data"]
|
||||
EXPOSE 80 5555 443
|
||||
|
||||
# Define the entrypoint
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
10
README.md
10
README.md
@ -4,7 +4,7 @@
|
||||
<br>
|
||||
<small><i>LOGO designed by <a href="https://xio.ng" target="_blank">熊大</a> .</i></small>
|
||||
<br><br>
|
||||
<img alt="GitHub release (with filter)" src="https://img.shields.io/github/v/release/naiba/nezha?color=brightgreen&style=for-the-badge&logo=github&label=Dashboard"> <img src="https://img.shields.io/github/v/release/nezhahq/agent?color=brightgreen&label=Agent&style=for-the-badge&logo=github"> <img src="https://img.shields.io/github/actions/workflow/status/nezhahq/agent/agent.yml?label=Agent%20CI&logo=github&style=for-the-badge"> <img src="https://img.shields.io/badge/Installer-v0.20.2-brightgreen?style=for-the-badge&logo=linux">
|
||||
<img alt="GitHub release (with filter)" src="https://img.shields.io/github/v/release/naiba/nezha?color=brightgreen&style=for-the-badge&logo=github&label=Dashboard"> <img src="https://img.shields.io/github/v/release/nezhahq/agent?color=brightgreen&label=Agent&style=for-the-badge&logo=github"> <img src="https://img.shields.io/github/actions/workflow/status/nezhahq/agent/agent.yml?label=Agent%20CI&logo=github&style=for-the-badge">
|
||||
<br>
|
||||
<br>
|
||||
<p>:trollface: <b>Nezha Monitoring: Self-hostable, lightweight, servers and websites monitoring and O&M tool.</b></p>
|
||||
@ -63,10 +63,12 @@ You can change the dashboard language in the settings page (`/setting`) after th
|
||||
<a href="https://github.com/iilemon" title="Sean"><img src="https://avatars.githubusercontent.com/u/33201711?v=4" width="50;" alt="Sean"/></a>
|
||||
<a href="https://github.com/fscarmen" title="fscarmen"><img src="https://avatars.githubusercontent.com/u/62703343?v=4" width="50;" alt="fscarmen"/></a>
|
||||
<a href="https://github.com/ch8o" title="no-name-now"><img src="https://avatars.githubusercontent.com/u/9103372?v=4" width="50;" alt="no-name-now"/></a>
|
||||
<a href="https://github.com/IamTaoChen" title="Tao Chen"><img src="https://avatars.githubusercontent.com/u/42793494?v=4" width="50;" alt="Tao Chen"/></a>
|
||||
<a href="https://github.com/HsukqiLee" title="HsukqiLee"><img src="https://avatars.githubusercontent.com/u/79034142?v=4" width="50;" alt="HsukqiLee"/></a>
|
||||
<a href="https://github.com/DarcJC" title="Darc Z."><img src="https://avatars.githubusercontent.com/u/53445798?v=4" width="50;" alt="Darc Z."/></a>
|
||||
<a href="https://github.com/Creling" title="Creling"><img src="https://avatars.githubusercontent.com/u/43109504?v=4" width="50;" alt="Creling"/></a>
|
||||
<a href="https://github.com/coreff" title="Core F"><img src="https://avatars.githubusercontent.com/u/38347122?v=4" width="50;" alt="Core F"/></a>
|
||||
<a href="https://github.com/Septrum101" title="Spetrum"><img src="https://avatars.githubusercontent.com/u/11692994?v=4" width="50;" alt="Spetrum"/></a>
|
||||
<a href="https://github.com/nickfox-taterli" title="Tater Li"><img src="https://avatars.githubusercontent.com/u/19658596?v=4" width="50;" alt="Tater Li"/></a>
|
||||
<a href="https://github.com/hmsjy2017" title="Tony"><img src="https://avatars.githubusercontent.com/u/42692274?v=4" width="50;" alt="Tony"/></a>
|
||||
<a href="https://github.com/adminsama" title="adminsama"><img src="https://avatars.githubusercontent.com/u/60880076?v=4" width="50;" alt="adminsama"/></a>
|
||||
@ -81,8 +83,6 @@ You can change the dashboard language in the settings page (`/setting`) after th
|
||||
<a href="https://github.com/ysicing" title="缘生"><img src="https://avatars.githubusercontent.com/u/8605565?v=4" width="50;" alt="缘生"/></a>
|
||||
<a href="https://github.com/arkylin" title="凌"><img src="https://avatars.githubusercontent.com/u/35104502?v=4" width="50;" alt="凌"/></a>
|
||||
<a href="https://github.com/colour93" title="玖叁"><img src="https://avatars.githubusercontent.com/u/64313711?v=4" width="50;" alt="玖叁"/></a>
|
||||
<a href="https://github.com/IamTaoChen" title="Tao Chen"><img src="https://avatars.githubusercontent.com/u/42793494?v=4" width="50;" alt="Tao Chen"/></a>
|
||||
<a href="https://github.com/Septrum101" title="Spetrum"><img src="https://avatars.githubusercontent.com/u/11692994?v=4" width="50;" alt="Spetrum"/></a>
|
||||
<a href="https://github.com/dreamingsleeping" title="Nanjing Hopefun Network Technology Co. Ltd."><img src="https://avatars.githubusercontent.com/u/13828658?v=4" width="50;" alt="Nanjing Hopefun Network Technology Co. Ltd."/></a>
|
||||
<a href="https://github.com/Moraxyc" title="Moraxyc"><img src="https://avatars.githubusercontent.com/u/69713071?v=4" width="50;" alt="Moraxyc"/></a>
|
||||
<a href="https://github.com/silver-ymz" title="Mingzhuo Yin"><img src="https://avatars.githubusercontent.com/u/78400701?v=4" width="50;" alt="Mingzhuo Yin"/></a>
|
||||
@ -94,7 +94,9 @@ You can change the dashboard language in the settings page (`/setting`) after th
|
||||
<a href="https://github.com/GreenTeodoro839" title="GreenTeodoro839"><img src="https://avatars.githubusercontent.com/u/77104800?v=4" width="50;" alt="GreenTeodoro839"/></a>
|
||||
<a href="https://github.com/Es-dese" title="Esdese"><img src="https://avatars.githubusercontent.com/u/71542548?v=4" width="50;" alt="Esdese"/></a>
|
||||
<a href="https://github.com/wwng2333" title=":D"><img src="https://avatars.githubusercontent.com/u/17147265?v=4" width="50;" alt=":D"/></a>
|
||||
<a href="https://github.com/wellcoming" title="Coming"><img src="https://avatars.githubusercontent.com/u/74850890?v=4" width="50;" alt="Coming"/></a><!--GAMFC_DELIMITER_END-->
|
||||
<a href="https://github.com/wellcoming" title="Coming"><img src="https://avatars.githubusercontent.com/u/74850890?v=4" width="50;" alt="Coming"/></a>
|
||||
<a href="https://github.com/choyri" title="Chotow"><img src="https://avatars.githubusercontent.com/u/13994362?v=4" width="50;" alt="Chotow"/></a>
|
||||
<a href="https://github.com/006lp" title="006lp"><img src="https://avatars.githubusercontent.com/u/144674902?v=4" width="50;" alt="006lp"/></a><!--GAMFC_DELIMITER_END-->
|
||||
|
||||
## Special Thanks
|
||||
- [IPInfo](https://ipinfo.io/) for providing an accurate GeoIP Database.
|
||||
|
@ -28,6 +28,7 @@ func (v *apiV1) serve() {
|
||||
}))
|
||||
r.GET("/server/list", v.serverList)
|
||||
r.GET("/server/details", v.serverDetails)
|
||||
r.POST("/server/register", v.RegisterServer)
|
||||
// 不强制认证的 API
|
||||
mr := v.r.Group("monitor")
|
||||
mr.Use(mygin.Authorize(mygin.AuthorizeOption{
|
||||
@ -83,6 +84,45 @@ func (v *apiV1) serverDetails(c *gin.Context) {
|
||||
c.JSON(200, singleton.ServerAPI.GetAllStatus())
|
||||
}
|
||||
|
||||
// RegisterServer adds a server and responds with the full ServerRegisterResponse
|
||||
// header: Authorization: Token
|
||||
// body: RegisterServer
|
||||
// response: ServerRegisterResponse or Secret string
|
||||
func (v *apiV1) RegisterServer(c *gin.Context) {
|
||||
var rs singleton.RegisterServer
|
||||
// Attempt to bind JSON to RegisterServer struct
|
||||
if err := c.ShouldBindJSON(&rs); err != nil {
|
||||
c.JSON(400, singleton.ServerRegisterResponse{
|
||||
CommonResponse: singleton.CommonResponse{
|
||||
Code: 400,
|
||||
Message: "Parse JSON failed",
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
// Check if simple mode is requested
|
||||
simple := c.Query("simple") == "true" || c.Query("simple") == "1"
|
||||
// Set defaults if fields are empty
|
||||
if rs.Name == "" {
|
||||
rs.Name = c.ClientIP()
|
||||
}
|
||||
if rs.Tag == "" {
|
||||
rs.Tag = "AutoRegister"
|
||||
}
|
||||
if rs.HideForGuest == "" {
|
||||
rs.HideForGuest = "on"
|
||||
}
|
||||
// Call the Register function and get the response
|
||||
response := singleton.ServerAPI.Register(&rs)
|
||||
// Respond with Secret only if in simple mode, otherwise full response
|
||||
if simple {
|
||||
c.JSON(response.Code, response.Secret)
|
||||
} else {
|
||||
c.JSON(response.Code, response)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func (v *apiV1) monitorHistoriesById(c *gin.Context) {
|
||||
idStr := c.Param("id")
|
||||
id, err := strconv.ParseUint(idStr, 10, 64)
|
||||
|
17
docker-compose.yml
Normal file
17
docker-compose.yml
Normal file
@ -0,0 +1,17 @@
|
||||
services:
|
||||
app:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.dev
|
||||
args:
|
||||
COUNTRY: CN
|
||||
image: nezha:dev
|
||||
container_name: nezha-dev
|
||||
ports:
|
||||
- ${NEZHA_PORT:-80}:18080
|
||||
- 5555:5555
|
||||
volumes:
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- ./data:/dashboard/data
|
||||
# - ./resource:/dashboard/resource
|
28
go.mod
28
go.mod
@ -14,6 +14,10 @@ require (
|
||||
github.com/hashicorp/go-uuid v1.0.3
|
||||
github.com/jinzhu/copier v0.4.0
|
||||
github.com/json-iterator/go v1.1.12
|
||||
github.com/knadh/koanf/parsers/yaml v0.1.0
|
||||
github.com/knadh/koanf/providers/env v1.0.0
|
||||
github.com/knadh/koanf/providers/file v1.1.2
|
||||
github.com/knadh/koanf/v2 v2.1.2
|
||||
github.com/libdns/cloudflare v0.1.1
|
||||
github.com/libdns/libdns v0.2.2
|
||||
github.com/miekg/dns v1.1.62
|
||||
@ -24,7 +28,6 @@ require (
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/spf13/viper v1.18.2
|
||||
github.com/tidwall/gjson v1.18.0
|
||||
github.com/xanzy/go-gitlab v0.103.0
|
||||
golang.org/x/crypto v0.25.0
|
||||
@ -34,14 +37,15 @@ require (
|
||||
golang.org/x/text v0.16.0
|
||||
google.golang.org/grpc v1.63.0
|
||||
google.golang.org/protobuf v1.34.2
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
gorm.io/driver/sqlite v1.5.5
|
||||
gorm.io/gorm v1.25.10
|
||||
sigs.k8s.io/yaml v1.4.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/bytedance/sonic v1.9.1 // indirect
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/davidmz/go-pageant v1.0.2 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
|
||||
@ -51,44 +55,36 @@ require (
|
||||
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.0 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
|
||||
github.com/hashicorp/go-version v1.6.0 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
|
||||
github.com/knadh/koanf/maps v0.1.1 // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/leodido/go-urn v1.2.4 // indirect
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.17 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
github.com/spf13/afero v1.11.0 // indirect
|
||||
github.com/spf13/cast v1.6.0 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.0 // indirect
|
||||
github.com/tidwall/sjson v1.2.5 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.11 // indirect
|
||||
go.uber.org/atomic v1.9.0 // indirect
|
||||
go.uber.org/multierr v1.9.0 // indirect
|
||||
golang.org/x/arch v0.3.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
|
||||
golang.org/x/mod v0.18.0 // indirect
|
||||
golang.org/x/sys v0.22.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
golang.org/x/tools v0.22.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
49
go.sum
49
go.sum
@ -21,8 +21,6 @@ github.com/davidmz/go-pageant v1.0.2 h1:bPblRCh5jGU+Uptpz6LgMZGD5hJoOt7otgT454Wv
|
||||
github.com/davidmz/go-pageant v1.0.2/go.mod h1:P2EDDnMqIwG5Rrp05dTRITj9z2zpGcD9efWSkTNKLIE=
|
||||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
|
||||
@ -54,13 +52,14 @@ github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg
|
||||
github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-github/v47 v47.1.0 h1:Cacm/WxQBOa9lF0FT0EMjZ2BWMetQ1TQfyurn4yF1z8=
|
||||
@ -82,8 +81,6 @@ github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/C
|
||||
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
|
||||
github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8=
|
||||
github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
@ -95,6 +92,16 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
|
||||
github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
||||
github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs=
|
||||
github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI=
|
||||
github.com/knadh/koanf/parsers/yaml v0.1.0 h1:ZZ8/iGfRLvKSaMEECEBPM1HQslrZADk8fP1XFUxVI5w=
|
||||
github.com/knadh/koanf/parsers/yaml v0.1.0/go.mod h1:cvbUDC7AL23pImuQP0oRw/hPuccrNBS2bps8asS0CwY=
|
||||
github.com/knadh/koanf/providers/env v1.0.0 h1:ufePaI9BnWH+ajuxGGiJ8pdTG0uLEUWC7/HDDPGLah0=
|
||||
github.com/knadh/koanf/providers/env v1.0.0/go.mod h1:mzFyRZueYhb37oPmC1HAv/oGEEuyvJDA98r3XAa8Gak=
|
||||
github.com/knadh/koanf/providers/file v1.1.2 h1:aCC36YGOgV5lTtAFz2qkgtWdeQsgfxUkxDOe+2nQY3w=
|
||||
github.com/knadh/koanf/providers/file v1.1.2/go.mod h1:/faSBcv2mxPVjFrXck95qeoyoZ5myJ6uxN8OOVNJJCI=
|
||||
github.com/knadh/koanf/v2 v2.1.2 h1:I2rtLRqXRy1p01m/utEtpZSSA6dcJbgGVuE27kW2PzQ=
|
||||
github.com/knadh/koanf/v2 v2.1.2/go.mod h1:Gphfaen0q1Fc1HTgJgSTC4oRX9R2R5ErYMZJy8fLJBo=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||
@ -111,8 +118,6 @@ github.com/libdns/cloudflare v0.1.1 h1:FVPfWwP8zZCqj268LZjmkDleXlHPlFU9KC4OJ3yn0
|
||||
github.com/libdns/cloudflare v0.1.1/go.mod h1:9VK91idpOjg6v7/WbjkEW49bSCxj00ALesIFDhJ8PBU=
|
||||
github.com/libdns/libdns v0.2.2 h1:O6ws7bAfRPaBsgAYt8MDe2HcNBGC29hkZ9MX2eUSX3s=
|
||||
github.com/libdns/libdns v0.2.2/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ=
|
||||
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
|
||||
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
@ -122,8 +127,10 @@ github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6
|
||||
github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ=
|
||||
github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
|
||||
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
|
||||
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
|
||||
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
@ -158,20 +165,8 @@ github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTE
|
||||
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
|
||||
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
|
||||
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
|
||||
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
|
||||
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
|
||||
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
|
||||
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
|
||||
github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
|
||||
github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ=
|
||||
github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk=
|
||||
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=
|
||||
@ -186,8 +181,6 @@ github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
|
||||
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
@ -205,10 +198,6 @@ github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4d
|
||||
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/xanzy/go-gitlab v0.103.0 h1:J9pTQoq0GsEFqzd6srCM1QfdfKAxSNz6mT6ntrpNF2w=
|
||||
github.com/xanzy/go-gitlab v0.103.0/go.mod h1:ETg8tcj4OhrB84UEgeE8dSuV/0h4BBL1uOV/qK0vlyI=
|
||||
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
|
||||
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
|
||||
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
|
||||
golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
@ -218,8 +207,6 @@ golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
|
||||
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
|
||||
golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
|
||||
golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
@ -267,8 +254,6 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
@ -281,5 +266,3 @@ gorm.io/driver/sqlite v1.5.5/go.mod h1:6NgQ7sQWAIFsPrJJl1lSNSu2TABh0ZZ/zm5fosATa
|
||||
gorm.io/gorm v1.25.10 h1:dQpO+33KalOA+aFYGlK+EfxcI5MbO7EP2yYygwh9h+s=
|
||||
gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
|
||||
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
|
||||
|
@ -1,12 +1,16 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
"sigs.k8s.io/yaml"
|
||||
kyaml "github.com/knadh/koanf/parsers/yaml"
|
||||
"github.com/knadh/koanf/providers/env"
|
||||
"github.com/knadh/koanf/providers/file"
|
||||
"github.com/knadh/koanf/v2"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
var Languages = map[string]string{
|
||||
@ -46,35 +50,6 @@ const (
|
||||
ConfigCoverIgnoreAll
|
||||
)
|
||||
|
||||
type AgentConfig struct {
|
||||
HardDrivePartitionAllowlist []string
|
||||
NICAllowlist map[string]bool
|
||||
v *viper.Viper
|
||||
}
|
||||
|
||||
// Read 从给定的文件目录加载配置文件
|
||||
func (c *AgentConfig) Read(path string) error {
|
||||
c.v = viper.New()
|
||||
c.v.SetConfigFile(path)
|
||||
err := c.v.ReadInConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = c.v.Unmarshal(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *AgentConfig) Save() error {
|
||||
data, err := yaml.Marshal(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return os.WriteFile(c.v.ConfigFileUsed(), data, 0600)
|
||||
}
|
||||
|
||||
// Config 站点配置
|
||||
type Config struct {
|
||||
Debug bool // debug模式开关
|
||||
@ -122,28 +97,52 @@ type Config struct {
|
||||
|
||||
Location string // 时区,默认为 Asia/Shanghai
|
||||
|
||||
v *viper.Viper
|
||||
IgnoredIPNotificationServerIDs map[uint64]bool // [ServerID] -> bool(值为true代表当前ServerID在特定服务器列表内)
|
||||
MaxTCPPingValue int32
|
||||
AvgPingCount int
|
||||
|
||||
DNSServers string
|
||||
|
||||
k *koanf.Koanf
|
||||
filePath string
|
||||
}
|
||||
|
||||
// Read 读取配置文件并应用
|
||||
func (c *Config) Read(path string) error {
|
||||
c.v = viper.New()
|
||||
c.v.SetConfigFile(path)
|
||||
err := c.v.ReadInConfig()
|
||||
c.k = koanf.New(".")
|
||||
c.filePath = path
|
||||
|
||||
// 先读取环境变量,然后读取配置文件;后者可以覆盖前者,因为哪吒支持在线修改配置
|
||||
|
||||
err := c.k.Load(env.Provider("NZ_", ".", func(s string) string {
|
||||
return strings.Replace(strings.ToLower(strings.TrimPrefix(s, "NZ_")), "_", ".", -1)
|
||||
}), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = c.v.Unmarshal(c)
|
||||
if _, err := os.Stat(path); err == nil {
|
||||
err = c.k.Load(file.Provider(path), kyaml.Parser())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = c.k.Unmarshal("", c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.Oauth2.Type == "" || c.Oauth2.Admin == "" || c.Oauth2.ClientID == "" || c.Oauth2.ClientSecret == "" {
|
||||
return errors.New("missing oauth2 config")
|
||||
}
|
||||
|
||||
if c.Site.Brand == "" {
|
||||
c.Site.Brand = "Nezha Monitoring"
|
||||
}
|
||||
if c.Site.CookieName == "" {
|
||||
c.Site.CookieName = "nezha-dashboard"
|
||||
}
|
||||
if c.Site.Theme == "" {
|
||||
c.Site.Theme = "default"
|
||||
}
|
||||
@ -153,6 +152,9 @@ func (c *Config) Read(path string) error {
|
||||
if c.Language == "" {
|
||||
c.Language = "zh-CN"
|
||||
}
|
||||
if c.HTTPPort == 0 {
|
||||
c.HTTPPort = 80
|
||||
}
|
||||
if c.GRPCPort == 0 {
|
||||
c.GRPCPort = 5555
|
||||
}
|
||||
@ -204,5 +206,5 @@ func (c *Config) Save() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return os.WriteFile(c.v.ConfigFileUsed(), data, 0600)
|
||||
return os.WriteFile(c.filePath, data, 0600)
|
||||
}
|
||||
|
3
resource/l10n/en-US.toml
vendored
3
resource/l10n/en-US.toml
vendored
@ -750,3 +750,6 @@ other = "d"
|
||||
|
||||
[CustomNameservers]
|
||||
other = "Custom Public DNS Nameservers for DDNS (separate with comma)"
|
||||
|
||||
[Plan]
|
||||
other = "Plan"
|
||||
|
3
resource/l10n/es-ES.toml
vendored
3
resource/l10n/es-ES.toml
vendored
@ -750,3 +750,6 @@ other = "d"
|
||||
|
||||
[CustomNameservers]
|
||||
other = "Servidores DNS públicos personalizados para DDNS (separar con coma)"
|
||||
|
||||
[Plan]
|
||||
other = "Plan"
|
||||
|
3
resource/l10n/zh-CN.toml
vendored
3
resource/l10n/zh-CN.toml
vendored
@ -750,3 +750,6 @@ other = "天"
|
||||
|
||||
[CustomNameservers]
|
||||
other = "自定义DDNS使用的公共DNS服务器(逗号分隔)"
|
||||
|
||||
[Plan]
|
||||
other = "套餐"
|
||||
|
3
resource/l10n/zh-TW.toml
vendored
3
resource/l10n/zh-TW.toml
vendored
@ -750,3 +750,6 @@ other = "天"
|
||||
|
||||
[CustomNameservers]
|
||||
other = "自訂DDNS使用的公共DNS伺服器(逗號分隔)"
|
||||
|
||||
[Plan]
|
||||
other = "套餐"
|
||||
|
BIN
resource/static/theme-daynight/img/flag/AQ.png
vendored
Normal file
BIN
resource/static/theme-daynight/img/flag/AQ.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.1 KiB |
BIN
resource/static/theme-hotaru/img/clients/AQ.png
vendored
Normal file
BIN
resource/static/theme-hotaru/img/clients/AQ.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.2 KiB |
@ -46,8 +46,6 @@ body[theme="dark"] .content {
|
||||
background-color: rgba(28, 29, 38, 1);
|
||||
border: none;
|
||||
box-shadow: rgba(0, 0, 0, 0.5) 0 0.625em 2em;
|
||||
-webkit-box-shadow: rgba(0, 0, 0, 0.5) 0 0.625em 2em;
|
||||
box-shadow: rgba(0, 0, 0, 0.5) 0 0.625em 2em;
|
||||
}
|
||||
|
||||
body[theme="dark"] .table {
|
||||
@ -90,6 +88,11 @@ body[theme="dark"] .table > tbody > tr.expandRow.odd > td:before {
|
||||
body[theme="dark"] .table > tbody > tr.expandRow.even > td:before {
|
||||
background-color: rgba(28, 29, 38, 1);
|
||||
}
|
||||
|
||||
body[theme="dark"] .plan {
|
||||
background-image: none;
|
||||
background-color: rgba(255, 255, 255, 0.075);
|
||||
}
|
||||
/* expandRow展开部分样式结束 */
|
||||
|
||||
body[theme="dark"] .progress {
|
||||
|
@ -74,8 +74,6 @@ body[theme="dark"] .content {
|
||||
background-color: rgba(28, 29, 38, 0.8);
|
||||
border: none;
|
||||
box-shadow: rgba(0, 0, 0, 0.5) 0 0.625em 2em;
|
||||
-webkit-box-shadow: rgba(0, 0, 0, 0.5) 0 0.625em 2em;
|
||||
box-shadow: rgba(0, 0, 0, 0.5) 0 0.625em 2em;
|
||||
}
|
||||
|
||||
body[theme="dark"] .table > thead > tr.node-group-tag > th,
|
||||
|
@ -69,8 +69,6 @@ body[theme="light"] .content {
|
||||
background: rgba(255, 255, 255, 1);
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
border: 1px #cecece solid;
|
||||
-webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, .1);
|
||||
-moz-box-shadow: 0 1px 10px rgba(0, 0, 0, .1);
|
||||
box-shadow: 0 1px 10px rgba(0, 0, 0, .1);
|
||||
}
|
||||
|
||||
@ -116,6 +114,12 @@ body[theme="light"] tr.odd.expandRow > :hover {
|
||||
background: #ffffff !important;
|
||||
}
|
||||
|
||||
body[theme="light"] .plan {
|
||||
color: #000000;
|
||||
background-color: #f5f5f5;
|
||||
box-shadow: inset 0 -0.5px 2px rgba(0, 0, 0, .1);
|
||||
}
|
||||
|
||||
body[theme="light"] .progress-bar {
|
||||
color: #000000;
|
||||
}
|
||||
|
@ -104,6 +104,11 @@ body[theme="light"] .table > tbody > tr.expandRow.odd > td:before {
|
||||
body[theme="light"] .table > tbody > tr.expandRow.even > td:before {
|
||||
background-color: unset;
|
||||
}
|
||||
|
||||
body[theme="light"] .plan {
|
||||
background-image: none;
|
||||
background-color: rgba(0, 0, 0, 0.015);
|
||||
}
|
||||
/* expandRow展开部分样式结束 */
|
||||
|
||||
body[theme="light"] .progress {
|
||||
|
23
resource/static/theme-server-status/css/main.css
vendored
23
resource/static/theme-server-status/css/main.css
vendored
@ -237,8 +237,8 @@ tr.accordion-toggle{
|
||||
}
|
||||
|
||||
.node-cell.network {
|
||||
min-width: 100px;
|
||||
max-width: 100px;
|
||||
min-width: 110px;
|
||||
max-width: 110px;
|
||||
}
|
||||
|
||||
.node-cell.traffic {
|
||||
@ -268,6 +268,22 @@ tr.accordion-toggle{
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
.plan {
|
||||
display: inline-block;
|
||||
font-size: 85%;
|
||||
margin-right: 2px;
|
||||
padding: 2px 5px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.network-route, .extra {
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
.last {
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
.temp-detail {
|
||||
cursor: pointer;
|
||||
}
|
||||
@ -557,6 +573,9 @@ footer p {
|
||||
min-width: 75px;
|
||||
max-width: 75px;
|
||||
}
|
||||
.plan {
|
||||
display: inline;
|
||||
}
|
||||
.accordian-body {
|
||||
margin: 5px 0px 5px 10px;
|
||||
}
|
||||
|
4
resource/template/component/server.html
vendored
4
resource/template/component/server.html
vendored
@ -53,7 +53,7 @@
|
||||
<label>{{tr "LinuxOneKeyInstall"}}</label>
|
||||
<div class="ui message">
|
||||
{{if .Conf.GRPCHost}}
|
||||
curl -L https://raw.githubusercontent.com/naiba/nezha/master/script/install.sh -o nezha.sh && chmod
|
||||
curl -L https://raw.githubusercontent.com/nezhahq/scripts/refs/heads/v0/install.sh -o nezha.sh && chmod
|
||||
+x nezha.sh && ./nezha.sh install_agent <code class="command">{{.Conf.GRPCHost}}</code> <code
|
||||
class="command">{{if .Conf.ProxyGRPCPort}}{{.Conf.ProxyGRPCPort}}{{else}}{{.Conf.GRPCPort}}{{end}}</code> <code
|
||||
class="command hostSecret"></code> <code class="command">{{if .Conf.TLS}}--tls{{end}}</code>
|
||||
@ -70,4 +70,4 @@
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
@ -55,17 +55,17 @@
|
||||
</td>
|
||||
<td>
|
||||
<button class="ui icon green mini button"
|
||||
data-clipboard-text="{{if $.Conf.GRPCHost}}{{if eq $.Conf.Language "zh-CN"}}curl -L https://raw.githubusercontent.com/naiba/nezha/master/script/install.sh{{else}}curl -L https://raw.githubusercontent.com/naiba/nezha/master/script/install_en.sh{{end}} -o nezha.sh && chmod +x nezha.sh && ./nezha.sh install_agent {{$.Conf.GRPCHost}} {{if $.Conf.ProxyGRPCPort}}{{$.Conf.ProxyGRPCPort}}{{else}}{{$.Conf.GRPCPort}}{{end}} {{$server.Secret}}{{if $.Conf.TLS}} --tls{{end}}{{else}}{{tr "NoDomainAlert"}}{{end}}"
|
||||
data-clipboard-text="{{if $.Conf.GRPCHost}}{{if eq $.Conf.Language "zh-CN"}}curl -L https://raw.githubusercontent.com/nezhahq/scripts/refs/heads/v0/install.sh{{else}}curl -L https://raw.githubusercontent.com/nezhahq/scripts/refs/heads/v0/install_en.sh{{end}} -o nezha.sh && chmod +x nezha.sh && ./nezha.sh install_agent {{$.Conf.GRPCHost}} {{if $.Conf.ProxyGRPCPort}}{{$.Conf.ProxyGRPCPort}}{{else}}{{$.Conf.GRPCPort}}{{end}} {{$server.Secret}}{{if $.Conf.TLS}} --tls{{end}}{{else}}{{tr "NoDomainAlert"}}{{end}}"
|
||||
data-tooltip="{{tr "ClickToCopy"}}">
|
||||
<i class="linux icon"></i>
|
||||
</button>
|
||||
<button class="ui icon green mini button"
|
||||
data-clipboard-text="{{if $.Conf.GRPCHost}}[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Ssl3 -bor [Net.SecurityProtocolType]::Tls -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls12;set-ExecutionPolicy RemoteSigned;Invoke-WebRequest https://raw.githubusercontent.com/naiba/nezha/master/script/install.ps1 -OutFile C:\install.ps1;powershell.exe C:\install.ps1 {{$.Conf.GRPCHost}}:{{if $.Conf.ProxyGRPCPort}}{{$.Conf.ProxyGRPCPort}}{{else}}{{$.Conf.GRPCPort}}{{end}} {{$server.Secret}}{{if $.Conf.TLS}} --tls{{end}}{{else}}{{tr "NoDomainAlert"}}{{end}}"
|
||||
data-clipboard-text="{{if $.Conf.GRPCHost}}[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Ssl3 -bor [Net.SecurityProtocolType]::Tls -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls12;set-ExecutionPolicy RemoteSigned;Invoke-WebRequest https://raw.githubusercontent.com/nezhahq/scripts/refs/heads/v0/extras/install.ps1 -OutFile C:\install.ps1;powershell.exe C:\install.ps1 {{$.Conf.GRPCHost}}:{{if $.Conf.ProxyGRPCPort}}{{$.Conf.ProxyGRPCPort}}{{else}}{{$.Conf.GRPCPort}}{{end}} {{$server.Secret}}{{if $.Conf.TLS}} --tls{{end}}{{else}}{{tr "NoDomainAlert"}}{{end}}"
|
||||
data-tooltip="{{tr "ClickToCopy"}}">
|
||||
<i class="windows icon"></i>
|
||||
</button>
|
||||
<button class="ui icon green mini button"
|
||||
data-clipboard-text="{{if $.Conf.GRPCHost}}curl -L https://raw.githubusercontent.com/naiba/nezha/master/script/install.command -o nezha.command && chmod +x nezha.command && sudo ./nezha.command install_agent {{$.Conf.GRPCHost}} {{if $.Conf.ProxyGRPCPort}}{{$.Conf.ProxyGRPCPort}}{{else}}{{$.Conf.GRPCPort}}{{end}} {{$server.Secret}}{{if $.Conf.TLS}} --tls{{end}}{{else}}{{tr "NoDomainAlert"}}{{end}}"
|
||||
data-clipboard-text="{{if $.Conf.GRPCHost}}curl -L https://raw.githubusercontent.com/nezhahq/scripts/refs/heads/v0/extras/install.command -o nezha.command && chmod +x nezha.command && sudo ./nezha.command install_agent {{$.Conf.GRPCHost}} {{if $.Conf.ProxyGRPCPort}}{{$.Conf.ProxyGRPCPort}}{{else}}{{$.Conf.GRPCPort}}{{end}} {{$server.Secret}}{{if $.Conf.TLS}} --tls{{end}}{{else}}{{tr "NoDomainAlert"}}{{end}}"
|
||||
data-tooltip="{{tr "ClickToCopy"}}">
|
||||
<i class="apple icon"></i>
|
||||
</button>
|
||||
|
@ -28,8 +28,8 @@
|
||||
</span>
|
||||
</aside>
|
||||
<template v-if="semiTransparent">
|
||||
<link rel="stylesheet" href="/static/theme-server-status/css/light.plus.css?v20241008">
|
||||
<link rel="stylesheet" href="/static/theme-server-status/css/dark.plus.css?v20241008">
|
||||
<link rel="stylesheet" href="/static/theme-server-status/css/light.plus.css?v20241103">
|
||||
<link rel="stylesheet" href="/static/theme-server-status/css/dark.plus.css?v20241103">
|
||||
</template>
|
||||
</div>
|
||||
{{if ts .CustomCode}}{{.CustomCode|safe}}{{end}}
|
||||
|
@ -26,9 +26,9 @@
|
||||
<script src="https://unpkg.com/bootstrap@3.4.1/dist/js/bootstrap.min.js"></script>
|
||||
<script src="https://unpkg.com/vue@2.6.14/dist/vue.min.js"></script>
|
||||
<script src="https://unpkg.com/echarts@5.5.0/dist/echarts.min.js"></script>
|
||||
<link rel="stylesheet" href="/static/theme-server-status/css/main.css?v20241008">
|
||||
<link rel="stylesheet" href="/static/theme-server-status/css/dark.css?v20241008">
|
||||
<link rel="stylesheet" href="/static/theme-server-status/css/light.css?v20241008">
|
||||
<link rel="stylesheet" href="/static/theme-server-status/css/main.css?v20241103">
|
||||
<link rel="stylesheet" href="/static/theme-server-status/css/dark.css?v20241103">
|
||||
<link rel="stylesheet" href="/static/theme-server-status/css/light.css?v20241103">
|
||||
<script src="/static/theme-server-status/js/mixin.js?v20240915"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -35,8 +35,8 @@
|
||||
<span class="node-cell-os-text">@#getPlatformName(node.os) === '' && node.stateuptime > 0 ? 'linux' : getPlatformName(node.os)#@</span>
|
||||
</td>
|
||||
<td class="node-cell location center">
|
||||
<i :class="'fi fi-' + (node.stateuptime > 0 ? (node.location || 'rb') : '')"></i>
|
||||
<span class="node-cell-location-text text-uppercase">@#node.stateuptime > 0 ? (node.location || 'RB') : ''#@</span>
|
||||
<i :class="'fi fi-' + (node.stateuptime > 0 ? (node.location || 'un') : '')"></i>
|
||||
<span class="node-cell-location-text text-uppercase">@#node.stateuptime > 0 ? (node.location || 'UN') : ''#@</span>
|
||||
</td>
|
||||
<td v-if="nodesNoTag.some(item => item.additional && item.additional.price && Object.keys(item.additional.price).length > 0)" class="node-cell price center">
|
||||
<template v-if="node.additional && node.additional.price">
|
||||
@ -88,6 +88,45 @@
|
||||
<td colspan="16">
|
||||
<div class="accordian-body collapse" :id="'rt'+node.ID">
|
||||
<div style="display: flex;left-items: center;justify-content: center;flex-direction: column; max-width: 89vw">
|
||||
<span v-if="node.additional && Object.keys(node.additional.plan).length > 0" class="node-cell-expand">
|
||||
<span class="node-cell-expand-label">{{tr "Plan"}}:</span>
|
||||
<span v-if="node.additional && Object.keys(node.additional.price).length > 0" class="plan price">
|
||||
<span v-if="node.additional.price.amount == 0">FREE</span>
|
||||
<span v-else-if="node.additional.price.amount == -1">PAYG</span>
|
||||
<span v-else><i class="bi bi-cash-stack"></i> @#node.additional.price.amount#@@#(node.additional.price.cycle ? '/' + node.additional.price.cycle : '')#@</span>
|
||||
</span>
|
||||
<span v-if="node.additional && node.additional.remaining.endDate" class="plan enddate">
|
||||
<span v-if="node.additional.remaining.days == 'lifetime'">{{tr "Lifetime"}}</span>
|
||||
<span v-else-if="node.additional.remaining.days < 0">{{tr "Expired"}}</span>
|
||||
<span v-else><i class="bi bi-clock-history"></i> @#node.additional.remaining.endDate.toISOString().split('T')[0]#@</span>
|
||||
</span>
|
||||
<span v-if="node.additional && node.additional.plan.bandwidth" class="plan bandwidth">
|
||||
<i class="bi bi-speedometer2"></i>
|
||||
<span>@#node.additional.plan.bandwidth#@</span>
|
||||
</span>
|
||||
<span v-if="node.additional && node.additional.plan.trafficVol" class="plan traffics">
|
||||
<i v-if="node.additional && node.additional.plan.trafficType == 1" class="bi bi-arrow-up"></i>
|
||||
<i v-else-if="node.additional && node.additional.plan.trafficType == 3" class="bi bi-arrows-collapse"></i>
|
||||
<i v-else class="bi bi-arrow-down-up"></i>
|
||||
<span>@#node.additional.plan.trafficVol#@</span>
|
||||
</span>
|
||||
<span v-if="node.additional && node.additional.plan.ipv4" class="plan ipv4">
|
||||
<span>IPv4</span>
|
||||
</span>
|
||||
<span v-if="node.additional && node.additional.plan.ipv6" class="plan ipv6">
|
||||
<span>IPv6</span>
|
||||
</span>
|
||||
<template v-if="node.additional && node.additional.plan.networkRoute.length>0" v-for="(item, index) in node.additional.plan.networkRoute" :key="index">
|
||||
<span class="plan network-route" :class="{ last: index === node.additional.plan.networkRoute.length - 1 }">
|
||||
<span>@#item#@</span>
|
||||
</span>
|
||||
</template>
|
||||
<template v-if="node.additional && node.additional.plan.extra.length>0" v-for="(item, index) in node.additional.plan.extra" :key="index">
|
||||
<span class="plan extra" :class="{ last: index === node.additional.plan.extra.length - 1 }">
|
||||
<span>@#item#@</span>
|
||||
</span>
|
||||
</template>
|
||||
</span>
|
||||
<span class="node-cell-expand">
|
||||
<span class="node-cell-expand-label">{{tr "Platform"}}:</span>
|
||||
<span v-if="node.host.Platform">@#node.host.Platform#@@#node.host.PlatformVersion ? '-' + node.host.PlatformVersion : ''#@</span>
|
||||
@ -120,10 +159,7 @@
|
||||
</span>
|
||||
<span class="node-cell-expand">
|
||||
<span class="node-cell-expand-label">{{tr "NetTransfer"}}:</span>
|
||||
<i class="arrow alternate circle down outline icon"
|
||||
style="margin: 0"></i>@#formatByteSize(node.state.NetInTransfer)#@
|
||||
<i class="arrow alternate circle up outline icon"
|
||||
style="margin: 0"></i>@#formatByteSize(node.state.NetOutTransfer)#@
|
||||
IN @#formatByteSize(node.state.NetInTransfer)#@ / OUT @#formatByteSize(node.state.NetOutTransfer)#@
|
||||
</span>
|
||||
<span class="node-cell-expand load">
|
||||
<span class="node-cell-expand-label">{{tr "Load"}}:</span>
|
||||
|
@ -38,8 +38,8 @@
|
||||
<span class="node-cell-os-text">@#getPlatformName(node.os) === '' && node.stateuptime > 0 ? 'linux' : getPlatformName(node.os)#@</span>
|
||||
</td>
|
||||
<td class="node-cell location center">
|
||||
<i :class="'fi fi-' + (node.stateuptime > 0 ? (node.location || 'rb') : '')"></i>
|
||||
<span class="node-cell-location-text text-uppercase">@#node.stateuptime > 0 ? (node.location || 'RB') : ''#@</span>
|
||||
<i :class="'fi fi-' + (node.stateuptime > 0 ? (node.location || 'un') : '')"></i>
|
||||
<span class="node-cell-location-text text-uppercase">@#node.stateuptime > 0 ? (node.location || 'UN') : ''#@</span>
|
||||
</td>
|
||||
<td v-if="group.data.some(item => item.additional && item.additional.price && Object.keys(item.additional.price).length > 0)" class="node-cell price center">
|
||||
<template v-if="node.additional && node.additional.price">
|
||||
@ -91,6 +91,45 @@
|
||||
<td colspan="16">
|
||||
<div class="accordian-body collapse" :id="'rt'+node.ID">
|
||||
<div style="display: flex;left-items: center;justify-content: center;flex-direction: column; max-width: 89vw">
|
||||
<span v-if="node.additional && Object.keys(node.additional.plan).length > 0" class="node-cell-expand">
|
||||
<span class="node-cell-expand-label">{{tr "Plan"}}:</span>
|
||||
<span v-if="node.additional && Object.keys(node.additional.price).length > 0" class="plan price">
|
||||
<span v-if="node.additional.price.amount == 0">FREE</span>
|
||||
<span v-else-if="node.additional.price.amount == -1">PAYG</span>
|
||||
<span v-else><i class="bi bi-cash-stack"></i> @#node.additional.price.amount#@@#(node.additional.price.cycle ? '/' + node.additional.price.cycle : '')#@</span>
|
||||
</span>
|
||||
<span v-if="node.additional && node.additional.remaining.endDate" class="plan enddate">
|
||||
<span v-if="node.additional.remaining.days == 'lifetime'">{{tr "Lifetime"}}</span>
|
||||
<span v-else-if="node.additional.remaining.days < 0">{{tr "Expired"}}</span>
|
||||
<span v-else><i class="bi bi-clock-history"></i> @#node.additional.remaining.endDate.toISOString().split('T')[0]#@</span>
|
||||
</span>
|
||||
<span v-if="node.additional && node.additional.plan.bandwidth" class="plan bandwidth">
|
||||
<i class="bi bi-speedometer2"></i>
|
||||
<span>@#node.additional.plan.bandwidth#@</span>
|
||||
</span>
|
||||
<span v-if="node.additional && node.additional.plan.trafficVol" class="plan traffics">
|
||||
<i v-if="node.additional && node.additional.plan.trafficType == 1" class="bi bi-arrow-up"></i>
|
||||
<i v-else-if="node.additional && node.additional.plan.trafficType == 3" class="bi bi-arrows-collapse"></i>
|
||||
<i v-else class="bi bi-arrow-down-up"></i>
|
||||
<span>@#node.additional.plan.trafficVol#@</span>
|
||||
</span>
|
||||
<span v-if="node.additional && node.additional.plan.ipv4" class="plan ipv4">
|
||||
<span>IPv4</span>
|
||||
</span>
|
||||
<span v-if="node.additional && node.additional.plan.ipv6" class="plan ipv6">
|
||||
<span>IPv6</span>
|
||||
</span>
|
||||
<template v-if="node.additional && node.additional.plan.networkRoute.length>0" v-for="(item, index) in node.additional.plan.networkRoute" :key="index">
|
||||
<span class="plan network-route" :class="{ last: index === node.additional.plan.networkRoute.length - 1 }">
|
||||
<span>@#item#@</span>
|
||||
</span>
|
||||
</template>
|
||||
<template v-if="node.additional && node.additional.plan.extra.length>0" v-for="(item, index) in node.additional.plan.extra" :key="index">
|
||||
<span class="plan extra" :class="{ last: index === node.additional.plan.extra.length - 1 }">
|
||||
<span>@#item#@</span>
|
||||
</span>
|
||||
</template>
|
||||
</span>
|
||||
<span class="node-cell-expand">
|
||||
<span class="node-cell-expand-label">{{tr "Platform"}}:</span>
|
||||
<span v-if="node.host.Platform">@#node.host.Platform#@@#node.host.PlatformVersion ? '-' + node.host.PlatformVersion : ''#@</span>
|
||||
@ -123,10 +162,7 @@
|
||||
</span>
|
||||
<span class="node-cell-expand">
|
||||
<span class="node-cell-expand-label">{{tr "NetTransfer"}}:</span>
|
||||
<i class="arrow alternate circle down outline icon"
|
||||
style="margin: 0"></i>@#formatByteSize(node.state.NetInTransfer)#@
|
||||
<i class="arrow alternate circle up outline icon"
|
||||
style="margin: 0"></i>@#formatByteSize(node.state.NetOutTransfer)#@
|
||||
IN @#formatByteSize(node.state.NetInTransfer)#@ / OUT @#formatByteSize(node.state.NetOutTransfer)#@
|
||||
</span>
|
||||
<span class="node-cell-expand load">
|
||||
<span class="node-cell-expand-label">{{tr "Load"}}:</span>
|
||||
|
90
resource/template/theme-server-status/home.html
vendored
90
resource/template/theme-server-status/home.html
vendored
@ -117,43 +117,54 @@
|
||||
initAdditional(servers) {
|
||||
let nodes = {};
|
||||
servers?.forEach(server => {
|
||||
if (server.PublicNote) {
|
||||
const remainingFormat = this.getRemainingFormat(server.live, server.PublicNote);
|
||||
const remainingDays = this.getRemainingDays(this.getNoteElementValue(server.PublicNote, "billingDataMod", "endDate"), server.PublicNote);
|
||||
const remainingPercent = this.getRemainingPercent(
|
||||
this.getNoteElementValue(server.PublicNote, "billingDataMod", "startDate"),
|
||||
this.getNoteElementValue(server.PublicNote, "billingDataMod", "endDate"),
|
||||
server.PublicNote
|
||||
);
|
||||
const priceAmount = this.getNoteElementValue(server.PublicNote, "billingDataMod", "amount");
|
||||
const priceCycle = this.getNoteElementValue(server.PublicNote, "billingDataMod", "cycle");
|
||||
//处理异常
|
||||
if (!server.PublicNote) return;
|
||||
|
||||
// 初始化节点
|
||||
nodes[server.ID] = {
|
||||
"remaining": {},
|
||||
"price": {}
|
||||
};
|
||||
// 初始化节点
|
||||
nodes[server.ID] = {
|
||||
"remaining": {},
|
||||
"price": {},
|
||||
"plan": {}
|
||||
};
|
||||
|
||||
if (remainingFormat) {
|
||||
nodes[server.ID].remaining.format = remainingFormat;
|
||||
}
|
||||
// 处理 billingDataMod 的 remaining 配置
|
||||
const remainingEndDate = this.getRemainingDays(this.getNoteElementValue(server.PublicNote, "billingDataMod", "endDate"), server.PublicNote, 1);
|
||||
const remainingFormat = this.getRemainingFormat(server.live, server.PublicNote);
|
||||
const remainingDays = this.getRemainingDays(this.getNoteElementValue(server.PublicNote, "billingDataMod", "endDate"), server.PublicNote);
|
||||
const remainingPercent = this.getRemainingPercent(
|
||||
this.getNoteElementValue(server.PublicNote, "billingDataMod", "startDate"),
|
||||
this.getNoteElementValue(server.PublicNote, "billingDataMod", "endDate"),
|
||||
server.PublicNote
|
||||
);
|
||||
// 设置 remaining 属性
|
||||
if (remainingEndDate) nodes[server.ID].remaining.endDate = remainingEndDate;
|
||||
if (remainingFormat) nodes[server.ID].remaining.format = remainingFormat;
|
||||
if (remainingDays) nodes[server.ID].remaining.days = remainingDays;
|
||||
if (remainingPercent) nodes[server.ID].remaining.percent = this.toFixed2(100 - remainingPercent);
|
||||
|
||||
if (remainingDays) {
|
||||
nodes[server.ID].remaining.days = remainingDays;
|
||||
}
|
||||
|
||||
if (remainingPercent) {
|
||||
nodes[server.ID].remaining.percent = this.toFixed2(100 - remainingPercent);
|
||||
}
|
||||
|
||||
if (priceAmount) {
|
||||
nodes[server.ID].price.amount = priceAmount;
|
||||
}
|
||||
|
||||
if (priceCycle && priceAmount) {
|
||||
nodes[server.ID].price.cycle = priceCycle;
|
||||
}
|
||||
}
|
||||
// 处理 billingDataMod 的 price 配置
|
||||
const priceAmount = this.getNoteElementValue(server.PublicNote, "billingDataMod", "amount");
|
||||
const priceCycle = this.getNoteElementValue(server.PublicNote, "billingDataMod", "cycle");
|
||||
// 设置 price 属性
|
||||
if (priceAmount) nodes[server.ID].price.amount = priceAmount;
|
||||
if (priceCycle && priceAmount) nodes[server.ID].price.cycle = priceCycle;
|
||||
|
||||
// 处理 planDataMod 配置
|
||||
const planBandwidth = this.getNoteElementValue(server.PublicNote, "planDataMod", "bandwidth");
|
||||
const planTrafficVol = this.getNoteElementValue(server.PublicNote, "planDataMod", "trafficVol");
|
||||
const planTrafficType = this.getNoteElementValue(server.PublicNote, "planDataMod", "trafficType");
|
||||
const planIPv4 = this.getNoteElementValue(server.PublicNote, "planDataMod", "IPv4");
|
||||
const planIPv6 = this.getNoteElementValue(server.PublicNote, "planDataMod", "IPv6");
|
||||
const planNetworkRoute = this.getNoteElementValue(server.PublicNote, "planDataMod", "networkRoute");
|
||||
const planExtra = this.getNoteElementValue(server.PublicNote, "planDataMod", "extra");
|
||||
// 设置 plan 属性
|
||||
if (planBandwidth) nodes[server.ID].plan.bandwidth = planBandwidth;
|
||||
if (planTrafficVol) nodes[server.ID].plan.trafficVol = planTrafficVol;
|
||||
if (planTrafficType) nodes[server.ID].plan.trafficType = planTrafficType;
|
||||
if (planIPv4) nodes[server.ID].plan.ipv4 = planIPv4 >= 1;
|
||||
if (planIPv6) nodes[server.ID].plan.ipv6 = planIPv6 >= 1;
|
||||
if (planNetworkRoute) nodes[server.ID].plan.networkRoute = planNetworkRoute.split(',');
|
||||
if (planExtra) nodes[server.ID].plan.extra = planExtra.split(',');
|
||||
});
|
||||
return nodes;
|
||||
},
|
||||
@ -859,7 +870,7 @@
|
||||
const expiration = new Date(endDate);
|
||||
const current = this.getAdjustTimezone(new Date(endDate), new Date());
|
||||
|
||||
// 如果 expiration 无效,返回 null 并记录日志
|
||||
// 如果 expiration 无效,记录日志
|
||||
if (isNaN(expiration.getTime())) {
|
||||
console.log("getAutoRenewalEndDate: Invalid expiration format");
|
||||
}
|
||||
@ -1055,7 +1066,7 @@
|
||||
return this.formatPercents(online, this.toFixed2(percent));
|
||||
|
||||
},
|
||||
getRemainingDays(endDate, note) {
|
||||
getRemainingDays(endDate, note, type) {
|
||||
// 检查 endDate 是否有效
|
||||
if (!endDate || typeof endDate !== 'string') {
|
||||
return null;
|
||||
@ -1066,9 +1077,9 @@
|
||||
return "lifetime";
|
||||
}
|
||||
|
||||
// 检查 startDate 和 endDate 是否为合法的Date
|
||||
// 检查 endDate 是否为合法的Date
|
||||
if (isNaN(new Date(endDate).getTime())) {
|
||||
return "NaN";
|
||||
return type === 1 ? null : "NaN";
|
||||
}
|
||||
|
||||
// 获取当前时间,并调整时区
|
||||
@ -1087,6 +1098,9 @@
|
||||
// 确定到期时间
|
||||
const end = autoRenewal ? autoEndDate.date : new Date(endDate);
|
||||
|
||||
// 直接返回处理后的到期时间
|
||||
if (type === 1) return end;
|
||||
|
||||
// 计算剩余天数
|
||||
const timeDiff = end - currentTime;
|
||||
const daysDiff = Math.ceil(timeDiff / (1000 * 60 * 60 * 24));
|
||||
|
@ -11,11 +11,11 @@
|
||||
<input type="text" id="dropdown-search" class="form-control" placeholder="Search...">
|
||||
</li>
|
||||
<li class="dropdown-item" v-for="server in servers" @click="showCharts(server.ID)">
|
||||
<a><i :class="'fi fi-' + (server.Host.CountryCode || 'rb')"></i> @#server.Name#@ <i v-if="server.ID == currentServerId" class="check icon"></i></a>
|
||||
<a><i :class="'fi fi-' + (server.Host.CountryCode || 'un')"></i> @#server.Name#@ <i v-if="server.ID == currentServerId" class="check icon"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="chartTitle" @click="showCharts(nextServerId)"><i class="chartCountryCode" :class="'fi fi-' + chartCountryCode"></i> @#chartTitle#@</div>
|
||||
<div v-if="chartTitle" class="chartTitle" @click="showCharts(nextServerId)"><i class="chartCountryCode" :class="'fi fi-' + chartCountryCode"></i> @#chartTitle#@</div>
|
||||
<div id="chartbox" style="width:100%;height:auto;"></div>
|
||||
</div>
|
||||
{{template "theme-server-status/footer" .}}
|
||||
@ -332,7 +332,7 @@
|
||||
},
|
||||
getServerCountryCode(id){
|
||||
const result = this.servers.find(item => item.ID == id);
|
||||
return result.Host.CountryCode ? result.Host.CountryCode : 'rb';
|
||||
return result.Host.CountryCode ? result.Host.CountryCode : 'un';
|
||||
},
|
||||
getNextServerId(id) {
|
||||
const currentIndex = this.servers.findIndex(item => item.ID === id);
|
||||
|
@ -1,63 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
#========================================================
|
||||
# System Required: CentOS 7+ / Debian 8+ / Ubuntu 16+ / Alpine 3+ /
|
||||
# Arch 仅测试了一次,如有问题带截图反馈 dysf888@pm.me
|
||||
# Description: 哪吒监控安装脚本
|
||||
# Github: https://github.com/naiba/nezha
|
||||
# v0 分支脚本强制重定向至新仓库
|
||||
#========================================================
|
||||
|
||||
NZ_BASE_PATH="/opt/nezha"
|
||||
NZ_DASHBOARD_PATH="${NZ_BASE_PATH}/dashboard"
|
||||
NZ_AGENT_PATH="${NZ_BASE_PATH}/agent"
|
||||
NZ_DASHBOARD_SERVICE="/etc/systemd/system/nezha-dashboard.service"
|
||||
NZ_DASHBOARD_SERVICERC="/etc/init.d/nezha-dashboard"
|
||||
NZ_VERSION="v0.20.2"
|
||||
|
||||
red='\033[0;31m'
|
||||
green='\033[0;32m'
|
||||
yellow='\033[0;33m'
|
||||
plain='\033[0m'
|
||||
export PATH="$PATH:/usr/local/bin"
|
||||
|
||||
os_arch=""
|
||||
[ -e /etc/os-release ] && grep -i "PRETTY_NAME" /etc/os-release | grep -qi "alpine" && os_alpine='1'
|
||||
|
||||
sudo() {
|
||||
myEUID=$(id -ru)
|
||||
if [ "$myEUID" -ne 0 ]; then
|
||||
if command -v sudo > /dev/null 2>&1; then
|
||||
command sudo "$@"
|
||||
else
|
||||
err "错误: 您的系统未安装 sudo,因此无法进行该项操作。"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
"$@"
|
||||
fi
|
||||
}
|
||||
|
||||
check_systemd() {
|
||||
if [ "$os_alpine" != 1 ] && ! command -v systemctl >/dev/null 2>&1; then
|
||||
echo "不支持此系统:未找到 systemctl 命令"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
err() {
|
||||
printf "${red}%s${plain}\n" "$*" >&2
|
||||
}
|
||||
|
||||
success() {
|
||||
printf "${green}%s${plain}\n" "$*"
|
||||
}
|
||||
|
||||
info() {
|
||||
printf "${yellow}%s${plain}\n" "$*"
|
||||
}
|
||||
# 判断是否应使用中国镜像
|
||||
|
||||
geo_check() {
|
||||
api_list="https://blog.cloudflare.com/cdn-cgi/trace https://dash.cloudflare.com/cdn-cgi/trace https://developers.cloudflare.com/cdn-cgi/trace"
|
||||
api_list="https://blog.cloudflare.com/cdn-cgi/trace https://developers.cloudflare.com/cdn-cgi/trace"
|
||||
ua="Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/81.0"
|
||||
set -- "$api_list"
|
||||
for url in $api_list; do
|
||||
@ -72,884 +22,47 @@ geo_check() {
|
||||
done
|
||||
}
|
||||
|
||||
pre_check() {
|
||||
umask 077
|
||||
# 向用户确认是否使用中国镜像
|
||||
geo_check
|
||||
|
||||
## os_arch
|
||||
if uname -m | grep -q 'x86_64'; then
|
||||
os_arch="amd64"
|
||||
elif uname -m | grep -q 'i386\|i686'; then
|
||||
os_arch="386"
|
||||
elif uname -m | grep -q 'aarch64\|armv8b\|armv8l'; then
|
||||
os_arch="arm64"
|
||||
elif uname -m | grep -q 'arm'; then
|
||||
os_arch="arm"
|
||||
elif uname -m | grep -q 's390x'; then
|
||||
os_arch="s390x"
|
||||
elif uname -m | grep -q 'riscv64'; then
|
||||
os_arch="riscv64"
|
||||
fi
|
||||
|
||||
## China_IP
|
||||
if [ -z "$CN" ]; then
|
||||
geo_check
|
||||
if [ -n "$isCN" ]; then
|
||||
echo "根据geoip api提供的信息,当前IP可能在中国"
|
||||
printf "是否选用中国镜像完成安装? [Y/n] (自定义镜像输入 3):"
|
||||
read -r input
|
||||
case $input in
|
||||
[yY][eE][sS] | [yY])
|
||||
echo "使用中国镜像"
|
||||
CN=true
|
||||
;;
|
||||
|
||||
[nN][oO] | [nN])
|
||||
echo "不使用中国镜像"
|
||||
;;
|
||||
|
||||
[3])
|
||||
echo "使用自定义镜像"
|
||||
printf "请输入自定义镜像 (例如:dn-dao-github-mirror.daocloud.io),留空为不使用: "
|
||||
read -r input
|
||||
case $input in
|
||||
*)
|
||||
CUSTOM_MIRROR=$input
|
||||
;;
|
||||
esac
|
||||
|
||||
;;
|
||||
*)
|
||||
echo "使用中国镜像"
|
||||
CN=true
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$CUSTOM_MIRROR" ]; then
|
||||
GITHUB_RAW_URL="gitee.com/naibahq/nezha/raw/master"
|
||||
GITHUB_URL=$CUSTOM_MIRROR
|
||||
Get_Docker_URL="get.docker.com"
|
||||
Get_Docker_Argu=" -s docker --mirror Aliyun"
|
||||
Docker_IMG="registry.cn-shanghai.aliyuncs.com\/naibahq\/nezha-dashboard"
|
||||
else
|
||||
if [ -z "$CN" ]; then
|
||||
GITHUB_RAW_URL="raw.githubusercontent.com/naiba/nezha/master"
|
||||
GITHUB_URL="github.com"
|
||||
Get_Docker_URL="get.docker.com"
|
||||
Get_Docker_Argu=" "
|
||||
Docker_IMG="ghcr.io\/naiba\/nezha-dashboard"
|
||||
else
|
||||
GITHUB_RAW_URL="gitee.com/naibahq/nezha/raw/master"
|
||||
GITHUB_URL="gitee.com"
|
||||
Get_Docker_URL="get.docker.com"
|
||||
Get_Docker_Argu=" -s docker --mirror Aliyun"
|
||||
Docker_IMG="registry.cn-shanghai.aliyuncs.com\/naibahq\/nezha-dashboard"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
installation_check() {
|
||||
if docker compose version >/dev/null 2>&1; then
|
||||
DOCKER_COMPOSE_COMMAND="docker compose"
|
||||
if sudo $DOCKER_COMPOSE_COMMAND ls | grep -qw "$NZ_DASHBOARD_PATH/docker-compose.yaml" >/dev/null 2>&1; then
|
||||
NEZHA_IMAGES=$(sudo docker images --format "{{.Repository}}:{{.Tag}}" | grep -w "nezha-dashboard")
|
||||
if [ -n "$NEZHA_IMAGES" ]; then
|
||||
echo "存在带有 nezha-dashboard 仓库的 Docker 镜像:"
|
||||
echo "$NEZHA_IMAGES"
|
||||
IS_DOCKER_NEZHA=1
|
||||
FRESH_INSTALL=0
|
||||
return
|
||||
else
|
||||
echo "未找到带有 nezha-dashboard 仓库的 Docker 镜像。"
|
||||
fi
|
||||
fi
|
||||
elif command -v docker-compose >/dev/null 2>&1; then
|
||||
DOCKER_COMPOSE_COMMAND="docker-compose"
|
||||
if sudo $DOCKER_COMPOSE_COMMAND -f "$NZ_DASHBOARD_PATH/docker-compose.yaml" config >/dev/null 2>&1; then
|
||||
NEZHA_IMAGES=$(sudo docker images --format "{{.Repository}}:{{.Tag}}" | grep -w "nezha-dashboard")
|
||||
if [ -n "$NEZHA_IMAGES" ]; then
|
||||
echo "存在带有 nezha-dashboard 仓库的 Docker 镜像:"
|
||||
echo "$NEZHA_IMAGES"
|
||||
IS_DOCKER_NEZHA=1
|
||||
FRESH_INSTALL=0
|
||||
return
|
||||
else
|
||||
echo "未找到带有 nezha-dashboard 仓库的 Docker 镜像。"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -f "$NZ_DASHBOARD_PATH/app" ]; then
|
||||
IS_DOCKER_NEZHA=0
|
||||
FRESH_INSTALL=0
|
||||
fi
|
||||
}
|
||||
|
||||
select_version() {
|
||||
if [ -z "$IS_DOCKER_NEZHA" ]; then
|
||||
info "请自行选择您的安装方式(如果你是安装Agent,输入哪个都是一样的):"
|
||||
info "1. Docker"
|
||||
info "2. 独立安装"
|
||||
while true; do
|
||||
printf "请输入选择 [1-2]:"
|
||||
read -r option
|
||||
case "${option}" in
|
||||
1)
|
||||
IS_DOCKER_NEZHA=1
|
||||
break
|
||||
;;
|
||||
2)
|
||||
IS_DOCKER_NEZHA=0
|
||||
break
|
||||
;;
|
||||
*)
|
||||
err "请输入正确的选择 [1-2]"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
update_script() {
|
||||
echo "> 更新脚本"
|
||||
|
||||
curl -sL https://${GITHUB_RAW_URL}/script/install.sh -o /tmp/nezha.sh
|
||||
new_version=$(grep "NZ_VERSION" /tmp/nezha.sh | head -n 1 | awk -F "=" '{print $2}' | sed 's/\"//g;s/,//g;s/ //g')
|
||||
if [ -z "$new_version" ]; then
|
||||
echo "脚本获取失败,请检查本机能否链接 https://${GITHUB_RAW_URL}/script/install.sh"
|
||||
return 1
|
||||
fi
|
||||
echo "当前最新版本为: ${new_version}"
|
||||
mv -f /tmp/nezha.sh ./nezha.sh && chmod a+x ./nezha.sh
|
||||
|
||||
echo "3s后执行新脚本"
|
||||
sleep 3s
|
||||
clear
|
||||
exec ./nezha.sh
|
||||
exit 0
|
||||
}
|
||||
|
||||
before_show_menu() {
|
||||
echo && info "* 按回车返回主菜单 *" && read temp
|
||||
show_menu
|
||||
}
|
||||
|
||||
install_base() {
|
||||
(command -v curl >/dev/null 2>&1 && command -v wget >/dev/null 2>&1 && command -v unzip >/dev/null 2>&1 && command -v getenforce >/dev/null 2>&1) ||
|
||||
(install_soft curl wget unzip)
|
||||
}
|
||||
|
||||
install_arch() {
|
||||
info "提示:Arch安装libselinux需添加nezha-agent用户,安装完会自动删除,建议手动检查一次"
|
||||
read -r -p "是否安装libselinux? [Y/n] " input
|
||||
case $input in
|
||||
[yY][eE][sS] | [yY])
|
||||
useradd -m nezha-agent
|
||||
sed -i "$ a\nezha-agent ALL=(ALL ) NOPASSWD:ALL" /etc/sudoers
|
||||
sudo -iu nezha-agent bash -c 'gpg --keyserver keys.gnupg.net --recv-keys 4695881C254508D1;
|
||||
cd /tmp; git clone https://aur.archlinux.org/libsepol.git; cd libsepol; makepkg -si --noconfirm --asdeps; cd ..;
|
||||
git clone https://aur.archlinux.org/libselinux.git; cd libselinux; makepkg -si --noconfirm; cd ..;
|
||||
rm -rf libsepol libselinux'
|
||||
sed -i '/nezha-agent/d' /etc/sudoers && sleep 30s && killall -u nezha-agent && userdel -r nezha-agent
|
||||
echo -e "${red}提示: ${plain}已删除用户nezha-agent,请务必手动核查一遍!\n"
|
||||
;;
|
||||
[nN][oO] | [nN])
|
||||
echo "不安装libselinux"
|
||||
;;
|
||||
*)
|
||||
echo "不安装libselinux"
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
install_soft() {
|
||||
(command -v yum >/dev/null 2>&1 && sudo yum makecache && sudo yum install "$@" selinux-policy -y) ||
|
||||
(command -v apt >/dev/null 2>&1 && sudo apt update && sudo apt install "$@" selinux-utils -y) ||
|
||||
(command -v pacman >/dev/null 2>&1 && sudo pacman -Syu "$@" base-devel --noconfirm && install_arch) ||
|
||||
(command -v apt-get >/dev/null 2>&1 && sudo apt-get update && sudo apt-get install "$@" selinux-utils -y) ||
|
||||
(command -v apk >/dev/null 2>&1 && sudo apk update && sudo apk add "$@" -f)
|
||||
}
|
||||
|
||||
install_dashboard() {
|
||||
check_systemd
|
||||
install_base
|
||||
|
||||
echo "> 安装面板"
|
||||
|
||||
# 哪吒监控文件夹
|
||||
if [ ! "$FRESH_INSTALL" = 0 ]; then
|
||||
sudo mkdir -p $NZ_DASHBOARD_PATH
|
||||
else
|
||||
echo "您可能已经安装过面板端,重复安装会覆盖数据,请注意备份。"
|
||||
printf "是否退出安装? [Y/n] "
|
||||
read -r input
|
||||
case $input in
|
||||
[yY][eE][sS] | [yY])
|
||||
echo "退出安装"
|
||||
exit 0
|
||||
if [ "$isCN" = true ]; then
|
||||
read -p "检测到您的IP可能来自中国大陆,是否使用中国镜像? [y/n] " choice
|
||||
case "$choice" in
|
||||
y|Y)
|
||||
echo "将使用中国镜像..."
|
||||
USE_CN_MIRROR=true
|
||||
;;
|
||||
[nN][oO] | [nN])
|
||||
echo "继续安装"
|
||||
n|N)
|
||||
echo "将使用国际镜像..."
|
||||
USE_CN_MIRROR=false
|
||||
;;
|
||||
*)
|
||||
echo "退出安装"
|
||||
exit 0
|
||||
echo "输入无效,将使用国际镜像..."
|
||||
USE_CN_MIRROR=false
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if [ "$IS_DOCKER_NEZHA" = 1 ]; then
|
||||
install_dashboard_docker
|
||||
elif [ "$IS_DOCKER_NEZHA" = 0 ]; then
|
||||
install_dashboard_standalone
|
||||
fi
|
||||
|
||||
modify_dashboard_config 0
|
||||
|
||||
if [ $# = 0 ]; then
|
||||
before_show_menu
|
||||
fi
|
||||
}
|
||||
|
||||
install_dashboard_docker() {
|
||||
if [ ! "$FRESH_INSTALL" = 0 ]; then
|
||||
if ! command -v docker >/dev/null 2>&1; then
|
||||
echo "正在安装 Docker"
|
||||
if [ "$os_alpine" != 1 ]; then
|
||||
if ! curl -sL https://${Get_Docker_URL} | sudo bash -s "${Get_Docker_Argu}"; then
|
||||
err "下载脚本失败,请检查本机能否连接 ${Get_Docker_URL}"
|
||||
return 0
|
||||
fi
|
||||
sudo systemctl enable docker.service
|
||||
sudo systemctl start docker.service
|
||||
else
|
||||
sudo apk add docker docker-compose
|
||||
sudo rc-update add docker
|
||||
sudo rc-service docker start
|
||||
fi
|
||||
success "Docker 安装成功"
|
||||
installation_check
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
install_dashboard_standalone() {
|
||||
if [ ! -d "${NZ_DASHBOARD_PATH}/resource/template/theme-custom" ] || [ ! -d "${NZ_DASHBOARD_PATH}/resource/static/custom" ]; then
|
||||
sudo mkdir -p "${NZ_DASHBOARD_PATH}/resource/template/theme-custom" "${NZ_DASHBOARD_PATH}/resource/static/custom" >/dev/null 2>&1
|
||||
fi
|
||||
}
|
||||
|
||||
selinux() {
|
||||
#Check SELinux
|
||||
if command -v getenforce >/dev/null 2>&1; then
|
||||
if getenforce | grep '[Ee]nfor'; then
|
||||
echo "SELinux是开启状态,正在关闭!"
|
||||
sudo setenforce 0 >/dev/null 2>&1
|
||||
find_key="SELINUX="
|
||||
sudo sed -ri "/^$find_key/c${find_key}disabled" /etc/selinux/config
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
install_agent() {
|
||||
install_base
|
||||
selinux
|
||||
|
||||
echo "> 安装监控Agent"
|
||||
|
||||
echo "正在获取监控Agent版本号"
|
||||
|
||||
|
||||
_version=$(curl -m 10 -sL "https://api.github.com/repos/nezhahq/agent/releases/latest" | grep "tag_name" | head -n 1 | awk -F ":" '{print $2}' | sed 's/\"//g;s/,//g;s/ //g')
|
||||
if [ -z "$_version" ]; then
|
||||
_version=$(curl -m 10 -sL "https://gitee.com/api/v5/repos/naibahq/agent/releases/latest" | awk -F '"' '{for(i=1;i<=NF;i++){if($i=="tag_name"){print $(i+2)}}}')
|
||||
fi
|
||||
if [ -z "$_version" ]; then
|
||||
_version=$(curl -m 10 -sL "https://fastly.jsdelivr.net/gh/nezhahq/agent/" | grep "option\.value" | awk -F "'" '{print $2}' | sed 's/nezhahq\/agent@/v/g')
|
||||
fi
|
||||
if [ -z "$_version" ]; then
|
||||
_version=$(curl -m 10 -sL "https://gcore.jsdelivr.net/gh/nezhahq/agent/" | grep "option\.value" | awk -F "'" '{print $2}' | sed 's/nezhahq\/agent@/v/g')
|
||||
fi
|
||||
|
||||
if [ -z "$_version" ]; then
|
||||
err "获取版本号失败,请检查本机能否链接 https://api.github.com/repos/nezhahq/agent/releases/latest"
|
||||
return 1
|
||||
else
|
||||
echo "当前最新版本为: ${_version}"
|
||||
fi
|
||||
|
||||
# 哪吒监控文件夹
|
||||
sudo mkdir -p $NZ_AGENT_PATH
|
||||
|
||||
echo "正在下载监控端"
|
||||
if [ -z "$CN" ]; then
|
||||
NZ_AGENT_URL="https://${GITHUB_URL}/nezhahq/agent/releases/download/${_version}/nezha-agent_linux_${os_arch}.zip"
|
||||
else
|
||||
NZ_AGENT_URL="https://${GITHUB_URL}/naibahq/agent/releases/download/${_version}/nezha-agent_linux_${os_arch}.zip"
|
||||
fi
|
||||
|
||||
_cmd="wget -t 2 -T 60 -O nezha-agent_linux_${os_arch}.zip $NZ_AGENT_URL >/dev/null 2>&1"
|
||||
if ! eval "$_cmd"; then
|
||||
err "Release 下载失败,请检查本机能否连接 ${GITHUB_URL}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
sudo unzip -qo nezha-agent_linux_${os_arch}.zip &&
|
||||
sudo mv nezha-agent $NZ_AGENT_PATH &&
|
||||
sudo rm -rf nezha-agent_linux_${os_arch}.zip README.md
|
||||
|
||||
if [ $# -ge 3 ]; then
|
||||
modify_agent_config "$@"
|
||||
else
|
||||
modify_agent_config 0
|
||||
fi
|
||||
|
||||
if [ $# = 0 ]; then
|
||||
before_show_menu
|
||||
fi
|
||||
}
|
||||
|
||||
modify_agent_config() {
|
||||
echo "> 修改Agent配置"
|
||||
|
||||
if [ $# -lt 3 ]; then
|
||||
echo "请先在管理面板上添加Agent,记录下密钥"
|
||||
printf "请输入一个解析到面板所在IP的域名(不可套CDN): "
|
||||
read -r nz_grpc_host
|
||||
printf "请输入面板RPC端口 (默认值 5555): "
|
||||
read -r nz_grpc_port
|
||||
printf "请输入Agent 密钥: "
|
||||
read -r nz_client_secret
|
||||
printf "是否启用针对 gRPC 端口的 SSL/TLS加密 (--tls),需要请按 [y],默认是不需要,不理解用户可回车跳过: "
|
||||
read -r nz_grpc_proxy
|
||||
echo "${nz_grpc_proxy}" | grep -qiw 'Y' && args='--tls'
|
||||
if [ -z "$nz_grpc_host" ] || [ -z "$nz_client_secret" ]; then
|
||||
err "所有选项都不能为空"
|
||||
before_show_menu
|
||||
return 1
|
||||
fi
|
||||
if [ -z "$nz_grpc_port" ]; then
|
||||
nz_grpc_port=5555
|
||||
fi
|
||||
else
|
||||
nz_grpc_host=$1
|
||||
nz_grpc_port=$2
|
||||
nz_client_secret=$3
|
||||
shift 3
|
||||
if [ $# -gt 0 ]; then
|
||||
args="$*"
|
||||
fi
|
||||
fi
|
||||
|
||||
_cmd="sudo ${NZ_AGENT_PATH}/nezha-agent service install -s $nz_grpc_host:$nz_grpc_port -p $nz_client_secret $args >/dev/null 2>&1"
|
||||
|
||||
if ! eval "$_cmd"; then
|
||||
sudo "${NZ_AGENT_PATH}"/nezha-agent service uninstall >/dev/null 2>&1
|
||||
sudo "${NZ_AGENT_PATH}"/nezha-agent service install -s "$nz_grpc_host:$nz_grpc_port" -p "$nz_client_secret" "$args" >/dev/null 2>&1
|
||||
fi
|
||||
|
||||
success "Agent配置 修改成功,请稍等重启生效"
|
||||
|
||||
#if [[ $# == 0 ]]; then
|
||||
# before_show_menu
|
||||
#fi
|
||||
}
|
||||
|
||||
modify_dashboard_config() {
|
||||
echo "> 修改面板配置"
|
||||
|
||||
if [ "$IS_DOCKER_NEZHA" = 1 ]; then
|
||||
if [ -n "$DOCKER_COMPOSE_COMMAND" ]; then
|
||||
echo "正在下载 Docker 脚本"
|
||||
_cmd="wget -t 2 -T 60 -O /tmp/nezha-docker-compose.yaml https://${GITHUB_RAW_URL}/script/docker-compose.yaml >/dev/null 2>&1"
|
||||
if ! eval "$_cmd"; then
|
||||
err "下载脚本失败,请检查本机能否连接 ${GITHUB_RAW_URL}"
|
||||
return 0
|
||||
fi
|
||||
else
|
||||
err "请手动安装 docker-compose。https://docs.docker.com/compose/install/linux/"
|
||||
before_show_menu
|
||||
fi
|
||||
fi
|
||||
|
||||
_cmd="wget -t 2 -T 60 -O /tmp/nezha-config.yaml https://${GITHUB_RAW_URL}/script/config.yaml >/dev/null 2>&1"
|
||||
if ! eval "$_cmd"; then
|
||||
err "下载脚本失败,请检查本机能否连接 ${GITHUB_RAW_URL}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "关于 GitHub Oauth2 应用:在 https://github.com/settings/developers 创建,无需审核,Callback 填 http(s)://域名或IP/oauth2/callback"
|
||||
echo "关于 Gitee Oauth2 应用:在 https://gitee.com/oauth/applications 创建,无需审核,Callback 填 http(s)://域名或IP/oauth2/callback"
|
||||
printf "请输入 OAuth2 提供商(github/gitlab/jihulab/gitee,默认 github): "
|
||||
read -r nz_oauth2_type
|
||||
printf "请输入 Oauth2 应用的 Client ID: "
|
||||
read -r nz_github_oauth_client_id
|
||||
printf "请输入 Oauth2 应用的 Client Secret: "
|
||||
read -r nz_github_oauth_client_secret
|
||||
printf "请输入 GitHub/Gitee 登录名作为管理员,多个以逗号隔开: "
|
||||
read -r nz_admin_logins
|
||||
printf "请输入站点标题: "
|
||||
read -r nz_site_title
|
||||
printf "请输入站点访问端口: (默认 8008)"
|
||||
read -r nz_site_port
|
||||
printf "请输入用于 Agent 接入的 RPC 端口: (默认 5555)"
|
||||
read -r nz_grpc_port
|
||||
|
||||
if [ -z "$nz_admin_logins" ] || [ -z "$nz_github_oauth_client_id" ] || [ -z "$nz_github_oauth_client_secret" ] || [ -z "$nz_site_title" ]; then
|
||||
err "所有选项都不能为空"
|
||||
before_show_menu
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ -z "$nz_site_port" ]; then
|
||||
nz_site_port=8008
|
||||
fi
|
||||
if [ -z "$nz_grpc_port" ]; then
|
||||
nz_grpc_port=5555
|
||||
fi
|
||||
if [ -z "$nz_oauth2_type" ]; then
|
||||
nz_oauth2_type=github
|
||||
fi
|
||||
|
||||
sed -i "s/nz_oauth2_type/${nz_oauth2_type}/" /tmp/nezha-config.yaml
|
||||
sed -i "s/nz_admin_logins/${nz_admin_logins}/" /tmp/nezha-config.yaml
|
||||
sed -i "s/nz_grpc_port/${nz_grpc_port}/" /tmp/nezha-config.yaml
|
||||
sed -i "s/nz_github_oauth_client_id/${nz_github_oauth_client_id}/" /tmp/nezha-config.yaml
|
||||
sed -i "s/nz_github_oauth_client_secret/${nz_github_oauth_client_secret}/" /tmp/nezha-config.yaml
|
||||
sed -i "s/nz_language/zh-CN/" /tmp/nezha-config.yaml
|
||||
sed -i "s/nz_site_title/${nz_site_title}/" /tmp/nezha-config.yaml
|
||||
if [ "$IS_DOCKER_NEZHA" = 1 ]; then
|
||||
sed -i "s/nz_site_port/${nz_site_port}/" /tmp/nezha-docker-compose.yaml
|
||||
sed -i "s/nz_grpc_port/${nz_grpc_port}/g" /tmp/nezha-docker-compose.yaml
|
||||
sed -i "s/nz_image_url/${Docker_IMG}/" /tmp/nezha-docker-compose.yaml
|
||||
elif [ "$IS_DOCKER_NEZHA" = 0 ]; then
|
||||
sed -i "s/80/${nz_site_port}/" /tmp/nezha-config.yaml
|
||||
fi
|
||||
|
||||
sudo mkdir -p $NZ_DASHBOARD_PATH/data
|
||||
sudo mv -f /tmp/nezha-config.yaml ${NZ_DASHBOARD_PATH}/data/config.yaml
|
||||
if [ "$IS_DOCKER_NEZHA" = 1 ]; then
|
||||
sudo mv -f /tmp/nezha-docker-compose.yaml ${NZ_DASHBOARD_PATH}/docker-compose.yaml
|
||||
fi
|
||||
|
||||
if [ "$IS_DOCKER_NEZHA" = 0 ]; then
|
||||
echo "正在下载服务文件"
|
||||
if [ "$os_alpine" != 1 ]; then
|
||||
_download="sudo wget -t 2 -T 60 -O $NZ_DASHBOARD_SERVICE https://${GITHUB_RAW_URL}/script/nezha-dashboard.service >/dev/null 2>&1"
|
||||
if ! eval "$_download"; then
|
||||
err "文件下载失败,请检查本机能否连接 ${GITHUB_RAW_URL}"
|
||||
return 0
|
||||
fi
|
||||
else
|
||||
_download="sudo wget -t 2 -T 60 -O $NZ_DASHBOARD_SERVICERC https://${GITHUB_RAW_URL}/script/nezha-dashboard >/dev/null 2>&1"
|
||||
if ! eval "$_download"; then
|
||||
err "文件下载失败,请检查本机能否连接 ${GITHUB_RAW_URL}"
|
||||
return 0
|
||||
fi
|
||||
sudo chmod +x $NZ_DASHBOARD_SERVICERC
|
||||
fi
|
||||
fi
|
||||
|
||||
success "面板配置 修改成功,请稍等重启生效"
|
||||
|
||||
restart_and_update
|
||||
|
||||
if [ $# = 0 ]; then
|
||||
before_show_menu
|
||||
fi
|
||||
}
|
||||
|
||||
restart_and_update() {
|
||||
echo "> 重启并更新面板"
|
||||
|
||||
if [ "$IS_DOCKER_NEZHA" = 1 ]; then
|
||||
_cmd="restart_and_update_docker"
|
||||
elif [ "$IS_DOCKER_NEZHA" = 0 ]; then
|
||||
_cmd="restart_and_update_standalone"
|
||||
fi
|
||||
|
||||
if eval "$_cmd"; then
|
||||
success "哪吒监控 重启成功"
|
||||
info "默认管理面板地址:域名:站点访问端口"
|
||||
else
|
||||
err "重启失败,可能是因为启动时间超过了两秒,请稍后查看日志信息"
|
||||
fi
|
||||
|
||||
if [ $# = 0 ]; then
|
||||
before_show_menu
|
||||
fi
|
||||
}
|
||||
|
||||
restart_and_update_docker() {
|
||||
sudo $DOCKER_COMPOSE_COMMAND -f ${NZ_DASHBOARD_PATH}/docker-compose.yaml pull
|
||||
sudo $DOCKER_COMPOSE_COMMAND -f ${NZ_DASHBOARD_PATH}/docker-compose.yaml down
|
||||
sudo $DOCKER_COMPOSE_COMMAND -f ${NZ_DASHBOARD_PATH}/docker-compose.yaml up -d
|
||||
}
|
||||
|
||||
restart_and_update_standalone() {
|
||||
_version=$(curl -m 10 -sL "https://api.github.com/repos/naiba/nezha/releases/latest" | grep "tag_name" | head -n 1 | awk -F ":" '{print $2}' | sed 's/\"//g;s/,//g;s/ //g')
|
||||
if [ -z "$_version" ]; then
|
||||
_version=$(curl -m 10 -sL "https://gitee.com/api/v5/repos/naibahq/nezha/releases/latest" | awk -F '"' '{for(i=1;i<=NF;i++){if($i=="tag_name"){print $(i+2)}}}')
|
||||
fi
|
||||
if [ -z "$_version" ]; then
|
||||
_version=$(curl -m 10 -sL "https://fastly.jsdelivr.net/gh/naiba/nezha/" | grep "option\.value" | awk -F "'" '{print $2}' | sed 's/naiba\/nezha@/v/g')
|
||||
fi
|
||||
if [ -z "$_version" ]; then
|
||||
_version=$(curl -m 10 -sL "https://gcore.jsdelivr.net/gh/naiba/nezha/" | grep "option\.value" | awk -F "'" '{print $2}' | sed 's/naiba\/nezha@/v/g')
|
||||
fi
|
||||
|
||||
if [ -z "$_version" ]; then
|
||||
err "获取版本号失败,请检查本机能否链接 https://api.github.com/repos/naiba/nezha/releases/latest"
|
||||
return 1
|
||||
else
|
||||
echo "当前最新版本为: ${_version}"
|
||||
fi
|
||||
|
||||
if [ "$os_alpine" != 1 ]; then
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl stop nezha-dashboard
|
||||
else
|
||||
sudo rc-service nezha-dashboard stop
|
||||
fi
|
||||
|
||||
if [ -z "$CN" ]; then
|
||||
NZ_DASHBOARD_URL="https://${GITHUB_URL}/naiba/nezha/releases/download/${_version}/dashboard-linux-${os_arch}.zip"
|
||||
else
|
||||
NZ_DASHBOARD_URL="https://${GITHUB_URL}/naibahq/nezha/releases/download/${_version}/dashboard-linux-${os_arch}.zip"
|
||||
fi
|
||||
|
||||
sudo wget -qO $NZ_DASHBOARD_PATH/app.zip "$NZ_DASHBOARD_URL" >/dev/null 2>&1 && sudo unzip -qq -o $NZ_DASHBOARD_PATH/app.zip -d $NZ_DASHBOARD_PATH && sudo mv $NZ_DASHBOARD_PATH/dashboard-linux-$os_arch $NZ_DASHBOARD_PATH/app && sudo rm $NZ_DASHBOARD_PATH/app.zip
|
||||
|
||||
if [ "$os_alpine" != 1 ]; then
|
||||
sudo systemctl enable nezha-dashboard
|
||||
sudo systemctl restart nezha-dashboard
|
||||
else
|
||||
sudo rc-update add nezha-dashboard
|
||||
sudo rc-service nezha-dashboard restart
|
||||
fi
|
||||
}
|
||||
|
||||
start_dashboard() {
|
||||
echo "> 启动面板"
|
||||
|
||||
if [ "$IS_DOCKER_NEZHA" = 1 ]; then
|
||||
_cmd="start_dashboard_docker"
|
||||
elif [ "$IS_DOCKER_NEZHA" = 0 ]; then
|
||||
_cmd="start_dashboard_standalone"
|
||||
fi
|
||||
|
||||
if eval "$_cmd"; then
|
||||
success "哪吒监控 启动成功"
|
||||
else
|
||||
err "启动失败,请稍后查看日志信息"
|
||||
fi
|
||||
|
||||
if [ $# = 0 ]; then
|
||||
before_show_menu
|
||||
fi
|
||||
}
|
||||
|
||||
start_dashboard_docker() {
|
||||
sudo $DOCKER_COMPOSE_COMMAND -f ${NZ_DASHBOARD_PATH}/docker-compose.yaml up -d
|
||||
}
|
||||
|
||||
start_dashboard_standalone() {
|
||||
if [ "$os_alpine" != 1 ]; then
|
||||
sudo systemctl start nezha-dashboard
|
||||
else
|
||||
sudo rc-service nezha-dashboard start
|
||||
fi
|
||||
}
|
||||
|
||||
stop_dashboard() {
|
||||
echo "> 停止面板"
|
||||
|
||||
if [ "$IS_DOCKER_NEZHA" = 1 ]; then
|
||||
_cmd="stop_dashboard_docker"
|
||||
elif [ "$IS_DOCKER_NEZHA" = 0 ]; then
|
||||
_cmd="stop_dashboard_standalone"
|
||||
fi
|
||||
|
||||
if eval "$_cmd"; then
|
||||
success "哪吒监控 停止成功"
|
||||
else
|
||||
err "停止失败,请稍后查看日志信息"
|
||||
fi
|
||||
|
||||
if [ $# = 0 ]; then
|
||||
before_show_menu
|
||||
fi
|
||||
}
|
||||
|
||||
stop_dashboard_docker() {
|
||||
sudo $DOCKER_COMPOSE_COMMAND -f ${NZ_DASHBOARD_PATH}/docker-compose.yaml down
|
||||
}
|
||||
|
||||
stop_dashboard_standalone() {
|
||||
if [ "$os_alpine" != 1 ]; then
|
||||
sudo systemctl stop nezha-dashboard
|
||||
else
|
||||
sudo rc-service nezha-dashboard stop
|
||||
fi
|
||||
}
|
||||
|
||||
show_dashboard_log() {
|
||||
echo "> 获取面板日志"
|
||||
|
||||
if [ "$IS_DOCKER_NEZHA" = 1 ]; then
|
||||
show_dashboard_log_docker
|
||||
elif [ "$IS_DOCKER_NEZHA" = 0 ]; then
|
||||
show_dashboard_log_standalone
|
||||
fi
|
||||
|
||||
if [ $# = 0 ]; then
|
||||
before_show_menu
|
||||
fi
|
||||
}
|
||||
|
||||
show_dashboard_log_docker() {
|
||||
sudo $DOCKER_COMPOSE_COMMAND -f ${NZ_DASHBOARD_PATH}/docker-compose.yaml logs -f
|
||||
}
|
||||
|
||||
show_dashboard_log_standalone() {
|
||||
if [ "$os_alpine" != 1 ]; then
|
||||
sudo journalctl -xf -u nezha-dashboard.service
|
||||
else
|
||||
sudo tail -n 10 /var/log/nezha-dashboard.err
|
||||
fi
|
||||
}
|
||||
|
||||
uninstall_dashboard() {
|
||||
echo "> 卸载管理面板"
|
||||
|
||||
if [ "$IS_DOCKER_NEZHA" = 1 ]; then
|
||||
uninstall_dashboard_docker
|
||||
elif [ "$IS_DOCKER_NEZHA" = 0 ]; then
|
||||
uninstall_dashboard_standalone
|
||||
fi
|
||||
|
||||
clean_all
|
||||
|
||||
if [ $# = 0 ]; then
|
||||
before_show_menu
|
||||
fi
|
||||
}
|
||||
|
||||
uninstall_dashboard_docker() {
|
||||
sudo $DOCKER_COMPOSE_COMMAND -f ${NZ_DASHBOARD_PATH}/docker-compose.yaml down
|
||||
sudo rm -rf $NZ_DASHBOARD_PATH
|
||||
sudo docker rmi -f ghcr.io/naiba/nezha-dashboard >/dev/null 2>&1
|
||||
sudo docker rmi -f registry.cn-shanghai.aliyuncs.com/naibahq/nezha-dashboard >/dev/null 2>&1
|
||||
}
|
||||
|
||||
uninstall_dashboard_standalone() {
|
||||
sudo rm -rf $NZ_DASHBOARD_PATH
|
||||
|
||||
if [ "$os_alpine" != 1 ]; then
|
||||
sudo systemctl disable nezha-dashboard
|
||||
sudo systemctl stop nezha-dashboard
|
||||
else
|
||||
sudo rc-update del nezha-dashboard
|
||||
sudo rc-service nezha-dashboard stop
|
||||
fi
|
||||
|
||||
if [ "$os_alpine" != 1 ]; then
|
||||
sudo rm $NZ_DASHBOARD_SERVICE
|
||||
else
|
||||
sudo rm $NZ_DASHBOARD_SERVICERC
|
||||
fi
|
||||
}
|
||||
|
||||
show_agent_log() {
|
||||
echo "> 获取Agent日志"
|
||||
|
||||
if [ "$os_alpine" != 1 ]; then
|
||||
sudo journalctl -xf -u nezha-agent.service
|
||||
else
|
||||
sudo tail -n 10 /var/log/nezha-agent.err
|
||||
fi
|
||||
|
||||
if [ $# = 0 ]; then
|
||||
before_show_menu
|
||||
fi
|
||||
}
|
||||
|
||||
uninstall_agent() {
|
||||
echo "> 卸载Agent"
|
||||
|
||||
sudo ${NZ_AGENT_PATH}/nezha-agent service uninstall
|
||||
|
||||
sudo rm -rf $NZ_AGENT_PATH
|
||||
clean_all
|
||||
|
||||
if [ $# = 0 ]; then
|
||||
before_show_menu
|
||||
fi
|
||||
}
|
||||
|
||||
restart_agent() {
|
||||
echo "> 重启Agent"
|
||||
|
||||
sudo ${NZ_AGENT_PATH}/nezha-agent service restart
|
||||
|
||||
if [ $# = 0 ]; then
|
||||
before_show_menu
|
||||
fi
|
||||
}
|
||||
|
||||
clean_all() {
|
||||
if [ -z "$(ls -A ${NZ_BASE_PATH})" ]; then
|
||||
sudo rm -rf ${NZ_BASE_PATH}
|
||||
fi
|
||||
}
|
||||
|
||||
show_usage() {
|
||||
echo "哪吒监控 管理脚本使用方法: "
|
||||
echo "--------------------------------------------------------"
|
||||
echo "./nezha.sh - 显示管理菜单"
|
||||
echo "./nezha.sh install_dashboard - 安装面板端"
|
||||
echo "./nezha.sh modify_dashboard_config - 修改面板配置"
|
||||
echo "./nezha.sh start_dashboard - 启动面板"
|
||||
echo "./nezha.sh stop_dashboard - 停止面板"
|
||||
echo "./nezha.sh restart_and_update - 重启并更新面板"
|
||||
echo "./nezha.sh show_dashboard_log - 查看面板日志"
|
||||
echo "./nezha.sh uninstall_dashboard - 卸载管理面板"
|
||||
echo "--------------------------------------------------------"
|
||||
echo "./nezha.sh install_agent - 安装监控Agent"
|
||||
echo "./nezha.sh modify_agent_config - 修改Agent配置"
|
||||
echo "./nezha.sh show_agent_log - 查看Agent日志"
|
||||
echo "./nezha.sh uninstall_agent - 卸载Agen"
|
||||
echo "./nezha.sh restart_agent - 重启Agen"
|
||||
echo "./nezha.sh update_script - 更新脚本"
|
||||
echo "--------------------------------------------------------"
|
||||
}
|
||||
|
||||
show_menu() {
|
||||
printf "
|
||||
${green}哪吒监控管理脚本${plain} ${red}${NZ_VERSION}${plain}
|
||||
--- https://github.com/naiba/nezha ---
|
||||
${green}1.${plain} 安装面板端
|
||||
${green}2.${plain} 修改面板配置
|
||||
${green}3.${plain} 启动面板
|
||||
${green}4.${plain} 停止面板
|
||||
${green}5.${plain} 重启并更新面板
|
||||
${green}6.${plain} 查看面板日志
|
||||
${green}7.${plain} 卸载管理面板
|
||||
————————————————-
|
||||
${green}8.${plain} 安装监控Agent
|
||||
${green}9.${plain} 修改Agent配置
|
||||
${green}10.${plain} 查看Agent日志
|
||||
${green}11.${plain} 卸载Agent
|
||||
${green}12.${plain} 重启Agent
|
||||
————————————————-
|
||||
${green}13.${plain} 更新脚本
|
||||
————————————————-
|
||||
${green}0.${plain} 退出脚本
|
||||
"
|
||||
echo && printf "请输入选择 [0-13]: " && read -r num
|
||||
case "${num}" in
|
||||
0)
|
||||
exit 0
|
||||
;;
|
||||
1)
|
||||
install_dashboard
|
||||
;;
|
||||
2)
|
||||
modify_dashboard_config
|
||||
;;
|
||||
3)
|
||||
start_dashboard
|
||||
;;
|
||||
4)
|
||||
stop_dashboard
|
||||
;;
|
||||
5)
|
||||
restart_and_update
|
||||
;;
|
||||
6)
|
||||
show_dashboard_log
|
||||
;;
|
||||
7)
|
||||
uninstall_dashboard
|
||||
;;
|
||||
8)
|
||||
install_agent
|
||||
;;
|
||||
9)
|
||||
modify_agent_config
|
||||
;;
|
||||
10)
|
||||
show_agent_log
|
||||
;;
|
||||
11)
|
||||
uninstall_agent
|
||||
;;
|
||||
12)
|
||||
restart_agent
|
||||
;;
|
||||
13)
|
||||
update_script
|
||||
;;
|
||||
*)
|
||||
err "请输入正确的数字 [0-13]"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
pre_check
|
||||
installation_check
|
||||
|
||||
if [ $# -gt 0 ]; then
|
||||
case $1 in
|
||||
"install_dashboard")
|
||||
install_dashboard 0
|
||||
;;
|
||||
"modify_dashboard_config")
|
||||
modify_dashboard_config 0
|
||||
;;
|
||||
"start_dashboard")
|
||||
start_dashboard 0
|
||||
;;
|
||||
"stop_dashboard")
|
||||
stop_dashboard 0
|
||||
;;
|
||||
"restart_and_update")
|
||||
restart_and_update 0
|
||||
;;
|
||||
"show_dashboard_log")
|
||||
show_dashboard_log 0
|
||||
;;
|
||||
"uninstall_dashboard")
|
||||
uninstall_dashboard 0
|
||||
;;
|
||||
"install_agent")
|
||||
shift
|
||||
if [ $# -ge 3 ]; then
|
||||
install_agent "$@"
|
||||
else
|
||||
install_agent 0
|
||||
fi
|
||||
;;
|
||||
"modify_agent_config")
|
||||
modify_agent_config 0
|
||||
;;
|
||||
"show_agent_log")
|
||||
show_agent_log 0
|
||||
;;
|
||||
"uninstall_agent")
|
||||
uninstall_agent 0
|
||||
;;
|
||||
"restart_agent")
|
||||
restart_agent 0
|
||||
;;
|
||||
"update_script")
|
||||
update_script 0
|
||||
;;
|
||||
*) show_usage ;;
|
||||
esac
|
||||
else
|
||||
select_version
|
||||
show_menu
|
||||
USE_CN_MIRROR=false
|
||||
fi
|
||||
|
||||
if [ "$USE_CN_MIRROR" = true ]; then
|
||||
shell_url="https://gitee.com/naibahq/scripts/raw/v0/install.sh"
|
||||
else
|
||||
shell_url="https://raw.githubusercontent.com/nezhahq/scripts/refs/heads/v0/install.sh"
|
||||
fi
|
||||
|
||||
|
||||
# 新地址 https://raw.githubusercontent.com/nezhahq/scripts/refs/heads/v0/install.sh
|
||||
if command -v wget >/dev/null 2>&1; then
|
||||
wget -O nezha_v0.sh "$shell_url"
|
||||
elif command -v curl >/dev/null 2>&1; then
|
||||
curl -o nezha_v0.sh "$shell_url"
|
||||
else
|
||||
echo "错误: 未找到 wget 或 curl,请安装其中任意一个后再试"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
chmod +x nezha_v0.sh
|
||||
|
||||
# 携带原参数运行新脚本
|
||||
exec ./nezha_v0.sh "$@"
|
||||
|
@ -1,954 +1,20 @@
|
||||
#!/bin/sh
|
||||
|
||||
#========================================================
|
||||
# System Required: CentOS 7+ / Debian 8+ / Ubuntu 16+ / Alpine 3+ /
|
||||
# Arch has only been tested once, if there is any problem, please report with screenshots Dysf888@pm.me
|
||||
# Description: Nezha Monitoring Install Script
|
||||
# Github: https://github.com/naiba/nezha
|
||||
# v0 script redirect to new repository
|
||||
#========================================================
|
||||
|
||||
NZ_BASE_PATH="/opt/nezha"
|
||||
NZ_DASHBOARD_PATH="${NZ_BASE_PATH}/dashboard"
|
||||
NZ_AGENT_PATH="${NZ_BASE_PATH}/agent"
|
||||
NZ_DASHBOARD_SERVICE="/etc/systemd/system/nezha-dashboard.service"
|
||||
NZ_DASHBOARD_SERVICERC="/etc/init.d/nezha-dashboard"
|
||||
NZ_VERSION="v0.20.2"
|
||||
|
||||
red='\033[0;31m'
|
||||
green='\033[0;32m'
|
||||
yellow='\033[0;33m'
|
||||
plain='\033[0m'
|
||||
export PATH="$PATH:/usr/local/bin"
|
||||
|
||||
os_arch=""
|
||||
[ -e /etc/os-release ] && grep -i "PRETTY_NAME" /etc/os-release | grep -qi "alpine" && os_alpine='1'
|
||||
|
||||
sudo() {
|
||||
myEUID=$(id -ru)
|
||||
if [ "$myEUID" -ne 0 ]; then
|
||||
if command -v sudo > /dev/null 2>&1; then
|
||||
command sudo "$@"
|
||||
else
|
||||
err "ERROR: sudo is not installed on the system, the action cannot be proceeded."
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
"$@"
|
||||
fi
|
||||
}
|
||||
|
||||
check_systemd() {
|
||||
if [ "$os_alpine" != 1 ] && ! command -v systemctl >/dev/null 2>&1; then
|
||||
echo "System not supported: systemctl not found"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
err() {
|
||||
printf "${red}%s${plain}\n" "$*" >&2
|
||||
}
|
||||
|
||||
success() {
|
||||
printf "${green}%s${plain}\n" "$*"
|
||||
}
|
||||
|
||||
info() {
|
||||
printf "${yellow}%s${plain}\n" "$*"
|
||||
}
|
||||
|
||||
geo_check() {
|
||||
api_list="https://blog.cloudflare.com/cdn-cgi/trace https://dash.cloudflare.com/cdn-cgi/trace https://developers.cloudflare.com/cdn-cgi/trace"
|
||||
ua="Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/81.0"
|
||||
set -- "$api_list"
|
||||
for url in $api_list; do
|
||||
text="$(curl -A "$ua" -m 10 -s "$url")"
|
||||
endpoint="$(echo "$text" | sed -n 's/.*h=\([^ ]*\).*/\1/p')"
|
||||
if echo "$text" | grep -qw 'CN'; then
|
||||
isCN=true
|
||||
break
|
||||
elif echo "$url" | grep -q "$endpoint"; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
pre_check() {
|
||||
umask 077
|
||||
|
||||
## os_arch
|
||||
if uname -m | grep -q 'x86_64'; then
|
||||
os_arch="amd64"
|
||||
elif uname -m | grep -q 'i386\|i686'; then
|
||||
os_arch="386"
|
||||
elif uname -m | grep -q 'aarch64\|armv8b\|armv8l'; then
|
||||
os_arch="arm64"
|
||||
elif uname -m | grep -q 'arm'; then
|
||||
os_arch="arm"
|
||||
elif uname -m | grep -q 's390x'; then
|
||||
os_arch="s390x"
|
||||
elif uname -m | grep -q 'riscv64'; then
|
||||
os_arch="riscv64"
|
||||
fi
|
||||
|
||||
## China_IP
|
||||
if [ -z "$CN" ]; then
|
||||
geo_check
|
||||
if [ -n "$isCN" ]; then
|
||||
echo "According to the information provided by various geoip api, the current IP may be in China"
|
||||
printf "Will the installation be done with a Chinese Mirror? [Y/n] (Custom Mirror Input 3): "
|
||||
read -r input
|
||||
case $input in
|
||||
[yY][eE][sS] | [yY])
|
||||
echo "Use Chinese Mirror"
|
||||
CN=true
|
||||
;;
|
||||
|
||||
[nN][oO] | [nN])
|
||||
echo "Do Not Use Chinese Mirror"
|
||||
;;
|
||||
|
||||
[3])
|
||||
echo "Use Custom Mirror"
|
||||
printf "Please enter a custom image (e.g. :dn-dao-github-mirror.daocloud.io). If left blank, it won't be used: "
|
||||
read -r input
|
||||
case $input in
|
||||
*)
|
||||
CUSTOM_MIRROR=$input
|
||||
;;
|
||||
esac
|
||||
|
||||
;;
|
||||
*)
|
||||
echo "Do Not Use Chinese Mirror"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$CUSTOM_MIRROR" ]; then
|
||||
GITHUB_RAW_URL="gitee.com/naibahq/nezha/raw/master"
|
||||
GITHUB_URL=$CUSTOM_MIRROR
|
||||
Get_Docker_URL="get.docker.com"
|
||||
Get_Docker_Argu=" -s docker --mirror Aliyun"
|
||||
Docker_IMG="registry.cn-shanghai.aliyuncs.com\/naibahq\/nezha-dashboard"
|
||||
else
|
||||
if [ -z "$CN" ]; then
|
||||
GITHUB_RAW_URL="raw.githubusercontent.com/naiba/nezha/master"
|
||||
GITHUB_URL="github.com"
|
||||
Get_Docker_URL="get.docker.com"
|
||||
Get_Docker_Argu=" "
|
||||
Docker_IMG="ghcr.io\/naiba\/nezha-dashboard"
|
||||
else
|
||||
GITHUB_RAW_URL="gitee.com/naibahq/nezha/raw/master"
|
||||
GITHUB_URL="gitee.com"
|
||||
Get_Docker_URL="get.docker.com"
|
||||
Get_Docker_Argu=" -s docker --mirror Aliyun"
|
||||
Docker_IMG="registry.cn-shanghai.aliyuncs.com\/naibahq\/nezha-dashboard"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
installation_check() {
|
||||
if docker compose version >/dev/null 2>&1; then
|
||||
DOCKER_COMPOSE_COMMAND="docker compose"
|
||||
if sudo $DOCKER_COMPOSE_COMMAND ls | grep -qw "$NZ_DASHBOARD_PATH/docker-compose.yaml" >/dev/null 2>&1; then
|
||||
NEZHA_IMAGES=$(sudo docker images --format "{{.Repository}}:{{.Tag}}" | grep -w "nezha-dashboard")
|
||||
if [ -n "$NEZHA_IMAGES" ]; then
|
||||
echo "Docker image with nezha-dashboard repository exists:"
|
||||
echo "$NEZHA_IMAGES"
|
||||
IS_DOCKER_NEZHA=1
|
||||
FRESH_INSTALL=0
|
||||
return
|
||||
else
|
||||
echo "No Docker images with the nezha-dashboard repository were found."
|
||||
fi
|
||||
fi
|
||||
elif command -v docker-compose >/dev/null 2>&1; then
|
||||
DOCKER_COMPOSE_COMMAND="docker-compose"
|
||||
if sudo $DOCKER_COMPOSE_COMMAND -f "$NZ_DASHBOARD_PATH/docker-compose.yaml" config >/dev/null 2>&1; then
|
||||
NEZHA_IMAGES=$(sudo docker images --format "{{.Repository}}:{{.Tag}}" | grep -w "nezha-dashboard")
|
||||
if [ -n "$NEZHA_IMAGES" ]; then
|
||||
echo "Docker image with nezha-dashboard repository exists:"
|
||||
echo "$NEZHA_IMAGES"
|
||||
IS_DOCKER_NEZHA=1
|
||||
FRESH_INSTALL=0
|
||||
return
|
||||
else
|
||||
echo "No Docker images with the nezha-dashboard repository were found."
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -f "$NZ_DASHBOARD_PATH/app" ]; then
|
||||
IS_DOCKER_NEZHA=0
|
||||
FRESH_INSTALL=0
|
||||
fi
|
||||
}
|
||||
|
||||
select_version() {
|
||||
if [ -z "$IS_DOCKER_NEZHA" ]; then
|
||||
info "Select your installation method(Input anything is ok if you are installing agent):"
|
||||
info "1. Docker"
|
||||
info "2. Standalone"
|
||||
while true; do
|
||||
printf "Please enter [1-2]: "
|
||||
read -r option
|
||||
case "${option}" in
|
||||
1)
|
||||
IS_DOCKER_NEZHA=1
|
||||
break
|
||||
;;
|
||||
2)
|
||||
IS_DOCKER_NEZHA=0
|
||||
break
|
||||
;;
|
||||
*)
|
||||
err "Please enter the correct number [1-2]"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
update_script() {
|
||||
echo "> Update Script"
|
||||
|
||||
curl -sL https://${GITHUB_RAW_URL}/script/install_en.sh -o /tmp/nezha.sh
|
||||
new_version=$(grep "NZ_VERSION" /tmp/nezha.sh | head -n 1 | awk -F "=" '{print $2}' | sed 's/\"//g;s/,//g;s/ //g')
|
||||
if [ -z "$new_version" ]; then
|
||||
echo "Script failed to get, please check if the network can link https://${GITHUB_RAW_URL}/script/install.sh"
|
||||
return 1
|
||||
fi
|
||||
echo "The current latest version is: ${new_version}"
|
||||
mv -f /tmp/nezha.sh ./nezha.sh && chmod a+x ./nezha.sh
|
||||
|
||||
echo "Execute new script after 3s"
|
||||
sleep 3s
|
||||
clear
|
||||
exec ./nezha.sh
|
||||
exit 0
|
||||
}
|
||||
|
||||
before_show_menu() {
|
||||
echo && info "* Press Enter to return to the main menu *" && read temp
|
||||
show_menu
|
||||
}
|
||||
|
||||
install_base() {
|
||||
(command -v curl >/dev/null 2>&1 && command -v wget >/dev/null 2>&1 && command -v unzip >/dev/null 2>&1 && command -v getenforce >/dev/null 2>&1) ||
|
||||
(install_soft curl wget unzip)
|
||||
}
|
||||
|
||||
install_arch() {
|
||||
info "Archlinux needs to add nezha-agent user to install libselinux. It will be deleted automatically after installation. It is recommended to check manually"
|
||||
read -r -p "Do you need to install libselinux? [Y/n] " input
|
||||
case $input in
|
||||
[yY][eE][sS] | [yY])
|
||||
useradd -m nezha-agent
|
||||
sed -i "$ a\nezha-agent ALL=(ALL ) NOPASSWD:ALL" /etc/sudoers
|
||||
sudo -iu nezha-agent bash -c 'gpg --keyserver keys.gnupg.net --recv-keys 4695881C254508D1;
|
||||
cd /tmp; git clone https://aur.archlinux.org/libsepol.git; cd libsepol; makepkg -si --noconfirm --asdeps; cd ..;
|
||||
git clone https://aur.archlinux.org/libselinux.git; cd libselinux; makepkg -si --noconfirm; cd ..;
|
||||
rm -rf libsepol libselinux'
|
||||
sed -i '/nezha-agent/d' /etc/sudoers && sleep 30s && killall -u nezha-agent && userdel -r nezha-agent
|
||||
echo -e "${red}Info: ${plain}user nezha-agent has been deleted, Be sure to check it manually!\n"
|
||||
;;
|
||||
[nN][oO] | [nN])
|
||||
echo "Libselinux will not be installed"
|
||||
;;
|
||||
*)
|
||||
echo "Libselinux will not be installed"
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
install_soft() {
|
||||
(command -v yum >/dev/null 2>&1 && sudo yum makecache && sudo yum install "$@" selinux-policy -y) ||
|
||||
(command -v apt >/dev/null 2>&1 && sudo apt update && sudo apt install "$@" selinux-utils -y) ||
|
||||
(command -v pacman >/dev/null 2>&1 && sudo pacman -Syu "$@" base-devel --noconfirm && install_arch) ||
|
||||
(command -v apt-get >/dev/null 2>&1 && sudo apt-get update && sudo apt-get install "$@" selinux-utils -y) ||
|
||||
(command -v apk >/dev/null 2>&1 && sudo apk update && sudo apk add "$@" -f)
|
||||
}
|
||||
|
||||
install_dashboard() {
|
||||
check_systemd
|
||||
install_base
|
||||
|
||||
echo "> Install Dashboard"
|
||||
|
||||
# Nezha Monitoring Folder
|
||||
if [ ! "$FRESH_INSTALL" = 0 ]; then
|
||||
sudo mkdir -p $NZ_DASHBOARD_PATH
|
||||
else
|
||||
echo "You may have already installed the dashboard, repeated installation will overwrite the data, please pay attention to backup."
|
||||
printf "Exit the installation? [Y/n] "
|
||||
read -r input
|
||||
case $input in
|
||||
[yY][eE][sS] | [yY])
|
||||
echo "Exit the installation."
|
||||
exit 0
|
||||
;;
|
||||
[nN][oO] | [nN])
|
||||
echo "Continue."
|
||||
;;
|
||||
*)
|
||||
echo "Exit the installation."
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if [ "$IS_DOCKER_NEZHA" = 1 ]; then
|
||||
install_dashboard_docker
|
||||
elif [ "$IS_DOCKER_NEZHA" = 0 ]; then
|
||||
install_dashboard_standalone
|
||||
fi
|
||||
|
||||
modify_dashboard_config 0
|
||||
|
||||
if [ $# = 0 ]; then
|
||||
before_show_menu
|
||||
fi
|
||||
}
|
||||
|
||||
install_dashboard_docker() {
|
||||
if [ ! "$FRESH_INSTALL" = 0 ]; then
|
||||
if ! command -v docker >/dev/null 2>&1; then
|
||||
echo "Installing Docker"
|
||||
if [ "$os_alpine" != 1 ]; then
|
||||
if ! curl -sL https://${Get_Docker_URL} | sudo bash -s "${Get_Docker_Argu}"; then
|
||||
err "Script failed to get, please check if the network can link ${Get_Docker_URL}"
|
||||
return 0
|
||||
fi
|
||||
sudo systemctl enable docker.service
|
||||
sudo systemctl start docker.service
|
||||
else
|
||||
sudo apk add docker docker-compose
|
||||
sudo rc-update add docker
|
||||
sudo rc-service docker start
|
||||
fi
|
||||
success "Docker installed successfully"
|
||||
installation_check
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
install_dashboard_standalone() {
|
||||
if [ ! -d "${NZ_DASHBOARD_PATH}/resource/template/theme-custom" ] || [ ! -d "${NZ_DASHBOARD_PATH}/resource/static/custom" ]; then
|
||||
sudo mkdir -p "${NZ_DASHBOARD_PATH}/resource/template/theme-custom" "${NZ_DASHBOARD_PATH}/resource/static/custom" >/dev/null 2>&1
|
||||
fi
|
||||
}
|
||||
|
||||
selinux() {
|
||||
#Check SELinux
|
||||
if command -v getenforce >/dev/null 2>&1; then
|
||||
if getenforce | grep '[Ee]nfor'; then
|
||||
echo "SELinux running, closing now!"
|
||||
sudo setenforce 0 >/dev/null 2>&1
|
||||
find_key="SELINUX="
|
||||
sudo sed -ri "/^$find_key/c${find_key}disabled" /etc/selinux/config
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
install_agent() {
|
||||
install_base
|
||||
selinux
|
||||
|
||||
echo "> Install Agent"
|
||||
|
||||
echo "Obtaining Agent version number"
|
||||
|
||||
|
||||
_version=$(curl -m 10 -sL "https://api.github.com/repos/nezhahq/agent/releases/latest" | grep "tag_name" | head -n 1 | awk -F ":" '{print $2}' | sed 's/\"//g;s/,//g;s/ //g')
|
||||
if [ -z "$_version" ]; then
|
||||
_version=$(curl -m 10 -sL "https://gitee.com/api/v5/repos/naibahq/agent/releases/latest" | awk -F '"' '{for(i=1;i<=NF;i++){if($i=="tag_name"){print $(i+2)}}}')
|
||||
fi
|
||||
if [ -z "$_version" ]; then
|
||||
_version=$(curl -m 10 -sL "https://fastly.jsdelivr.net/gh/nezhahq/agent/" | grep "option\.value" | awk -F "'" '{print $2}' | sed 's/nezhahq\/agent@/v/g')
|
||||
fi
|
||||
if [ -z "$_version" ]; then
|
||||
_version=$(curl -m 10 -sL "https://gcore.jsdelivr.net/gh/nezhahq/agent/" | grep "option\.value" | awk -F "'" '{print $2}' | sed 's/nezhahq\/agent@/v/g')
|
||||
fi
|
||||
|
||||
if [ -z "$_version" ]; then
|
||||
err "Fail to obtain agent version, please check if the network can link https://api.github.com/repos/nezhahq/agent/releases/latest"
|
||||
return 1
|
||||
else
|
||||
echo "The current latest version is: ${_version}"
|
||||
fi
|
||||
|
||||
# Nezha Monitoring Folder
|
||||
sudo mkdir -p $NZ_AGENT_PATH
|
||||
|
||||
echo "Downloading Agent"
|
||||
if [ -z "$CN" ]; then
|
||||
NZ_AGENT_URL="https://${GITHUB_URL}/nezhahq/agent/releases/download/${_version}/nezha-agent_linux_${os_arch}.zip"
|
||||
else
|
||||
NZ_AGENT_URL="https://${GITHUB_URL}/naibahq/agent/releases/download/${_version}/nezha-agent_linux_${os_arch}.zip"
|
||||
fi
|
||||
|
||||
_cmd="wget -t 2 -T 60 -O nezha-agent_linux_${os_arch}.zip $NZ_AGENT_URL >/dev/null 2>&1"
|
||||
if ! eval "$_cmd"; then
|
||||
err "Fail to download agent, please check if the network can link ${GITHUB_URL}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
sudo unzip -qo nezha-agent_linux_${os_arch}.zip &&
|
||||
sudo mv nezha-agent $NZ_AGENT_PATH &&
|
||||
sudo rm -rf nezha-agent_linux_${os_arch}.zip README.md
|
||||
|
||||
if [ $# -ge 3 ]; then
|
||||
modify_agent_config "$@"
|
||||
else
|
||||
modify_agent_config 0
|
||||
fi
|
||||
|
||||
if [ $# = 0 ]; then
|
||||
before_show_menu
|
||||
fi
|
||||
}
|
||||
|
||||
modify_agent_config() {
|
||||
echo "> Modify Agent Configuration"
|
||||
|
||||
if [ $# -lt 3 ]; then
|
||||
echo "Please add Agent in the Dashboard first, record the secret"
|
||||
printf "Please enter a domain that resolves to the IP where Dashboard is located (no CDN): "
|
||||
read -r nz_grpc_host
|
||||
printf "Please enter Dashboard RPC port (default 5555): "
|
||||
read -r nz_grpc_port
|
||||
printf "Please enter the Agent secret: "
|
||||
read -r nz_client_secret
|
||||
printf "Do you want to enable SSL/TLS encryption for the gRPC port (--tls)? Press [y] if yes, the default is not required, and users can press Enter to skip if you don't understand: "
|
||||
read -r nz_grpc_proxy
|
||||
echo "${nz_grpc_proxy}" | grep -qiw 'Y' && args='--tls'
|
||||
if [ -z "$nz_grpc_host" ] || [ -z "$nz_client_secret" ]; then
|
||||
err "All options cannot be empty"
|
||||
before_show_menu
|
||||
return 1
|
||||
fi
|
||||
if [ -z "$nz_grpc_port" ]; then
|
||||
nz_grpc_port=5555
|
||||
fi
|
||||
else
|
||||
nz_grpc_host=$1
|
||||
nz_grpc_port=$2
|
||||
nz_client_secret=$3
|
||||
shift 3
|
||||
if [ $# -gt 0 ]; then
|
||||
args="$*"
|
||||
fi
|
||||
fi
|
||||
|
||||
_cmd="sudo ${NZ_AGENT_PATH}/nezha-agent service install -s $nz_grpc_host:$nz_grpc_port -p $nz_client_secret $args >/dev/null 2>&1"
|
||||
|
||||
if ! eval "$_cmd"; then
|
||||
sudo "${NZ_AGENT_PATH}"/nezha-agent service uninstall >/dev/null 2>&1
|
||||
sudo "${NZ_AGENT_PATH}"/nezha-agent service install -s "$nz_grpc_host:$nz_grpc_port" -p "$nz_client_secret" "$args" >/dev/null 2>&1
|
||||
fi
|
||||
|
||||
success "Agent configuration modified successfully, please wait for agent self-restart to take effect"
|
||||
|
||||
#if [[ $# == 0 ]]; then
|
||||
# before_show_menu
|
||||
#fi
|
||||
}
|
||||
|
||||
modify_dashboard_config() {
|
||||
echo "> Modify Dashboard Configuration"
|
||||
|
||||
if [ "$IS_DOCKER_NEZHA" = 1 ]; then
|
||||
if [ -n "$DOCKER_COMPOSE_COMMAND" ]; then
|
||||
echo "Download Docker Script"
|
||||
_cmd="wget -t 2 -T 60 -O /tmp/nezha-docker-compose.yaml https://${GITHUB_RAW_URL}/script/docker-compose.yaml >/dev/null 2>&1"
|
||||
if ! eval "$_cmd"; then
|
||||
err "Script failed to get, please check if the network can link ${GITHUB_RAW_URL}"
|
||||
return 0
|
||||
fi
|
||||
else
|
||||
err "Please install docker-compose manually. https://docs.docker.com/compose/install/linux/"
|
||||
before_show_menu
|
||||
fi
|
||||
fi
|
||||
|
||||
_cmd="wget -t 2 -T 60 -O /tmp/nezha-config.yaml https://${GITHUB_RAW_URL}/script/config.yaml >/dev/null 2>&1"
|
||||
if ! eval "$_cmd"; then
|
||||
err "Script failed to get, please check if the network can link ${GITHUB_RAW_URL}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "About the GitHub Oauth2 application: create it at https://github.com/settings/developers, no review required, and fill in the http(s)://domain_or_IP/oauth2/callback"
|
||||
echo "(Not recommended) About the Gitee Oauth2 application: create it at https://gitee.com/oauth/applications, no auditing required, and fill in the http(s)://domain_or_IP/oauth2/callback"
|
||||
printf "Please enter the OAuth2 provider (github/gitlab/jihulab/gitee, default github): "
|
||||
read -r nz_oauth2_type
|
||||
printf "Please enter the Client ID of the Oauth2 application: "
|
||||
read -r nz_github_oauth_client_id
|
||||
printf "Please enter the Client Secret of the Oauth2 application: "
|
||||
read -r nz_github_oauth_client_secret
|
||||
printf "Please enter your GitHub/Gitee login name as the administrator, separated by commas: "
|
||||
read -r nz_admin_logins
|
||||
printf "Please enter the site title: "
|
||||
read -r nz_site_title
|
||||
printf "Please enter the site access port: (default 8008)"
|
||||
read -r nz_site_port
|
||||
printf "Please enter the RPC port to be used for Agent access: (default 5555)"
|
||||
read -r nz_grpc_port
|
||||
|
||||
if [ -z "$nz_admin_logins" ] || [ -z "$nz_github_oauth_client_id" ] || [ -z "$nz_github_oauth_client_secret" ] || [ -z "$nz_site_title" ]; then
|
||||
err "All options cannot be empty"
|
||||
before_show_menu
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ -z "$nz_site_port" ]; then
|
||||
nz_site_port=8008
|
||||
fi
|
||||
if [ -z "$nz_grpc_port" ]; then
|
||||
nz_grpc_port=5555
|
||||
fi
|
||||
if [ -z "$nz_oauth2_type" ]; then
|
||||
nz_oauth2_type=github
|
||||
fi
|
||||
|
||||
sed -i "s/nz_oauth2_type/${nz_oauth2_type}/" /tmp/nezha-config.yaml
|
||||
sed -i "s/nz_admin_logins/${nz_admin_logins}/" /tmp/nezha-config.yaml
|
||||
sed -i "s/nz_grpc_port/${nz_grpc_port}/" /tmp/nezha-config.yaml
|
||||
sed -i "s/nz_github_oauth_client_id/${nz_github_oauth_client_id}/" /tmp/nezha-config.yaml
|
||||
sed -i "s/nz_github_oauth_client_secret/${nz_github_oauth_client_secret}/" /tmp/nezha-config.yaml
|
||||
sed -i "s/nz_language/zh-CN/" /tmp/nezha-config.yaml
|
||||
sed -i "s/nz_site_title/${nz_site_title}/" /tmp/nezha-config.yaml
|
||||
if [ "$IS_DOCKER_NEZHA" = 1 ]; then
|
||||
sed -i "s/nz_site_port/${nz_site_port}/" /tmp/nezha-docker-compose.yaml
|
||||
sed -i "s/nz_grpc_port/${nz_grpc_port}/g" /tmp/nezha-docker-compose.yaml
|
||||
sed -i "s/nz_image_url/${Docker_IMG}/" /tmp/nezha-docker-compose.yaml
|
||||
elif [ "$IS_DOCKER_NEZHA" = 0 ]; then
|
||||
sed -i "s/80/${nz_site_port}/" /tmp/nezha-config.yaml
|
||||
fi
|
||||
|
||||
sudo mkdir -p $NZ_DASHBOARD_PATH/data
|
||||
sudo mv -f /tmp/nezha-config.yaml ${NZ_DASHBOARD_PATH}/data/config.yaml
|
||||
if [ "$IS_DOCKER_NEZHA" = 1 ]; then
|
||||
sudo mv -f /tmp/nezha-docker-compose.yaml ${NZ_DASHBOARD_PATH}/docker-compose.yaml
|
||||
fi
|
||||
|
||||
if [ "$IS_DOCKER_NEZHA" = 0 ]; then
|
||||
echo "Downloading service file"
|
||||
if [ "$os_alpine" != 1 ]; then
|
||||
_download="sudo wget -t 2 -T 60 -O $NZ_DASHBOARD_SERVICE https://${GITHUB_RAW_URL}/script/nezha-dashboard.service >/dev/null 2>&1"
|
||||
if ! eval "$_download"; then
|
||||
err "File failed to get, please check if the network can link ${GITHUB_RAW_URL}"
|
||||
return 0
|
||||
fi
|
||||
else
|
||||
_download="sudo wget -t 2 -T 60 -O $NZ_DASHBOARD_SERVICERC https://${GITHUB_RAW_URL}/script/nezha-dashboard >/dev/null 2>&1"
|
||||
if ! eval "$_download"; then
|
||||
err "File failed to get, please check if the network can link ${GITHUB_RAW_URL}"
|
||||
return 0
|
||||
fi
|
||||
sudo chmod +x $NZ_DASHBOARD_SERVICERC
|
||||
fi
|
||||
fi
|
||||
|
||||
success "Dashboard configuration modified successfully, please wait for Dashboard self-restart to take effect"
|
||||
|
||||
restart_and_update
|
||||
|
||||
if [ $# = 0 ]; then
|
||||
before_show_menu
|
||||
fi
|
||||
}
|
||||
|
||||
restart_and_update() {
|
||||
echo "> Restart and Update Dashboard"
|
||||
|
||||
if [ "$IS_DOCKER_NEZHA" = 1 ]; then
|
||||
_cmd="restart_and_update_docker"
|
||||
elif [ "$IS_DOCKER_NEZHA" = 0 ]; then
|
||||
_cmd="restart_and_update_standalone"
|
||||
fi
|
||||
|
||||
if eval "$_cmd"; then
|
||||
success "Nezha Monitoring Restart Successful"
|
||||
info "Default Dashboard address: domain:site_access_port"
|
||||
else
|
||||
err "The restart failed, probably because the boot time exceeded two seconds, please check the log information later"
|
||||
fi
|
||||
|
||||
if [ $# = 0 ]; then
|
||||
before_show_menu
|
||||
fi
|
||||
}
|
||||
|
||||
restart_and_update_docker() {
|
||||
sudo $DOCKER_COMPOSE_COMMAND -f ${NZ_DASHBOARD_PATH}/docker-compose.yaml pull
|
||||
sudo $DOCKER_COMPOSE_COMMAND -f ${NZ_DASHBOARD_PATH}/docker-compose.yaml down
|
||||
sudo $DOCKER_COMPOSE_COMMAND -f ${NZ_DASHBOARD_PATH}/docker-compose.yaml up -d
|
||||
}
|
||||
|
||||
restart_and_update_standalone() {
|
||||
_version=$(curl -m 10 -sL "https://api.github.com/repos/naiba/nezha/releases/latest" | grep "tag_name" | head -n 1 | awk -F ":" '{print $2}' | sed 's/\"//g;s/,//g;s/ //g')
|
||||
if [ -z "$_version" ]; then
|
||||
_version=$(curl -m 10 -sL "https://gitee.com/api/v5/repos/naibahq/nezha/releases/latest" | awk -F '"' '{for(i=1;i<=NF;i++){if($i=="tag_name"){print $(i+2)}}}')
|
||||
fi
|
||||
if [ -z "$_version" ]; then
|
||||
_version=$(curl -m 10 -sL "https://fastly.jsdelivr.net/gh/naiba/nezha/" | grep "option\.value" | awk -F "'" '{print $2}' | sed 's/naiba\/nezha@/v/g')
|
||||
fi
|
||||
if [ -z "$_version" ]; then
|
||||
_version=$(curl -m 10 -sL "https://gcore.jsdelivr.net/gh/naiba/nezha/" | grep "option\.value" | awk -F "'" '{print $2}' | sed 's/naiba\/nezha@/v/g')
|
||||
fi
|
||||
|
||||
if [ -z "$_version" ]; then
|
||||
err "Fail to obtain agent version, please check if the network can link https://api.github.com/repos/nezhahq/agent/releases/latest"
|
||||
return 1
|
||||
else
|
||||
echo "The current latest version is: ${_version}"
|
||||
fi
|
||||
|
||||
if [ "$os_alpine" != 1 ]; then
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl stop nezha-dashboard
|
||||
else
|
||||
sudo rc-service nezha-dashboard stop
|
||||
fi
|
||||
|
||||
if [ -z "$CN" ]; then
|
||||
NZ_DASHBOARD_URL="https://${GITHUB_URL}/naiba/nezha/releases/download/${_version}/dashboard-linux-${os_arch}.zip"
|
||||
else
|
||||
NZ_DASHBOARD_URL="https://${GITHUB_URL}/naibahq/nezha/releases/download/${_version}/dashboard-linux-${os_arch}.zip"
|
||||
fi
|
||||
|
||||
sudo wget -qO $NZ_DASHBOARD_PATH/app.zip "$NZ_DASHBOARD_URL" >/dev/null 2>&1 && sudo unzip -qq -o $NZ_DASHBOARD_PATH/app.zip -d $NZ_DASHBOARD_PATH && sudo mv $NZ_DASHBOARD_PATH/dashboard-linux-$os_arch $NZ_DASHBOARD_PATH/app && sudo rm $NZ_DASHBOARD_PATH/app.zip
|
||||
|
||||
if [ "$os_alpine" != 1 ]; then
|
||||
sudo systemctl enable nezha-dashboard
|
||||
sudo systemctl restart nezha-dashboard
|
||||
else
|
||||
sudo rc-update add nezha-dashboard
|
||||
sudo rc-service nezha-dashboard restart
|
||||
fi
|
||||
}
|
||||
|
||||
start_dashboard() {
|
||||
echo "> Start Dashboard"
|
||||
|
||||
if [ "$IS_DOCKER_NEZHA" = 1 ]; then
|
||||
_cmd="start_dashboard_docker"
|
||||
elif [ "$IS_DOCKER_NEZHA" = 0 ]; then
|
||||
_cmd="start_dashboard_standalone"
|
||||
fi
|
||||
|
||||
if eval "$_cmd"; then
|
||||
success "Nezha Monitoring Start Successful"
|
||||
else
|
||||
err "Failed to start, please check the log message later"
|
||||
fi
|
||||
|
||||
if [ $# = 0 ]; then
|
||||
before_show_menu
|
||||
fi
|
||||
}
|
||||
|
||||
start_dashboard_docker() {
|
||||
sudo $DOCKER_COMPOSE_COMMAND -f ${NZ_DASHBOARD_PATH}/docker-compose.yaml up -d
|
||||
}
|
||||
|
||||
start_dashboard_standalone() {
|
||||
if [ "$os_alpine" != 1 ]; then
|
||||
sudo systemctl start nezha-dashboard
|
||||
else
|
||||
sudo rc-service nezha-dashboard start
|
||||
fi
|
||||
}
|
||||
|
||||
stop_dashboard() {
|
||||
echo "> Stop Dashboard"
|
||||
|
||||
if [ "$IS_DOCKER_NEZHA" = 1 ]; then
|
||||
_cmd="stop_dashboard_docker"
|
||||
elif [ "$IS_DOCKER_NEZHA" = 0 ]; then
|
||||
_cmd="stop_dashboard_standalone"
|
||||
fi
|
||||
|
||||
if eval "$_cmd"; then
|
||||
success "Nezha Monitoring Stop Successful"
|
||||
else
|
||||
err "Failed to stop, please check the log message later"
|
||||
fi
|
||||
|
||||
if [ $# = 0 ]; then
|
||||
before_show_menu
|
||||
fi
|
||||
}
|
||||
|
||||
stop_dashboard_docker() {
|
||||
sudo $DOCKER_COMPOSE_COMMAND -f ${NZ_DASHBOARD_PATH}/docker-compose.yaml down
|
||||
}
|
||||
|
||||
stop_dashboard_standalone() {
|
||||
if [ "$os_alpine" != 1 ]; then
|
||||
sudo systemctl stop nezha-dashboard
|
||||
else
|
||||
sudo rc-service nezha-dashboard stop
|
||||
fi
|
||||
}
|
||||
|
||||
show_dashboard_log() {
|
||||
echo "> View Dashboard Log"
|
||||
|
||||
if [ "$IS_DOCKER_NEZHA" = 1 ]; then
|
||||
show_dashboard_log_docker
|
||||
elif [ "$IS_DOCKER_NEZHA" = 0 ]; then
|
||||
show_dashboard_log_standalone
|
||||
fi
|
||||
|
||||
if [ $# = 0 ]; then
|
||||
before_show_menu
|
||||
fi
|
||||
}
|
||||
|
||||
show_dashboard_log_docker() {
|
||||
sudo $DOCKER_COMPOSE_COMMAND -f ${NZ_DASHBOARD_PATH}/docker-compose.yaml logs -f
|
||||
}
|
||||
|
||||
show_dashboard_log_standalone() {
|
||||
if [ "$os_alpine" != 1 ]; then
|
||||
sudo journalctl -xf -u nezha-dashboard.service
|
||||
else
|
||||
sudo tail -n 10 /var/log/nezha-dashboard.err
|
||||
fi
|
||||
}
|
||||
|
||||
uninstall_dashboard() {
|
||||
echo "> Uninstall Dashboard"
|
||||
|
||||
if [ "$IS_DOCKER_NEZHA" = 1 ]; then
|
||||
uninstall_dashboard_docker
|
||||
elif [ "$IS_DOCKER_NEZHA" = 0 ]; then
|
||||
uninstall_dashboard_standalone
|
||||
fi
|
||||
|
||||
clean_all
|
||||
|
||||
if [ $# = 0 ]; then
|
||||
before_show_menu
|
||||
fi
|
||||
}
|
||||
|
||||
uninstall_dashboard_docker() {
|
||||
sudo $DOCKER_COMPOSE_COMMAND -f ${NZ_DASHBOARD_PATH}/docker-compose.yaml down
|
||||
sudo rm -rf $NZ_DASHBOARD_PATH
|
||||
sudo docker rmi -f ghcr.io/naiba/nezha-dashboard >/dev/null 2>&1
|
||||
sudo docker rmi -f registry.cn-shanghai.aliyuncs.com/naibahq/nezha-dashboard >/dev/null 2>&1
|
||||
}
|
||||
|
||||
uninstall_dashboard_standalone() {
|
||||
sudo rm -rf $NZ_DASHBOARD_PATH
|
||||
|
||||
if [ "$os_alpine" != 1 ]; then
|
||||
sudo systemctl disable nezha-dashboard
|
||||
sudo systemctl stop nezha-dashboard
|
||||
else
|
||||
sudo rc-update del nezha-dashboard
|
||||
sudo rc-service nezha-dashboard stop
|
||||
fi
|
||||
|
||||
if [ "$os_alpine" != 1 ]; then
|
||||
sudo rm $NZ_DASHBOARD_SERVICE
|
||||
else
|
||||
sudo rm $NZ_DASHBOARD_SERVICERC
|
||||
fi
|
||||
}
|
||||
|
||||
show_agent_log() {
|
||||
echo "> View Agent Log"
|
||||
|
||||
if [ "$os_alpine" != 1 ]; then
|
||||
sudo journalctl -xf -u nezha-agent.service
|
||||
else
|
||||
sudo tail -n 10 /var/log/nezha-agent.err
|
||||
fi
|
||||
|
||||
if [ $# = 0 ]; then
|
||||
before_show_menu
|
||||
fi
|
||||
}
|
||||
|
||||
uninstall_agent() {
|
||||
echo "> Uninstall Agent"
|
||||
|
||||
sudo ${NZ_AGENT_PATH}/nezha-agent service uninstall
|
||||
|
||||
sudo rm -rf $NZ_AGENT_PATH
|
||||
clean_all
|
||||
|
||||
if [ $# = 0 ]; then
|
||||
before_show_menu
|
||||
fi
|
||||
}
|
||||
|
||||
restart_agent() {
|
||||
echo "> Restart Agent"
|
||||
|
||||
sudo ${NZ_AGENT_PATH}/nezha-agent service restart
|
||||
|
||||
if [ $# = 0 ]; then
|
||||
before_show_menu
|
||||
fi
|
||||
}
|
||||
|
||||
clean_all() {
|
||||
if [ -z "$(ls -A ${NZ_BASE_PATH})" ]; then
|
||||
sudo rm -rf ${NZ_BASE_PATH}
|
||||
fi
|
||||
}
|
||||
|
||||
show_usage() {
|
||||
echo "Nezha Monitor Management Script Usage: "
|
||||
echo "--------------------------------------------------------"
|
||||
echo "./nezha.sh - Show Menu"
|
||||
echo "./nezha.sh install_dashboard - Install Dashboard"
|
||||
echo "./nezha.sh modify_dashboard_config - Modify Dashboard Configuration"
|
||||
echo "./nezha.sh start_dashboard - Start Dashboard"
|
||||
echo "./nezha.sh stop_dashboard - Stop Dashboard"
|
||||
echo "./nezha.sh restart_and_update - Restart and Update the Dashboard"
|
||||
echo "./nezha.sh show_dashboard_log - View Dashboard Log"
|
||||
echo "./nezha.sh uninstall_dashboard - Uninstall Dashboard"
|
||||
echo "--------------------------------------------------------"
|
||||
echo "./nezha.sh install_agent - Install Agent"
|
||||
echo "./nezha.sh modify_agent_config - Modify Agent Configuration"
|
||||
echo "./nezha.sh show_agent_log - View Agent Log"
|
||||
echo "./nezha.sh uninstall_agent - Uninstall Agent"
|
||||
echo "./nezha.sh restart_agent - Restart Agent"
|
||||
echo "./nezha.sh update_script - Update Script"
|
||||
echo "--------------------------------------------------------"
|
||||
}
|
||||
|
||||
show_menu() {
|
||||
printf "
|
||||
${green}Nezha Monitor Management Script${plain} ${red}${NZ_VERSION}${plain}
|
||||
--- https://github.com/naiba/nezha ---
|
||||
${green}1.${plain} Install Dashboard
|
||||
${green}2.${plain} Modify Dashbaord Configuration
|
||||
${green}3.${plain} Start Dashboard
|
||||
${green}4.${plain} Stop Dashboard
|
||||
${green}5.${plain} Restart and Update Dashboard
|
||||
${green}6.${plain} View Dashboard Log
|
||||
${green}7.${plain} Uninstall Dashboard
|
||||
————————————————-
|
||||
${green}8.${plain} Install Agent
|
||||
${green}9.${plain} Modify Agent Configuration
|
||||
${green}10.${plain} View Agent Log
|
||||
${green}11.${plain} Uninstall Agent
|
||||
${green}12.${plain} Restart Agent
|
||||
————————————————-
|
||||
${green}13.${plain} Update Script
|
||||
————————————————-
|
||||
${green}0.${plain} Exit Script
|
||||
"
|
||||
echo && printf "Please enter [0-13]: " && read -r num
|
||||
case "${num}" in
|
||||
0)
|
||||
exit 0
|
||||
;;
|
||||
1)
|
||||
install_dashboard
|
||||
;;
|
||||
2)
|
||||
modify_dashboard_config
|
||||
;;
|
||||
3)
|
||||
start_dashboard
|
||||
;;
|
||||
4)
|
||||
stop_dashboard
|
||||
;;
|
||||
5)
|
||||
restart_and_update
|
||||
;;
|
||||
6)
|
||||
show_dashboard_log
|
||||
;;
|
||||
7)
|
||||
uninstall_dashboard
|
||||
;;
|
||||
8)
|
||||
install_agent
|
||||
;;
|
||||
9)
|
||||
modify_agent_config
|
||||
;;
|
||||
10)
|
||||
show_agent_log
|
||||
;;
|
||||
11)
|
||||
uninstall_agent
|
||||
;;
|
||||
12)
|
||||
restart_agent
|
||||
;;
|
||||
13)
|
||||
update_script
|
||||
;;
|
||||
*)
|
||||
err "Please enter the correct number [0-13]"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
pre_check
|
||||
installation_check
|
||||
|
||||
if [ $# -gt 0 ]; then
|
||||
case $1 in
|
||||
"install_dashboard")
|
||||
install_dashboard 0
|
||||
;;
|
||||
"modify_dashboard_config")
|
||||
modify_dashboard_config 0
|
||||
;;
|
||||
"start_dashboard")
|
||||
start_dashboard 0
|
||||
;;
|
||||
"stop_dashboard")
|
||||
stop_dashboard 0
|
||||
;;
|
||||
"restart_and_update")
|
||||
restart_and_update 0
|
||||
;;
|
||||
"show_dashboard_log")
|
||||
show_dashboard_log 0
|
||||
;;
|
||||
"uninstall_dashboard")
|
||||
uninstall_dashboard 0
|
||||
;;
|
||||
"install_agent")
|
||||
shift
|
||||
if [ $# -ge 3 ]; then
|
||||
install_agent "$@"
|
||||
else
|
||||
install_agent 0
|
||||
fi
|
||||
;;
|
||||
"modify_agent_config")
|
||||
modify_agent_config 0
|
||||
;;
|
||||
"show_agent_log")
|
||||
show_agent_log 0
|
||||
;;
|
||||
"uninstall_agent")
|
||||
uninstall_agent 0
|
||||
;;
|
||||
"restart_agent")
|
||||
restart_agent 0
|
||||
;;
|
||||
"update_script")
|
||||
update_script 0
|
||||
;;
|
||||
*) show_usage ;;
|
||||
esac
|
||||
# new address https://raw.githubusercontent.com/nezhahq/scripts/refs/heads/v0/install.sh
|
||||
if command -v wget >/dev/null 2>&1; then
|
||||
wget -O nezha_v0.sh https://raw.githubusercontent.com/nezhahq/scripts/refs/heads/v0/install_en.sh
|
||||
elif command -v curl >/dev/null 2>&1; then
|
||||
curl -o nezha_v0.sh https://raw.githubusercontent.com/nezhahq/scripts/refs/heads/v0/install_en.sh
|
||||
else
|
||||
select_version
|
||||
show_menu
|
||||
echo "Error: wget or curl not found, please install one of them first"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
chmod +x nezha_v0.sh
|
||||
|
||||
# run new script with original parameters
|
||||
exec ./nezha_v0.sh "$@"
|
||||
|
@ -25,6 +25,19 @@ type CommonResponse struct {
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
type RegisterServer struct {
|
||||
Name string
|
||||
Tag string
|
||||
Note string
|
||||
HideForGuest string
|
||||
}
|
||||
|
||||
type ServerRegisterResponse struct {
|
||||
CommonResponse
|
||||
Secret string `json:"secret"`
|
||||
}
|
||||
|
||||
|
||||
type CommonServerInfo struct {
|
||||
ID uint64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
@ -227,6 +240,55 @@ func (s *ServerAPIService) GetAllList() *ServerInfoResponse {
|
||||
}
|
||||
return res
|
||||
}
|
||||
func (s *ServerAPIService) Register(rs *RegisterServer) *ServerRegisterResponse {
|
||||
var serverInfo model.Server
|
||||
var err error
|
||||
// Populate serverInfo fields
|
||||
serverInfo.Name = rs.Name
|
||||
serverInfo.Tag = rs.Tag
|
||||
serverInfo.Note = rs.Note
|
||||
serverInfo.HideForGuest = rs.HideForGuest == "on"
|
||||
// Generate a random secret
|
||||
serverInfo.Secret, err = utils.GenerateRandomString(18)
|
||||
if err != nil {
|
||||
return &ServerRegisterResponse{
|
||||
CommonResponse: CommonResponse{
|
||||
Code: 500,
|
||||
Message: "Generate secret failed: " + err.Error(),
|
||||
},
|
||||
Secret: "",
|
||||
}
|
||||
}
|
||||
// Attempt to save serverInfo in the database
|
||||
err = DB.Create(&serverInfo).Error
|
||||
if err != nil {
|
||||
return &ServerRegisterResponse{
|
||||
CommonResponse: CommonResponse{
|
||||
Code: 500,
|
||||
Message: "Database error: " + err.Error(),
|
||||
},
|
||||
Secret: "",
|
||||
}
|
||||
}
|
||||
|
||||
serverInfo.Host = &model.Host{}
|
||||
serverInfo.State = &model.HostState{}
|
||||
serverInfo.TaskCloseLock = new(sync.Mutex)
|
||||
ServerLock.Lock()
|
||||
SecretToID[serverInfo.Secret] = serverInfo.ID
|
||||
ServerList[serverInfo.ID] = &serverInfo
|
||||
ServerTagToIDList[serverInfo.Tag] = append(ServerTagToIDList[serverInfo.Tag], serverInfo.ID)
|
||||
ServerLock.Unlock()
|
||||
ReSortServer()
|
||||
// Successful response
|
||||
return &ServerRegisterResponse{
|
||||
CommonResponse: CommonResponse{
|
||||
Code: 200,
|
||||
Message: "Server created successfully",
|
||||
},
|
||||
Secret: serverInfo.Secret,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *MonitorAPIService) GetMonitorHistories(query map[string]any) *MonitorInfoResponse {
|
||||
var (
|
||||
|
Loading…
Reference in New Issue
Block a user