Linux 如何获取 CPU 使用率

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11356330/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 13:43:37  来源:igfitidea点击:

How to get CPU usage

linuxgo

提问by Sebastián Grignoli

My Go program needs to know the current cpu usage percentage of all system and user processes.

我的 Go 程序需要知道当前所有系统和用户进程的 CPU 使用百分比。

How can I obtain that?

我怎样才能得到它?

采纳答案by bertimus9

I had a similar issue and never found a lightweight implementation. Here is a slimmed down version of my solution that answers your specific question. I sample the /proc/statfile just like tylerl recommends. You'll notice that I wait 3 seconds between samples to match top's output, but I have also had good results with 1 or 2 seconds. I run similar code in a loop within a go routine, then I access the cpu usage when I need it from other go routines.

我有一个类似的问题,但从未找到轻量级实现。这是我的解决方案的精简版,可以回答您的特定问题。我/proc/stat就像 tylerl 推荐的那样对文件进行采样。您会注意到我在样本之间等待 3 秒以匹配 top 的输出,但我也有 1 或 2 秒的良好结果。我在 go 例程中的循环中运行类似的代码,然后在需要时从其他 go 例程访问 cpu 使用情况。

You can also parse the output of top -n1 | grep -i cputo get the cpu usage, but it only samples for half a second on my linux box and it was way off during heavy load. Regular top seemed to match very closely when I synchronized it and the following program:

您还可以解析 的输出top -n1 | grep -i cpu以获取 cpu 使用情况,但它仅在我的 linux 机器上采样半秒,并且在重负载期间它会消失。当我将它与以下程序同步时,常规顶部似乎非常匹配:

package main

import (
    "fmt"
    "io/ioutil"
    "strconv"
    "strings"
    "time"
)

func getCPUSample() (idle, total uint64) {
    contents, err := ioutil.ReadFile("/proc/stat")
    if err != nil {
        return
    }
    lines := strings.Split(string(contents), "\n")
    for _, line := range(lines) {
        fields := strings.Fields(line)
        if fields[0] == "cpu" {
            numFields := len(fields)
            for i := 1; i < numFields; i++ {
                val, err := strconv.ParseUint(fields[i], 10, 64)
                if err != nil {
                    fmt.Println("Error: ", i, fields[i], err)
                }
                total += val // tally up all the numbers to get total ticks
                if i == 4 {  // idle is the 5th field in the cpu line
                    idle = val
                }
            }
            return
        }
    }
    return
}

func main() {
    idle0, total0 := getCPUSample()
    time.Sleep(3 * time.Second)
    idle1, total1 := getCPUSample()

    idleTicks := float64(idle1 - idle0)
    totalTicks := float64(total1 - total0)
    cpuUsage := 100 * (totalTicks - idleTicks) / totalTicks

    fmt.Printf("CPU usage is %f%% [busy: %f, total: %f]\n", cpuUsage, totalTicks-idleTicks, totalTicks)
}

It seems like I'm allowed to link to the full implementation that I wrote on bitbucket; if it's not, feel free to delete this. It only works on linux so far, though: systemstat.go

似乎我被允许链接到我在 bitbucket 上写的完整实现;如果不是,请随意删除它。不过,它目前只适用于 linux:systemstat.go

回答by Denys Séguret

You can use the os.execpackage to execute the pscommand and get the result.

您可以使用该os.exec包执行ps命令并获取结果。

Here is a program issuing the ps auxcommand, parsing the result and printing the CPU usage of all processes on linux :

这是一个发出ps aux命令的程序,解析结果并打印 linux 上所有进程的 CPU 使用率:

package main

import (
    "bytes"
    "log"
    "os/exec"
    "strconv"
    "strings"
)

type Process struct {
    pid int
    cpu float64
}

func main() {
    cmd := exec.Command("ps", "aux")
    var out bytes.Buffer
    cmd.Stdout = &out
    err := cmd.Run()
    if err != nil {
        log.Fatal(err)
    }
    processes := make([]*Process, 0)
    for {
        line, err := out.ReadString('\n')
        if err!=nil {
            break;
        }
        tokens := strings.Split(line, " ")
        ft := make([]string, 0)
        for _, t := range(tokens) {
            if t!="" && t!="\t" {
                ft = append(ft, t)
            }
        }
        log.Println(len(ft), ft)
        pid, err := strconv.Atoi(ft[1])
        if err!=nil {
            continue
        }
        cpu, err := strconv.ParseFloat(ft[2], 64)
        if err!=nil {
            log.Fatal(err)
        }
        processes = append(processes, &Process{pid, cpu})
    }
    for _, p := range(processes) {
        log.Println("Process ", p.pid, " takes ", p.cpu, " % of the CPU")
    }
}

