Initial commit

This commit is contained in:
yan.y
2024-03-27 23:25:08 +08:00
commit 0884384e91
127 changed files with 9353 additions and 0 deletions
+85
View File
@@ -0,0 +1,85 @@
package global
import (
"fmt"
"net"
"regexp"
"strings"
"time"
"pet-house.com/core/helper/arr"
)
func GetMacAddr() string {
if getMacAddrInterface() == nil {
return ""
}
addr := getMacAddrInterface().HardwareAddr.String()
if len(addr) > 0 {
addr = strings.ReplaceAll(addr, ":", "")
addr = strings.ToUpper(addr)
return addr
}
return ""
}
func getMacAddrInterface() *net.Interface {
netInterfaces, err := net.Interfaces()
if err != nil {
return nil
}
re, err := regexp.Compile(`^(ens|eth|waln|以太网|Ethernet)[0-9]*`)
if err != nil {
return nil
}
nameCheck := arr.NewCheckArrayType(0)
nameCheck.AddMutil("eth0", "waln0", "以太网", "Ethernet", "ens0")
for _, netInterface := range netInterfaces {
if nameCheck.Check(netInterface.Name) {
return &netInterface
}
}
for _, netInterface := range netInterfaces {
if re.MatchString(netInterface.Name) {
return &netInterface
}
}
return nil
}
func check(ip, network string) bool {
parseIp, subnet, err := net.ParseCIDR(network)
if err != nil {
return false
}
if ip == parseIp.String() {
return false
}
return subnet.Contains(net.ParseIP(ip))
}
func LocalIP(network string) string {
ip := ""
if addrs, err := net.InterfaceAddrs(); err == nil {
for i, addr := range addrs {
i += 1
if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() && !ipnet.IP.IsMulticast() && !ipnet.IP.IsLinkLocalUnicast() && !ipnet.IP.IsLinkLocalMulticast() && ipnet.IP.To4() != nil {
ip = ipnet.IP.String()
if len(ip) > 0 && check(ip, network) {
return ip
}
}
}
}
return ip
}
func IsPortInUse(host string, port int64) bool {
conn, err := net.DialTimeout("tcp", net.JoinHostPort(host, fmt.Sprintf("%d", port)), time.Second*1)
if err == nil {
conn.Close()
return true
}
return false
}
+62
View File
@@ -0,0 +1,62 @@
package global
import (
"strings"
"testing"
)
var network = "10.0.0.1/22"
func TestLocalIP(t *testing.T) {
want := "172.18.236.240"
t.Run("test get local ip", func(t *testing.T) {
ip := LocalIP(network)
if ip != want {
t.Errorf("LocalIP() want get %s but get %s", want, ip)
}
})
}
func TestGetMacAddrs(t *testing.T) {
want := "00155DDB2E65"
t.Run("test get mac addr", func(t *testing.T) {
mac := GetMacAddr()
if mac != strings.ToUpper(want) {
t.Errorf("GetMacAddr() want get %s but get %s", want, mac)
}
})
}
func TestGetMacAddrInterface(t *testing.T) {
want := "eth0"
t.Run("test get mac addr interface", func(t *testing.T) {
mai := getMacAddrInterface()
if mai == nil {
t.Error("mac addr interface is nil")
return
}
if mai.Name != want {
t.Errorf("getMacAddrInterface() want get %s but get %s", want, mai.Name)
}
})
}
func TestCheck(t *testing.T) {
t.Run("test ip check", func(t *testing.T) {
if !check("10.0.1.1", network) {
t.Error("ip check is fail")
return
}
if check("192.168.0.1", network) {
t.Error("ip check is fail")
return
}
})
}
func TestIsPortInUse(t *testing.T) {
t.Run("test is port in use", func(t *testing.T) {
if !IsPortInUse("10.0.0.26", 9092) {
t.Errorf("IsPortInUse(9092) must be return ture but return false")
}
})
}
+214
View File
@@ -0,0 +1,214 @@
package global
import (
"errors"
"fmt"
"net"
"regexp"
"strconv"
"strings"
"time"
"log"
"github.com/shopspring/decimal"
"golang.org/x/crypto/ssh"
)
var (
ErrConnectFail = errors.New("SSH 连接失败")
ErrNewSessionFail = errors.New("SSH 新建会话失败")
ErrRunCommandFail = errors.New("SSH 执行命令失败")
)
type Cli struct {
IP string //IP地址
Username string //用户名
Password string //密码
Port int //端口号
client *ssh.Client //ssh客户端
LastResult string //最近一次Run的结果
Debug bool
}
// 创建命令行对象
// @param ip IP地址
// @param username 用户名
// @param password 密码
// @param debug 是否调试
// @param port 端口号,默认22
func NewSSH(ip string, username string, password string, debug bool, port ...int) *Cli {
cli := new(Cli)
cli.IP = ip
cli.Username = username
cli.Password = password
cli.Debug = debug
if len(port) <= 0 {
cli.Port = 22
} else {
cli.Port = port[0]
}
return cli
}
// 执行shell
// @param shell shell脚本命令
func (c Cli) Run(shell string) (string, error) {
if c.client == nil {
if err := c.connect(); err != nil {
if c.Debug {
log.Println(err.Error())
}
return "", ErrConnectFail
}
}
defer c.client.Close()
session, err := c.client.NewSession()
if err != nil {
if c.Debug {
log.Println(err.Error())
}
return "", ErrNewSessionFail
}
defer session.Close()
buf, err := session.CombinedOutput(shell)
if err != nil {
if c.Debug {
log.Println(err.Error())
}
return "", ErrRunCommandFail
}
c.LastResult = string(buf)
return c.LastResult, nil
}
// 连接
func (c *Cli) connect() error {
config := ssh.ClientConfig{
User: c.Username,
Auth: []ssh.AuthMethod{ssh.Password(c.Password)},
HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
return nil
},
Timeout: 10 * time.Second,
}
addr := fmt.Sprintf("%s:%d", c.IP, c.Port)
sshClient, err := ssh.Dial("tcp", addr, &config)
if err != nil {
if c.Debug {
log.Println(err.Error())
}
return err
}
c.client = sshClient
return nil
}
type DeviceMem struct {
Free decimal.Decimal
Total decimal.Decimal
FreeRound decimal.Decimal
}
// GetMem 内存信息
func (c *Cli) GetMem() (DeviceMem, error) {
var deviceMen DeviceMem
totalDec, err := c.getMenInfo("cat /proc/meminfo | grep -w MemTotal", "MemTotal:")
if err != nil {
return deviceMen, fmt.Errorf("memTotal %w", err)
}
freeDec, err := c.getMenInfo("cat /proc/meminfo | grep -w MemFree", "MemFree:")
if err != nil {
return deviceMen, fmt.Errorf("memFree %w", err)
}
buffersDec, err := c.getMenInfo("cat /proc/meminfo | grep -w Buffers", "Buffers:")
if err != nil {
return deviceMen, fmt.Errorf("buffers %w", err)
}
cachedDec, err := c.getMenInfo("cat /proc/meminfo | grep -w Cached", "Cached:")
if err != nil {
return deviceMen, fmt.Errorf("cached %w", err)
}
deviceMen.Total = totalDec
deviceMen.Free = freeDec.Add(buffersDec).Add(cachedDec)
deviceMen.FreeRound = deviceMen.Free.DivRound(deviceMen.Total, 2)
return deviceMen, nil
}
// getMenInfo 内存信息
func (c *Cli) getMenInfo(cmd, key string) (decimal.Decimal, error) {
info, err := c.Run(cmd)
if err != nil {
return decimal.Zero, fmt.Errorf("%s %w", cmd, err)
}
dec, err := decimal.NewFromString(strings.TrimSpace(strings.ReplaceAll(strings.ReplaceAll(info, key, ""), "kB", "")))
if err != nil {
return decimal.Zero, fmt.Errorf("NewFromString %w", err)
}
return dec, err
}
// GetDf 硬盘率
func (c *Cli) GetDf() (string, error) {
total, err := c.Run("df /sdcard -h")
if err != nil {
return "", fmt.Errorf("df /sdcard -h %w", err)
}
flysnowRegexp := regexp.MustCompile(`(100|[1-9]?\d(\.\d\d?\d?)?)%`)
params := flysnowRegexp.FindStringSubmatch(total)
if len(params) > 0 {
return params[0], nil
}
return "", nil
}
// GetSignal wifi信号
func (c *Cli) GetSignal() (string, error) {
signal, err := c.Run("iw dev wlan0 link | grep -w signal:")
if err != nil {
return "", fmt.Errorf("iw dev wlan0 link | grep -w signal: %w", err)
}
return strings.TrimSpace(strings.ReplaceAll(signal, "signal:", "")), nil
}
// GetDatetime 当前时间
func (c *Cli) GetDatetime() (string, error) {
datetime, err := c.Run("date +'%Y/%m/%d %T %Z'")
if err != nil {
return "", fmt.Errorf("date %w", err)
}
return datetime, nil
}
// GetCpuTemp CPU温度
func (c *Cli) GetCpuTemp() (float64, error) {
var ct float64
cmd := "acpi -t"
cpuTemp, err := c.Run(cmd)
if err != nil {
return 0, fmt.Errorf("%s : %w", cmd, err)
}
cpuTemps := strings.Split(cpuTemp, "\n")
for _, v := range cpuTemps {
flysnowRegexp := regexp.MustCompile(`[1-9]\d*\.\d*|0\.\d*[1-9]\d*`)
params := flysnowRegexp.FindStringSubmatch(v)
if len(params) > 0 {
f, err := strconv.ParseFloat(strings.Trim(params[0], "\n"), 64)
if err != nil {
return 0, fmt.Errorf("ParseFloat %w", err)
}
current := f / 100
if current > ct {
ct = current
}
}
}
return ct, nil
}
+111
View File
@@ -0,0 +1,111 @@
package global
import (
_ "embed"
"log"
"os"
"testing"
)
func Test_NewSSH(t *testing.T) {
sshPwd := os.Getenv("sshPwd")
t.Run("测试新建ssh链接", func(t *testing.T) {
ip := "10.0.1.14"
name := "root"
sshClient := NewSSH(ip, name, sshPwd, true, 2022)
if sshClient == nil {
t.Errorf("客户端为空")
return
}
})
}
func Test_GetMem(t *testing.T) {
sshPwd := os.Getenv("sshPwd")
t.Run("测试获取设备内存", func(t *testing.T) {
ip := "10.0.1.14"
name := "root"
sshClient := NewSSH(ip, name, sshPwd, true, 2022)
if sshClient == nil {
t.Errorf("客户端为空")
return
}
mem, err := sshClient.GetMem()
if err != nil {
t.Errorf(err.Error())
return
}
log.Println(mem.Total.String())
})
}
func Test_GetDf(t *testing.T) {
sshPwd := os.Getenv("sshPwd")
t.Run("测试获取设备硬盘使用", func(t *testing.T) {
ip := "10.0.1.14"
name := "root"
sshClient := NewSSH(ip, name, sshPwd, true, 2022)
if sshClient == nil {
t.Errorf("客户端为空")
return
}
_, err := sshClient.GetDf()
if err != nil {
t.Errorf(err.Error())
return
}
})
}
func Test_GetSignal(t *testing.T) {
sshPwd := os.Getenv("sshPwd")
t.Run("测试获取设备信号使用", func(t *testing.T) {
ip := "10.0.1.14"
name := "root"
sshClient := NewSSH(ip, name, sshPwd, true, 2022)
if sshClient == nil {
t.Errorf("客户端为空")
return
}
_, err := sshClient.GetSignal()
if err != nil {
t.Errorf(err.Error())
return
}
})
}
func Test_GetDatetime(t *testing.T) {
sshPwd := os.Getenv("sshPwd")
t.Run("测试获取设备时间使用", func(t *testing.T) {
ip := "10.0.1.14"
name := "root"
sshClient := NewSSH(ip, name, sshPwd, true, 2022)
if sshClient == nil {
t.Errorf("客户端为空")
return
}
_, err := sshClient.GetDatetime()
if err != nil {
t.Errorf(err.Error())
return
}
})
}
func Test_GetCpuTemp(t *testing.T) {
sshPwd := os.Getenv("sshPwd")
t.Run("测试获取设备时间使用", func(t *testing.T) {
ip := "10.0.1.14"
name := "root"
sshClient := NewSSH(ip, name, sshPwd, true, 2022)
if sshClient == nil {
t.Errorf("客户端为空")
return
}
cpuTemp, err := sshClient.GetCpuTemp()
if err != nil {
t.Errorf(err.Error())
return
}
if cpuTemp <= 0 {
t.Errorf("cpu temp is 0")
}
})
}
+121
View File
@@ -0,0 +1,121 @@
package global
import (
"database/sql/driver"
"fmt"
"math"
"math/rand"
"strings"
"time"
)
// DateTime 自定义事件类型
type DateTime time.Time
// 日期格式
const (
DateLayout = "2006-01-02"
DateTimeLayout = "2006-01-02 15:04:05"
TimeLayout = "15:04:05"
BuildTimeLayout = "2006.0102.150405"
TimestampLayout = "20060102150405"
)
var StartTime = time.Now()
func (dt *DateTime) UnmarshalJSON(data []byte) (err error) {
value := strings.Trim(string(data), "\"")
now, err := time.ParseInLocation(DateTimeLayout, value, time.Local)
*dt = DateTime(now)
return
}
func (dt DateTime) MarshalJSON() ([]byte, error) {
b := make([]byte, 0, len(DateTimeLayout)+2)
b = append(b, '"')
b = time.Time(dt).AppendFormat(b, DateTimeLayout)
b = append(b, '"')
return b, nil
}
func (dt DateTime) Value() (driver.Value, error) {
var zeroTime time.Time
ti := time.Time(dt)
if ti.UnixNano() == zeroTime.UnixNano() {
return nil, nil
}
return ti, nil
}
func (dt *DateTime) Scan(v interface{}) error {
if value, ok := v.(time.Time); ok {
*dt = DateTime(value)
return nil
}
return nil
}
func (dt DateTime) String() string {
return time.Time(dt).Format(DateTimeLayout)
}
func UpTime() time.Duration {
return time.Since(StartTime)
}
func UpTimeString() string {
d := UpTime()
days := d / (time.Hour * 24)
d -= days * 24 * time.Hour
hours := d / time.Hour
d -= hours * time.Hour
minutes := d / time.Minute
d -= minutes * time.Minute
seconds := d / time.Second
return fmt.Sprintf("%d Days %d Hours %d Mins %d Secs", days, hours, minutes, seconds)
}
// 获取时区
func GetLocation() (*time.Location, error) {
location, err := time.LoadLocation("Local")
if err != nil {
return location, nil
}
return location, nil
}
func GetDuration(t int64, v string) time.Duration {
switch v {
case "h":
return time.Hour * time.Duration(t)
case "m":
return time.Minute * time.Duration(t)
case "s":
return time.Second * time.Duration(t)
default:
return time.Minute * time.Duration(t)
}
}
func SleepRandomDuration() {
ns := int64(5) * 1000000000
// 以当前时间为随机数种子,如果所有 log-agent-updater 在同一时间启动,系统时间是相同的,那么随机种子就是一样的
// 问题不大,批量ssh去启动 log-agent-updater 的话也是一个顺次的过程
r := rand.New(rand.NewSource(time.Now().UnixNano()))
d := time.Duration(r.Int63n(ns)) * time.Nanosecond
time.Sleep(d)
}
// OverTimeNow 超时比较
func OverTimeNow(compareTime, subTime time.Time, sub int64) (bool, int64, error) {
location, err := GetLocation()
if err != nil {
return false, 0, err
}
subT := compareTime.In(location).Sub(subTime)
abs := int64(math.Abs(math.Ceil(subT.Minutes())))
if abs > sub {
return true, abs, nil
}
return false, abs, nil
}