-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
101 lines (89 loc) · 2.79 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package main
import (
"fmt"
"github.com/spf13/cobra"
"os"
"time"
)
var (
promMetric bool
interval int
// number topN
number int
ipVersion int
)
var rootCmd = cobra.Command{
Use: "portstat",
Short: "monitor tcp available ports",
Long: "portstat is a tool to monitor tcp available ports",
Example: `
1. portstat
> Connect UsedPorts AvailablePorts
> 192.168.170.132->192.168.170.132:22 2 28229
> 127.0.0.1->127.0.0.1:22 1 28230
2. portstat --prom
> tcp_used_ports_total{connect="192.168.170.132->192.168.170.132:22"} 2
> tcp_available_ports_total{connect="192.168.170.132->192.168.170.132:22"} 28229
> tcp_used_ports_total{connect="127.0.0.1->127.0.0.1:22"} 1
> tcp_available_ports_total{connect="127.0.0.1->127.0.0.1:22"} 28230
`,
Run: func(cmd *cobra.Command, args []string) {
var (
netVersions []int
)
switch ipVersion {
case 4:
netVersions = []int{4}
case 6:
netVersions = []int{6}
default:
netVersions = []int{4, 6}
}
if !promMetric {
fmt.Printf("%-98s %-10s %-5s\n", "Connect", "UsedPorts", "AvailablePorts")
}
for {
topN := number
portCounters := make([]*PortCounter, 0, number*2)
for _, netVersion := range netVersions {
portCountersV, err := GetMiniTcpAvailablePorts(netVersion, topN)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
portCounters = append(portCounters, portCountersV...)
}
if len(portCounters) < topN {
topN = len(portCounters)
}
for i := 0; i < topN; i++ {
minIndex := i
for j := i + 1; j < len(portCounters); j++ {
if portCounters[j].availablePorts < portCounters[minIndex].availablePorts {
minIndex = j
}
}
if minIndex != i {
portCounters[i], portCounters[minIndex] = portCounters[minIndex], portCounters[i]
}
}
if promMetric {
OutputPromMetric(topN, portCounters)
break
}
for i := 0; i < topN; i++ {
fmt.Printf("%-98s %-10d %-5d\n", portCounters[i].connectID, portCounters[i].usedPorts, portCounters[i].availablePorts)
}
time.Sleep(time.Duration(interval) * time.Second)
}
},
}
func init() {
rootCmd.Flags().IntVarP(&interval, "interval", "i", 3, `monitor interval, unit is seconds`)
rootCmd.Flags().IntVarP(&number, "number", "n", 10, `outputs the topN smallest available ports`)
rootCmd.Flags().BoolVarP(&promMetric, "prom", "p", false, "output in prometheus metrics format. only once, interval doesn't work")
rootCmd.Flags().IntVarP(&ipVersion, "ipVersion", "e", 0, `ip version, 4 or 6, default is 0, means both`)
}
func main() {
rootCmd.Execute()
}