diff --git a/config.go b/config.go index 10e50a6..22b3932 100644 --- a/config.go +++ b/config.go @@ -44,7 +44,7 @@ func parseConfig() *Config { flag.StringSliceUniqVar(&conf.Forwards, "forward", nil, "forward url, format: SCHEME://[USER|METHOD:PASSWORD@][HOST]:PORT?PARAMS[,SCHEME://[USER|METHOD:PASSWORD@][HOST]:PORT?PARAMS]") flag.StringVar(&conf.Strategy.Strategy, "strategy", "rr", "forward strategy, default: rr") - flag.StringVar(&conf.Strategy.Check, "check", "http://www.msftconnecttest.com/connecttest.txt#expect=200", "check=disable: disable health check\ncheck=tcp[://HOST:PORT]: tcp port connect check\ncheck=http://HOST[:PORT][/URI][#expect=STRING_IN_RESP_LINE]") + flag.StringVar(&conf.Strategy.Check, "check", "http://www.msftconnecttest.com/connecttest.txt#expect=200", "check=tcp[://HOST:PORT]: tcp port connect check\ncheck=http://HOST[:PORT][/URI][#expect=STRING_IN_RESP_LINE]\ncheck=file://SCRIPT_PATH: run a check script, healthy when exitcode=0, environment variables: FORWARDER_ADDR\ncheck=disable: disable health check") flag.IntVar(&conf.Strategy.CheckInterval, "checkinterval", 30, "fowarder check interval(seconds)") flag.IntVar(&conf.Strategy.CheckTimeout, "checktimeout", 10, "fowarder check timeout(seconds)") flag.IntVar(&conf.Strategy.CheckTolerance, "checktolerance", 0, "fowarder check tolerance(ms), switch only when new_latency < old_latency - tolerance, only used in lha mode") diff --git a/go.mod b/go.mod index ef9f245..0609f9b 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/xtaci/kcp-go/v5 v5.6.1 golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 // indirect - golang.org/x/tools v0.0.0-20201120032337-6d151481565c // indirect + golang.org/x/tools v0.0.0-20201120155355-20be4ac4bd6e // indirect gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect ) diff --git a/go.sum b/go.sum index bda791f..a456fa6 100644 --- a/go.sum +++ b/go.sum @@ -141,8 +141,8 @@ golang.org/x/tools v0.0.0-20200425043458-8463f397d07c/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200808161706-5bf02b21f123/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20201105001634-bc3cf281b174 h1:0rx0F4EjJNbxTuzWe0KjKcIzs+3VEb/Mrs/d1ciNz1c= golang.org/x/tools v0.0.0-20201105001634-bc3cf281b174/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201120032337-6d151481565c h1:IXtuZap6vTKIQ3jemmcwf2gY4BT+lwfZHBYwxMGe5/k= -golang.org/x/tools v0.0.0-20201120032337-6d151481565c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201120155355-20be4ac4bd6e h1:t96dS3DO8DGjawSLJL/HIdz8CycAd2v07XxqB3UPTi0= +golang.org/x/tools v0.0.0-20201120155355-20be4ac4bd6e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/rule/check.go b/rule/check.go index bc9737d..77e7ca7 100644 --- a/rule/check.go +++ b/rule/check.go @@ -3,6 +3,8 @@ package rule import ( "bytes" "io" + "os" + "os/exec" "time" "github.com/nadoo/glider/log" @@ -115,3 +117,27 @@ func (c *httpChecker) Check(fwdr *Forwarder) bool { return true } + +type fileChecker struct { + path string +} + +func newFileChecker(path string) *fileChecker { + return &fileChecker{path} +} + +func (c *fileChecker) Check(fwdr *Forwarder) bool { + cmd := exec.Command(c.path) + cmd.Stdout = os.Stdout + cmd.Env = os.Environ() + cmd.Env = append(cmd.Env, "FORWARDER_ADDR="+fwdr.Addr()) + + err := cmd.Run() + if err != nil { + log.F("[check] file:%s, %s(%d), FAILED. err: %s", c.path, fwdr.Addr(), fwdr.Priority(), err) + return false + } + + log.F("[check] file:%s(%d), SUCCESS.", fwdr.Addr(), fwdr.Priority()) + return true +} diff --git a/rule/config.go b/rule/config.go index ded066a..aa844f7 100644 --- a/rule/config.go +++ b/rule/config.go @@ -44,7 +44,7 @@ func NewConfFromFile(ruleFile string) (*Config, error) { f := conflag.NewFromFile("rule", ruleFile) f.StringSliceUniqVar(&p.Forward, "forward", nil, "forward url, format: SCHEME://[USER|METHOD:PASSWORD@][HOST]:PORT?PARAMS[,SCHEME://[USER|METHOD:PASSWORD@][HOST]:PORT?PARAMS]") f.StringVar(&p.Strategy.Strategy, "strategy", "rr", "forward strategy, default: rr") - f.StringVar(&p.Strategy.Check, "check", "http://www.msftconnecttest.com/connecttest.txt#expect=200", "check=disable: disable health check\ncheck=tcp[://HOST:PORT]: tcp port connect check\ncheck=http://HOST[:PORT][/URI][#expect=STRING_IN_RESP_LINE]") + f.StringVar(&p.Strategy.Check, "check", "http://www.msftconnecttest.com/connecttest.txt#expect=200", "check=tcp[://HOST:PORT]: tcp port connect check\ncheck=http://HOST[:PORT][/URI][#expect=STRING_IN_RESP_LINE]\ncheck=file://SCRIPT_PATH: run a check script, healthy when exitcode=0, environment variables: FORWARDER_ADDR\ncheck=disable: disable health check") f.IntVar(&p.Strategy.CheckInterval, "checkinterval", 30, "fowarder check interval(seconds)") f.IntVar(&p.Strategy.CheckTimeout, "checktimeout", 10, "fowarder check timeout(seconds)") f.IntVar(&p.Strategy.CheckTolerance, "checktolerance", 0, "fowarder check tolerance(ms), switch only when new_latency < old_latency - tolerance, only used in lha mode") diff --git a/rule/group.go b/rule/group.go index b72163c..3b40b5b 100644 --- a/rule/group.go +++ b/rule/group.go @@ -209,6 +209,8 @@ func (p *FwdrGroup) Check() { expect = ex } checker = newHttpChecker(addr, u.RequestURI(), expect, timeout) + case "file": + checker = newFileChecker(u.Host + u.Path) default: p.config.MaxFailures = 0 log.F("[group] invalid check config `%s`, disable health checking", p.config.Check)