定期获取一个单个过程的CPU使用
1. 概述
我们经常需要在 Linux 命令行中通过当前正在运行的进程来获取或监控资源使用情况。当我们面对这种需求时,可能会出现两个方便的命令:ps 命令和top 命令。
默认情况下,它们会列出当前登录用户可以看到的所有进程的资源使用情况。但是,有时,我们希望定期记录特定进程的资源使用情况,例如 CPU 使用情况。
本教程将讨论做到这一点的最佳方法。
2. 问题介绍
假设我们想每两秒将特定进程的 CPU 使用率写入日志文件,以便稍后分析数据。
我们将基于ps和top命令构建我们的解决方案。
为了使我们的测试更简单,让我们使用*mpv *媒体播放器播放高清电影来模拟长时间运行且随机消耗 CPU 的目标进程。
3. CPU 使用率:ps与top
我们知道ps和 top命令都可以报告进程的 CPU 使用率。
在我们开始研究如何使用这些命令获取单个进程的 CPU 使用率之前,我们应该首先了解这两个命令如何计算它们的 CPU 使用率数据。
这很重要,因为它们的 CPU 使用率值具有不同的含义。
3.1. 使用ps命令了解 CPU 使用情况
我们先来看看 ps命令。ps 命令报告当前进程的快照状态。
但是,它的 CPU 使用率值并不是我们执行命令的时间点的实时使用指标。相反,ps命令提供的 CPU 使用率表示为在进程的整个生命周期内运行所花费时间的百分比。
因此,换句话说,它是进程在运行期间的平均 CPU 使用率。
接下来我们看看top命令是如何计算它的CPU使用值的。
3.2. 使用top命令了解 CPU 使用情况
与ps命令不同 ,top命令可以在交互式用户界面中显示进程的详细信息。此外,它以我们可以使用*-d*选项定义的时间间隔刷新结果。
它以不同于 ps命令的方式计算 CPU 使用值。
top命令计算自上次屏幕更新以来经过的 CPU 时间,以占总 CPU 时间的百分比表示。
例如,假设我们设置刷新间隔为两秒,刷新一次后CPU使用率报50%。使用率值“50%”表示在最后两秒内,该进程累计CPU运行时间为一秒。
**尽管ps和top 都以百分比形式报告 CPU 使用率值,但含义不同。**因此,我们应该根据需要选择合适的工具。否则,我们基于记录数据的分析可能会走向错误的方向。
4. 每两秒将 CPU 使用情况写入日志文件
现在,我们将讨论如何创建基于ps和top 的shell 脚本,以将给定进程的 CPU 使用情况写入日志文件。
前面说过,我们以正在运行的mpv进程为例。此外,我们将跳过示例脚本中的参数检查和错误处理部分。
4.1. 基于ps命令构建 Shell 脚本
我们可以使用命令“ ps -C PROCESS_NAME -o %cpu ”来检索给定进程的 CPU 使用率,例如:
$ ps -C mpv -o %cpu
%CPU
63.8
我们可以构建一个简单的 shell 脚本,每两秒将 CPU 使用率写入日志文件:
$ cat ./cpu_usage_ps.sh
#!/bin/bash
PNAME="$1"
LOG_FILE="$2"
while true ; do
echo "$(date) :: $PNAME[$(pidof ${PNAME})] $(ps -C ${PNAME} -o %cpu | tail -1)%" >> $LOG_FILE
sleep 2
done
上面的脚本需要两个参数:进程名称和日志文件路径。
我们将日志记录实现放在“ while true… ”中。因此,当我们启动脚本时,它会一直将给定进程的 CPU 使用率写入日志文件,直到我们手动终止它。
此外,我们将当前时间“ $(date)”、进程名称和 PID“ $PNAME[$(pidof ${PNAME})] ”与 CPU 使用数据一起写入日志文件。
接下来,让我们开始脚本:
$ ./cpu_usage_ps.sh mpv /tmp/log_ps.txt
然后,我们可以使用tail -f 命令来监控日志文件的变化:
$ tail -f /tmp/log_ps.txt
Fri Sep 3 10:05:08 PM CEST 2021 :: mpv[215406] 40.9%
Fri Sep 3 10:05:10 PM CEST 2021 :: mpv[215406] 40.9%
Fri Sep 3 10:05:12 PM CEST 2021 :: mpv[215406] 41.0%
Fri Sep 3 10:05:14 PM CEST 2021 :: mpv[215406] 41.1%
Fri Sep 3 10:05:16 PM CEST 2021 :: mpv[215406] 41.2%
Fri Sep 3 10:05:18 PM CEST 2021 :: mpv[215406] 41.2%
...
如输出所示,我们的脚本每两秒将mpv进程的 CPU 使用情况写入指定的日志文件。
4.2. 使用top命令批量打印单个进程状态
通常,top命令会以交互界面方式启动,显示进程状态。
但是,** -b选项告诉top命令以批处理模式运行**以将输出重定向到日志文件。
此外,我们需要使用*-d*选项设置刷新间隔。
例如,我们可以让top命令每两秒持续报告mpv进程的状态,直到我们手动杀死它:
$ top -b -d 2 -p $(pidof mpv)
top - 21:26:39 up 1 day, 12:05, 1 user, load average: 1.42, 1.35, 1.34
Tasks: 1 total, 0 running, 1 sleeping, 0 stopped, 0 zombie
%Cpu(s): 5.3 us, 4.8 sy, 1.6 ni, 87.2 id, 0.0 wa, 0.5 hi, 0.5 si, 0.0 st
MiB Mem : 31891.0 total, 6762.8 free, 10898.7 used, 14229.6 buff/cache
MiB Swap: 0.0 total, 0.0 free, 0.0 used. 16885.9 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
185292 kent 20 0 3077452 282804 82880 S 56.7 0.9 2:01.35 mpv
top - 21:26:41 up 1 day, 12:05, 1 user, load average: 1.47, 1.36, 1.35
( ... summary omitted ... )
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
185292 kent 20 0 3077452 283332 82880 S 58.0 0.9 2:01.41 mpv
top - 21:26:43 up 1 day, 12:05, 1 user, load average: 1.47, 1.36, 1.35
( ... summary omitted ... )
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
185292 kent 20 0 3077452 284124 82880 S 57.0 0.9 2:01.47 mpv
top - 21:26:45 up 1 day, 12:05, 1 user, load average: 1.43, 1.36, 1.34
( ... summary omitted ... )
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
185292 kent 20 0 3077452 284916 82880 S 53.5 0.9 2:01.54 mpv
^C
如上面的输出所示, top命令每两秒打印一次进程状态。在四次迭代后,我们通过按Ctrl-C终止了top命令。
根据这个问题,我们只需要CPU使用数据。因此,我们需要从该输出中提取时间戳和 CPU 使用率。
4.3. 基于top命令构建Shell脚本
awk 是处理文本的有力武器。因此,让我们将顶部输出通过管道传递给 awk命令来解决问题:
$ cat cpu_usage_top.sh
#!/bin/bash
PNAME="$1"
LOG_FILE="$2"
PID=$(pidof ${PNAME})
top -b -d 2 -p $PID | awk \
-v cpuLog="$LOG_FILE" -v pid="$PID" -v pname="$PNAME" '
/^top -/{time = $3}
$1+0>0 {printf "%s %s :: %s[%s] CPU Usage: %d%%\n", \
strftime("%Y-%m-%d"), time, pname, pid, $9 > cpuLog
fflush(cpuLog)}'
剧本不难理解。awk命令从top输出中提取所需的数据并重定向到日志文件。
我们应该注意,在awk命令结束时,我们必须调用fflush函数将任何新输出写入日志文件。
否则,它会缓冲输出,我们可能会在手动终止脚本时丢失数据。
现在,让我们试试这个脚本。首先,我们启动脚本并将mpv和日志文件*/tmp/log_top.txt*作为参数传递:
$ ./cpu_usage_top.sh mpv /tmp/log_top.txt
同样,我们转到日志文件并检查我们的脚本是否每两秒向其中写入预期数据:
$ tail -f /tmp/log_top.txt
2021-09-03 22:14:37 :: mpv[215406] CPU Usage: 40%
2021-09-03 22:14:39 :: mpv[215406] CPU Usage: 43%
2021-09-03 22:14:41 :: mpv[215406] CPU Usage: 40%
2021-09-03 22:14:43 :: mpv[215406] CPU Usage: 54%
2021-09-03 22:14:45 :: mpv[215406] CPU Usage: 57%
2021-09-03 22:14:47 :: mpv[215406] CPU Usage: 56%
...
如我们所见,我们的脚本按预期工作。