监控和管理Linux进程

进程状态和生命周期

进程的定义

​ 进程是已启动的可执行程序中运行的实例。从进程创建那一刻起,它由以下项目组成:

  • 已分配内存的地址空间
  • 安全属性,包括所有权凭据和特权
  • 程序代码的一个或多个执行线程
  • 进程状态

进程的环境是包含以下项目的信息列表:

  • 本地和全局变量
  • 当前调度上下文
  • 分配的系统资源,如文件描述的网络端口

​ 现有的父进程复制自己的地址空间(成为进程分叉)来创建子进程结构。每个新进程分配有一个唯一进程ID(PID),满足跟踪和安全性之需。PID和父进程ID(PPID)是新进程环境的元素。任何进程都可以创建子进行。所有进程都是第一个系统进程的后代,在RedHat Linux中,第一个系统进程是systemd。

image-20250527112636921

​ 通过分叉进程,子进程继承安全性身份、过去和当前的文件描述符、端口和资源特权、环境变量,以及程序代码。随后,子进程可以执行其自己的代码程序。

​ 通常,父进程在子进程运行期间处于睡眠状态,设置一个在子进程完成时发出信号的等待请求。子进程退出后,他会关闭或丢弃其资源和环境,并留下僵停资源,即进程表中的一个条目。父进程在子进程退出时收到信号而被唤醒,清理子进程条目的进程表,由此释放子进程的最后一个资源,然后,父进程继续执行自己的程序代码。

描述进程状态

​ 在多任务处理操作系统中,每个CPU(或CPU核心)在一个时间上处理一个进程。在进程运行时,它对CPU时间和资源分配的直接要求会有变化。进程分配有一个状态,它随着环境要求而改变。

​ 以下图示和表格详细描述了Linux进程状态。

image-20250527115327090

Linux进程状态

名称 标志 内核定义的状态名称和描述
运行中 R TASK_RUNNING:进程正在CPU上执行,或者正在等待运行。处于运行中(或可运行)状态时,进程可能正在执行用户例程或内核例程(系统调用),或者已经排队并就绪。
睡眠 S TASK_INTERRUPTIBLEl:进程正在等待某一条件:硬件请求、系统资源访问或信号。当事件或信号满足该条件时,该进程将返回运行中。
睡眠 D TASK_UNINERRUPTIBLE:此进程也正在睡眠,但与S状态不同,不会响应信号。仅在进程终端可能会导致以外设备状态下使用。
睡眠 K TASK_KILLABLE:与不可中断的D状态相同,但有所修改,允许等待中的任务响应要被中止(彻底退出)的信号。实用程序通常将可中止的进程显示为D状态。
睡眠 I TASK_REPORT_IDLE:D状态的一个子集。在计算负载平均值时,内核不会统计这些进程。用于内核线程。设置了TASK_UNINTEERRUPTIBLE和TASK_NOLOAD标志。类似于TASK_KILLABLE,也是D状态的一个子集。它接受致命信号。
已停止 T TASK_STOPPED:进程已被停止(暂停),通常是通过用户或其他进程发出的信号。进程可以通过另一信号返回到运行中状态,继续执行(恢复)。
已停止 T TASK_TRACED:正在被调试的进程也会临时停止,并且共享同一个T状态标识。
僵停 Z EXIT_TRACED:子进程在退出时向父进程发送信号。除进程身份(PID)之外的所有资源都已释放。
僵停 X EXIT_DEAD:当父进程清理(获取)剩余的子进程结构时,进程现在已经彻底释放。次状态无法在进程列出实用程序中看到。

进程状态的重要性

​ 在对系统进行故障排除时,了解内核如何于进程通信以及进程如何相互通信非常重要。系统为每个新进程分配一个状态。top命令的S列或ps的STAT列显示每个进程的状态。在单CPU系统上,一次只能运行一个进程。您可以看到多个状态为R的进程。但是,并非所有进程都在连续运行。其中一些处于等待状态。

