DDR爱好者之家 Design By 杰米

上次发了一个单机版的主机状态监控程序(https://www.52pojie.cn/thread-1680459-1-1.html)
这次来个网络版本的.
linux 和 windows 版本任意搭配.
只需要有一个server端用来接收client发送的消息就可以了。

主机状态监控程序网络版

运行截图.jpg



功能

server 端

启动 server 端, 监听指定端口, 生成状态信息页面.
发现接收到的状态信息中达到阈值,发送钉钉报警通知.

Usage of ./server_linux:  -p string        监听端口,默认8080 (default "8080")root@test:~/run/server# ./server_linux -p 802022/09/06 06:49:39 服务已启动,监听端号 :80

client 端

给server 定时发送主机状态信息.

./client_linux -s "http://127.0.0.1:80"

源码:
server端:
[Golang] 纯文本查看 复制代码
package mainimport (        "flag"        "fmt"        "log"        "net/http"        "os"        "time"        "github.com/spf13/viper"        "github.com/wanghuiyt/ding"        "github.com/gin-gonic/gin")type ClientInfo struct {        HostName   string  `json:"hostname"`        Cpu        float64 `json:"cpu"`        Mem        float64 `json:"mem"`        Disk       float64 `json:"disk"`        ProcessNum uint64  `json:"processnum"`        BootTime   string  `json:"bootTime"`}var htmlCode stringvar serversInfo stringvar num int// 全局配置变量var config *viper.Viperfunc Index(c *gin.Context) {        htmlCode = `<!DOCTYPE html><html><head><meta http-equiv="refresh" content="5" URL="#" /><script type="text/javascript">        window.onload=function(){        var tfrow = document.getElementById('tfhover').rows.length;        var tbRow=[];        for (var i=1;i<tfrow;i++) {                tbRow[i]=document.getElementById('tfhover').rows[i];                tbRow[i].onmouseover = function(){                  this.style.backgroundColor = '#f3f8aa';                };                tbRow[i].onmouseout = function() {                  this.style.backgroundColor = '#ffffff';                };        }};</script><style type="text/css">table.tftable {font-size:12px;color:#333333;border-width: 1px;border-color: #9dcc7a;border-collapse: collapse;}table.tftable th {font-size:12px;background-color:#abd28e;border-width: 1px;padding: 8px;border-style: solid;border-color: #ffffff;text-align:left;}table.tftable tr {background-color:#ffffff;}table.tftable td {font-size:12px;border-width: 1px;padding: 8px;border-style: solid;border-color: #9dcc7a;}</style><title>vsyour 监控中心</title></head><body><table id="tfhover" class="tftable" border="1"><caption><b>有【%v】台服务器在线</b></caption><tr><th>序号</th><th>主机名</th><th>IP地址</th><th>CPU使用率</th><th>内存使用率</th><th>进程数量</th><th>开机时间</th></tr>%v</table></body></html>`        c.Header("Content-Type", "text/html; charset=utf-8")        c.String(http.StatusOK, fmt.Sprintf(htmlCode, num, serversInfo))        return}//  初始化全局map 参考 http://niliu.me/articles/1590.htmlvar hostList map[string]ClientInfo = make(map[string]ClientInfo)func Add(c *gin.Context) {        reqInfo := ClientInfo{}        err := c.BindJSON(&reqInfo)        if err != nil {                c.JSONP(http.StatusNotAcceptable, "Error: "+err.Error())                return        }        clientIP := c.ClientIP()        //clientIP := reqInfo.IP  测试时直接写死方便用post man测试        hostList[clientIP] = ClientInfo{                reqInfo.HostName,                reqInfo.Cpu,                reqInfo.Mem,                reqInfo.Disk,                reqInfo.ProcessNum,                reqInfo.BootTime,        }        n := 0        serversInfo = ""        num = 0        for k, v := range hostList {                num++                n++                // <tr><th>序号</th><th>主机名</th><th>IP地址</th><th>CPU占用率</th><th>内存占用</th><th>任务数量</th><th>执行命令</th></tr>                serversInfo = serversInfo + fmt.Sprintf(`<tr><td>%v</td><td>%v</td><td>%v</td><td>%.2f%%</td><td>%.2f%%</td><td>%v</td><td>%v</td></tr>`, n, v.HostName, k, v.Cpu, v.Mem, v.ProcessNum, v.BootTime)                //log.Println(v.CPU, v.Mem, v.Disk)                if v.Cpu > config.GetFloat64(`checkItems.cpu`) || v.Mem > config.GetFloat64(`checkItems.mem`) || v.Disk > config.GetFloat64(`checkItems.disk`) {                        outStr := fmt.Sprintf(`异常主机信息: HostName:%v IP:%v CPU:%v Mem:%v Disk:%v`, v.HostName, c.ClientIP(), v.Cpu, v.Mem, v.Disk)                        log.Println(outStr)                        sendToDingDing(outStr)                }        }        //log.Println(hostList)        c.JSONP(http.StatusOK, hostList)        return}func sendToDingDing(sendContent string) {        // 接收string类型并发送内容        d := ding.Webhook{                AccessToken: config.GetString("dingding.AccessToken"),                Secret:      config.GetString("dingding.Secret"),                EnableAt:    true, // 开启艾特                AtAll:       true, // 艾特所有人        }        err := d.SendMessage(sendContent)        if err != nil {                fmt.Println(err)        }}func main() {        //获取项目的执行路径        path, _ := os.Getwd()        config = viper.New()        config.AddConfigPath(path)     //设置读取的文件路径        config.SetConfigName("config") //设置读取的文件名        config.SetConfigType("yaml")   //设置文件的类型        //尝试进行配置读取        if err := config.ReadInConfig(); err != nil {                log.Println(err)                log.Println("读取配置文件出错!")                os.Exit(1)        }        // Set Gin to production mode        gin.SetMode(gin.ReleaseMode)        // Set the router as the default one provided by Gin        router := gin.Default()        //router := gin.New()        router.GET("/", Index)        router.POST("/", Add)        go func() {                sleepTime := config.GetInt32("checkTime")                // 定期对服务器信息清空,达到下线后没有心跳信息不再显示                for {                        time.Sleep(time.Duration(sleepTime) * time.Second)                        //log.Println("Clear .... ")                        serversInfo = ""                        num = 0                }        }()        // 监听端口        var port string        flag.StringVar(&port, "p", "8080", "监听端口,默认8080")        flag.Parse()        listenPort := fmt.Sprintf(":%v", port)        log.Println("服务已启动,监听端号 " + listenPort)        err := router.Run(listenPort)        if err != nil {                return        }}

client端:
[Golang] 纯文本查看 复制代码
package mainimport (        "bytes"        "encoding/json"        "flag"        "fmt"        "log"        "net/http"        "os"        "time"        "github.com/shirou/gopsutil/v3/cpu"        "github.com/shirou/gopsutil/v3/disk"        "github.com/shirou/gopsutil/v3/host"        "github.com/shirou/gopsutil/v3/mem")func GetCpuPercent() float64 {        percent, _ := cpu.Percent(time.Second, false)        return percent[0]}func GetMemPercent() float64 {        memInfo, _ := mem.VirtualMemory()        return memInfo.UsedPercent}func GetDiskPercent() float64 {        parts, _ := disk.Partitions(true)        diskInfo, _ := disk.Usage(parts[1].Mountpoint)        return diskInfo.UsedPercent}func GetHostName() string {        name, _ := os.Hostname()        return name}func GetBootTime() string {        // BootTime 开机时间        t, _ := host.BootTime()        return fmt.Sprintf("%v", time.Unix(int64(t), 0))}func GetProcessNum() uint64 {        // 获取所有的pids        infoStat, _ := host.Info()        return infoStat.Procs}type ClientInfo struct {        HostName   string  `json:"hostname"`        Cpu        float64 `json:"cpu"`        Mem        float64 `json:"mem"`        Disk       float64 `json:"disk"`        ProcessNum uint64  `json:"processnum"`        BootTime   string  `json:"bootTime"`}func sendInfo(server string) {        defer func() {                if r := recover(); r != nil {                        fmt.Println("发送状态信息出错,请检测server端.", r)                }        }()        sendInfo := ClientInfo{                HostName:   GetHostName(),                Cpu:        GetCpuPercent(),                Mem:        GetMemPercent(),                Disk:       GetDiskPercent(),                ProcessNum: GetProcessNum(),                BootTime:   GetBootTime(),        }        //fmt.Println(sendInfo)        body, _ := json.Marshal(sendInfo)        resp, _ := http.Post(server, "application/json", bytes.NewBuffer(body))        defer resp.Body.Close()}func main() {        var server string        flag.StringVar(&server, "s", "http://127.0.0.1:8080", "服务器信息")        flag.Parse()        log.Println("52pojie_vsyour提醒: 采集端已启动. 每10秒发送状态信息到 " + server)        for {                sendInfo(server)                //timeStr := time.Now().Format("2006-01-02 15:04:05")                //fmt.Printf("[%v] 52pojie_vsyour提醒: 本次检测已完成, [%v秒] 后再次检测!\n", timeStr, 10)                time.Sleep(time.Duration(10) * time.Second)        }}

下载地址:
外链:https://vsyour.lanzoub.com/b02jl9ayb 密码:52pj
DDR爱好者之家 Design By 杰米
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
DDR爱好者之家 Design By 杰米