使用go写一个监控域名解析变化的命令行工具

最近收到了一个需求, 要统计一个域名在一段时间内, A记录的变化.

由于今年学了go, 所以所有的需求都优先考虑用go实现. 下面是源代码

package main

import (
	"flag"
	"fmt"
	"log"
	"net"
	"os"
	"time"
)

var (
	url            string
	dns            []net.IP
	interval       int
	intervalTime   time.Duration
	changeInterval int
	temp           net.IP
	consolePrint   bool
	dnsSlice       []string
	count          int
	Max            int
	Min            int
	Avg            int
	changeSlice    []int
)

func removeDuplicateElement(slice []string) []string {
	result := make([]string, 0, len(slice))
	temp := map[string]struct{}{}
	for _, item := range slice {
		if _, ok := temp[item]; !ok {
			temp[item] = struct{}{}
			result = append(result, item)
		}
	}
	return result
}

func main() {
	flag.IntVar(&interval, "i", 10, "dns解析地址, 时间间隔, 单位秒")
	flag.StringVar(&url, "d", "", "要解析的url")
	flag.BoolVar(&consolePrint, "p", false, "是否打印在标准输出")
	flag.Parse()
	if url == "" {
		flag.Usage()
		os.Exit(1)
	}
	file, err := os.Create("log.txt")
	if err != nil {
		fmt.Println("没有权限创建日志文件")
		os.Exit(1)
	}
	startTime := time.Now()
	intervalTime = time.Duration(interval) * time.Second
	var lastDns []string = nil
	var ipSlice []string = nil
	log.SetOutput(file)
	for {
		dns, err = net.LookupIP(url)
		if err != nil {
			log.Printf("解析错误: %v", err)
			continue
		}
		now := time.Now().Format("2006-01-02 15:04:05")

		//把解析的ipv4 地址构成数组
		dnsSlice = []string{}
		for _, i := range dns {
			if temp = i.To4(); temp == nil {
				continue
			}
			dnsSlice = append(dnsSlice, i.String())
			ipSlice = append(ipSlice, dnsSlice...)
		}

		if lastDns == nil {
			lastDns = dnsSlice
			if consolePrint {
				fmt.Printf("%s %s的解析是: %v\n", now, url, dnsSlice)
			}
			changeInterval = 0
			log.Printf("%s的解析是: %v\n", url, dnsSlice)
		} else {
			var flag bool = false
			lastDnsLen := len(lastDns)
			dnsSliceLen := len(dnsSlice)
			if lastDnsLen != dnsSliceLen {
				flag = true
			} else {
				tNum := 0
				for _, i := range lastDns {
					for _, j := range dnsSlice {
						if i == j {
							tNum += 1
							break
						}
					}
				}
				if tNum != lastDnsLen {
					flag = true
				}

			}
			if flag {
				ipSlice = append(ipSlice, dnsSlice...)
				ipSlice = removeDuplicateElement(ipSlice)
				count += 1
				if Min == 0 {
					Min = changeInterval
				}
				if changeInterval < Min {
					Min = changeInterval
				}
				if changeInterval > Max {
					Max = changeInterval
				}
				changeSlice = append(changeSlice, changeInterval)
				x := 0
				for _, i := range changeSlice {
					x += i
				}
				Avg = x / len(changeSlice)

				if consolePrint {
					fmt.Printf("%s %s解析发生了变化: %v -> %v, 间隔了%d秒\n", now, url, lastDns, dnsSlice, changeInterval)
					fmt.Printf("%s 当前已经变化过的ip地址有%d个, 列表: %v\n", now, len(ipSlice), ipSlice)
					fmt.Printf("%s 已经监控了%d秒, 解析变化了%d次, 解析变化间隔列表:%v, 解析变化最长间隔%d秒, 最短%d秒, 平均%d秒\n", now, int(time.Since(startTime).Seconds()), count, changeSlice, Max, Min, Avg)
				}

				log.Printf("%s解析发生了变化: %v -> %v, 间隔了%d秒\n", url, lastDns, dnsSlice, changeInterval)
				log.Printf("当前已经变化过的ip地址有%d个, 列表: %v", len(ipSlice), ipSlice)
				log.Printf("已经监控了%d秒, 解析变化了%d次, 解析变化间隔列表:%v, 解析变化最长间隔%d秒, 最短%d秒, 平均%d秒\n", int(time.Since(startTime).Seconds()), count, changeSlice, Max, Min, Avg)
				lastDns = dnsSlice
				changeInterval = 0
			} else {
				if consolePrint {
					fmt.Printf("%s %s的解析是: %v\n", now, url, dnsSlice)
				}
				log.Printf("%s的解析是: %v\n", url, dnsSlice)
			}
		}

		time.Sleep(intervalTime)
		changeInterval += interval
	}
}

由于是go写的,所以可以编译成exe和二进制程序, 可以直接运行在linux和windows上, 非常方便

选项

  • -d 要监控的域名 //必填
  • -i 间隔 //可选, 给定一个数字, 默认10, 单位秒
  • -p 输出在标准输出 // 可选, 默认不输出

基本用法

monitorDNS.exe  -d 域名

运行后默认无限循环, 会在运行目录生成一个log.txt文件, 监控指定域名的A记录解析变化, 会统计A记录变化的频率,以及最大,最小,平均值, 并收集所有出现过的A记录


评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注