image-20250527134505011

image-20250527134807084

​ 使用信号来暂停、停止、恢复、终止或中断进程。进程可以捕获来自同一系统上内核、其他进程和其他用户的信号。

列出进程

​ ps命令用于列出当前进程的详细信息。

  • 用户标识符(UID),它确定进程的特权。
  • 唯一进程标识符(PID)。
  • 已用CPU量和实际时间。
  • 分配的内存量。
  • 进程stdout位置,称为控制终端。
  • 当前的进程状态。

重要:Linux版的ps命令支持以下选项格式:

  • UNIX(POSIX)选项,可以分组单必须以连字符开头。

  • BSD选项,可以分组但不可以与短划线同用。

  • GNU长选项,以爽连字符开头。

    例如:ps -aux 命令与ps aux命令不同。

​ 常见的ps命令aux选项显示包括无控制终端的进程在内的所有进程。长列表(lax选项)提供更多详细信息,并且通过避免查询用户名可用加快显示。相似的UNIX语法使用-ef选项来显示所有进程。在以下示例中,调度的内核线程显示在列表顶部,并用方括号括起。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
[kiosk@foundation0 ~]$ ps aux | tail -n 10
root 2313 0.0 0.0 0 0 ? I 13:44 0:00 [kworker/1:0-events_long]
root 2314 0.0 0.0 0 0 ? I 13:44 0:00 [kworker/0:0-mm_percpu_wq]
root 2336 0.0 0.0 0 0 ? I 13:45 0:00 [kworker/5:0-events_freezable]
root 2337 0.0 0.0 0 0 ? I 13:45 0:00 [kworker/4:2-events_power_efficient]
root 2363 0.0 0.0 0 0 ? I 13:49 0:00 [kworker/3:1-events]
root 2364 0.0 0.0 0 0 ? I 13:50 0:00 [kworker/6:0-mm_percpu_wq]
root 2366 0.0 0.0 0 0 ? I 13:52 0:00 [kworker/u256:0-events_unbound]
root 2367 0.0 0.0 0 0 ? I 13:55 0:00 [kworker/3:2-mm_percpu_wq]
kiosk 2376 0.0 0.0 225500 3720 pts/0 R+ 13:57 0:00 ps aux
kiosk 2377 0.0 0.0 220988 1040 pts/0 S+ 13:57 0:00 tail -n 10
[kiosk@foundation0 ~]$
[kiosk@foundation0 ~]$
[kiosk@foundation0 ~]$
[kiosk@foundation0 ~]$ ps lax | tail -n 10
1 0 2314 2 20 0 0 0 - I ? 0:00 [kworker/0:0-events]
1 0 2336 2 20 0 0 0 - I ? 0:00 [kworker/5:0-events_freezable]
1 0 2337 2 20 0 0 0 - I ? 0:00 [kworker/4:2-events_power_efficient]
1 0 2363 2 20 0 0 0 - I ? 0:00 [kworker/3:1-events]
1 0 2364 2 20 0 0 0 - I ? 0:00 [kworker/6:0-mm_percpu_wq]
1 0 2366 2 20 0 0 0 - I ? 0:00 [kworker/u256:0-nfsd4]
1 0 2367 2 20 0 0 0 - I ? 0:00 [kworker/3:2-events_freezable_power_]
1 0 2378 2 20 0 0 0 - I ? 0:00 [kworker/u256:1-events_unbound]
0 1000 2379 2304 20 0 225500 1568 - R+ pts/0 0:00 ps lax
0 1000 2380 2304 20 0 220988 980 pipe_r S+ pts/0 0:00 tail -n 10
[kiosk@foundation0 ~]$
[kiosk@foundation0 ~]$
[kiosk@foundation0 ~]$
[kiosk@foundation0 ~]$
[kiosk@foundation0 ~]$ ps -ef | tail -n 10
root 2314 2 0 13:44 ? 00:00:00 [kworker/0:0-events]
root 2336 2 0 13:45 ? 00:00:00 [kworker/5:0-events_freezable]
root 2337 2 0 13:45 ? 00:00:00 [kworker/4:2-events_power_efficient]
root 2363 2 0 13:49 ? 00:00:00 [kworker/3:1-events]
root 2364 2 0 13:50 ? 00:00:00 [kworker/6:0-mm_percpu_wq]
root 2366 2 0 13:52 ? 00:00:00 [kworker/u256:0-nfsd4]
root 2367 2 0 13:55 ? 00:00:00 [kworker/3:2-events_freezable_power_]
root 2378 2 0 13:57 ? 00:00:00 [kworker/u256:1-events_unbound]
kiosk 2381 2304 0 13:57 pts/0 00:00:00 ps -ef
kiosk 2382 2304 0 13:57 pts/0 00:00:00 tail -n 10

