package stat import ( "bufio" "fmt" "io" "regexp" "strings" "strconv" "git.loafle.net/overflow/ssh_crawler/util" ) type NetDevStat struct { Iface, RecvByte, RecvPacket, RecvErr, RecvDrop, RecvFifo, RecvFrame, RecvCompressed, RecvMulticast, TransByte, TransPacket, TransErr, TransDrop, TransFifo, TransFrame, TransCompressed, TransMulticast string } func (net *NetDevStat) Command() string { return "cat /proc/net/dev" } func (net *NetDevStat) Read(r io.Reader, keys []string) (interface{}, error) { var ( scanner = bufio.NewScanner(r) procNetDevFieldSep = regexp.MustCompile("[ :] *") stats = []NetDevStat{} ) scanner.Scan() scanner.Scan() parts := strings.Split(scanner.Text(), "|") if len(parts) != 3 { // interface + receive + transmit return nil, fmt.Errorf("invalid header line in net/dev: %s", scanner.Text()) } header := strings.Fields(parts[1]) for scanner.Scan() { line := strings.TrimLeft(scanner.Text(), " ") parts := procNetDevFieldSep.Split(line, -1) if len(parts) != 2*len(header)+1 { return nil, fmt.Errorf("invalid line in net/dev: %s", scanner.Text()) } dev := parts[0][:len(parts[0])] stats = append(stats, NetDevStat{ Iface: dev, RecvByte: parts[1], RecvPacket: parts[2], RecvErr: parts[3], RecvDrop: parts[4], RecvFifo: parts[5], RecvFrame: parts[6], RecvCompressed: parts[7], RecvMulticast: parts[8], TransByte: parts[9], TransPacket: parts[10], TransErr: parts[11], TransDrop: parts[12], TransFifo: parts[13], TransFrame: parts[14], TransCompressed: parts[15], TransMulticast: parts[16], }) } if keys == nil { return &stats, nil } res, err := net.parse(keys, stats) if err != nil { return nil, err } return &res, scanner.Err() } func (net *NetDevStat) parse(keys []string, data []NetDevStat) (map[string]string, error) { resMap := make(map[string]string) for _, key := range keys { t := strings.Split(key, ".") suffix := t[len(t)-1] ext := util.ExtractInBracket(key) idx, _ := strconv.Atoi(ext) var regex = regexp.MustCompile(`\[(.*?)\]`) rk := regex.ReplaceAllString(key, ``) switch suffix { case "iface": resMap[rk] = data[idx].Iface case "recv_byte": resMap[rk] = data[idx].RecvByte case "recv_packet": resMap[rk] = data[idx].RecvPacket case "recv_err": resMap[rk] = data[idx].RecvErr case "recv_drop": resMap[rk] = data[idx].RecvDrop case "recv_fifo": resMap[rk] = data[idx].RecvFifo case "recv_frame": resMap[rk] = data[idx].RecvFrame case "recv_compressed": resMap[rk] = data[idx].RecvCompressed case "recv_multicast": resMap[rk] = data[idx].RecvMulticast case "send_byte": resMap[rk] = data[idx].TransByte case "send_packet": resMap[rk] = data[idx].TransPacket case "send_err": resMap[rk] = data[idx].TransErr case "send_drop": resMap[rk] = data[idx].TransDrop case "send_fifo": resMap[rk] = data[idx].TransFifo case "send_frame": resMap[rk] = data[idx].TransFrame case "send_compressed": resMap[rk] = data[idx].TransCompressed case "send_multicast": resMap[rk] = data[idx].TransMulticast default: } } return resMap, nil }