Ежедневная библиотека gopsutil

Go

Введение

gopsutilэто библиотека инструментов PythonpsutilПорт Golang может помочь нам легко получить различную информацию о системе и оборудовании.gopsutilОн скрывает для нас различия между различными системами и обладает очень мощной мобильностью. имеютgopsutil, нам больше не нужно ориентироваться на разные системы, используяsyscallВызовите соответствующий системный метод. Лучшая частьgopsutilНет реализацииcgoкода, что делает возможной кросс-компиляцию.

быстрый в использовании

Сначала установите:

$ go get github.com/shirou/gopsutil

так какgopsutilиспользуемая библиотекаgolang.org/x/sys, последний находится вне стены, если возникает ошибка, подобная следующей:

cannot find package "golang.org/x/sys/windows"

Его можно скачать с помощью следующей командыgolang.org/x/sysЗеркало на GitHub:

$ git clone git@github.com:golang/sys.git $GOPATH/src/golang.org/x/sys

использовать:

package main

import (
  "fmt"

  "github.com/shirou/gopsutil/mem"
)

func main() {
  v, _ := mem.VirtualMemory()

  fmt.Printf("Total: %v, Available: %v, UsedPercent:%f%%\n", v.Total, v.Available, v.UsedPercent)

  fmt.Println(v)
}

gopsutilРазделите разные функции на разные подпакеты:

  • cpu: связанный с процессором;
  • disk: Относится к диску;
  • docker: связанный с докером;
  • host: связанный с хостом;
  • mem: связанные с памятью;
  • net: связанный с сетью;
  • process: связанные с процессом;
  • winservices: Связано со службой Windows.

Если вы хотите использовать соответствующую функцию, вам необходимо импортировать соответствующий подпакет. Например, в приведенном выше коде мы хотим получить информацию о памяти, а импортmemподпакет.mem.VirtualMemory()Метод возвращает структуру информации о памятиmem.VirtualMemoryStat, структура имеет богатые поля, наиболее часто используемые из них не что иное, какTotal(Общая память),Available(доступная память),Used(используемая память) иUsedPercent(процент использования памяти).mem.VirtualMemoryStatтакже понялfmt.StringerИнтерфейс, который возвращает информацию о памяти в формате JSON. утверждениеfmt.Println(v)будет вызываться автоматическиv.String(), который вернет информационный вывод. Вывод программы:

Total: 8526921728, Available: 3768975360, UsedPercent:55.000000%
{"total":8526921728,"available":3768975360,"used":4757946368,"usedPercent":55,"free":0,"active":0,"inactive":0,"wired":0,"laundry":0,"buffers":0,"cached":0,"writeback":0,"dirty":0,"writebacktmp":0,"shared":0,"slab":0,"sreclaimable":0,"sunreclaim":0,"pagetables":0,"swapcached":0,"commitlimit":0,"committedas":0,"hightotal":0,"highfree":0,"lowtotal":0,"lowfree":0,"swaptotal":0,"swapfree":0,"mapped":0,"vmalloctotal":0,"vmallocused":0,"vmallocchunk":0,"hugepagestotal":0,"hugepagesfree":0,"hugepagesize":0}

Единица измерения — байты, память моего компьютера — 8 ГБ, текущий процент использования — 55%, а доступная память — 3768975360 байт (т. е. 3,51 ГБ).

CPU

Мы знаем, что существует два типа ядер ЦП: одно — физическое, а другое — логическое. Количество физических ядер — это фактическое количество ЦП на материнской плате.На физическом ЦП может быть несколько ядер, и эти ядра называются логическими ядрами.gopsutilСредние функции, связанные с ЦП, находятся вcpuподпакет,cpuПодпакеты предоставляют интерфейсы для получения количества физических и логических ядер и использования ЦП:

  • Counts(logical bool): входящийfalse, возвращает количество физических ядер, переданных вtrue, возвращает логическое количество ядер;
  • Percent(interval time.Duration, percpu bool): означает получитьintervalИспользование ЦП в течение интервала,percpuзаfalse, получить общее использование ЦП,percpuзаtrueКогда , получить использование каждого процессора отдельно, вернуть[]float64значение типа.

Например:

