Initial commit
This commit is contained in:
@@ -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
|
||||
}
|
||||
@@ -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")
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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")
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user