github.com/PandaGoAdmin/utils@v0.0.0-20211208134815-d5461603a00f/os_darwin.go (about) 1 // +build darwin 2 3 package kgo 4 5 import ( 6 "encoding/binary" 7 "fmt" 8 "golang.org/x/sys/unix" 9 "os/exec" 10 "strconv" 11 "strings" 12 "sync/atomic" 13 "time" 14 ) 15 16 // cachedBootTime must be accessed via atomic.Load/StoreUint64 17 var cachedBootTime uint64 18 19 //系统IO信息 20 var cacheIOInfos []byte 21 22 // bootTime 获取系统启动时间,秒. 23 func bootTime() (uint64, error) { 24 t := atomic.LoadUint64(&cachedBootTime) 25 if t != 0 { 26 return t, nil 27 } 28 tv, err := unix.SysctlTimeval("kern.boottime") 29 if err != nil { 30 return 0, err 31 } 32 33 atomic.StoreUint64(&cachedBootTime, uint64(tv.Sec)) 34 35 return uint64(tv.Sec), nil 36 } 37 38 // getPidByPort 根据端口号获取监听的进程PID. 39 func getPidByPort(port int) (pid int) { 40 return 41 } 42 43 // getIOInfos 获取系统IO信息 44 func (ko *LkkOS) getIOInfos() []byte { 45 if len(cacheIOInfos) == 0 { 46 _, cacheIOInfos, _ = ko.System("ioreg -l") 47 } 48 return cacheIOInfos 49 } 50 51 // MemoryUsage 获取内存使用率,单位字节. 52 // 参数 virtual(仅支持linux),是否取虚拟内存. 53 // used为已用, 54 // free为空闲, 55 // total为总数. 56 func (ko *LkkOS) MemoryUsage(virtual bool) (used, free, total uint64) { 57 totalStr, err := unix.Sysctl("hw.memsize") 58 if err != nil { 59 return 60 } 61 62 vm_stat, err := exec.LookPath("vm_stat") 63 if err != nil { 64 return 65 } 66 67 _, out, _ := ko.Exec(vm_stat) 68 lines := strings.Split(string(out), "\n") 69 pagesize := uint64(unix.Getpagesize()) 70 var inactive uint64 71 for _, line := range lines { 72 fields := strings.Split(line, ":") 73 if len(fields) < 2 { 74 continue 75 } 76 key := strings.TrimSpace(fields[0]) 77 value := strings.Trim(fields[1], " .") 78 switch key { 79 case "Pages free": 80 f, e := strconv.ParseUint(value, 10, 64) 81 if e != nil { 82 err = e 83 } 84 free = f * pagesize 85 case "Pages inactive": 86 ina, e := strconv.ParseUint(value, 10, 64) 87 if e != nil { 88 err = e 89 } 90 inactive = ina * pagesize 91 } 92 } 93 94 // unix.sysctl() helpfully assumes the result is a null-terminated string and 95 // removes the last byte of the result if it's 0 :/ 96 totalStr += "\x00" 97 total = uint64(binary.LittleEndian.Uint64([]byte(totalStr))) 98 used = total - (free + inactive) 99 return 100 } 101 102 // DiskUsage 获取磁盘(目录)使用情况,单位字节.参数path为路径. 103 // used为已用, 104 // free为空闲, 105 // total为总数. 106 func (ko *LkkOS) DiskUsage(path string) (used, free, total uint64) { 107 stat := unix.Statfs_t{} 108 err := unix.Statfs(path, &stat) 109 if err != nil { 110 return 111 } 112 113 total = uint64(stat.Blocks) * uint64(stat.Bsize) 114 free = uint64(stat.Bavail) * uint64(stat.Bsize) 115 used = (uint64(stat.Blocks) - uint64(stat.Bfree)) * uint64(stat.Bsize) 116 return 117 } 118 119 // Uptime 获取系统运行时间,秒. 120 func (ko *LkkOS) Uptime() (uint64, error) { 121 boot, err := bootTime() 122 if err != nil { 123 return 0, err 124 } 125 126 res := uint64(time.Now().Unix()) - boot 127 return res, nil 128 } 129 130 // GetBiosInfo 获取BIOS信息. 131 // 注意:Mac机器没有BIOS信息,它使用EFI. 132 func (ko *LkkOS) GetBiosInfo() *BiosInfo { 133 res := &BiosInfo{ 134 Vendor: "", 135 Version: "", 136 Date: "", 137 } 138 139 infos := ko.getIOInfos() 140 if len(infos) > 0 { 141 infoStr := string(infos) 142 res.Version = KStr.Trim(KStr.GetEquationValue(infoStr, "SMBIOS-EPS"), "<", ">", `"`, `'`) 143 } 144 145 return res 146 } 147 148 // GetBoardInfo 获取Board信息. 149 func (ko *LkkOS) GetBoardInfo() *BoardInfo { 150 res := &BoardInfo{ 151 Name: "", 152 Vendor: "", 153 Version: "", 154 Serial: "", 155 AssetTag: "", 156 } 157 158 infos := ko.getIOInfos() 159 if len(infos) > 0 { 160 infoStr := string(infos) 161 res.Name = KStr.Trim(KStr.GetEquationValue(infoStr, "product-name"), "<", ">", `"`, `'`) 162 res.Version = KStr.Trim(KStr.GetEquationValue(infoStr, "board-id"), "<", ">", `"`, `'`) 163 res.Serial = KStr.Trim(KStr.GetEquationValue(infoStr, "IOPlatformUUID"), "<", ">", `"`, `'`) 164 } 165 166 return res 167 } 168 169 // GetCpuInfo 获取CPU信息. 170 func (ko *LkkOS) GetCpuInfo() *CpuInfo { 171 var res = &CpuInfo{ 172 Vendor: "", 173 Model: "", 174 Speed: "", 175 Cache: 0, 176 Cpus: 0, 177 Cores: 0, 178 Threads: 0, 179 } 180 181 res.Model, _ = unix.Sysctl("machdep.cpu.brand_string") 182 res.Vendor, _ = unix.Sysctl("machdep.cpu.vendor") 183 184 cacheSize, _ := unix.SysctlUint32("machdep.cpu.cache.size") 185 cpus, _ := unix.SysctlUint32("hw.physicalcpu") 186 cores, _ := unix.SysctlUint32("machdep.cpu.core_count") 187 threads, _ := unix.SysctlUint32("machdep.cpu.thread_count") 188 res.Cache = uint(cacheSize) 189 res.Cpus = uint(cpus) 190 res.Cores = uint(cores) 191 res.Threads = uint(threads) 192 193 // Use the rated frequency of the CPU. This is a static value and does not 194 // account for low power or Turbo Boost modes. 195 cpuFrequency, err := unix.SysctlUint64("hw.cpufrequency") 196 if err == nil { 197 speed := float64(cpuFrequency) / 1000000.0 198 res.Speed = KNum.NumberFormat(speed, 2, ".", "") 199 } 200 201 return res 202 } 203 204 // GetPidByPort 根据端口号获取监听的进程PID. 205 // linux可能要求root权限; 206 // darwin依赖lsof; 207 // windows依赖netstat. 208 func (ko *LkkOS) GetPidByPort(port int) (pid int) { 209 command := fmt.Sprintf("lsof -i tcp:%d", port) 210 _, out, _ := ko.System(command) 211 lines := strings.Split(string(out), "\n") 212 for _, line := range lines { 213 fields := strings.Fields(line) 214 if len(fields) >= 9 && isNumeric(fields[1]) { 215 p := toInt(fields[1]) 216 if p > 0 { 217 pid = p 218 break 219 } 220 } 221 } 222 223 return 224 }