func main() {
  physicalCnt, _ := cpu.Counts(false)
  logicalCnt, _ := cpu.Counts(true)
  fmt.Printf("physical count:%d logical count:%d\n", physicalCnt, logicalCnt)

  totalPercent, _ := cpu.Percent(3*time.Second, false)
  perPercents, _ := cpu.Percent(3*time.Second, true)
  fmt.Printf("total percent:%v per percents:%v", totalPercent, perPercents)
}

Приведенный выше код получает количество физических ядер и логических ядер, а также общее использование ЦП в течение 3 с и соответствующее использование каждого ЦП, а также выходные данные программы (обратите внимание, что выходные данные каждого запуска могут быть разными):

physical count:4 logical count:8
total percent:[30.729166666666668] per percents:[32.64248704663213 26.94300518134715 44.559585492227974 23.958333333333336 36.787564766839374 20.3125 38.54166666666667 28.125]

Детали

перечислитьcpu.Info()Можно получить подробную информацию о процессоре, вернуть[]cpu.InfoStat:

func main() {
  infos, _ := cpu.Info()
  for _, info := range infos {
    data, _ := json.MarshalIndent(info, "", " ")
    fmt.Print(string(data))
  }
}

Для удобства просмотра вывожу результат в JSON:

{
 "cpu": 0,
 "vendorId": "GenuineIntel",
 "family": "198",
 "model": "",
 "stepping": 0,
 "physicalId": "BFEBFBFF000906E9",
 "coreId": "",
 "cores": 8,
 "modelName": "Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz",
 "mhz": 3601,
 "cacheSize": 0,
 "flags": [],
 "microcode": ""
}

Из результатов видно, что процессор представляет собой серию Intel i7-7700 с частотой 3,60 ГГц. Вышеприведенное — это то, что я вернул при работе в Windows, внутренне используяgithub.com/StackExchange/wmiбиблиотека. В Linux каждый логический ЦП возвращаетInfoStatструктура.

занятое время

перечислитьcpu.Times(percpu bool)Вы можете получить общее использование ЦП и каждого отдельного времени ЦП с момента загрузки. входящийpercpu=falseвернуть итог, передатьpercpu=trueВернуть один. Каждое использование процессорного времени являетсяTimeStatструктура:

// src/github.com/shirou/gopsutil/cpu/cpu.go
type TimesStat struct {
  CPU       string  `json:"cpu"`
  User      float64 `json:"user"`
  System    float64 `json:"system"`
  Idle      float64 `json:"idle"`
  Nice      float64 `json:"nice"`
  Iowait    float64 `json:"iowait"`
  Irq       float64 `json:"irq"`
  Softirq   float64 `json:"softirq"`
  Steal     float64 `json:"steal"`
  Guest     float64 `json:"guest"`
  GuestNice float64 `json:"guestNice"`
}
  • CPU: Идентификация ЦП, если она общая, полеcpu-total, в противном случаеcpu0,cpu1...;
  • User: Занятие пользовательского времени (пользовательский режим);
  • System: занятость системного времени (состояние ядра);
  • Idle:свободное время;
  • ...

Например:

func main() {
  infos, _ := cpu.Times(true)
  for _, info := range infos {
    data, _ := json.MarshalIndent(info, "", " ")
    fmt.Print(string(data))
  }
}

Для удобства просмотра я вывожу результаты в JSON, и вот один из выходов:

{
 "cpu": "cpu0",
 "user": 674.46875,
 "system": 1184.984375,
 "idle": 7497.1875,
 "nice": 0,
 "iowait": 0,
 "irq": 75.578125,
 "softirq": 0,
 "steal": 0,
 "guest": 0,
 "guestNice": 0
}

диск

подпакетdiskИспользуется для получения информации о диске.diskПолучите статистику ввода-вывода, разделы и информацию об использовании. Следующие разделы вводятся по очереди.

Статистика ИО

перечислитьdisk.IOCounters()Функция, возвращаемая статистика ввода-вывода используется дляmap[string]IOCountersStatТиповое представление. Одна структура на раздел, ключ — это имя раздела, а значение — статистика. Здесь извлекаются некоторые поля статистической структуры, в основном включая количество операций чтения и записи, количество байтов и время:

