1
1
package main
2
2
3
3
import (
4
+ "crypto/sha256"
4
5
"flag"
5
6
"fmt"
7
+ "io"
6
8
"io/ioutil"
7
9
"os"
8
10
"os/exec"
9
11
"path/filepath"
12
+ "strconv"
10
13
"sync"
11
- "syscall"
12
14
"text/template"
15
+ "time"
13
16
14
17
"gopkg.in/yaml.v2"
15
18
16
19
"github.com/caicloud/logging-admin/pkg/util/graceful"
17
20
"github.com/caicloud/logging-admin/pkg/util/osutil"
18
21
19
22
"github.com/caicloud/nirvana/log"
20
- "gopkg.in/fsnotify/fsnotify.v1"
23
+ )
24
+
25
+ const (
26
+ HeatlthCheckInterval = "HEATLTH_CHECK_INTERVAL"
27
+ ConfigCheckInterval = "CONFIG_CHECK_INTERVAL"
21
28
)
22
29
23
30
var (
24
31
filebeatExecutablePath = osutil .Getenv ("FB_EXE_PATH" , "filebeat" )
25
32
srcConfigPath = osutil .Getenv ("SRC_CONFIG_PATH" , "/config/filebeat-output.yml" )
26
33
dstConfigPath = osutil .Getenv ("DST_CONFIG_PATH" , "/etc/filebeat/filebeat.yml" )
34
+ heatlthCheckInterval = int64 (10 )
35
+ configCheckInterval = int64 (600 )
27
36
)
28
37
29
- // When configmap being created for the first time, following events received:
30
- // INFO 1206-09:38:39.496+00 main.go:41 | Event: "/config/..2018_12_06_09_38_39.944532540": CREATE
31
- // INFO 1206-09:38:39.496+00 main.go:41 | Event: "/config/..2018_12_06_09_38_39.944532540": CHMOD
32
- // INFO 1206-09:38:39.497+00 main.go:41 | Event: "/config/filebeat-output.yml": CREATE
33
- // INFO 1206-09:38:39.497+00 main.go:41 | Event: "/config/..data_tmp": RENAME
34
- // INFO 1206-09:38:39.497+00 main.go:41 | Event: "/config/..data": CREATE
35
- // INFO 1206-09:38:39.497+00 main.go:41 | Event: "/config/..2018_12_06_09_37_32.878326343": REMOVE
36
- // When configmap being modified, following events received:
37
- // INFO 1206-09:42:56.488+00 main.go:41 | Event: "/config/..2018_12_06_09_42_56.160544363": CREATE
38
- // INFO 1206-09:42:56.488+00 main.go:41 | Event: "/config/..2018_12_06_09_42_56.160544363": CHMOD
39
- // INFO 1206-09:42:56.488+00 main.go:41 | Event: "/config/..data_tmp": RENAME
40
- // INFO 1206-09:42:56.488+00 main.go:41 | Event: "/config/..data": CREATE
41
- // INFO 1206-09:42:56.488+00 main.go:41 | Event: "/config/..2018_12_06_09_38_39.944532540": REMOVE
42
- func watchFileChange (path string , reloadCh chan <- struct {}) error {
43
- w , err := fsnotify .NewWatcher ()
38
+ func init () {
39
+ sec , err := strconv .ParseInt (osutil .Getenv (HeatlthCheckInterval ,
40
+ strconv .FormatInt (heatlthCheckInterval , 10 )), 10 , 64 )
41
+ if err != nil || sec < 0 {
42
+ log .Warningf ("%s is Invalid, use default value %d" , HeatlthCheckInterval , heatlthCheckInterval )
43
+ } else {
44
+ heatlthCheckInterval = sec
45
+ }
46
+
47
+ sec , err = strconv .ParseInt (osutil .Getenv (ConfigCheckInterval ,
48
+ strconv .FormatInt (configCheckInterval , 10 )), 10 , 64 )
49
+ if err != nil || sec < 0 {
50
+ log .Warningf ("%s is Invalid, use default value %d" , ConfigCheckInterval , configCheckInterval )
51
+ } else {
52
+ configCheckInterval = sec
53
+ }
54
+ }
55
+
56
+ func hashFile (path string ) (string , error ) {
57
+ f , err := os .Open (path )
44
58
if err != nil {
45
- return err
59
+ return "" , err
46
60
}
47
- if err := w .Add (path ); err != nil {
48
- return err
61
+ defer f .Close ()
62
+
63
+ h := sha256 .New ()
64
+ if _ , err := io .Copy (h , f ); err != nil {
65
+ return "" , err
49
66
}
50
67
51
- for {
52
- select {
53
- case ev := <- w .Events :
54
- log .Infoln ("Event:" , ev .String ())
55
- if ev .Op & fsnotify .Create == fsnotify .Create {
56
- if filepath .Base (ev .Name ) == "..data" {
57
- log .Infoln ("Configmap updated" )
58
- reloadCh <- struct {}{}
59
- }
60
- }
61
- case err := <- w .Errors :
62
- log .Errorf ("Watch error: %v" , err )
68
+ return string (h .Sum (nil )), nil
69
+ }
70
+
71
+ func newFileChecker (path string , notify func ()) func () {
72
+ var (
73
+ curHash string
74
+ mtx sync.Mutex
75
+ err error
76
+ )
77
+
78
+ curHash , err = hashFile (path )
79
+ if err != nil {
80
+ log .Warningln (err )
81
+ }
82
+
83
+ return func () {
84
+ mtx .Lock ()
85
+ defer mtx .Unlock ()
86
+
87
+ h , err := hashFile (path )
88
+ if err != nil {
89
+ log .Warningln (err )
90
+ return
91
+ }
92
+
93
+ if curHash != h {
94
+ log .Infof ("file need reload, old: %x, new: %x" , curHash , h )
95
+ curHash = h
96
+ notify ()
63
97
}
64
98
}
65
99
}
66
100
101
+ func watchFileChange (path string , reloadCh chan <- struct {}) {
102
+ checker := newFileChecker (path , func () { reloadCh <- struct {}{} })
103
+
104
+ //watch CM
105
+ go watchConfigMapUpdate (filepath .Dir (path ), checker )
106
+
107
+ //定时监测
108
+ go func (checkFile func ()) {
109
+ check := time .Tick (time .Duration (configCheckInterval ) * time .Second )
110
+ for range check {
111
+ checkFile ()
112
+ }
113
+ }(checker )
114
+ }
115
+
67
116
func run (stopCh <- chan struct {}) error {
68
117
reloadCh := make (chan struct {}, 1 )
69
118
started := false
70
119
cmd := newCmd ()
71
120
72
- go watchFileChange (filepath . Dir ( srcConfigPath ) , reloadCh )
121
+ watchFileChange (srcConfigPath , reloadCh )
73
122
74
123
if err := applyChange (); err == nil {
75
124
reloadCh <- struct {}{}
@@ -78,11 +127,12 @@ func run(stopCh <-chan struct{}) error {
78
127
log .Infoln ("Filebeat will not start until configmap being updated" )
79
128
}
80
129
130
+ check := time .Tick (time .Duration (heatlthCheckInterval ) * time .Second )
81
131
for {
82
132
select {
83
133
case <- stopCh :
84
134
log .Infoln ("Wait filebeat shutdown" )
85
- if err := cmd .Wait (); err != nil {
135
+ if err := cmd .Stop (); err != nil {
86
136
return fmt .Errorf ("filebeat quit with error: %v" , err )
87
137
}
88
138
return nil
@@ -100,11 +150,7 @@ func run(stopCh <-chan struct{}) error {
100
150
log .Infoln ("Filebeat start" )
101
151
started = true
102
152
} else {
103
- log .Infoln ("Send TERM signal" )
104
- if err := cmd .Process .Signal (syscall .SIGTERM ); err != nil {
105
- return fmt .Errorf ("error send signal: %v" , err )
106
- }
107
- if err := cmd .Wait (); err != nil {
153
+ if err := cmd .Stop (); err != nil {
108
154
return fmt .Errorf ("filebeat quit with error: %v" , err )
109
155
}
110
156
log .Infoln ("Filebeat quit" )
@@ -114,6 +160,13 @@ func run(stopCh <-chan struct{}) error {
114
160
return fmt .Errorf ("error run filebeat: %v" , err )
115
161
}
116
162
}
163
+ case <- check :
164
+ if started {
165
+ if cmd != nil && cmd .Exited () {
166
+ log .Fatalln ("Filebeat has unexpectedly exited" )
167
+ os .Exit (1 )
168
+ }
169
+ }
117
170
}
118
171
}
119
172
}
@@ -158,12 +211,13 @@ var (
158
211
fbArgs []string
159
212
)
160
213
161
- func newCmd () * exec. Cmd {
214
+ func newCmd () * AsyncCmd {
162
215
log .Infof ("Will run filebeat with command: %v %v" , filebeatExecutablePath , fbArgs )
163
216
cmd := exec .Command (filebeatExecutablePath , fbArgs ... )
164
217
cmd .Stderr = os .Stderr
165
218
cmd .Stdout = os .Stdout
166
- return cmd
219
+
220
+ return WrapCmd (cmd )
167
221
}
168
222
169
223
func main () {
0 commit comments