douying9296
2016-12-21 09:25
浏览 287
已采纳

Golang定期检查端口上打开的TCP连接

I am trying write a small golang program which will periodically execute lsof -i:<port> to check number of open TCP connections at a port. Code looks like below:-

package main

import (
    "fmt"
    "log"
    "os/exec"
    "strings"
    "sync"
    "time"
)

type Lsof struct {
    Command  string
    Pid      string
    User     string
    Fd       string
    Type     string
    Device   string
    SizeOff  string
    Node     string
    Name     string
    TCPState string
}

//var result = make([]*Lsof, 0)
var ports = []int{30001, 30002}

func main() {
    done := make(chan bool)
    ticker := time.NewTicker(5 * time.Millisecond)
    go func() {
        for t := range ticker.C {
            fmt.Println("Tick at", t)
            connectionsCount()
        }
    }()
    <-done
}

func connectionsCount() {
    var wg sync.WaitGroup
    wg.Add(len(ports))
    for _, v := range ports {
        go count(v, wg)
    }
    wg.Wait()
}

func count(port int, wg sync.WaitGroup) {
    defer wg.Done()
    var tcpState = make(map[string]int)
    out, err := exec.Command("/bin/sh", "-c", fmt.Sprintf("lsof -i:%d", port)).Output()
    if err != nil {
        log.Fatal(err)
    }
    //fmt.Println(string(out))
    num := strings.Split(string(out), "
")
    for no, n := range num {
        if no == 0 {
            continue
        }
        n = strings.TrimSpace(n)
        if len(n) <= 0 {
            continue
        }
        i := 0
        temp := strings.Split(n, " ")
        cleanedVal := make([]string, 10)
        for _, v := range temp {
            v = strings.TrimSpace(v)
            if len(v) <= 0 {
                continue
            }
            cleanedVal[i] = v
            i++
        }
        if len(cleanedVal) < 8 {
            //log.Println(n)
            continue
        }
        l := new(Lsof)
        l.Command = cleanedVal[0]
        l.Pid = cleanedVal[1]
        l.User = cleanedVal[2]
        l.Fd = cleanedVal[3]
        l.Type = cleanedVal[4]
        l.Device = cleanedVal[5]
        l.SizeOff = cleanedVal[6]
        l.Node = cleanedVal[7]
        l.Name = cleanedVal[8]
        if l.Node == "TCP" {
            l.TCPState = cleanedVal[9]
            count, ok := tcpState[l.TCPState]
            if !ok {
                tcpState[l.TCPState] = 1
            } else {
                tcpState[l.TCPState] = count + 1
            }
        }
        //fmt.Printf("
%+v", *l)
        //result = append(result, l)
    }
    fmt.Printf("Port=%d ", port)
    for k, v := range tcpState {
        fmt.Printf("{TCP State=%s,Value=%d},", k, v)
    }
    fmt.Println()
}

But on running the program I am seeing the ticker is not ticking periodically.

Tick at 2016-12-21 14:37:03.847694697 +0530 IST
Port=30002 {TCP State=(LISTEN),Value=2},
Port=30001 {TCP State=(LISTEN),Value=2},

Can someone let me know what is going wrong?

  • Go Version - 1.7.3
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

1条回答 默认 最新

  • dpmkif3097 2016-12-21 10:57
    已采纳

    Here the issue is not with the Ticker try

    for t := range ticker.C {
            fmt.Println("Tick at", t)
            // connectionsCount()
        }
    

    You shall not pass WaitGroup by value . Passing wg as pointer will solve the issue. The fuction was waiting for ever

    update it to

        .....
        func connectionsCount() {
            var wg = &sync.WaitGroup{}
            wg.Add(len(ports))
            for _, v := range ports {
                go count(v, wg)
            }
            wg.Wait()
        }
       func count(port int, wg *sync.WaitGroup) {
       .......
    

    Here is the play link

    已采纳该答案
    打赏 评论

相关推荐 更多相似问题