// src/github.com/shirou/gopsutil/disk/disk.go
type IOCountersStat struct {
  ReadCount        uint64 `json:"readCount"`
  MergedReadCount  uint64 `json:"mergedReadCount"`
  WriteCount       uint64 `json:"writeCount"`
  MergedWriteCount uint64 `json:"mergedWriteCount"`
  ReadBytes        uint64 `json:"readBytes"`
  WriteBytes       uint64 `json:"writeBytes"`
  ReadTime         uint64 `json:"readTime"`
  WriteTime        uint64 `json:"writeTime"`
  // ...
}

Например:

func main() {
  mapStat, _ := disk.IOCounters()
  for name, stat := range mapStat {
    fmt.Println(name)
    data, _ := json.MarshalIndent(stat, "", "  ")
    fmt.Println(string(data))
  }
}

Вывод включает все разделы, здесь я показываю только один:

C:
{
  "readCount": 184372,
  "mergedReadCount": 0,
  "writeCount": 42252,
  "mergedWriteCount": 0,
  "readBytes": 5205152768,
  "writeBytes": 701583872,
  "readTime": 333,
  "writeTime": 27,
  "iopsInProgress": 0,
  "ioTime": 0,
  "weightedIO": 0,
  "name": "C:",
  "serialNumber": "",
  "label": ""
}

Уведомление,disk.IOCounters()Для идентификации раздела может быть передано переменное количество строковых параметров.Этот параметр недействителен в Windows.

раздел

перечислитьdisk.PartitionStat(all bool)Функция, которая возвращает информацию о разделе. еслиall = false, возвращает только фактический физический раздел (включая жесткий диск, CD-ROM, USB), игнорируя другие виртуальные разделы. еслиall = trueВсе разделы возвращаются. Тип возврата[]PartitionStat, каждому разделу соответствуетPartitionStatструктура:

// src/github.com/shirou/gopsutil/disk/
type PartitionStat struct {
  Device     string `json:"device"`
  Mountpoint string `json:"mountpoint"`
  Fstype     string `json:"fstype"`
  Opts       string `json:"opts"`
}
  • Device: идентификатор раздела, в Windows этоC:такие форматы;
  • Mountpoint: точка монтирования, то есть начальная позиция пути к файлу раздела;
  • Fstype: Тип файловой системы, в Windows обычно используется FAT, NTFS и т. д., в Linux есть ext, ext2, ext3 и т. д.;
  • Opts: опция, зависящая от системы.

Например:

func main() {
  infos, _ := disk.Partitions(false)
  for _, info := range infos {
    data, _ := json.MarshalIndent(info, "", "  ")
    fmt.Println(string(data))
  }
}

Вывод с моей машины Windows (показан только первый раздел):

{
  "device": "C:",
  "mountpoint": "C:",
  "fstype": "NTFS",
  "opts": "rw.compress"
}

Из приведенного выше вывода мой первый разделC:, тип файловой системыNTFS.

использование

перечислитьdisk.Usage(path string)получить путьpathИспользование диска, на котором он расположен, возвращаетUsageStatструктура:

// src/github.com/shirou/gopsutil/disk.go
type UsageStat struct {
  Path              string  `json:"path"`
  Fstype            string  `json:"fstype"`
  Total             uint64  `json:"total"`
  Free              uint64  `json:"free"`
  Used              uint64  `json:"used"`
  UsedPercent       float64 `json:"usedPercent"`
  InodesTotal       uint64  `json:"inodesTotal"`
  InodesUsed        uint64  `json:"inodesUsed"`
  InodesFree        uint64  `json:"inodesFree"`
  InodesUsedPercent float64 `json:"inodesUsedPercent"`
}
  • Path: путь, входящие параметры;
  • Fstype: тип файловой системы;
  • Total: общая емкость раздела;
  • Free: свободная мощность;
  • Used: используемая мощность;
  • UsedPercent: Использовать процент.

Например:

func main() {
  info, _ := disk.Usage("D:/code/golang")
  data, _ := json.MarshalIndent(info, "", "  ")
  fmt.Println(string(data))
}

Поскольку возвращается использование диска, путьD:/code/golangиD:возвращает тот же результат, только структуруPathПросто поля разные. Вывод программы:

