记录Linux上的内存消耗
1. 概述
在我们的机器上运行的任何进程都需要内存。内存需求因进程而异。
有时我们需要监控内存使用情况。有时它会用于调试新创建的应用程序。或者它将用于查找服务器的整体内存使用情况。无论如何,第一步是记录内存使用情况。
在本教程中,我们将检查监控内存消耗的不同方法。
2. 使用free命令
我们想到的第一个检查内存使用情况的命令是free 命令。正如我们所知,此命令打印已用、空闲、缓冲和可用内存。
用法是:
free [options]
free命令有两种模式。一种是打印一次内存使用情况并退出,这是默认行为。另一种是连续打印。由于我们的目标是监控内存使用情况,因此我们将使用后一种模式。
让我们来看看它:
$ free -s 1 -h -c 3
total used free shared buff/cache available
Mem: 7.7G 2.9G 2.7G 175M 2.2G 4.4G
Swap: 0B 0B 0B
total used free shared buff/cache available
Mem: 7.7G 2.9G 2.7G 175M 2.2G 4.4G
Swap: 0B 0B 0B
total used free shared buff/cache available
Mem: 7.7G 2.9G 2.7G 176M 2.2G 4.4G
Swap: 0B 0B 0B
上面的命令每秒打印内存使用情况三次。
从结果中,我们可以看到总 RAM 为 7.7GB。其中,已使用 2.9GB。并且有 2.7GB 的免费 RAM。
让我们检查一下我们使用的选项:
- -s 1 : 设置打印结果的延迟;在这里,我们用了一秒钟
- -h:以人类可读的格式打印结果
- -c 3 : 设置打印结果的次数
正如我们所见,当我们需要长时间监控内存使用情况时,这些选项就派上用场了。此外,我们可以将输出重定向到一个文件。这样,我们可以在以后需要时参考它。
3. 使用top命令
top 命令在 Linux 用户中也是典型的free命令。但是,此命令提供了有关 CPU、内存和进程的更多信息。
默认情况下,运行此命令会以交互模式启动命令。并打印所有正在运行的进程及其对各种系统资源的使用情况。用户可以从此屏幕与任何进程进行交互。
为了持续监控内存消耗,我们必须使用top命令提供的批处理模式选项。 让我们来看看它:
$ top -b -d1 -o +%MEM > memory.log
上面的命令将结果重定向到memory.log文件。并且它每秒都会有top命令的结果。
让我们检查一下我们在这里使用的不同选项:
- -b:启用批处理模式,不接受用户输入
- -d1:在每个结果之间设置 1 秒的延迟
- -o +%MEM:覆盖默认排序选项以使用*%MEM列值;+*号用于降序排序
此命令会将所有进程的详细信息记录到memory.log文件中。这样,我们还可以看到使用更多内存的进程。
另一方面,如果我们只想记录整体内存消耗,我们可以使用grep 命令进行过滤。 让我们看看它是如何工作的:
$ top -b -d1 -o +%MEM | grep -A1 'KiB Mem'
KiB Mem : 8072956 total, 2813224 free, 3001308 used, 2258424 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 4596252 avail Mem
--
KiB Mem : 8072956 total, 2813224 free, 3001308 used, 2258424 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 4596252 avail Mem
--
KiB Mem : 8072956 total, 2813224 free, 3001308 used, 2258424 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 4596252 avail Mem
在这里,我们使用了与之前尝试过的相同的top命令。除此之外,我们还使用了grep命令来过滤与内存相关的信息。结果,我们可以看到它打印了主内存和交换内存的使用情况。我们需要按ctrl-c退出命令。
为了显示交换内存使用情况,我们在grep命令中使用**-A1选项在匹配行下方打印一行。
4. 使用sar命令
让我们看看另一个用于打印系统信息的命令。**sar 命令打印系统活动信息。**它还包括一个连续打印使用统计信息的选项。
与我们之前看到的其他两个命令不同,这会打印有关内存使用情况的更多信息。
一般用法是:
sar [ options ] [ <interval> [ <count> ] ]
让我们看一个示例用法:
$ sar -o memory.log -r 1 3 --human
Linux 4.15.0-76-generic (slave-node) 04/21/22 _x86_64_ (4 CPU)
15:00:23 kbmemfree kbavail kbmemused %memused kbbuffers kbcached kbcommit %commit kbactive kbinact kbdirty
15:00:24 2.7G 4.4G 5.0G 65.2% 779.4M 1012.5M 7.5G 97.4% 3.8G 605.7M 84.0k
15:00:25 2.7G 4.4G 5.0G 65.2% 779.4M 1012.5M 7.5G 97.4% 3.8G 605.8M 120.0k
15:00:26 2.7G 4.4G 5.0G 65.2% 779.4M 1012.6M 7.5G 97.4% 3.8G 605.9M 156.0k
Average: 2.7G 4.4G 5.0G 65.2% 779.4M 1012.5M 7.5G 97.4% 3.8G 605.8M 120.0k
上面的结果表明它打印了三次内存细节,延迟一秒。它还打印了该会话的平均值。
为了得到这个结果,我们使用了以下选项:
- -o:使用此标志将输出捕获到以二进制格式指定的文件名
- -r:打印内存统计信息;默认情况下,它会打印 CPU 详细信息
- 1:我们给了 1 秒作为间隔
- 3:打印3次结果
- –human:以人类可读的格式显示结果
运行此命令后,我们将在当前目录中创建一个名为*memory.log的新文件。*由于此文件是二进制格式,我们必须使用带有 -f选项的 sar 命令来读取它。
即使我们使用了*-o选项,该命令也会将相同的信息打印到屏幕上。如果我们想将其作为守护进程运行,我们可以将此输出重定向到/dev/null*。
5. 使用vmstat命令
**vmstat 命令 用于显示有关内存、CPU、磁盘和进程的信息。**与sar命令类似,vmstat命令也监视系统资源。这也提供了很多关于他们状态的信息。
用法是:
vmstat [options] [delay [count]]
让我们检查一下如何运行此命令:
$ vmstat 1 3 -a -S M -w -t
procs -----------------------memory---------------------- ---swap-- -----io---- -system-- --------cpu-------- -----timestamp-----
r b swpd free inact active si so bi bo in cs us sy id wa st IST
0 0 0 2747 605 3855 0 0 1 20 1 0 1 0 98 1 0 2022-04-21 15:00:35
0 0 0 2747 605 3855 0 0 0 0 222 428 1 0 99 0 0 2022-04-21 15:00:36
0 0 0 2747 605 3855 0 0 0 0 138 341 1 0 100 0 0 2022-04-21 15:00:37
从结果中,我们可以看到内存使用情况和其他统计信息被打印了三次。
让我们看看我们给出的不同选项:
- 1:延迟打印统计信息
- 3:我们想要打印统计信息的次数
- -a:打印活跃和不活跃的内存信息;默认情况下,它打印缓冲区和缓存信息
- -SM:告诉以 MB 为单位打印统计信息
- -w:设置宽模式以适应大值
- -t:在结果中打印时间戳
6. /proc/meminfo文件
最后,让我们检查一下proc文件系统中的meminfo文件。**该文件包含所有与内存相关的信息。**事实上,free和top命令使用这个文件来收集内存使用信息。
我们可以cat 这个文件来查看它的内容。但这会给我们一次信息。所以我们可以写一个单行脚本来连续打印内存参数。
让我们检查一下:
$ while true; do cat /proc/meminfo | grep 'MemTotal\|MemFree'; echo; sleep 1; done
MemTotal: 8072956 kB
MemFree: 2813452 kB
MemTotal: 8072956 kB
MemFree: 2812972 kB
MemTotal: 8072956 kB
MemFree: 2812576 kB
在这里,我们有一个无限的 while 循环来访问*/proc/meminfo文件。然后它被提供给grep命令以过滤MemTotal和MemFree字段。我们可以根据需要向grep命令添加更多字段。然后我们回显一个空行作为分隔符。最后,我们sleep一秒钟并重复整个过程,直到用户按下ctrl-c*。