使用uptime命令查看平均负载结果如下
# uptime
04:13:44 up 3 days, 1 min, 2 users, load average: 0.05, 0.05, 0.05
# 其中load average:0.05, 0.05, 0.05
# 分别表示过去1分钟,5分钟,15分钟的平均负载
# man uptime解释如下:
# System load averages is the average number of processes that are either in a runnable or uninterruptable state. A process in
# a runnable state is either using the CPU or waiting to use the CPU. A process in uninterruptable state is waiting for some
# I/O access, eg waiting for disk. The averages are taken over the three time intervals. Load averages are not normalized for
# the number of CPUs in a system, so a load average of 1 means a single CPU system is loaded all the time while on a 4 CPU sys‐
# tem it means it was idle 75% of the time.
平均负载指的是单位时间内,系统处于可运行状态和不可中断状态的平均进程数,也就是平均活跃进程数。可运行状态指的是正在使用CPU或正在等待CPU的进程,也就是ps命令中查看的处于R(Running或Runnable)状态的进程,不可中断状态的进程则处于内核态关键流程中的进程,并且这些流程是不可打断的,比如常见的等待硬件设备的IO响应,也就是ps命令查看的D(Uninterruptible Sleep,也成为Disk Sleep)状态,不可中断状态实际上是系统对进程和硬件设备的一种保护机制。
CPU使用类别有:
CPU使用率就是除了空闲时间外的其他时间占总CPU时间的百分比:
c p u 使 用 率 = 1 − 空 闲 时 间 / 总 c p u 时 间 cpu使用率=1-空闲时间/总cpu时间 cpu使用率=1−空闲时间/总cpu时间
平均负载指的是单位时间内,处于可运行状态和不可运行状态的进程数,所以不仅包括了正在使用CPU的进程,还包括等待CPU和等待I/O的进程,而CPU使用率是单位时间内CPU繁忙情况的统计,跟平均负载不一定完全对应。如:
CPU 使用率是最直观和最常用的系统性能指标,更是我们在排查性能问题时,通常会关注的第一个指标。所以我们更要熟悉它的含义,尤其要弄清楚用户(%user)、Nice(%nice)、系统(%system) 、等待 I/O(%iowait) 、中断(%irq)以及软中断(%softirq)这几种不同 CPU 的使用率。比如说:
碰到 CPU 使用率升高的问题,你可以借助 top、pidstat 等工具,确认引发 CPU 性能问题的来源;再使用 perf 等工具,排查出引起性能问题的具体函数
Linux是一个多任务操作系统,它支持远大于CPU数量的任务同时运行,这些任务并非真正同时运行,而是因为系统在很短时间内,将CPU轮流分配给他们,造成多任务同时运行的错觉。而在每个任务运行前,需要系统事先帮它设置好CPU寄存器和程序计数器(Program Counter,PC)
CPU寄存器是CPU内置的容量很小,但是速度极快的内存,而程序计数器则是用来存储CPU正在执行的指令位置,或即将执行的下一条指令位置,他们都是CPU在运行任何任务前必须依赖的环境,因此也叫CPU上下文
CPU上下文切换就是把前一个任务的CPU上下文(CPU寄存器和程序计数器)保存起来,然后加载新任务的上下文到这些寄存器和程序计数器,最后再跳转到程序计数器所指的新位置,运行新任务
根据任务的不同CPU上下文切换可以分为几个不同的场景,也就是进程上下文切换,线程上下文切换以及中断上下文切换。
不管是那种上下文切换,需要注意的是:
Linux按照特权等级,把进程的运行空间分为内核空间和用户空间,分别对应CPU特权等级的Ring 0 和 Ring 3。
也就是进程可以在用户空间运行,也可以在内核空间运行,进程在用户空间运行时,称为进程的用户态,陷入内核空间的时候,被称为进程的内核态
从用户态到内核态的切换需要通过系统调用来完成,比如当查看文件内容时,就需要多次系统调用来完成,先调用open()打开文件,然后调用read()读取文件内容,并调用write()将内容写到标准输出,最后再调用close文件
而系统调用的过程中会将CPU寄存器里原来用户态的指令位置保存起来,接着为了执行内核态代码,CPU寄存器需要更新为内核态指令的新位置,最后再跳转到内核态运行内核任务。
系统调用结束后,CPU寄存器需要恢复原来保存的用户态,再切换到用户空间,继续运行进程,所以,一次系统调用,实际上发生了2此CPU上下文切换
不过,需要注意的是,系统调用过程中,并不会涉及到虚拟内存等进程用户态的资源,也不会切换进程。这跟我们通常所说的进程上下文切换是不一样的:
所以,**系统调用过程通常称为特权模式切换,而不是上下文切换。**但实际上,系统调用过程中,CPU 的上下文切换还是无法避免的。
进程是由内核来管理和调度的,进程的切换只能发生在内核态。所以,进程的上下文不仅包括了虚拟内存、栈、全局变量等用户空间的资源,还包括了内核堆栈、寄存器等内核空间的状态。
因此,进程的上下文切换就比系统调用时多了一步:在保存当前进程的内核状态和 CPU 寄存器之前,需要先把该进程的虚拟内存、栈等保存下来;而加载了下一进程的内核态后,还需要刷新进程的虚拟内存和用户栈。
保存上下文和恢复上下文并不是免费的需要内核再CPU上运行才能完成
每次上下文切换都需要几十纳秒到数微秒的 CPU 时间。这个时间还是相当可观的,特别是在进程上下文切换次数较多的情况下,很容易导致 CPU 将大量时间耗费在寄存器、内核栈以及虚拟内存等资源的保存和恢复上,进而大大缩短了真正运行进程的时间。
另外,我们知道, Linux 通过 TLB(Translation Lookaside Buffer)来管理虚拟内存到物理内存的映射关系。当虚拟内存更新后,TLB 也需要刷新,内存的访问也会随之变慢。特别是在多处理器系统上,缓存是被多个处理器共享的,刷新缓存不仅会影响当前处理器的进程,还会影响共享缓存的其他处理器的进程。
进程切换时才需要切换上下文,换句话说,只有在进程调度的时候,才需要切换上下文。Linux 为每个 CPU 都维护了一个就绪队列,将活跃进程(即正在运行和正在等待 CPU 的进程)按照优先级和等待 CPU 的时间排序,然后选择最需要 CPU 的进程,也就是优先级最高和等待 CPU 时间最长的进程来运行。
触发进程调度到CPU运行的场景:
线程与进程最大的区别在于,线程是调度的基本单位,而进程则是资源拥有的基本单位。所谓内核中的任务调度,实际上的调度对象是线程;而进程只是给线程提供了虚拟内存、全局变量等资源。
当线程发生上下文切换就分为两种情况:
同为上下文切换,可以看出同进程内的线程切换要比多进程间的切换消耗更少的资源,这也是多线程代替多进程的一个优势
为了快速响应硬件事件,中断程序会打断进程的正常调度和执行,转而调用中断处理程序,响应设备事件,而在打断其他进程时,就需要将进程当前的状态保存下来,这样在中断结束后,进程仍然可以从原来的状态中恢复运行,跟进程上下文不同,中断上下文切换不涉及进程的用户态,所以中断过程打断了一个正处于用户态的进程,也不需要保存和恢复这个进程的虚拟内存,全局变量等用户态资源,中断上下文,其实只包括内核态终端服务程序执行所必须的状态,包括CPU寄存器,内核堆栈,硬件中断等参数。
对同一个 CPU 来说,中断处理比进程拥有更高的优先级,所以中断上下文切换并不会与进程上下文切换同时发生。同样道理,由于中断会打断正常进程的调度和执行,所以大部分中断处理程序都短小精悍,以便尽可能快的执行结束。
另外,跟进程上下文切换一样,中断上下文切换也需要消耗 CPU,切换次数过多也会耗费大量的 CPU,甚至严重降低系统的整体性能。所以,当你发现中断次数过多时,就需要注意去排查它是否会给你的系统带来严重的性能问题。
cswch ,表示每秒自愿上下文切换(voluntary context switches)的次数,
nvcswch ,表示每秒非自愿上下文切换(non voluntary context switches)的次数。
这两个指标可以通过pidstat -w
查看,其中:
关于上下文切换的瓶颈分析:
watch -d "cat /proc/interrupts"
文件来分析具体的中断类型。中断其实是一种异步的事件处理机制,可以提高系统的并发处理能力。由于中断处理程序会打断其他进程的运行,所以,为了减少对正常进程运行调度的影响,中断处理程序就需要尽可能快地运行。如果中断本身要做的事情不多,那么处理起来也不会有太大问题;但如果中断要处理的事情很多,中断服务程序就有可能要运行很长时间。特别是,中断处理程序在响应中断时,还会临时关闭中断。这就会导致上一次中断处理完成之前,其他中断都不能响应,也就是说中断有可能会丢失。
Linux将中断处理过程分为上半部和下半部:
例如:网卡接收到数据包后,会通过硬件中断的方式,通知内核有新的数据到了。这时,内核就应该调用中断处理程序来响应它。对上半部来说,既然是快速处理,其实就是要把网卡的数据读到内存中,然后更新一下硬件寄存器的状态(表示数据已经读好了),最后再发送一个软中断信号,通知下半部做进一步的处理。而下半部被软中断信号唤醒后,需要从内存中找到网络数据,再按照网络协议栈,对数据进行逐层解析和处理,直到把它送给应用程序。
所以,这两个阶段你也可以这样理解:
实际上,上半部会打断 CPU 正在执行的任务,然后立即执行中断处理程序。而下半部以内核线程的方式执行,并且每个 CPU 都对应一个软中断内核线程,名字为 “ksoftirqd/CPU 编号”,比如说, 0 号 CPU 对应的软中断内核线程的名字就是 ksoftirqd/0。不过要注意的是,软中断不只包括了刚刚所讲的硬件设备中断处理程序的下半部,一些内核自定义的事件也属于软中断,比如内核调度和 RCU 锁(Read-Copy Update 的缩写,RCU 是 Linux 内核中最常用的锁之一)等。
查看中断信息:
# cat /proc/softirqs | awk '{print $1,$2,$3,$4} '
CPU0 CPU1 CPU2 CPU3
HI: 0 2 0
TIMER: 52776094 26302251 0
NET_TX: 54647 3 0
NET_RX: 3299726 839641 0
BLOCK: 241695 358027 0
BLOCK_IOPOLL: 0 0 0
TASKLET: 10020 103 0
SCHED: 6887846 4866827 0
HRTIMER: 0 0 0
RCU: 7585671 5658226 0
# 第一,要注意软中断的类型,也就是这个界面中第一列的内容。从第一列你可以看到,软中断包括了 10 个类别,分别对应不同的工作类型。比如 NET_RX 表示网络接收中断,而 NET_TX 表示网络发送中断。
# 第二,要注意同一种软中断在不同 CPU 上的分布情况,也就是同一行的内容。正常情况下,同一种中断在不同 CPU 上的累积次数应该差不多。比如这个界面中,NET_RX 在 CPU0 和 CPU1 上的中断次数基本是同一个数量级,相差不大。
mpstat
:常用的多核 CPU 性能分析工具,用来实时查看每个 CPU 的性能指标,以及所有 CPU 的平均指标。
pidstat
:一个常用的进程性能分析工具,用来实时查看进程的 CPU、内存、I/O 以及上下文切换等性能指标。
uptime
:查看系统平均负载,可以结合pidstat,mpstat进一步分析排查
vmstat
:查看上下文切换和中断次数异常,可以结合pidstat进一步排查
perf top/record/report -g
:查看系统和进程的CPU使用状况
execsnoop
:监控进程调用,系统默认没有
dstat
:查看系统整体状态,可以结合pidstat,strace,perf进一步排查
sar -n DEV 1
:查看网络情况,后续可以再结合tcpdump进一步排查
watch -d cat /proc/softirqs || cat /proc/interrupts
:监控中断状态
pstree
:查看进程之间的父子关系
mpstat 是一个常用的多核 CPU 性能分析工具,用来实时查看每个 CPU 的性能指标,以及所有 CPU 的平均指标。
# 1. 显示所有CPU的指标,并在间隔5秒输出一组数据
# mpstat -P ALL 5 1
Linux 3.10.0-957.el7.x86_64 (localhost.localdomain) 07/29/2020 _x86_64_ (2 CPU)
04:34:45 AM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
04:34:50 AM all 0.30 0.00 0.60 0.00 0.00 0.00 0.00 0.00 0.00 99.09
04:34:50 AM 0 0.20 0.00 0.60 0.00 0.00 0.20 0.00 0.00 0.00 99.00
04:34:50 AM 1 0.40 0.00 0.80 0.00 0.00 0.00 0.00 0.00 0.00 98.80
Average: CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
Average: all 0.30 0.00 0.60 0.00 0.00 0.00 0.00 0.00 0.00 99.09
Average: 0 0.20 0.00 0.60 0.00 0.00 0.20 0.00 0.00 0.00 99.00
Average: 1 0.40 0.00 0.80 0.00 0.00 0.00 0.00 0.00 0.00 98.80
# 输出完毕后会计算这段时间内的平均值,也就是Average
pidstat 是一个常用的进程性能分析工具,用来实时查看进程的 CPU、内存、I/O 以及上下文切换等性能指标。
# 1. 间隔5秒后输出一组数据
# pidstat -u 5 1
Linux 3.10.0-957.el7.x86_64 (localhost.localdomain) 07/29/2020 _x86_64_ (2 CPU)
04:36:32 AM UID PID %usr %system %guest %CPU CPU Command
04:36:37 AM 0 2607 0.00 0.20 0.00 0.20 1 sshd
04:36:37 AM 0 2628 0.00 0.40 0.00 0.40 1 bash
04:36:37 AM 1000 30315 0.40 0.20 0.00 0.60 1 mysqld
04:36:37 AM 0 114958 0.20 0.00 0.00 0.20 0 pidstat
Average: UID PID %usr %system %guest %CPU CPU Command
Average: 0 2607 0.00 0.20 0.00 0.20 - sshd
Average: 0 2628 0.00 0.40 0.00 0.40 - bash
Average: 1000 30315 0.40 0.20 0.00 0.60 - mysqld
Average: 0 114958 0.20 0.00 0.00 0.20 - pidstat
# 输出完毕后会计算这段时间内的平均值,也就是Average
# 2. w查看上下文切换相关数据,t表示输出线程信息,默认只显示进程信息
# pidstat -wt 5 1
Linux 3.10.0-957.el7.x86_64 (localhost.localdomain) 07/29/2020 _x86_64_ (2 CPU)
06:02:08 AM UID TGID TID cswch/s nvcswch/s Command
06:02:13 AM 0 3 - 1.31 0.00 ksoftirqd/0
06:02:13 AM 0 - 3 1.31 0.00 |__ksoftirqd/0
06:02:13 AM 0 7 - 2.43 0.00 migration/0
06:02:13 AM 0 - 7 2.43 0.00 |__migration/0
06:02:13 AM 0 9 - 40.67 0.00 rcu_sched
...
Average: UID TGID TID cswch/s nvcswch/s Command
Average: 0 3 - 1.31 0.00 ksoftirqd/0
Average: 0 - 3 1.31 0.00 |__ksoftirqd/0
Average: 0 7 - 2.43 0.00 migration/0
Average: 0 - 7 2.43 0.00 |__migration/0
Average: 0 9 - 40.67 0.00 rcu_sched
Average: 0 - 9 36.01 0.00 |__rcu_sched
...
# UID: The real user identification number of the task being monitored.
# USER: The name of the real user owning the task being monitored.
# PID: The identification number of the task being monitored.
# cswch/s: Total number of voluntary context switches the task made per second. A voluntary context switch occurs when a task blocks because it requires a resource that is unavailable.表示每秒自愿上下文切换(voluntary context switches)的次数
# nvcswch/s: Total number of non voluntary context switches the task made per second. A involuntary context switch takes place when a task executes for the duration of its time slice and then is forced to relinquish the processor.非自愿上下文切换,则是指进程由于时间片已到等原因,被系统强制调度,进而发生的上下文切换。
# Command:The command name of the task.
# -d 展示 I/O 统计数据,-p 指定进程号,间隔 1 秒输出 3 组数据
# pidstat -d -p 4344 1 3
06:38:50 UID PID kB_rd/s kB_wr/s kB_ccwr/s iodelay Command
06:38:51 0 4344 0.00 0.00 0.00 0 app
06:38:52 0 4344 0.00 0.00 0.00 0 app
06:38:53 0 4344 0.00 0.00 0.00 0 app
# kB_rd/s:Number of kilobytes the task has caused to be read from disk per second.每秒读的 KB 数
# kB_wr/s:Number of kilobytes the task has caused, or shall cause to be written to disk per second.每秒写的 KB 数
# kB_ccwr/s:Number of kilobytes whose writing to disk has been cancelled by the task. This may occur when the task truncates some dirty pagecache. In this case, some IO which another task has been accounted for will not be happening.任务已取消对磁盘的写入的千字节数。当任务truncates一些脏页面时,可能会发生这种情况。在这种情况下,其他任务已经考虑的一些IO将不会发生。
vmstat 是一个常用的系统性能分析工具,主要用来分析系统的内存使用情况,也常用来分析 CPU 上下文切换和中断的次数。
# 1. 每隔5秒输出1组数据
# vmstat 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 19712 158884 0 2959688 0 0 6 31 71 51 11 1 88 0 0
0 0 19712 158984 0 2959704 0 0 0 0 258 413 0 1 99 0 0
0 0 19712 159020 0 2959704 0 0 0 0 251 413 0 1 99 0 0
0 0 19712 158876 0 2959704 0 0 0 0 258 420 0 1 99 0 0
0 0 19712 158504 0 2959704 0 0 0 0 261 420 0 1 99 0 0
# 其中第一组数据是系统运行至今的平均数据
# 第二组开始时每隔5s的系统资源情况
# Procs
# r: The number of runnable processes (running or waiting for run time).正在运行和等待 CPU 的进程数。
# b: The number of processes in uninterruptible sleep.处于不可中断睡眠进程数
# Memory
# swpd: the amount of virtual memory used.已被使用的虚拟内存
# free: the amount of idle memory.空闲内存
# buff: the amount of memory used as buffers.被用于buffer的内存
# cache: the amount of memory used as cache.被用于cache的内存
# Swap
# si: Amount of memory swapped in from disk (/s).
# so: Amount of memory swapped to disk (/s).
# IO
# bi: Blocks received from a block device (blocks/s).
# bo: Blocks sent to a block device (blocks/s).
# System
# in: The number of interrupts per second, including the clock.每秒中断数
# cs: The number of context switches per second.每秒上下文切换数
# CPU
# These are percentages of total CPU time.
# us: Time spent running non-kernel code. (user time, including nice time)
# sy: Time spent running kernel code. (system time)
# id: Time spent idle. Prior to Linux 2.5.41, this includes IO-wait time.
# wa: Time spent waiting for IO. Prior to Linux 2.5.41, included in idle.
# st: Time stolen from a virtual machine. Prior to Linux 2.6.11, unknown.
perf 是 Linux 2.6.31 以后内置的性能分析工具。它以性能事件采样为基础,不仅可以分析系统的各种事件和内核性能,还可以用来分析指定应用程序的性能问题。
# -g表示开启调用关系采样
# perf top -g
Samples: 833 of event 'cpu-clock', Event count (approx.): 97742399
Overhead Shared Object Symbol
7.28% perf [.] 0x00000000001f78a4
4.72% [kernel] [k] vsnprintf
4.32% [kernel] [k] module_get_kallsym
3.65% [kernel] [k] _raw_spin_unlock_irqrestore
...
# 输出结果中,第一行包含三个数据,分别是采样数(Samples)、事件类型(event)和事件总数量(Event count)。
# 比如这个例子中,perf 总共采集了 833 个 CPU 时钟事件,而总事件数则为 97742399。
# 第一列 Overhead ,是该符号的性能事件在所有采样中的比例,用百分比来表示。
# 第二列 Shared ,是该函数或指令所在的动态共享对象(Dynamic Shared Object),如内核、进程名、动态链接库名、内核模块名等。
# 第三列 Object ,是动态共享对象的类型。比如 [.] 表示用户空间的可执行程序、或者动态链接库,而 [k] 则表示内核空间。
# 最后一列 Symbol 是符号名,也就是函数名。当函数名未知时,用十六进制的地址来表示。
# perf record 则提供了保存数据的功能
# perf record -g # 按Ctrl+C终止采样
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.452 MB perf.data (6093 samples) ]
# # 展示类似于perf top的报告
# perf report
pstree 就可以用树状形式显示所有进程之间的关系
# pstree | grep stress
|-docker-containe-+-php-fpm-+-php-fpm---sh---stress
| |-3*[php-fpm---sh---stress---stress]
常用的查看进程状态的工具
top - 07:42:47 up 3 days, 3:30, 3 users, load average: 0.37, 0.34, 0.18
Tasks: 127 total, 1 running, 126 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.2 us, 0.9 sy, 0.0 ni, 98.9 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 3861512 total, 120708 free, 836384 used, 2904420 buff/cache
KiB Swap: 2097148 total, 2077436 free, 19712 used. 2704060 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
2607 root 20 0 158856 6164 4732 S 4.3 0.2 5:45.27 sshd
50252 root 20 0 113180 1588 1332 S 4.3 0.0 0:00.79 bash
49990 root 20 0 319260 11780 4780 S 2.7 0.3 0:11.46 urlgrabber-ext-
30315 mysql 20 0 1810792 620164 9112 S 1.0 16.1 53:35.23 mysqld
49194 root 20 0 583032 27888 9604 S 0.3 0.7 0:11.04 yum
1 root 20 0 128148 4332 2680 S 0.0 0.1 1:02.07 systemd
# S 列(也就是 Status 列)表示进程的状态,有如下选项:
# |-- R 是 Running 或 Runnable 的缩写,表示进程在 CPU 的就绪队列中,正在运行或者正在等待运行。
# |-- D 是 Disk Sleep 的缩写,也就是不可中断状态睡眠(Uninterruptible Sleep),一般表示进程正在跟硬件交互,并且交互过程不允许被其他进程或中断打断。
# |-- Z 是 Zombie 的缩写,表示僵尸进程,也就是进程实际上已经结束了,但是父进程还没有回收它的资源(比如进程的描述符、PID 等)。
# |-- S 是 Interruptible Sleep 的缩写,也就是可中断状态睡眠,表示进程因为等待某个事件而被系统挂起。当进程等待的事件发生时,它会被唤醒并进入 R 状态。
# |-- I 是 Idle 的缩写,也就是空闲状态,用在不可中断睡眠的内核线程上。前面说了,硬件交互导致的不可中断进程用 D 表示,但对某些内核线程来说,它们有可能实际上并没有任何负载,用 Idle 正是为了区分这种情况。要注意,D 状态的进程会导致平均负载升高, I 状态的进程却不会。
# |-- T 或者 t,也就是 Stopped 或 Traced 的缩写,表示进程处于暂停或者跟踪状态。向一个进程发送 SIGSTOP 信号,它就会因响应这个信号变成暂停状态(Stopped);再向它发送 SIGCONT 信号,进程又会恢复运行(如果进程是终端里直接启动的,则需要你用 fg 命令,恢复到前台运行)。而当你用调试器(如 gdb)调试一个进程时,在使用断点中断进程后,进程就会变成跟踪状态,这其实也是一种特殊的暂停状态,只不过你可以用调试器来跟踪并按需要控制进程的运行。
# |-- X,也就是 Dead 的缩写,表示进程已经消亡,所以你不会在 top 或者 ps 命令中看到它。
这里补充一个孤儿进程和僵尸进程的区别
孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。
僵尸进程:正常情况下,当一个进程创建了子进程后,它应该通过系统调用 wait()
或者 waitpid()
等待子进程结束,回收子进程的资源;而子进程在结束时,会向它的父进程发送 SIGCHLD 信号,所以,父进程还可以注册 SIGCHLD 信号的处理函数,异步回收资源。如果父进程没这么做,或是子进程执行太快,父进程还没来得及处理子进程状态,子进程就已经提前退出,那这时的子进程就会变成僵尸进程。换句话说,父亲应该一直对儿子负责,善始善终,如果不作为或者跟不上,都会导致“问题少年”的出现。通常,僵尸进程持续的时间都比较短,在父进程回收它的资源后就会消亡;或者在父进程退出后,由 init 进程回收后也会消亡。一旦父进程没有处理子进程的终止,还一直保持运行状态,那么子进程就会一直处于僵尸状态。大量的僵尸进程会用尽 PID 进程号,导致新进程不能创建,所以这种情况一定要避免。
查看当前程序的快照信息
# ps aux | grep /app
root 4009 0.0 0.0 4376 1008 pts/0 Ss+ 05:51 0:00 /app
root 4287 0.6 0.4 37280 33660 pts/0 D+ 05:54 0:00 /app
root 4288 0.6 0.4 37280 33668 pts/0 D+ 05:54 0:00 /app
# S 表示可中断睡眠状态,
# D 表示不可中断睡眠状态,我们在前面刚学过,
# s 表示这个进程是一个会话的领导进程
# + 表示前台进程组。
# 进程组表示一组相互关联的进程,比如每个子进程都是父进程所在组的成员;而会话是指共享同一个控制终端的一个或多个进程组。
可以同时查看 CPU 和 I/O 这两种资源的使用情况
# 间隔1秒输出10组数据
# dstat 1 10
You did not select any stats, using -cdngy by default.
--total-cpu-usage-- -dsk/total- -net/total- ---paging-- ---system--
usr sys idl wai stl| read writ| recv send| in out | int csw
0 0 96 4 0|1219k 408k| 0 0 | 0 0 | 42 885
0 0 2 98 0| 34M 0 | 198B 790B| 0 0 | 42 138
0 0 0 100 0| 34M 0 | 66B 342B| 0 0 | 42 135
0 0 84 16 0|5633k 0 | 66B 342B| 0 0 | 52 177
0 3 39 58 0| 22M 0 | 66B 342B| 0 0 | 43 144
0 0 0 100 0| 34M 0 | 200B 450B| 0 0 | 46 147
0 0 2 98 0| 34M 0 | 66B 342B| 0 0 | 45 134
0 0 0 100 0| 34M 0 | 66B 342B| 0 0 | 39 131
0 0 83 17 0|5633k 0 | 66B 342B| 0 0 | 46 168
0 3 39 59 0| 22M 0 | 66B 342B| 0 0 | 37 134
sar 可以用来查看系统的网络收发情况,还有一个好处是,不仅可以观察网络收发的吞吐量(BPS,每秒收发的字节数),还可以观察网络收发的 PPS,即每秒收发的网络帧数。
# -n DEV 表示显示网络收发的报告,间隔1秒输出一组数据
$ sar -n DEV 1
15:03:46 IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s %ifutil
15:03:47 eth0 12607.00 6304.00 664.86 358.11 0.00 0.00 0.00 0.01
15:03:47 docker0 6302.00 12604.00 270.79 664.66 0.00 0.00 0.00 0.00
15:03:47 lo 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
15:03:47 veth9f6bbcd 6302.00 12604.00 356.95 664.66 0.00 0.00 0.00 0.05
# 第一列:表示报告的时间。
# 第二列:IFACE 表示网卡。
# 第三、四列:rxpck/s 和 txpck/s 分别表示每秒接收、发送的网络帧数,也就是 PPS。
# 第五、六列:rxkB/s 和 txkB/s 分别表示每秒接收、发送的千字节数,也就是 BPS。