package tcping import ( "fmt" "github.com/spf13/cobra" "os" "os/signal" "strconv" "syscall" "time" ) var ( counter int timeout string interval string sigs chan os.Signal httpMode bool httpHead bool httpPost bool httpUA string permanent bool dnsServer []string ) var Cmd = &cobra.Command{ Use: "tcping", Short: "tcp/http ping 工具", Long: "使用进行Tcp或Http协议进行ping探测", Example: ` 1. dns over tcp > tcping google.com 2. dns over tcp with custom port > tcping google.com 443 3. dns over http > tcping -H google.com 4. dns with URI schema > tcping http://hui.lu `, Run: func(cmd *cobra.Command, args []string) { sigs = make(chan os.Signal, 1) signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) if permanent && counter != 4 { fmt.Println("不能同时指定-t与-c,请检查您的输入") return } if permanent { counter = 0 } if len(args) != 2 && len(args) != 1 { cmd.Usage() return } host := args[0] var ( err error port int schema string ) if len(args) == 2 { port, err = strconv.Atoi(args[1]) if err != nil { fmt.Println("端口应当为Int类型") cmd.Usage() return } schema = TCP.String() } else { var matched bool schema, host, port, matched = CheckURI(host) if !matched { fmt.Println("不是一个合法的URI") cmd.Usage() return } } var timeoutDuration time.Duration if res, err := strconv.Atoi(timeout); err == nil { timeoutDuration = time.Duration(res) * time.Millisecond } else { timeoutDuration, err = time.ParseDuration(timeout) if err != nil { fmt.Println("parse timeout failed", err) cmd.Usage() return } } var intervalDuration time.Duration if res, err := strconv.Atoi(interval); err == nil { intervalDuration = time.Duration(res) * time.Millisecond } else { intervalDuration, err = time.ParseDuration(interval) if err != nil { fmt.Println("parse interval failed", err) cmd.Usage() return } } var protocol Protocol if httpMode { protocol = HTTP } else { protocol, err = NewProtocol(schema) if err != nil { fmt.Println(err) cmd.Usage() return } } if len(dnsServer) != 0 { UseCustomeDNS(dnsServer) } parseHost := FormatIP(host) target := Target{ Timeout: timeoutDuration, Interval: intervalDuration, Host: parseHost, Port: port, Counter: counter, Protocol: protocol, } var pinger Pinger switch protocol { case TCP: pinger = NewTCPing() case HTTP, HTTPS: var httpMethod string switch { case httpHead: httpMethod = "HEAD" case httpPost: httpMethod = "POST" default: httpMethod = "GET" } pinger = NewHTTPing(httpMethod) default: fmt.Printf("schema: %s not support\n", schema) cmd.Usage() return } pinger.SetTarget(&target) pingerDone := pinger.Start() select { case <-pingerDone: break case <-sigs: break } fmt.Println(pinger.Result()) }, } func init() { Cmd.Flags().IntVarP(&counter, "counter", "c", 4, "ping的次数") Cmd.Flags().BoolVarP(&permanent, "permanent", "t", false, "一直ping下去") Cmd.Flags().StringVarP(&timeout, "timeout", "T", "1s", `超时时间, 单位为 "ns", "us" (or "µs"), "ms", "s", "m", "h"`) Cmd.Flags().StringVarP(&interval, "interval", "I", "1s", `ping间隔时间, 单位为 "ns", "us" (or "µs"), "ms", "s", "m", "h"`) Cmd.Flags().BoolVarP(&httpMode, "http", "H", false, `Use "HTTP" mode. will ignore URI Schema, force to http`) Cmd.Flags().BoolVar(&httpHead, "head", false, `使用http head模式`) Cmd.Flags().BoolVar(&httpPost, "post", false, `使用http post模式`) Cmd.Flags().StringVar(&httpUA, "user-agent", "victorique/tcping", `自定义UA`) Cmd.Flags().StringArrayVarP(&dnsServer, "dns-server", "D", nil, `使用自定义DNS服务器`) }