​ 默认情况下,不带选项运行ps命令会选择具有与当前用户相同的有效用户ID(EUID)并与运行命令所处同一终端关联的所有进程。僵停进程使用exiting 或defunct标签列出。

​ 您可以使用ps 命令 –forest 选项以树形格式显示进程,从而查看父进程和子进程之间的关系。

​ ps 命令的默认输出按进程ID编号排序。输出中似乎使用了时间顺序,但内核重复使用了进程ID,因此其顺序不如看起来那样有序。使用ps 命令-o 或 –sort 选项对输出进行排序。显示顺序与系统进程表的顺序匹配,在进程终止和进程运行时重新使用列表行。

控制作业

描述作业和会话

​ 借助作业控制shell功能,单个shell实例可以运行和管理多个命令。

​ 作业与在shell提示符中输入的每个管道相关联。该管道中的所有进程均是作业的一部分,并且是同一个进程组的成员。最小管道可以被视为在shell提示符处输入的唯一一个命令,创建仅含有一个成员的一个作业。

​ 一次只能有一个作业从特定终端窗口中读取输入和键盘生成的信号。属于改作业的进程是该终端的前台进程。

​ 该控制终端的后台进程是与该终端相关联的任何其他作业。终端的后台进程无法从终端读取输入或接收键盘生成的中断,但可以写入到终端。后台作业可能已停止(暂停),也可能正在运行。如果某个正在运行的后台作业尝试从终端读取内容,则该作业将自动暂停。

​ 每个终端在其自身的会话中运行,并且可以具有一个前台进程和任意数量的后台进程。一个作业仅在属于其控制终端的一个会话中。

​ ps命令在TTY列中显示控制终端的设备名称。某些进程(如系统守护进行)由系统启动,并不是从控制终端启动的。这些进程不是作业的成员,并且无法转至前台。ps命令在TTY列中针对这些进程显示一个问号(?)。

在后台运行作业

​ 任何命令或管道都可以在后台启动,只需在命令上附加一个&符号即可。Bash Shell显示作业编号(特定于会话的唯一编号)在新建子进程的PID。shell不等待子进程终止,而会显示shell提示符。

1
2
3
[kiosk@foundation0 ~]$ sleep 10000 &
[1] 2490
[kiosk@foundation0 ~]$

​ 如果将包含竖线(|)的命令发送到后台,将显示管道中最后一个命令的PID。所有管道进程仍是该作业的成员。

1
2
[kiosk@foundation0 ~]$ echo example_command | sort | mail -s "Sort Output" &
[3] 2553

​ 使用jobs命令显示当前shell会话的作业列表

1
2
3
[kiosk@foundation0 ~]$ jobs 
[1] Running sleep 10000 &
[2] Stopped example_command | sort | mail -s "Sort Output"

​ 使用fg命令将后台作业置于前台。使用(%jobNumber)格式将进程指定到前台。

1
2
3
[kiosk@foundation0 ~]$ fg %1
sleep 10000

