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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
|
package main
import (
"dtail/clients"
"dtail/color"
"dtail/config"
"dtail/logger"
"dtail/omode"
"dtail/server"
"dtail/version"
"flag"
"fmt"
"net/http"
_ "net/http"
_ "net/http/pprof"
"os"
"os/user"
"runtime"
"sync"
"time"
)
// The evil begins here.
func main() {
var cfgFile, modeStr string
var checkHealth bool
var clientServerEnable bool
var connectionsPerCPU int
var debugEnable bool
var discovery string
var displayVersion bool
var files string
var grep, regex string
var maxInitConnections int
var noColor bool
var pprofEnable bool
var queryStr string
var serversStr string
var shutdownAfter int
var silent bool
var sshPort int
var trustAllHosts bool
var userName string
user, err := user.Current()
if err != nil {
panic(err)
}
if user.Uid == "0" {
panic("Not allowed to run as UID 0")
}
if user.Gid == "0" {
panic("Not allowed to run as GID 0")
}
defaultMode := omode.Default()
serverEnable := defaultMode == omode.Server
clientEnable := !serverEnable
// Based on the mode we have different default timeouts
var pingTimeoutS int
switch defaultMode {
case omode.CatClient:
fallthrough
case omode.GrepClient:
pingTimeoutS = 60
case omode.MapClient:
pingTimeoutS = 900
default:
pingTimeoutS = 5
}
flag.BoolVar(&checkHealth, "checkHealth", false, "Only check for server health")
flag.BoolVar(&clientServerEnable, "clientServer", false, "Enable client and server (dev purposes)")
flag.BoolVar(&debugEnable, "debug", false, "Activate debug messages")
flag.BoolVar(&displayVersion, "version", false, "Display version")
flag.BoolVar(&noColor, "noColor", false, "Disable ANSII terminal colors")
flag.BoolVar(&pprofEnable, "pprofEnable", false, "Enable pprof server")
flag.BoolVar(&serverEnable, "server", serverEnable, "Start as a DTail server")
flag.BoolVar(&silent, "silent", false, "Reduce output")
flag.BoolVar(&trustAllHosts, "trustAllHosts", false, "Auto trust all unknown host keys")
flag.IntVar(&connectionsPerCPU, "cpc", 10, "How many connections established per CPU core concurrently")
flag.IntVar(&maxInitConnections, "mic", 20, "Max cpc")
flag.IntVar(&shutdownAfter, "shutdownAfter", 0, "Automatically shutdown after so many seconds")
flag.IntVar(&sshPort, "port", 2222, "SSH server port")
flag.IntVar(&pingTimeoutS, "pingTimeout", 10, "The server ping timeout (0 means disable pings)")
flag.StringVar(&cfgFile, "cfg", "", "Config file path")
flag.StringVar(&discovery, "discovery", "", "Server discovery method")
flag.StringVar(&files, "files", "", "File(s) to read")
flag.StringVar(&grep, "grep", "", "Regular expression (deprecated)")
flag.StringVar(&modeStr, "mode", defaultMode.String(), "Operating mode (tail, grep, cat, map, server)")
flag.StringVar(&queryStr, "query", "", "Map reduce query")
flag.StringVar(®ex, "regex", "", "Regular expression")
flag.StringVar(&serversStr, "servers", "", "Remote servers to connect")
flag.StringVar(&userName, "user", user.Username, "Your system user name")
mode := omode.New(modeStr)
flag.Parse()
config.Init(cfgFile)
color.Init(!noColor)
if displayVersion {
fmt.Println(version.PaintedString())
os.Exit(0)
}
// Figure out how many SSH sessions can be established concurrently.
if connectionsPerCPU*runtime.NumCPU() < maxInitConnections {
maxInitConnections = connectionsPerCPU * runtime.NumCPU()
}
// Figure out in which mode I am? Server or client or both (the latter for dev purposes)?
if serverEnable {
clientEnable = false
}
if clientServerEnable {
clientEnable = true
serverEnable = true
}
// If non-standard port specified, overwrite config
if sshPort != 2222 {
config.Common.SSHPort = sshPort
}
// Figure out the log level.
var logMode logger.LogMode
switch {
case debugEnable:
logMode = logger.DebugMode
case checkHealth:
logMode = logger.NothingMode
case config.Common.TraceEnable:
logMode = logger.TraceMode
case config.Common.DebugEnable:
logMode = logger.DebugMode
case silent:
logMode = logger.SilentMode
default:
logMode = logger.NormalMode
}
// Figure out the log strategy.
var logStrategy logger.LogStrategy
switch config.Common.LogStrategy {
case "daily":
logStrategy = logger.DailyStrategy
case "stdout":
fallthrough
default:
logStrategy = logger.StdoutStrategy
}
logger.Init(serverEnable, logMode, logStrategy)
// Wait group for shutting down logger.
var wg sync.WaitGroup
if serverEnable {
wg.Add(1)
}
if clientEnable {
wg.Add(1)
}
logger.Debug("Common config", config.Common)
logger.Debug("Client config", config.Client)
logger.Debug("Server config", config.Server)
if grep != "" {
logger.Warn("Flag 'grep' is deprecated and may be removed in the future, please use 'regex' instead")
if regex == "" {
regex = grep
}
}
if checkHealth {
healthClient, _ := clients.NewHealthClient(omode.HealthClient)
os.Exit(healthClient.Start(&wg))
}
if shutdownAfter > 0 {
go func() {
defer os.Exit(1)
logger.Info("Enabling auto shutdown timer", shutdownAfter)
time.Sleep(time.Duration(shutdownAfter) * time.Second)
logger.Info("Auto shutdown timer reached, shutting down now")
}()
}
if pprofEnable || config.Common.PProfEnable {
bindAddr := fmt.Sprintf("%s:%d", config.Common.PProfBindAddress, config.Common.PProfPort)
logger.Info("Starting PProf server", bindAddr)
go http.ListenAndServe(bindAddr, nil)
}
if serverEnable {
logger.Info("Launching server", mode, version.String())
sshServer := server.New()
go sshServer.Start(&wg)
}
if clientEnable {
var client clients.Client
var err error
logger.Info("Launching client", mode, version.String())
args := clients.Args{
Mode: mode,
ServersStr: serversStr,
Discovery: discovery,
UserName: userName,
Files: files,
Regex: regex,
TrustAllHosts: trustAllHosts,
MaxInitConnections: maxInitConnections,
PingTimeout: pingTimeoutS,
}
switch mode {
case omode.TailClient:
switch queryStr {
case "":
client, err = clients.NewTailClient(args)
default:
client, err = clients.NewMaprClient(args, queryStr)
}
case omode.GrepClient:
client, err = clients.NewGrepClient(args)
case omode.CatClient:
client, err = clients.NewCatClient(args)
case omode.MapClient:
client, err = clients.NewMaprClient(args, queryStr)
}
if err != nil {
panic(err)
}
go client.Start(&wg)
}
wg.Wait()
logger.Stop()
}
|