forked from ochinchina/supervisord
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcontent_checker.go
149 lines (131 loc) · 2.75 KB
/
content_checker.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
package main
import (
"fmt"
"net"
"net/http"
"os/exec"
"strings"
"time"
)
type ContentChecker interface {
Check() bool
}
type BaseChecker struct {
data string
includes []string
//timeout in second
timeoutTime time.Time
notifyChannel chan string
}
func NewBaseChecker(includes []string, timeout int) *BaseChecker {
return &BaseChecker{data: "",
includes: includes,
timeoutTime: time.Now().Add(time.Duration(timeout) * time.Second),
notifyChannel: make(chan string, 1)}
}
func (bc *BaseChecker) Write(b []byte) (int, error) {
bc.notifyChannel <- string(b)
return len(b), nil
}
func (bc *BaseChecker) isReady() bool {
find_all := true
for _, include := range bc.includes {
if strings.Index(bc.data, include) == -1 {
find_all = false
break
}
}
return find_all
}
func (bc *BaseChecker) Check() bool {
d := bc.timeoutTime.Sub(time.Now())
if d < 0 {
return false
}
timeoutSignal := time.After(d)
for {
select {
case data := <-bc.notifyChannel:
bc.data = bc.data + data
if bc.isReady() {
return true
}
case <-timeoutSignal:
return false
}
}
}
type ScriptChecker struct {
args []string
}
func NewScriptChecker(args []string) *ScriptChecker {
return &ScriptChecker{args: args}
}
func (sc *ScriptChecker) Check() bool {
cmd := exec.Command(sc.args[0])
if len(sc.args) > 1 {
cmd.Args = sc.args
}
err := cmd.Run()
return err == nil && cmd.ProcessState != nil && cmd.ProcessState.Success()
}
type TcpChecker struct {
host string
port int
conn net.Conn
baseChecker *BaseChecker
}
func NewTcpChecker(host string, port int, includes []string, timeout int) *TcpChecker {
checker := &TcpChecker{host: host,
port: port,
baseChecker: NewBaseChecker(includes, timeout)}
checker.start()
return checker
}
func (tc *TcpChecker) start() {
go func() {
b := make([]byte, 1024)
var err error = nil
for {
tc.conn, err = net.Dial("tcp", fmt.Sprintf("%s:%d", tc.host, tc.port))
if err == nil || tc.baseChecker.timeoutTime.Before(time.Now()) {
break
}
}
if err == nil {
for {
n, err := tc.conn.Read(b)
if err != nil {
break
}
tc.baseChecker.Write(b[0:n])
}
}
}()
}
func (tc *TcpChecker) Check() bool {
ret := tc.baseChecker.Check()
if tc.conn != nil {
tc.conn.Close()
}
return ret
}
type HttpChecker struct {
url string
timeoutTime time.Time
}
func NewHttpChecker(url string, timeout int) *HttpChecker {
return &HttpChecker{url: url,
timeoutTime: time.Now().Add(time.Duration(timeout) * time.Second)}
}
func (hc *HttpChecker) Check() bool {
for {
if hc.timeoutTime.After(time.Now()) {
resp, err := http.Get(hc.url)
if err == nil {
return resp.StatusCode >= 200 && resp.StatusCode < 300
}
}
}
return false
}