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  }