{
  "path": "D:/code/golang",
  "fstype": "",
  "total": 475779821568,
  "free": 385225650176,
  "used": 90554171392,
  "usedPercent": 19.032789388496106,
  "inodesTotal": 0,
  "inodesUsed": 0,
  "inodesFree": 0,
  "inodesUsedPercent": 0
}

хозяин

подпакетhostВы можете получить информацию о хосте, такую ​​как время загрузки, номер версии ядра, информацию о платформе и так далее.

время загрузки

host.BootTime()Возвращает метку времени включения хоста:

func main() {
  timestamp, _ := host.BootTime()
  t := time.Unix(int64(timestamp), 0)
  fmt.Println(t.Local().Format("2006-01-02 15:04:05"))
}

Вышеупомянутое сначала получает время загрузки, а затем проходитtime.Unix()превратить его вtime.Timeтип, последний вывод2006-01-02 15:04:05Время формата:

2020-04-06 20:25:32

Информация о версии ядра и платформе

func main() {
  version, _ := host.KernelVersion()
  fmt.Println(version)

  platform, family, version, _ := host.PlatformInformation()
  fmt.Println("platform:", platform)
  fmt.Println("family:", family,
  fmt.Println("version:", version)
}

Запуск вывода на моей Win10:

10.0.18362 Build 18362
platform: Microsoft Windows 10 Pro
family: Standalone Workstation
version: 10.0.18362 Build 18362

конечный пользователь

host.Users()Возвращает информацию о пользователе, подключенном к терминалу, по одному для каждого пользователяUserStatструктура:

// src/github.com/shirou/gopsutil/host/host.go
type UserStat struct {
  User     string `json:"user"`
  Terminal string `json:"terminal"`
  Host     string `json:"host"`
  Started  int    `json:"started"`
}

Поля понятны с первого взгляда, см. пример:

func main() {
  users, _ := host.Users()
  for _, user := range users {
    data, _ := json.MarshalIndent(user, "", " ")
    fmt.Println(string(data))
  }
}

ОЗУ

существуетбыстрый старт, мы демонстрируем, как использоватьmem.VirtualMemory()получить информацию о памяти. Эта функция возвращает только информацию о физической памяти. мы также можем использоватьmem.SwapMemory()Получить информацию о памяти подкачки, информация хранится в структуреSwapMemoryStatсередина:

// src/github.com/shirou/gopsutil/mem/
type SwapMemoryStat struct {
  Total       uint64  `json:"total"`
  Used        uint64  `json:"used"`
  Free        uint64  `json:"free"`
  UsedPercent float64 `json:"usedPercent"`
  Sin         uint64  `json:"sin"`
  Sout        uint64  `json:"sout"`
  PgIn        uint64  `json:"pgin"`
  PgOut       uint64  `json:"pgout"`
  PgFault     uint64  `json:"pgfault"`
}

Значение поля легко понять,PgIn/PgOut/PgFaultМы сосредоточимся на этих трех областях. подкачка памятиСтраницаединиц, если происходит ошибка страницы (page fault), операционная система загрузит некоторые страницы с диска в память, и в то же время удалит некоторые страницы в памяти по определенному механизму.PgInпредставляет количество загруженных страниц,PgOutудаленные страницы,PgFaultКоличество ошибок страницы.

Например:

func main() {
  swapMemory, _ := mem.SwapMemory()
  data, _ := json.MarshalIndent(swapMemory, "", " ")
  fmt.Println(string(data))
}

процесс

processЕго можно использовать для получения информации о процессе, запущенном в данный момент в системе, создания нового процесса, выполнения некоторых операций над процессом и т. д.

func main() {
  var rootProcess *process.Process
  processes, _ := process.Processes()
  for _, p := range processes {
    if p.Pid == 0 {
      rootProcess = p
      break
    }
  }

  fmt.Println(rootProcess)

  fmt.Println("children:")
  children, _ := rootProcess.Children()
  for _, p := range children {
    fmt.Println(p)
  }
}

сначала позвониprocess.Processes()Получите все процессы, запущенные в текущей системе, и найдитеPidПроцесс 0, то есть первый процесс операционной системы, и последний вызовChildren()Вернитесь к его дочернему процессу. Есть много способов получить информацию о процессе, если вам интересно, вы можете проверить документацию~

Служба Windows

winservicesПодпакет может получать служебную информацию в системе Windows, которая используется внутриgolang.org/x/sysСумка. существуетwinservices, одна услуга соответствует однойServiceструктура:

// src/github.com/shirou/gopsutil/winservices/winservices.go
type Service struct {
  Name   string
  Config mgr.Config
  Status ServiceStatus
  // contains filtered or unexported fields
}

mgr.Configдля пакетаgolang.org/x/sysСтруктура в структуре детализирует тип службы, тип запуска (автоматический/ручной), путь к двоичному файлу и другую информацию:

// src/golang.org/x/sys/windows/svc/mgr/config.go
type Config struct {
  ServiceType      uint32
  StartType        uint32
  ErrorControl     uint32
  BinaryPathName   string
  LoadOrderGroup   string
  TagId            uint32
  Dependencies     []string
  ServiceStartName string
  DisplayName      string
  Password         string
  Description      string
  SidType          uint32
  DelayedAutoStart bool
}

ServiceStatusСтруктура записывает состояние сервиса:

// src/github.com/shirou/gopsutil/winservices/winservices.go
type ServiceStatus struct {
  State         svc.State
  Accepts       svc.Accepted
  Pid           uint32
  Win32ExitCode uint32
}
  • State: статус службы, включая остановленную, работающую, приостановленную и т. д.;
  • Accepts: указывает, какие операции получает служба, включая паузу, возобновление, переключение сеанса и т. д.;
  • Pid: идентификатор процесса;
  • Win32ExitCode: Код состояния выхода приложения.

В приведенной ниже программе я вывожу в консоль имена, бинарные пути и статус всех служб в системе:

func main() {
  services, _ := winservices.ListServices()

  for _, service := range services {
    newservice, _ := winservices.NewService(service.Name)
    newservice.GetServiceDetail()
    fmt.Println("Name:", newservice.Name, "Binary Path:", newservice.Config.BinaryPathName, "State: ", newservice.Status.State)
  }
}

Обратите внимание, что вызовwinservices.ListServices()возвращениеServiceИнформация об объекте неполная, проходимNewService()Создайте службу с этим именем службы, затем вызовитеGetServiceDetail()метод получения подробной информации об услуге. не может пройти напрямуюservice.GetServiceDetail()звонить, потому чтоListService()В возвращаемом объекте отсутствуют необходимые дескрипторы системных ресурсов (для экономии ресурсов), вызываяGetServiceDetail()метод будетpanic! ! !

ошибки и тайм-ауты

Поскольку большинство функций связаны с низкоуровневыми системными вызовами, ошибки и тайм-ауты неизбежны. Почти все интерфейсы имеют два возвращаемых значения, второе как ошибку. В предыдущих примерах мы игнорировали ошибки для упрощения кода, в реальных условиях рекомендуется обрабатывать ошибки.

Кроме того, большинство интерфейсов парные, один безcontext.ContextПараметр типа и еще один с этим параметром типа для управления контекстом. Его можно обработать вовремя после возникновения ошибки или тайм-аута во внутреннем вызове, чтобы избежать длительного ожидания возврата. Фактически, безcontext.ContextПараметры функции находятся внутриcontext.Background()вызов с параметромcontext.Contextфункции:

// src/github.com/shirou/gopsutil/cpu_windows.go
func Times(percpu bool) ([]TimesStat, error) {
  return TimesWithContext(context.Background(), percpu)
}

func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
  // ...
}

Суммировать

gopsutilБиблиотека облегчает нам получение информации о машине, хорошо справляется с проблемами совместимости между различными системами и обеспечивает согласованный интерфейс. Есть также несколько подпакетов, таких какnet/dockerПредставления нет из-за нехватки места, и заинтересованная детская обувь может изучить ее самостоятельно.

Если вы найдете забавную и простую в использовании языковую библиотеку Go, вы можете отправить сообщение о проблеме в ежедневной библиотеке Go GitHub😄

Ссылаться на

  1. gopsutil GitHub:GitHub.com/meat/go PS…
  2. Перейти на ежедневный репозиторий GitHub:GitHub.com/Darenjun/go-of…

я

мой блог:darjun.github.io

Добро пожаловать, чтобы обратить внимание на мою общедоступную учетную запись WeChat [GoUpUp], учитесь вместе и добивайтесь прогресса вместе ~