nezha/cmd/agent/main.go

187 lines
4.2 KiB
Go
Raw Normal View History

2019-12-05 09:36:58 -05:00
package main
import (
"context"
2019-12-07 05:14:40 -05:00
"fmt"
2019-12-09 03:02:49 -05:00
"io"
2019-12-05 09:36:58 -05:00
"log"
2019-12-08 10:49:38 -05:00
"os"
2019-12-07 05:14:40 -05:00
"time"
2019-12-05 09:36:58 -05:00
2020-11-29 11:07:27 -05:00
"github.com/blang/semver"
2020-12-12 12:31:22 -05:00
"github.com/p14yground/go-github-selfupdate/selfupdate"
2019-12-08 10:49:38 -05:00
"github.com/spf13/cobra"
2019-12-05 09:36:58 -05:00
"google.golang.org/grpc"
2019-12-05 10:42:20 -05:00
2020-11-10 21:07:45 -05:00
"github.com/naiba/nezha/model"
pb "github.com/naiba/nezha/proto"
"github.com/naiba/nezha/service/dao"
"github.com/naiba/nezha/service/monitor"
"github.com/naiba/nezha/service/rpc"
2019-12-05 09:36:58 -05:00
)
2019-12-08 10:49:38 -05:00
var (
2020-11-29 11:07:27 -05:00
clientID string
server string
clientSecret string
debug bool
2020-12-18 23:43:03 -05:00
version string
2020-11-29 11:07:27 -05:00
2019-12-08 10:49:38 -05:00
rootCmd = &cobra.Command{
Use: "nezha-agent",
Short: "「哪吒面板」监控、备份、站点管理一站式服务",
Long: `哪吒面板
================================
监控备份站点管理一站式服务
啦啦啦啦啦啦我是 mjj 小行家`,
2020-11-29 11:07:27 -05:00
Run: run,
Version: version,
2019-12-08 10:49:38 -05:00
}
)
2020-11-30 01:24:00 -05:00
var (
reporting bool
client pb.NezhaServiceClient
ctx = context.Background()
delayWhenError = time.Second * 10
updateCh = make(chan struct{}, 0)
)
2020-11-29 11:07:27 -05:00
func doSelfUpdate() {
defer func() {
2020-11-30 00:49:31 -05:00
time.Sleep(time.Minute * 20)
2020-11-29 11:07:27 -05:00
updateCh <- struct{}{}
}()
v := semver.MustParse(version)
2020-11-30 00:22:58 -05:00
log.Println("check update", v)
2020-11-29 11:07:27 -05:00
latest, err := selfupdate.UpdateSelf(v, "naiba/nezha")
if err != nil {
log.Println("Binary update failed:", err)
return
}
if latest.Version.Equals(v) {
// latest version is the same as current version. It means current binary is up to date.
log.Println("Current binary is the latest version", version)
} else {
log.Println("Successfully updated to version", latest.Version)
2020-12-20 00:03:03 -05:00
os.Exit(1)
2020-11-29 11:07:27 -05:00
}
}
2019-12-05 09:36:58 -05:00
func main() {
2020-11-29 23:45:51 -05:00
// 来自于 GoReleaser 的版本号
dao.Version = version
2019-12-09 10:45:23 -05:00
rootCmd.PersistentFlags().StringVarP(&server, "server", "s", "localhost:5555", "客户端ID")
2019-12-09 03:02:49 -05:00
rootCmd.PersistentFlags().StringVarP(&clientID, "id", "i", "", "客户端ID")
rootCmd.PersistentFlags().StringVarP(&clientSecret, "secret", "p", "", "客户端Secret")
rootCmd.PersistentFlags().BoolVarP(&debug, "debug", "d", false, "开启Debug")
2019-12-08 10:49:38 -05:00
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
func run(cmd *cobra.Command, args []string) {
2019-12-09 03:02:49 -05:00
dao.Conf = &model.Config{
Debug: debug,
2019-12-05 09:36:58 -05:00
}
2019-12-09 03:02:49 -05:00
auth := rpc.AuthHandler{
ClientID: clientID,
ClientSecret: clientSecret,
2019-12-05 09:36:58 -05:00
}
2019-12-10 04:57:57 -05:00
// 上报服务器信息
go reportState()
if version != "" {
go func() {
for range updateCh {
go doSelfUpdate()
}
}()
updateCh <- struct{}{}
}
2020-11-29 11:07:27 -05:00
2019-12-10 04:57:57 -05:00
var err error
var conn *grpc.ClientConn
var hc pb.NezhaService_HeartbeatClient
2020-02-09 09:04:59 -05:00
retry := func() {
log.Println("Error to close connection ...")
if conn != nil {
conn.Close()
}
time.Sleep(delayWhenError)
log.Println("Try to reconnect ...")
}
2019-12-09 05:14:31 -05:00
for {
2019-12-09 10:45:23 -05:00
conn, err = grpc.Dial(server, grpc.WithInsecure(), grpc.WithPerRPCCredentials(&auth))
2019-12-09 03:02:49 -05:00
if err != nil {
log.Printf("grpc.Dial err: %v", err)
2019-12-09 05:14:31 -05:00
retry()
2019-12-09 03:02:49 -05:00
continue
}
client = pb.NewNezhaServiceClient(conn)
// 第一步注册
2019-12-09 05:14:31 -05:00
_, err = client.Register(ctx, monitor.GetHost().PB())
if err != nil {
log.Printf("client.Register err: %v", err)
retry()
continue
}
2019-12-10 04:57:57 -05:00
// 心跳接收控制命令
2019-12-09 03:02:49 -05:00
hc, err = client.Heartbeat(ctx, &pb.Beat{
Timestamp: fmt.Sprintf("%v", time.Now()),
})
if err != nil {
2019-12-09 05:14:31 -05:00
log.Printf("client.Heartbeat err: %v", err)
retry()
2019-12-09 03:02:49 -05:00
continue
}
err = receiveCommand(hc)
log.Printf("receiveCommand exit to main: %v", err)
2019-12-09 05:14:31 -05:00
retry()
2019-12-07 05:14:40 -05:00
}
2019-12-09 03:02:49 -05:00
}
2019-12-07 05:14:40 -05:00
2019-12-09 03:02:49 -05:00
func receiveCommand(hc pb.NezhaService_HeartbeatClient) error {
var err error
var action *pb.Command
defer log.Printf("receiveCommand exit %v %v => %v", time.Now(), action, err)
for {
action, err = hc.Recv()
if err == io.EOF {
return nil
}
if err != nil {
return err
}
switch action.GetType() {
default:
log.Printf("Unknown action: %v", action)
}
2019-12-07 05:14:40 -05:00
}
2019-12-09 03:02:49 -05:00
}
2019-12-05 09:36:58 -05:00
2019-12-09 03:02:49 -05:00
func reportState() {
var lastReportHostInfo time.Time
2019-12-09 03:02:49 -05:00
var err error
defer log.Printf("reportState exit %v => %v", time.Now(), err)
2019-12-09 03:02:49 -05:00
for {
if client != nil {
2019-12-09 10:45:23 -05:00
monitor.TrackNetworkSpeed()
2020-12-19 23:18:27 -05:00
_, err = client.ReportState(ctx, monitor.GetState(dao.ReportDelay).PB())
2019-12-09 05:14:31 -05:00
if err != nil {
log.Printf("reportState error %v", err)
time.Sleep(delayWhenError)
}
if lastReportHostInfo.Before(time.Now().Add(-10 * time.Minute)) {
lastReportHostInfo = time.Now()
client.Register(ctx, monitor.GetHost().PB())
}
2019-12-05 10:42:20 -05:00
}
}
2019-12-05 09:36:58 -05:00
}