​ 在上述例子中,sleep命令现在正在控制终端的前台运行。shell本身将睡眠,并等待这一子进程退出。

​ 若要将前台进程发送到后台,请首先在终端中按键盘生成暂停请求(Ctrl+z)。该作业将被置于后台并暂停。

1
2
3
4
[kiosk@foundation0 ~]$ fg %1
sleep 10000
^Z
[1]+ Stopped sleep 10000

​ ps命令 j选项显示与作业相关的信息。使用ps命令j选项来查找进行和会话信息。

  • PID是唯一的进程ID。
  • PPID是此进程的父进程(即启动(分叉)此进程的进程)的PID。
  • PGID是进程组首进程的PID,通常是作业管道中的第一个进程。
  • SID是会话首进程的PID,对于作业而言,这通常是正在其控制终端上运行的交互shell。

以下示例中,sleep命令当前已停止,其状态为T。

1
2
3
4
5
6
[kiosk@foundation0 ~]$ ps j
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
2297 2304 2304 2304 pts/0 2595 Ss 1000 0:00 -bash
2304 2490 2490 2304 pts/0 2595 T 1000 0:00 sleep 10000
2304 2533 2531 2304 pts/0 2595 T 1000 0:00 -bash
2304 2597 2597 2304 pts/0 2597 R+ 1000 0:00 ps j

使用bg命令和作业ID来启动暂停的进程。

1
2
3
4
5
6
7
8
[kiosk@foundation0 ~]$ bg %1
[1]+ sleep 10000 &
[kiosk@foundation0 ~]$ ps j
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
2297 2304 2304 2304 pts/0 2597 Ss 1000 0:00 -bash
2304 2490 2490 2304 pts/0 2597 S 1000 0:00 sleep 10000
2304 2533 2531 2304 pts/0 2597 T 1000 0:00 -bash
2304 2597 2597 2304 pts/0 2597 R+ 1000 0:00 ps j

​ 如果用户尝试退出带有暂停作业的终端窗口(会话),那么shell会发出警告。如果用户再次尝试立即退出,暂停的作业将会被终止。

注意:在前面示例中,【[1]+ sleep 10000 &】+符号表示此作业是当前的默认作业。如果不带%jobNumber参数使用作业控制命令,则对默认作业执行操作。-符号表示在当前默认作业完成时即将成为下一个默认作业。

中止进程

使用信号控制进程

​ 信号是传递至进程的软件中断。信号向执行中的程序报告事件。生成信号的时间可以是错误或外部事件(I/O请求或定时器过期),或者来自于显示使用信号发送命令或键盘序列。

​ 下表列出了系统管理员常用进程管理的基本信号。请通过短名称(HUP)或全称(SIGHUP)来指代信号。

基本进程信号

信号 名称 定义
1 HUP Hangup:报告终端控制进程的终止。也请求进程重新初始化(重新加载配置)而不终止。
2 INT Keyboard interrupt:导致程序终止。可以被拦截或处理。通过按INTR(中断)键序列(Ctrl+c)发送
3 QUIT Keyboard quit:与SIGINT相似;在终止时添加进程转储。通过按QUIT键序列(Ctrl+\)发送。
9 KILL Kill, unblockable:导致立即终止程序。无法被拦截、忽略或处理;总是致命的。
15(默认) TERM Terminate:导致程序终止。与SIGKILL不同,可以被拦截、忽略或处理。要求程序以”干净“的方式终止;它允许程序完成基本操作和自我清理后再终止。
18 CONT Continue:发送至进程使其恢复(若已停止)。无法拦截。即使被处理,也始终恢复进程。
19 STOP Stop, unblockable:暂停进程。无法被拦截或处理
20 TSTP Keyboard stop:和SIGSTOP不通,可以被拦截、忽略或处理。通过按暂停键序列(Ctrl+z)发送。