回答by tylerl

The mechanism for getting CPU usage is OS-dependent, since the numbers mean slightly different things to different OS kernels.

获取 CPU 使用率的机制取决于操作系统,因为这些数字对不同的操作系统内核的含义略有不同。

On Linux, you can query the kernel to get the latest stats by reading the pseudo-files in the /proc/filesystem. These are generated on-the-fly when you read them to reflect the current state of the machine.

在 Linux 上,您可以通过读取文件/proc/系统中的伪文件来查询内核以获取最新的统计信息。这些是在您阅读它们以反映机器的当前状态时即时生成的。

Specifically, the /proc/<pid>/statfile for each process contains the associated process accounting information. It's documented in proc(5). You're interested specifically in fields utime, stime, cutimeand cstime(starting at the 14th field).

具体来说,/proc/<pid>/stat每个进程的文件都包含相关的进程记帐信息。它记录在proc(5) 中。你在领域特别感兴趣utimestimecutimecstime(在第14场首发)。

You can calculate the percentage easily enough: just read the numbers, wait some time interval, and read them again. Take the difference, divide by the amount of time you waited, and there's your average. This is precisely what the topprogram does (as well as all other programs that perform the same service). Bear in mind that you can have over 100% cpu usage if you have more than 1 CPU.

您可以很容易地计算百分比:只需读取数字,等待一段时间间隔,然后再次读取它们。取差值,除以您等待的时间,就是您的平均值。这正是该top程序所做的(以及执行相同服务的所有其他程序)。请记住,如果您有 1 个以上的 CPU,则 CPU 使用率可能会超过 100%。

If you just want a system-wide summary, that's reported in /proc/stat-- calculate your average using the same technique, but you only have to read one file.

如果您只想要一个系统范围的摘要,可以/proc/stat使用相同的技术计算您的平均值,但您只需阅读一个文件。

回答by c9s

Check out this package http://github.com/c9s/goprocinfo, goprocinfo package does the parsing stuff for you.

查看这个包http://github.com/c9s/goprocinfo, goprocinfo 包为你做解析的东西。

stat, err := linuxproc.ReadStat("/proc/stat")
if err != nil {
    t.Fatal("stat read fail")
}

for _, s := range stat.CPUStats {
    // s.User
    // s.Nice
    // s.System
    // s.Idle
    // s.IOWait
}

回答by Kyle Kloepper

Here is an OS independent solution using Cgoto harness the clock()function provided by C standard library:

这是一个独立于操作系统的解决方案,它使用Cgo来利用C 标准库提供的clock()函数:

//#include <time.h>
import "C"
import "time"

var startTime = time.Now()
var startTicks = C.clock()

func CpuUsagePercent() float64 {
    clockSeconds := float64(C.clock()-startTicks) / float64(C.CLOCKS_PER_SEC)
    realSeconds := time.Since(startTime).Seconds()
    return clockSeconds / realSeconds * 100
}

回答by tgogos

I recently had to take CPU usage measurements from a Raspberry Pi (Raspbian OS) and used github.com/c9s/goprocinfocombined with what is proposed here:

我最近不得不从 Raspberry Pi(Raspbian 操作系统)进行 CPU 使用率测量,并使用github.com/c9s/goprocinfo结合这里提出的内容:

The idea comes from the htopsource code and is to have two measurements (previous / current) in order to calculate the CPU usage:

这个想法来自htop源代码,并且有两个测量值(以前的/当前的)来计算 CPU 使用率:

func calcSingleCoreUsage(curr, prev linuxproc.CPUStat) float32 {

  PrevIdle := prev.Idle + prev.IOWait
  Idle := curr.Idle + curr.IOWait

  PrevNonIdle := prev.User + prev.Nice + prev.System + prev.IRQ + prev.SoftIRQ + prev.Steal
  NonIdle := curr.User + curr.Nice + curr.System + curr.IRQ + curr.SoftIRQ + curr.Steal

  PrevTotal := PrevIdle + PrevNonIdle
  Total := Idle + NonIdle
  // fmt.Println(PrevIdle, Idle, PrevNonIdle, NonIdle, PrevTotal, Total)

  //  differentiate: actual value minus the previous one
  totald := Total - PrevTotal
  idled := Idle - PrevIdle

  CPU_Percentage := (float32(totald) - float32(idled)) / float32(totald)

  return CPU_Percentage
}

For more you can also check https://github.com/tgogos/rpi_cpu_memory

有关更多信息,您还可以查看https://github.com/tgogos/rpi_cpu_memory