master
dustoair 3 years ago
commit fbb75c3d35

8
.gitignore vendored

@ -0,0 +1,8 @@
/.idea
/.idea/
/.idea/*
.idea
.idea/
.idea/*
go.sum
nogit.txt

@ -0,0 +1,49 @@
探测url的ssl证书过期时间 并发微信告警
## build on arm64
```bash
cd /root
rm -rf remoteMonitor
git clone https://git.sre.ink/go/remoteMonitor.git
cd remoteMonitor
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 GO111MODULE=on go get github.com/shirou/gopsutil/v3/cpu@v3.21.12
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 GO111MODULE=on go get github.com/shirou/gopsutil/v3/disk@v3.21.12
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 GO111MODULE=on go mod tidy
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 GO111MODULE=on go build -v -a -o rtm main.go
chmod +x rtm
rm -rf /usr/bin/rtm
mv rtm /usr/bin/
rtm
```
## build
```bash
cd /root
rm -rf remoteMonitor
git clone https://git.sre.ink/go/remoteMonitor.git
cd remoteMonitor
GOPROXY="https://goproxy.cn,direct" go get github.com/shirou/gopsutil/v3/cpu@v3.21.12
GOPROXY="https://goproxy.cn,direct" go get github.com/shirou/gopsutil/v3/disk@v3.21.12
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GO111MODULE=on GOPROXY="https://goproxy.cn,direct" go build -v -a -o rtm main.go
chmod +x rtm
rm -rf /usr/bin/rtm
mv rtm /usr/bin/
```
## crontab
```bash
*/1 * * * * /usr/bin/rtm
```
## usage
```bash
chmod +x /usr/bin/rtm
rtm
```
## build for arm64
```bash
CGO_ENABLED=0 GOARM=7 GOOS=linux GOARCH=arm64 GO111MODULE=on GOPROXY="https://goproxy.cn,direct" go build -v -a -o certmonitor main.go
```

@ -0,0 +1,23 @@
module remoteMonitor
go 1.18
require (
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1449
github.com/shirou/gopsutil/v3 v3.21.12
)
require (
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af // indirect
github.com/json-iterator/go v1.1.5 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.1 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/tklauser/go-sysconf v0.3.9 // indirect
github.com/tklauser/numcpus v0.3.0 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
golang.org/x/sys v0.0.0-20211013075003-97ac67df715c // indirect
gopkg.in/ini.v1 v1.66.2 // indirect
)

@ -0,0 +1,28 @@
package main
import (
"fmt"
"remoteMonitor/thirdpart"
"remoteMonitor/util"
)
func main() {
fmt.Println("获取主机信息")
util.GetHostInfo()
fmt.Println("获取CPU信息")
util.GetCpuInfo()
fmt.Println("获取内存信息")
util.GetMemInfo()
fmt.Println("获取系统负载")
util.GetSysLoad()
fmt.Println("获取硬盘存储信息")
util.GetDiskInfo()
if util.IsAlert {
thirdpart.SendWechat(util.MSG)
//thirdpart.SendToPhone("13152148384", "9999")
}
}

@ -0,0 +1,43 @@
/**
* https://next.api.aliyun.com/api-tools/sdk/Dysmsapi?spm=a2c4g.11186623.0.0.257a7218t3HRei&version=2017-05-25&language=go-tea
*/
package thirdpart
import (
"fmt"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
"github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi"
)
func SendToPhone(phone string, code string) bool {
//调用阿里云短信接口发送短信 从配置中心拿配置项
sign_name := "333333333333"
template_code := "3333333333333333"
app_key := "33333333333333333333333333"
app_secret := "333333333333333333333333333333"
region_id := "cn-hangzhou"
client, err := dysmsapi.NewClientWithAccessKey(region_id, app_key, app_secret)
request := requests.NewCommonRequest()
request.Method = "POST"
request.Scheme = "https" // https | http
request.Domain = "dysmsapi.aliyuncs.com"
request.Version = "2017-05-25"
request.ApiName = "SendSms"
request.QueryParams["RegionId"] = region_id
request.QueryParams["PhoneNumbers"] = phone //手机号
request.QueryParams["SignName"] = sign_name //阿里云验证过的项目名 自己设置
request.QueryParams["TemplateCode"] = template_code //阿里云的短信模板号 自己设置
request.QueryParams["TemplateParam"] = "{\"code\":" + code + "}" //短信模板中的验证码内容。
response, err := client.ProcessCommonRequest(request)
fmt.Print(client.DoAction(request, response))
// fmt.Print(response)
if err != nil {
fmt.Print(err.Error())
return false
}
fmt.Printf("response is %#v\n", response)
//json数据解析
return true
}

@ -0,0 +1,114 @@
package thirdpart
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"reflect"
)
var WECOM_CID string = GetEnvDefault("WECOM_CID", "333333333333333333333")
var WECOM_SECRET string = GetEnvDefault("WECOM_SECRET", "33333333333333333333333333")
var WECOM_AID string = GetEnvDefault("WECOM_AID", "33333333333333")
var WECOM_TOUID string = GetEnvDefault("WECOM_TOUID", "333333333333333333333")
var REDIS_STAT string = GetEnvDefault("REDIS_STAT", "OFF")
var REDIS_PASSWORD string = GetEnvDefault("REDIS_PASSWORD", "")
var ctx = context.Background()
func GetEnvDefault(key, defVal string) string {
val, ex := os.LookupEnv(key)
if !ex {
return defVal
}
return val
}
func praser_json(json_str string) map[string]interface{} {
var wecom_response map[string]interface{}
if string(json_str) != "" {
err := json.Unmarshal([]byte(string(json_str)), &wecom_response)
if err != nil {
log.Println("生成json字符串错误")
}
}
return wecom_response
}
func get_token(corpid, app_secret string) string {
resp, err := http.Get("https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=" + corpid + "&corpsecret=" + app_secret)
if err != nil {
log.Println(err)
}
defer resp.Body.Close()
resp_data, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Println(err)
}
token_response := praser_json(string(resp_data))
return token_response["access_token"].(string)
}
func post_msg(text_msg, msg_type, post_url string) string {
type msg struct {
Content string `json:"content"`
}
type JsonData struct {
Touser string `json:"touser"`
Agentid string `json:"agentid"`
Msgtype string `json:"msgtype"`
Text msg `json:"text"`
Duplicate_check_interval int `json:"duplicate_check_interval"`
}
post_data := JsonData{
Touser: WECOM_TOUID,
Agentid: WECOM_AID,
Msgtype: msg_type,
Duplicate_check_interval: 600,
Text: msg{Content: text_msg},
}
post_json, _ := json.Marshal(post_data)
log.Println(string(post_json))
msg_req, err := http.NewRequest("POST", post_url, bytes.NewBuffer(post_json))
if err != nil {
log.Println(err)
}
msg_req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(msg_req)
if err != nil {
panic(err)
}
defer msg_req.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
return string(body)
}
func IsZero(v interface{}) (bool, error) {
t := reflect.TypeOf(v)
if !t.Comparable() {
return false, fmt.Errorf("type is not comparable: %v", t)
}
return v == reflect.Zero(t).Interface(), nil
}
func SendWechat(msg string) {
access_token := get_token(WECOM_CID, WECOM_SECRET)
post_url := "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=" + access_token
msg_type := "text"
post_status := post_msg(msg, msg_type, post_url)
log.Println(post_status)
post_response := praser_json(string(post_status))
log.Println(post_response)
errcode := post_response["errcode"]
_, err := IsZero(errcode)
if err != nil {
fmt.Printf("%v", err)
}
}

@ -0,0 +1,133 @@
package util
import (
"fmt"
"github.com/shirou/gopsutil/v3/cpu"
"github.com/shirou/gopsutil/v3/disk"
"github.com/shirou/gopsutil/v3/host"
"github.com/shirou/gopsutil/v3/load"
"github.com/shirou/gopsutil/v3/mem"
"net"
"strings"
"time"
)
var (
IsAlert = false
MSG = ""
)
// 获取网络信息
func GetNetInfo() string {
addrs, err := net.InterfaceAddrs()
if err != nil {
fmt.Println(err)
return ""
}
for _, address := range addrs {
// 检查ip地址判断是否回环地址
if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
if ipnet.IP.To4() != nil {
//fmt.Println(ipnet.Mask)
//fmt.Println(ipnet.IP)
return ipnet.IP.String()
}
}
}
return ""
}
// 获取主机信息
func GetHostInfo() {
hostInfo, err := host.Info()
if err != nil {
fmt.Println("get host info fail, error: ", err)
}
fmt.Printf("hostname is: %v, os platform: %v \n", hostInfo.Hostname, hostInfo.Platform)
MSG += fmt.Sprintf("hostname is: %v, os platform: %v \n", hostInfo.Hostname, hostInfo.Platform)
}
// 获取CPU信息
func GetCpuInfo() {
// cpuInfo,err := cpu.Info()
// if err != nil {
// fmt.Println("get cpu info fail, err: %v",err)
// }
// for _,ci := range cpuInfo {
// fmt.Printf("%v \n",ci)
// }
cpuPercent, _ := cpu.Percent(time.Second, true)
cpuNumber, _ := cpu.Counts(true)
if cpuPercent[0] >= 95 {
//IsAlert = true
//暂时不监控cpu情况
MSG += fmt.Sprintf("CPU核心数: %v \n", cpuNumber)
MSG += fmt.Sprintf("CPU使用率: %.3f%% \n", cpuPercent[0])
}
}
// 获取内存信息
func GetMemInfo() {
memInfo, err := mem.VirtualMemory()
if err != nil {
fmt.Println("get memory info fail. err ", err)
}
// 获取总内存大小单位GB
memTotal := memInfo.Total / 1024 / 1024 / 1024
// 获取已用内存大小单位MB
memUsed := memInfo.Used / 1024 / 1024
// 可用内存大小
memAva := memInfo.Available / 1024 / 1024
// 内存可用率
memUsedPercent := memInfo.UsedPercent
if memUsedPercent >= 95 {
IsAlert = true
MSG += fmt.Sprintf("总内存: %v GB, 已用内存: %v MB, 可用内存: %v MB, 内存使用率: %.3f %% \n", memTotal, memUsed, memAva, memUsedPercent)
}
}
// 获取系统负载
func GetSysLoad() {
loadInfo, err := load.Avg()
if err != nil {
fmt.Println("get average load fail. err: ", err)
}
if loadInfo.Load15 >= 10 {
IsAlert = true
MSG += fmt.Sprintf("系统平均负载: %v \n", loadInfo)
}
}
// 获取硬盘存储信息
func GetDiskInfo() {
diskPart, err := disk.Partitions(false)
if err != nil {
fmt.Println(err)
}
for _, dp := range diskPart {
if find := strings.Contains(dp.String(), "/snap/core"); find {
//oracle arm cpu core 被误认为分区
return
}
fmt.Println(dp)
diskUsed, _ := disk.Usage(dp.Mountpoint)
fmt.Printf("分区总大小: %d MB \n", diskUsed.Total/1024/1024)
fmt.Printf("分区使用率: %.3f %% \n", diskUsed.UsedPercent)
fmt.Printf("分区inode使用率: %.3f %% \n", diskUsed.InodesUsedPercent)
if diskUsed.UsedPercent >= 80 || diskUsed.InodesUsedPercent >= 80 {
IsAlert = true
MSG += fmt.Sprintf("异常分区: %s \n", dp.Mountpoint)
MSG += fmt.Sprintf("分区总大小: %d GB \n", diskUsed.Total/1024/1024/1024)
MSG += fmt.Sprintf("分区使用率: %.3f %% \n", diskUsed.UsedPercent)
MSG += fmt.Sprintf("分区inode使用率: %.3f %% \n", diskUsed.InodesUsedPercent)
}
}
}

@ -0,0 +1,12 @@
package util
import (
"fmt"
"testing"
)
func TestGetNetInfo(t *testing.T) {
fmt.Println("获取网络信息")
fmt.Println(GetNetInfo())
}

@ -0,0 +1,144 @@
package netTest
//原文链接https://blog.csdn.net/qq_38858546/article/details/119873424
//【golang】syscall 获取本机网卡IP、网关可以通过IP地址来进行路由选择多网卡
import (
"fmt"
"net"
"sort"
"syscall"
"testing"
"unsafe"
)
type rtInfo struct {
Dst net.IPNet
Gateway, PrefSrc net.IP
OutputIface uint32
Priority uint32
}
type routeSlice []*rtInfo
type router struct {
ifaces []net.Interface
addrs []net.IP
v4 routeSlice
}
func getRouteInfo() (*router, error) {
rtr := &router{}
tab, err := syscall.NetlinkRIB(syscall.RTM_GETROUTE, syscall.AF_INET)
if err != nil {
return nil, err
}
msgs, err := syscall.ParseNetlinkMessage(tab)
if err != nil {
return nil, err
}
for _, m := range msgs {
switch m.Header.Type {
case syscall.NLMSG_DONE:
break
case syscall.RTM_NEWROUTE:
rtmsg := (*syscall.RtMsg)(unsafe.Pointer(&m.Data[0]))
attrs, err := syscall.ParseNetlinkRouteAttr(&m)
if err != nil {
return nil, err
}
routeInfo := rtInfo{}
rtr.v4 = append(rtr.v4, &routeInfo)
for _, attr := range attrs {
switch attr.Attr.Type {
case syscall.RTA_DST:
routeInfo.Dst.IP = net.IP(attr.Value)
routeInfo.Dst.Mask = net.CIDRMask(int(rtmsg.Dst_len), len(attr.Value)*8)
case syscall.RTA_GATEWAY:
routeInfo.Gateway = net.IPv4(attr.Value[0], attr.Value[1], attr.Value[2], attr.Value[3])
case syscall.RTA_OIF:
routeInfo.OutputIface = *(*uint32)(unsafe.Pointer(&attr.Value[0]))
case syscall.RTA_PRIORITY:
routeInfo.Priority = *(*uint32)(unsafe.Pointer(&attr.Value[0]))
case syscall.RTA_PREFSRC:
routeInfo.PrefSrc = net.IPv4(attr.Value[0], attr.Value[1], attr.Value[2], attr.Value[3])
}
}
}
}
sort.Slice(rtr.v4, func(i, j int) bool {
return rtr.v4[i].Priority < rtr.v4[j].Priority
})
ifaces, err := net.Interfaces()
if err != nil {
return nil, err
}
for i, iface := range ifaces {
if i != iface.Index-1 {
break
}
if iface.Flags&net.FlagUp == 0 {
continue
}
rtr.ifaces = append(rtr.ifaces, iface)
ifaceAddrs, err := iface.Addrs()
if err != nil {
return nil, err
}
var addrs net.IP
for _, addr := range ifaceAddrs {
if inet, ok := addr.(*net.IPNet); ok {
if v4 := inet.IP.To4(); v4 != nil {
if addrs == nil {
addrs = v4
}
}
}
}
rtr.addrs = append(rtr.addrs, addrs)
}
return rtr, nil
}
func TestRoute(tt *testing.T) {
newRoute, err := getRouteInfo()
if err != nil {
fmt.Println(err)
return
}
fmt.Println("**************************************")
fmt.Printf("%-15v %-15v %-15v\n", "interfaceName", "gateway", "ip")
for _, rt := range newRoute.v4 {
if rt.Gateway != nil {
fmt.Printf("%-15v %-15v %-15v\n", newRoute.ifaces[rt.OutputIface-1].Name, rt.Gateway.String(), newRoute.addrs[rt.OutputIface-1])
}
}
fmt.Println("**************************************")
newRoute.getRoute(net.ParseIP("192.168.2.100"))
newRoute.getRoute(net.ParseIP("10.10.100.100"))
newRoute.getRoute(net.ParseIP("172.1.2.100"))
}
func (r *router) getRoute(dst net.IP) {
for _, rt := range r.v4 {
if rt.Dst.IP != nil && !rt.Dst.Contains(dst) {
continue
}
fmt.Printf("%-15v : ", dst.String())
if rt.PrefSrc == nil {
fmt.Println(r.ifaces[rt.OutputIface-1].Name, rt.Gateway.String(), r.addrs[rt.OutputIface-1].String())
} else {
fmt.Println(r.ifaces[rt.OutputIface-1].Name, rt.Gateway.String(), rt.PrefSrc.String())
}
return
}
}
Loading…
Cancel
Save