注意:信号编号视不通Linux硬件平台而异,但信号名称和含义都是标准的。建议再发送信号时使用信号名称,而不是数字。本章节适用于X86_64架构系统。

​ 每个信号都有一个默认操作,通常是如下操作之一:

  • Term:立即终止程序(退出)。

  • Core:保存程序的内存镜像(核心转储),然后终止。

  • Stop:停止运行中的程序(暂停),再等待继续(恢复)。

    程序通过实施处理程序例程来响应预期的事件信号,以忽略、替换或扩展信号的默认操作。

通过显示请求发送信号

​ 您可以想当前的前台进程发送信号,具体操作为案件键盘控制序列以暂停(Ctrl+z)、中止(Ctrl+c)或核心转储(Ctrl+\)该进程。不过,您可以使用信用发送命令向另一会话中的后台进程发送信号。

​ 您可以通过名称(例如 -HUP 或 -SIGHUP)或编号(相关的 -1 选项)来指定信号。用户可以中止自己的进程,但需要root权限才能终止其他人拥有的进程。

​ kill命令使用PID编号向进程发送信号。芮苒其名为kill,但您可以使用这个命令来发送任何信号,而不仅仅是终止程序的信号。您可以使用kill命令 -l选项列出所有可用信号的名称和编号。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
[kiosk@foundation0 ~]$ kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX
[root@foundation0 Videos]# ps -aux | grep sleep
root 2912 0.0 0.0 220956 1048 pts/0 S 17:09 0:00 sleep 1000
root 2913 0.0 0.0 220956 996 pts/0 S 17:10 0:00 sleep 2000
root 2914 0.0 0.0 220956 1012 pts/0 S 17:10 0:00 sleep 3000
root 2920 0.0 0.0 221668 2368 pts/0 S+ 17:10 0:00 grep --color=auto sleep
[root@foundation0 Videos]# kill 2912
[1] Terminated sleep 1000
[root@foundation0 Videos]# ps -aux | grep sleep
root 2913 0.0 0.0 220956 996 pts/0 S 17:10 0:00 sleep 2000
root 2914 0.0 0.0 220956 1012 pts/0 S 17:10 0:00 sleep 3000
root 2922 0.0 0.0 221668 2368 pts/0 S+ 17:10 0:00 grep --color=auto sleep
[root@foundation0 Videos]# kill -9 2913
[root@foundation0 Videos]# ps -aux | grep sleep
root 2914 0.0 0.0 220956 1012 pts/0 S 17:10 0:00 sleep 3000
root 2924 0.0 0.0 221668 2356 pts/0 S+ 17:11 0:00 grep --color=auto sleep
[2]- Killed sleep 2000
[root@foundation0 Videos]# kill -SIGTERM 2914
[root@foundation0 Videos]# ps -aux | grep sleep
root 2942 0.0 0.0 221668 2260 pts/0 S+ 17:11 0:00 grep --color=auto sleep
[3]+ Terminated sleep 3000

控制特定进程

​ 使用pkill命令向一个或多个符合选择条件的进程发送信号。选择条件可用是命令名称、特定用户拥有的进程,或所有系统范围进程。

​ 可用逐一向进程和会话发送信号,也可以集体发送。要终止一个用户的所有进程,可使用pkill命令。

​ 由于登录会话中的初始进程(会话首进程)设计为可以处理会话终止请求并忽略不想要的键盘信号,中断某一用户的所有进程和登录shell需要使用SIGKILL信号。

​ 首先,使用pgrep命令来确定要中止的PID编号。此命令的操作与pkill命令类似,大部分选项相同,但是pgrep命令列出进程而不是中止它们。

​ 使用pgrep命令和-l选项列出进程名称和ID。使用任一命令和-u选项来指定拥有进程的用户的ID。

1
2
3
4
5
6
7
8
[root@foundation0 home]# pgrep -l -u user03
3174 systemd
3179 (sd-pam)
3200 sshd
3207 bash
[root@foundation0 home]# pkill -SIGKILL -u user03
[root@foundation0 home]# pgrep -l -u user03
[root@foundation0 home]#

