forked from bytedance/Elkeid
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
151 lines (145 loc) · 4.41 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package main
import (
"net"
"net/http"
_ "net/http/pprof"
"os"
"os/signal"
"path/filepath"
"runtime"
"runtime/debug"
"strconv"
"sync"
"syscall"
"time"
"github.com/bytedance/Elkeid/agent/agent"
"github.com/bytedance/Elkeid/agent/heartbeat"
"github.com/bytedance/Elkeid/agent/host"
"github.com/bytedance/Elkeid/agent/log"
"github.com/bytedance/Elkeid/agent/plugin"
"github.com/bytedance/Elkeid/agent/transport"
"github.com/nightlyone/lockfile"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"gopkg.in/natefinch/lumberjack.v2"
)
const (
pidFile = "/var/run/elkeid-agent.pid"
)
func init() {
// 手动设置,防止采用默认值导致GC时间大幅度上升
runtime.GOMAXPROCS(8)
}
func main() {
// 初始化logger
grpcConfig := zap.NewProductionEncoderConfig()
grpcConfig.CallerKey = "source"
grpcConfig.TimeKey = "timestamp"
grpcConfig.EncodeTime = func(t time.Time, z zapcore.PrimitiveArrayEncoder) {
z.AppendString(strconv.FormatInt(t.Unix(), 10))
}
grpcEncoder := zapcore.NewJSONEncoder(grpcConfig)
grpcWriter := &log.GrpcWriter{}
fileEncoder := zapcore.NewConsoleEncoder(zap.NewDevelopmentEncoderConfig())
fileWriter := zapcore.AddSync(&lumberjack.Logger{
Filename: "log/" + agent.Product + ".log",
MaxSize: 1, // megabytes
MaxBackups: 10,
MaxAge: 10, //days
Compress: true, // disabled by default
})
var core zapcore.Core
if os.Getenv("RUNTIME_MODE") == "DEBUG" {
core = zapcore.NewTee(zapcore.NewCore(grpcEncoder, grpcWriter, zap.ErrorLevel), zapcore.NewCore(fileEncoder, fileWriter, zap.DebugLevel))
} else {
core = zapcore.NewTee(
zapcore.NewSamplerWithOptions(
zapcore.NewCore(grpcEncoder, grpcWriter, zap.ErrorLevel), time.Second, 4, 1),
zapcore.NewSamplerWithOptions(
zapcore.NewCore(fileEncoder, fileWriter, zap.InfoLevel), time.Second, 4, 1),
)
}
logger := zap.New(core, zap.AddCaller())
defer logger.Sync()
zap.ReplaceGlobals(logger)
if os.Getenv("service_type") == "sysvinit" {
l, _ := lockfile.New(pidFile)
if err := l.TryLock(); err != nil {
zap.S().Error(err)
return
}
}
zap.S().Info("++++++++++++++++++++++++++++++startup++++++++++++++++++++++++++++++")
zap.S().Info("product:", agent.Product)
zap.S().Info("version:", agent.Version)
zap.S().Info("id:", agent.ID)
zap.S().Info("hostname:", host.Name.Load())
zap.S().Infof("intranet_ipv4:%v", host.PrivateIPv4.Load())
zap.S().Infof("intranet_ipv6:%v", host.PrivateIPv6.Load())
zap.S().Infof("extranet_ipv4:%v", host.PublicIPv4.Load())
zap.S().Infof("extranet_ipv6:%v", host.PublicIPv6.Load())
zap.S().Info("platform:", host.Platform)
zap.S().Info("platform_family:", host.PlatformFamily)
zap.S().Info("platform_version:", host.PlatformVersion)
zap.S().Info("kernel_version:", host.KernelVersion)
zap.S().Info("arch:", host.Arch)
// 同步task,但是注意:不要把wg传递到子gorountine中,每个task应该要保证退出前等待并关闭所有子gorountine
wg := &sync.WaitGroup{}
logger.Info("++++++++++++++++++++++++++++++running++++++++++++++++++++++++++++++")
wg.Add(3)
go heartbeat.Startup(agent.Context, wg)
go plugin.Startup(agent.Context, wg)
go func() {
transport.Startup(agent.Context, wg)
agent.Cancel()
}()
go func() {
var l net.Listener
var mu = &sync.Mutex{}
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGTERM, syscall.SIGUSR1, syscall.SIGUSR2)
for {
switch <-sigs {
case syscall.SIGTERM:
zap.S().Error("receive signal: ", syscall.SIGTERM.String())
zap.S().Info("wait for 5 secs to exit")
<-time.After(time.Second * 5)
agent.Cancel()
case syscall.SIGUSR1:
mu.Lock()
if l == nil {
zap.S().Info("opening pprof service...")
var err error
l, err = net.Listen("tcp", "127.0.0.1:")
mu.Unlock()
if err != nil {
zap.S().Error("open pprof port failed: ", err.Error())
} else {
zap.S().Info("listening pprof on: ", l.Addr())
go func() {
http.Serve(l, nil)
zap.S().Info("pprof service stopped")
mu.Lock()
if l != nil {
l.Close()
l = nil
}
mu.Unlock()
}()
}
} else {
zap.S().Info("stopping pprof service...")
l.Close()
l = nil
mu.Unlock()
}
case syscall.SIGUSR2:
zap.S().Info("freeing os memory...")
debug.FreeOSMemory()
}
}
}()
wg.Wait()
os.RemoveAll(filepath.Join(agent.WorkingDirectory, "tmp"))
logger.Info("++++++++++++++++++++++++++++++exit++++++++++++++++++++++++++++++")
}