Linux Top 命令指南
top
命令允许用户监视 Linux 上的进程和系统资源使用情况,它是系统管理员工具箱中最有用的工具之一,并且在每个发行版中都预装了它。与 ps
等其他命令不同,它是交互式的,我们可以浏览进程列表、终止进程,等等。本文中,我们将了解如何使用 top
命令。
Getting started
top
命令非常简单,只需要在终端中输入 top
即可。top
指令将启动一个交互式命令行应用程序,如下所示,输出的上半部分包含有关进程和资源使用情况的统计信息,下半部分包含当前运行的进程的列表。可以使用箭头键和页面向上/向下键浏览列表。如果你想退出,只需按 q
键。
1 | $ top |
top
有许多变体,但在本文的其余部分中,我们将讨论最常见的变体 — props -ng
包附带的变体,下面来运行验证体验下:
1 | $ top -v |
在 top
的界面中发生了相当多的事情,将在下一节中对其逐一进行分析。
了解 top 的界面 - the summary area
第一小节中 top
的输出界面,我们可以比较明显的看到被分成了两个部分,这个小节中我们将关注在上半部分信息,这部分一般被称之为:summary area
系统时间、正常运行时间和用户会话
- 系统时间:当前系统的时间(21:07:28)
- 正常运行:系统运行时长(21 days, 4:31)
- 活动用户会话个数:1
1 | top - 21:07:28 up 21 days, 4:31, 1 user, |
活动用户会话包括 TTY
和 PTY
两种。实际上,如果您通过桌面环境登录到 Linux 系统,然后启动终端模拟器,您将发现将有两个活动会话。
TTY: 通过命令行或桌面环境在系统上物理地运行
PTY: 终端模拟器窗口或通过 SSH
如果我们期望得到更多关于活动用户会话的信息,可以通过 who
命令来得到,如下:
1 | $ who |
内存使用情况
Memory
部分显示的是关于系统内存使用情况的信息,如下:
1 | KiB Mem : 33554432 total, 31188208 free, 513488 used, 1852736 buff/cache |
Mem
和 Swap
分别显示的是 RAM
和 swap
空间信息;当 RAM
使用率接近满时,RAM
中不经常使用的区域将被写入 Swap
空间,以便稍后需要时检索。但是,由于访问磁盘的速度很慢,过分依赖 Swap
可能会损害系统性能。
关于 Swap
- 物理内存就是计算机的实际内存大小,由RAM芯片组成的。虚拟内存则是虚拟出来的、使用磁盘代替内存。虚拟内存的出现,让机器内存不够的情况得到部分解决。当程序运行起来由操作系统做具体虚拟内存到物理内存的替换和加载(相应的页与段的虚拟内存管理)。这里的虚拟内存即所谓的 swap;
- 当用户提交程序,然后产生进程,在机器上运行。机器会判断当前物理内存是否还有空闲允许进程调入内存运行,如果有那么则直接调入内存进行运行;如果没有,那么会根据优先级选择一个进程挂起,把该进程交换到swap中等待,然后把新的进程调入到内存中运行。根据这种换入和换出,实现了内存的循环利用,让用户感觉不到内存的限制。从这也可以看出swap扮演了一个非常重要的角色,就是暂存被换出的进程。
- 内存与swap之间是按照内存页为单位来交换数据的,一般Linux中页的大小设置为4kb。而内存与磁盘则是按照块来交换数据的
total
、free
、used
就是这些单词含义所描述的一样,分别是当前对应空间的总大小、空闲大小、已使用大小。avail mem
值指的是可以分配给进程而不会导致更多的交换的内存量。
Linux
内核层面上总是以不同的方式来尝试减少访问磁盘的次数;它在 RAM
中维护一个“磁盘缓存(disk cache)”,存储磁盘中经常使用的区域,另外,磁盘写被存储到一个“磁盘缓冲区(disk buffer)”,内核最终将它们写到磁盘上。它们消耗的总内存是 buff/cache
值。这看起来像是一件坏事,但实际上不是,原因是缓存使用的内存将在需要时分配给进程。
任务-Tasks
Tasks
部分显示的是有关系统上运行的进程的统计信息
1 | Tasks: 33 total, 1 running, 31 sleeping, 0 stopped, 1 zombie |
total
比较好理解,它表示的就是当前系统正在运行的进程总数。但是对于其他几个状态相关的数字,我们需要了解一点 Linux
内核如何处理进程的背景知识。
进程执行是 I/O 限制的工作(如读取磁盘)和 cpu 限制的工作(如执行算术操作)的混合模式。当一个进程执行 I/O 时,CPU 是空闲的,所以 os 在这段时间切换到执行其他进程。此外,该操作系统允许一个给定的进程执行非常短的时间,然后它切换到另一个进程。这就是操作系统“多任务处理”的表现。做所有这些需要我们跟踪流程的“状态”。在 Linux 中,进程可能处于以下状态:
1、Runnable (R): 处于这种状态的进程要么在 CPU 上执行,要么存在于运行队列中,准备执行。
2、Interruptible sleep(S): 处于这种状态的进程在等待事件完成。
3、Uninterruptible sleep (D): 在这种情况下,一个进程正在等待一个 I/O 操作完成。
4、Stopped (T): 这些进程已经被一个作业控制信号(如按 Ctrl+Z)停止,或者因为它们正在被跟踪。
5、Zombie (Z): 僵尸进程
一个进程可以创建许多子进程,当父进程仍然存在时,这些子进程是可以退出的,但是,这些数据结构必须保留下来,直到父进程获得子进程的状态。这种数据结构仍然存在的终止进程称为僵尸进程。D 和 S 状态都是在 top
信息中体现为 sleeping
,T 状态体现为 stopped
,Z 状态体现为 zombie
。
CPU 使用情况
CPU
使用情况,显示了在各种任务上花费的 CPU
时间的百分比。
1 | %Cpu(s): 0.3 us, 0.4 sy, 0.0 ni, 90.3 id, 0.0 wa, 0.0 hi, 0.0 si, 9.0 st |
us
指的是 CPU
在用户空间中执行进程所花费的时间。类似地,sy
指的就是运行内核空间进程所花费的时间。Linux
中使用 nice
值来表示进程的优先级,值越高,优先级越低,后面我们会了解到,默认的 nice
值是可以被修改的。在手动设置 nice 的情况下,执行进程所花费的时间显示为 ni
值。ni
后面是 id
,它是 CPU
保持空闲的时间,大多数操作系统在 CPU
空闲时将其设置为“省电模式”。接下来是 wa
值,它是 CPU
等待 I/O
完成所花费的时间。
中断(Interrupt)是向处理器发出的有关需要立即关注的事件的信号;外设通常使用硬件中断来告知系统有关事件的信息,例如键盘上的按键。另一方面,软件中断是由于处理器上执行的特定指令而产生的。在这两种情况下,操作系统都将处理它们,处理硬件中断和软件中断所花费的时间分别由hi和si给出。
在虚拟化环境中,会将一部分 CPU
资源分配给每个虚拟机(VM
)。操作系统会检测到何时有工作要做,如果检测到他需要执行但是由于 CPU
在其他 VM
上繁忙而无法执行时,以这种方式浪费的时间就是“窃取”时间,显示为st
。
平均负载-Load average
load average
部分表示的是在最近 1、5 和 15 分钟内的系统平均“负载”。
1 | load average: 0.11, 0.07, 0.07 |
负载是对系统执行的计算工作量的度量。在 Linux
上,负载是在任何给定时刻处于 R
和 D
状态的进程数。load average
值为您提供了必须等待多长时间才能完成任务的相对度量。这里有几个小例子,我们来直观的理解下这两个概念。
- 1、在单核心系统上,
load average
为 0.4 意味着系统只完成了它能完成的 40% 的工作。load average
为 1 意味着系统正好处于满负荷状态——即使添加一点点额外的工作,系统也会过载。一个load average
为 2.12 的系统意味着它超载了 112% 的工作,超出了它的处理能力。 - 2、在多核系统上,应该首先用
load average
除以CPU
核数,以得到类似的度量。
此外,load average
实际上并不是我们大多数人所知道的典型的平均负载。它是一个“指数移动平均”,这意味着以前的 load average
的一小部分被考虑到当前的值(关于这个点,可以通过这篇文章来了解更多技术细节)。
了解 top 的界面 - the task area
summury area
相对简单,通过它我们可以快速了解到当前系统运行的一些摘要统计信息。但是一个细节性的信息,我们只能通过 task area
中来得到。
1 | PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND |
先来说明下各个列的含义:
项目 | 解释 |
---|---|
PID | 这是进程ID ,一个惟一的正整数,用于标识进程。 |
USER | 这是启动进程的用户的“有效”用户名(映射到用户ID )。Linux 为进程分配一个真实的用户 ID 和一个有效的用户ID ;后者允许进程代表另一个用户进行操作。(例如,非 root 用户可以提升到 root 用户来安装软件) |
PR NI | “NI” 字段显示进程的 “nice” 值,“PR” 字段是从内核的角度显示了进程的调度优先级,“nice” 值影响的是进程的优先级。 |
VIRT, RES, SHR and %MEM | VIRT 、RES 、SHR 这三个字段都与进程的内存消耗有关。VIRT 是一个进程所消耗的内存总量。这包括程序代码、进程在内存中存储的数据,以及已经 swap 到磁盘的任何内存区域。RES是进程在 RAM 中消耗的内存,%MEM 表示这个值占总可用 RAM 的百分比。最后,SHR 是与其他进程共享的内存量。 |
S | 表示进程状态 |
TIME+ | TIME+ 列表示的是进程自启动以来所使用的总 CPU 时间,精确到百分之一秒。 |
COMMAND | COMMAND 列表示的是当前进程的名称。 |
top 命令的使用示例
到目前为止,我们已经讨论了 top
的界面信息所描述的含义。但是,top
除了显示这个信息之外,它还可以管理进程,并且我们可以控制 top
输出的各个方面。在本节中,我们将举几个例子。(在下面的大多数例子中,你必须在 top
运行时按下一个键。这些按键是区分大小写的,所以如果你在大写锁定状态下按了k,你实际上已经按了一个k
,但是这个命令并不会工作)
kill 进程
如果你想杀死一个进程,只要在top
运行时按k
。这将出现一个提示,它将询问进程的进程ID
并按enter
。
1 | PID to signal/kill [default pid = 384] |
当然上面的这段输出的后面是可以手动输入进程 ID
,下面的 34444444444444 就是手动输入的进程ID
1 | PID to signal/kill [default pid = 384] 34444444444444 |
如果保留此空白,top
将使用一个SIGTERM
,它允许进程优雅地终止。如果您想强制终止进程,您可以在这里输入SIGKILL
。你也可以在这里输入信号号,例如,SIGTERM
的数字是 384,而 SIGKILL
的数字是。如果你将进程ID
留空并直接按enter
,它将终止列表中最顶端的进程。正如前面提到的,我们也可以使用箭头键滚动,并通过这种方式更改想要终止的进程。
排序进程列表
使用像 top
这样的工具的一个最常见的原因是找出哪个进程消耗的资源最多。我们可以按以下键排序列表:
- M:用于按内存使用情况排序
- P:来按
CPU
使用率排序 - N:按进程
ID
排序 - T:来按运行时间排序
默认情况下,top
按降序显示所有结果,但是我们可以通过按R键切换到升序。还可以使用-o
开关对列表进行排序。例如,如果想排序进程的CPU
使用量,可以这样做:1
top -o %CPU
显示线程列表而不是进程列表
前面已经介绍过 Linux
如何在进程之间切换。我们知道,进程是不共享内存或其他资源的,这使得这种切换相当慢。和其他操作系统一样,Linux
支持一种“轻量级”的替代方案,称为“线程”。“线程”是进程的一部分,“线程”可以共享内存和其他资源的某些区域,同时它们也可以像进程一样并发运行。默认情况下,top
在其输出中显示一个进程列表。如果想列出线程代替进程,按 H
即可,此时 “Tasks”
行将显示的是 “Threads”
,显示的是线程的数量,而不是进程的数量。
1 | 1 Threads: 351 total, 2 running, 349 sleeping, 0 stopped, 0 zombie |
细心的读者可能会发现, summury area
中的 “Tasks”
行已经改变成 “Threads”
的了,但是在 task area
中,对应的列表中的属性却没有任何更改,那既然进程和线程不同,这怎么可能呢? 原因是在 Linux
内核内部,线程和进程使用相同的数据结构进行处理,因此,每个线程都有自己的ID
、状态等等。如果我们要切换回进程视图,则再次按 H
即可。此外,也可以使用 top -H
在默认情况下显示线程。
显示进程完整路径
默认情况下,COMMAND
列下的所有进程名显示的都是摘要名,如果我们期望显示当前进程的完成路径,可以通过按 c
来切换视角,或者直接使用 top -c
来启动交互界面。
以树形结构显示父子进程
可以通过在 top
交互中按 V
来切到 forest view
视角,即以以树形结构显示父子进程。
1 | 432 root 20 0 84760 5852 4984 S 0.0 0.0 0:00.01 - /usr/sbin/sshd -D |
列出用户的进程
要列出某个用户的进程,请在top
运行时按 u
。然后,输入用户名,或者留空以显示所有用户的进程;或者直接通过 top -u xxx
来指定 xxx
用户的所有进程信息。
1 | KiB Swap: 2097148 total, 2097148 free, 0 used. 31179088 avail Mem |
过滤进程
如果我们需要处理许多进程,那么简单的排序实际上对我们的帮助并不是很大。那么在这种情况下,我们可以按 o
来激活 top
的过滤模式,然后通过输入一个过滤器表达式来过滤到我们的目前进程。过滤器表达式是指定属性和值之间关系的语句,例如:
- COMMAND=java: 进程名=java 的
- !COMMAND=java: 进程名 !=java 的
- %CPU>3.0: CPU > 3.0 的
如果要清除所有过滤条件的话,按=
即可。
总结
本文主要是对
A Guide to the Linux “Top” Command
这篇文章的一些内容翻译,感谢原作者提供的分享
top
命令对于监视和管理 Linux
系统上的进程非常有帮助,本文只是从表面做了一些简单的介绍,还有很多我们没有涉及到的内容;例如,如何在 top
中添加更多的列。更多信息,可以通过运行 man top
查看 man
页面,来进行更深层面的学习。
Linux Top 命令指南