​ 当需要注意的进程在同一登录会话中时,可能不需要中止用户所有的进程。使用w命令来确定会话的控制终端,然后仅中止引用同一中断ID的进程。

​ 除非指定了SIGKILL,否则会话首进程(此处为Bash登录shell)可以成功处理中止请求并继续运行,但所有其他会话进程将被终止。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@foundation0 ~]# pgrep -l -u user03
3283 systemd
3287 (sd-pam)
3304 sshd
3313 bash
[root@foundation0 ~]# w -u user03
18:22:33 up 7:15, 2 users, load average: 0.00, 0.00, 0.00
USER TTY LOGIN@ IDLE JCPU PCPU WHAT
user03 pts/1 18:16 5:49 0.03s 0.03s -bash
[root@foundation0 ~]# pkill -t pts/1
# 此刻发现user03的bash会话首进程依然存在,有效忽略掉了中止信号
[root@foundation0 ~]# pgrep -l -u user03
3283 systemd
3287 (sd-pam)
3304 sshd
3313 bash
[root@foundation0 ~]# pkill -SIGKILL -t pts/1
# 使用SIGKILL信号,则会无视忽略,强制中止
[root@foundation0 ~]# pgrep -l -u user03

重要:管理员通常使用SIGKILL。

由于SIGKILL信号无法被处理或忽视,它总是致命的。然而,它会强制终止进程,而不允许被中断的进程运行自我清理例程。RedHat Linux建议先发送SIGTERM,然后尝试SIGINT;只有这两个都失败时,在尝试SIGKILL。

​ 您可以借助父进程和子进程关系应用相同的选择性进程终止。使用pstree命令查看系统或单个用户的进程树。使用父进程的PID中止其创建的所有子进程。父进程Bash登录Shell不通被终止,因为信号仅定向至它的子进程。

1
2
3
4
5
6
7
8
9
10
11
[root@foundation0 ~]# pstree -p kiosk
sshd(2255)───bash(2262)─┬─sleep(2296)
├─sleep(2297)
└─sleep(2298)
[root@foundation0 ~]# pkill -P 2262
[root@foundation0 ~]# pstree -p kiosk
sshd(2255)───bash(2262)
[root@foundation0 ~]# pkill -SIGKILL -P 2262
[root@foundation0 ~]# pstree -p kiosk
sshd(2255)───bash(2262)
[root@foundation0 ~]#

向多个进程发送信号

​ killall命令可以根据命令名称向多个进程发送信号。

1
2
3
4
5
6
7
8
[root@foundation0 ~]# ps aux | grep sleep
kiosk 2346 0.0 0.0 220956 988 pts/1 S 17:12 0:00 sleep 1000
kiosk 2347 0.0 0.0 220956 988 pts/1 S 17:12 0:00 sleep 2000
kiosk 2348 0.0 0.0 220956 1040 pts/1 S 17:12 0:00 sleep 3000
root 2350 0.0 0.0 221668 2212 pts/0 S+ 17:12 0:00 grep --color=auto sleep
[root@foundation0 ~]# killall sleep
[root@foundation0 ~]# ps aux | grep sleep
root 2360 0.0 0.0 221668 2268 pts/0 S+ 17:13 0:00 grep --color=auto sleep

​ 使用kill命令终止特定的作业。在作业编号上添加前缀百分号(%)

1
2
3
4
5
6
[kiosk@foundation0 ~]$ jobs
[1]+ Running sleep 3000 &
[kiosk@foundation0 ~]$ kill -SIGTERM %1
[kiosk@foundation0 ~]$ jobs
[1]+ Terminated sleep 3000
[kiosk@foundation0 ~]$ jobs

以管理员身份注销用户

