|
|
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服务器`)
|
|
|
|
|
|
}
|