​ 出于各种原因,您可能需要注销其他用户。一些可能的情景:用户做出了安全违规行为;用户可能过度使用了资源;用户的系统不响应;或者,用户不当访问了资料。在这些情形中,您必须以管理员身份使用信号来终止其会话。

​ 要注销某个用户,首先确定要终止的登录会话。使用w命令列出用户登录和当前运行的进程。记录TTY和FROM列,以确定要关闭的会话。

​ 所有用户登录会话都与某个中断设备(TTY)相关联。如果设备名称为pts/N,说明这时一个与图形终端窗口或远程登录会话相关联的伪终端。如果为ttyN,则说明用户位于一个系统控制台、替代控制台或其他直接连接的终端设备上。

1
2
3
4
5
6
[root@foundation0 ~]# w
17:49:39 up 1:06, 3 users, load average: 1.29, 0.29, 0.10
USER TTY LOGIN@ IDLE JCPU PCPU WHAT
kiosk pts/0 16:44 1.00s 0.22s 0.06s sshd: kiosk [priv]
kiosk pts/1 16:50 34.00s 0.05s 0.05s -bash
user01 tty2 17:49 1:05m 0.08s 0.07s /usr/libexec/gnome-session-binary

​ 查看会话登录时间,了解用户已登录该系统的时长。对于每个会话,当前作业占用的CPU资源(包括后台任务和子进程)位于JCPU列中。当前的前台进程CPU占用情况列在PCPU中。

监控进程活动

描述负载平均值

​ 负载平均值是Linux内核提供的一种度量,可以表示一段时间内感知的系统负载。它可用来粗略衡量待处理的系统资源请求数量,并确定系统负载的增减。

​ 根据处于可运行和不可中断状态的进程数,内核会每五秒收集一次当前的负载数。通过汇总这些数值,可以得到最近1分钟、5分钟和15分钟内的指数移动平均值。

负载平均值计算

​ 负载平均值代表一段时间内感知的系统负载。通过报告CPU上准备运行的进程数以及等待磁盘或网络I/O完成的进程数,Linux可以确定负载平均值。

  • 负载数是准备运行的进程数(进程状态为R)或等待I/O完成的进程数(进程状态为D)的运行平均值。
  • 一些UNIX系统仅考虑CPU使用率或运行列长度来指示系统负载。Linux还包含磁盘或网络利用率,因为与CPU负载一样,这些资源使用量较高会对系统性能产生重大影响。如果负载平均值很高但CPU活动很低,请检查磁盘和网络活动。

​ 负载平均值可以粗略衡量在执行其他任何作业之前,有多少进程当前在等待请求完成。请求可能是用于运行进程的CPU时间。或者,请求可能是让关键磁盘I/O操作完成;在其他作业请求完成之前,不能在CPU上运行该进程,即使CPU空闲也不行。无论是哪种方法,都会影响系统负载;系统的运行看起来会变慢,因为有进程正在等待运行。

解读负载平均值

​ uptime命令是显示当前负载平均值的一种方法。它可显示当前时间、计算机启动时长、运行的用户会话数以及当前的负载平均值。

1
2
[root@foundation0 ~]# uptime 
16:30:20 up 6:24, 1 user, load average: 0.07, 0.03, 0.01

​ 这三个负载平均值代表了最近1、5和15分钟的负载情况。它指出了系统负载似乎在增高还是降低。

​ 如果等待CPU处理的进程是负载平均值的主要贡献因素,则可以计算近似的每个CPU负载值以判断系统是否在遭遇显著的等待。

​ 使用lscpu命令来确定系统上存在的CPU数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@foundation0 ~]# lscpu 
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Address sizes: 45 bits physical, 48 bits virtual
Byte Order: Little Endian
CPU(s): 8
On-line CPU(s) list: 0-7
Vendor ID: GenuineIntel
BIOS Vendor ID: GenuineIntel
Model name: 13th Gen Intel(R) Core(TM) i9-13980HX
BIOS Model name: 13th Gen Intel(R) Core(TM) i9-13980HX
CPU family: 6
Model: 183
Thread(s) per core: 1
Core(s) per socket: 2
Socket(s): 4
Stepping: 1
BogoMIPS: 4838.40
Flags: fpu vme de pse tsc msr pae mce cx8 ...忽略....

​ 暂时不妨设想,需要CPU时间的进程是负载数的唯一贡献因素。然后您可以用显示的负载平均值除以系统中的逻辑CPU数。值低于1表示资源利用率适当,等待时间较短。值高于1表示资源饱和,而且有一些处理处于延迟。

​ 空闲CPU队列的负载数为0。每个等待CPU处理的进程都会使负载数加1.如果有一个进程在CPU上运行,则负载数为1;虽然资源(CPU)处于使用状态,单没有等待的请求。如果改进程运行了整整一分钟,那么它对这一分钟负载平均值的贡献就是1。

​ 不过,因为磁盘或忘了资源忙碌而等待关键I/O并处于不可中断睡眠状态的进行也包含在该计数内,而且会使负载平均值增大。虽然不能表示CPU使用率,但这些进程也被添加到队列数中,因为它们正在等待资源,并且在获取资源之前无法在CPU上运行。由于资源限制导致无法运行,因此这一指标仍被视为系统负载。

​ 在资源饱和之前,负载平均值将保持在1以下,因为几乎不会在队列中发现等待的认为。只有资源饱和导致请求留在排队状态并且被负载计算例程计数时,负载平均值才会增大。当资源使用率接近100%时,每个增加的请求将开始遭遇服务等待时间。

实时进程监控

​ top命令显示系统进程的动态视图,以及一个摘要标题,后跟一个进程或线程列表。与静态的ps命令输出不同,top命令以可配置的间隔持续刷新,而且也提供列重新排列、排序和突出显示功能。您可以对top设置进行持久更改。默认的top输出列如下:

  • 进程ID(PID)
  • 进程所有者用户名(USER)
  • 虚拟内存(VIRT)是进程正在使用的所有内存,包括常驻集合、共享库,以及任何映射或交换的内存页。(在ps命令中标题为VSZ)
  • 常驻内存(ERS)是进程所使用的物流内存,包括任何驻留2的共享对象(在ps命令中标题为RSS)
  • 进程状态(S)可以是以下状态之一:
    • D= 不可中断睡眠
    • R=运行中可运行
    • S=睡眠中
    • T=已停止或已跟踪
    • Z=僵停
  • CPU时间(TIME)是进程启动以来总的处理时间。可以切换为包含所有过去子进程的累计时间。
  • 进程命令名称(CMMMAND)。

top命令中的基本击键操作

用途
?或h 交互式击键操作的帮助。
l、t、m 切换到负载、线程和内存标题行。
1 标题张却换显示单独CPU信息或所有CPU汇总。
s 更改(屏幕)刷新率,以小数点的秒数表示(如0.5、1、5)
b 却换反色突出显示Running进程;默认为仅粗体。
Sheift+b 在显示中使用粗体,用于标题以及运行中的进程。
Sheift+h 切换线程;显示进程摘要或单独线程。
u、Sheift+u 过滤任何用户名(有效、真实)
Sheift+m 按照内存使用率,以降序方式对进程列表排序。
Sheift+p 按照处理器使用率,以降序方式对进程列表排序。
k 中止进程。如有提示,输入PID,在输入signal。
r 调整进程的nice值。若有提示,输入PID,再输入nice_value。(nice值为-20到19,值越低代表该进程优先级越高)
Sheift+w 写入(保存)当前的显示配置,一遍下一次重新启动top时使用
q 退出
f 通过启用或禁用字段的方式来管理列。也可以为top设置排序字段。(d选中或显示列,s切换该列进行排序,q退出设置)

注意:再安全模式下启动top命令时,s、k和r击键操作不可用。