参考文献

系统信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# cat /etc/issue
Ubuntu 20.04.6 LTS \n \l

# cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04.6 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.6 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal

硬件信息

获取USER_HZ

1
getconf CLK_TCK

dmidecode

  • 使用dmidecode命令可以读取/dev/mem二进制文件并进行解析,然后以人类可读的格式转储计算机的DMI(或者SMBIOS)表内容,该表中包含了系统硬件组件的描述,以及其他有用的信息(例如: BIOS 序列号和版本信息).借助此表的信息,虽然可以不需要实际去机房查看硬件的型号,但是这也使得查询的信息可能不可靠
1
2
# 显示硬件系统部件
dmidecode -q

hdparm

1
2
# 在磁盘上执行测试性读取操作系统信息
hdparm -tT /dev/sda

lspci

1
2
# 罗列 PCI 设备
lspci -tv

lsusb

1
2
# 显示 USB 设备
lsusb -tv

lshw

  • 使用lshw命令可以查看服务器硬件配置的详细信息.使用它可以在支持DMI的x86或IA-64系统以及某些PowerPC机器上打印内存配置、固件版本、主板配置、CPU版本、CPU频率、缓存、总线速度等信息(已知PowerMac G4可以工作).目前该命令支持DMI(仅限x86和IA-64)、OpenFirmware设备树(仅限PowerPC)、PCI/AGP、CPUID(x86)、IDE/ATA/ATAPI、PCMCIA(仅在x86上测试)、SCSI和USB等信息的查看.
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
# lshw --help
Hardware Lister (lshw) - B.02.18
usage: lshw [-format] [-options ...]
lshw -version

-version print program version (B.02.18)

format can be
-html output hardware tree as HTML
-xml output hardware tree as XML
-json output hardware tree as a JSON object
-short output hardware paths
-businfo output bus information

options can be
-class CLASS only show a certain class of hardware
-C CLASS same as '-class CLASS'
-c CLASS same as '-class CLASS'
-disable TEST disable a test (like pci, isapnp, cpuid, etc. )
-enable TEST enable a test (like pci, isapnp, cpuid, etc. )
-quiet don't display status
-sanitize sanitize output (remove sensitive information like serial numbers, etc.)
-numeric output numeric IDs (for PCI, USB, etc.)
-notime exclude volatile attributes (timestamps) from output

# lshw -short

lsblk

  • 查看硬件型号

lscpu

  • 查看CPU信息

    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
    # CPU架构
    Architecture: x86_64
    CPU op-mode(s): 32-bit, 64-bit
    Byte Order: Little Endian
    CPU(s): 40
    On-line CPU(s) list: 0-39
    # 开启超线程,所以一核2线程
    Thread(s) per core: 2
    # 每个CPU 10核心
    Core(s) per socket: 10
    # 2个CPU
    Socket(s): 2
    NUMA node(s): 2
    Vendor ID: GenuineIntel
    CPU family: 6
    Model: 85
    Model name: Intel(R) Xeon(R) Silver 4210R CPU @ 2.40GHz
    Stepping: 7
    CPU MHz: 1000.132
    BogoMIPS: 4800.00
    # 开启虚拟化,可以按装虚拟机
    Virtualization: VT-x
    L1d cache: 32K
    L1i cache: 32K
    L2 cache: 1024K
    L3 cache: 14080K
    # 这个十分有用,特别是调用GPU的时候
    NUMA node0 CPU(s): 0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38
    NUMA node1 CPU(s): 1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39
    Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb cat_l3 cdp_l3 invpcid_single intel_ppin ssbd mba ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid cqm mpx rdt_a avx512f avx512dq rdseed adx smap clflushopt clwb intel_pt avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts pku ospke avx512_vnni md_clear flush_l1d arch_capabilities

内存

  • 查看内存信息

    1
    # cat /proc/meminfo

free

1
2
3
4
5
6
7
8
9
# free
total used free shared buff/cache available
Mem: 32888420 25741148 391076 16788 6756196 6664188
Swap: 0 0 0

#free -h
total used free shared buff/cache available
Mem: 31Gi 24Gi 485Mi 16Mi 6.4Gi 6.4Gi
Swap: 0B 0B 0B
  • total: 总内存量,包括物理内存和交换空间.
  • used: 已使用的内存数量,包含了共享内存.
  • free: 可用的内存数量.
  • shared: 被共享使用的内存数量.
  • buff/cache: 用于缓存文件系统的缓存内存数量.
  • available: 预计可立即使用的内存数量.
    • 这里尤其注意一下,最后一列的可用内存 available .available 不仅包含未使用内存,还包括了可回收的缓存,所以一般会比未使用内存更大.不过,并不是所有缓存都可以回收,因为有些缓存可能正在使用中.

vmstat

1
2
3
4
5
# vmstat
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 0 556156 139236 9329812 0 0 820 37 0 0 1 0 98 0 0

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
41
42
43
44
45
46
47
48
49
50
Procs
// 正在运行和等待 CPU 的进程数,“r”值大于CPU数量就是饱和.
r: The number of runnable processes (running or waiting for run time).
// 处于不可中断睡眠状态的进程数
b: The number of processes in uninterruptible sleep.

Memory
These are affected by the --unit option.
// 使用虚拟内存大小
swpd: the amount of virtual memory used.
// 可用内存大小
free: the amount of idle memory.
// 用作缓冲的内存大小
buff: the amount of memory used as buffers.
// 用作缓存的内存大小
cache: the amount of memory used as cache.
inact: the amount of inactive memory. (-a option)
active: the amount of active memory. (-a option)

Swap
These are affected by the --unit option.
// 如果si和so这些不为零,则说明内存不足
// 每秒从交换区写到内存的大小
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)
// 空闲时间(包括IO等待时间)
id: Time spent idle. Prior to Linux 2.5.41, this includes IO-wait time.
// 等待IO时间
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.
选项 描述
-a 显示活跃和非活跃内存
-f 显示子系统启动以来发生的fork数量
-m 显示slabinfo
-n 显示每列一次,与延迟时间配合使用vmstat -n 5
-s 显示内存相关统计
-d 显示磁盘相关统计
-p 显示指定磁盘分区的统计
-S 设置显示单位(K,M)
-t 显示时间戳
瓶颈类型 需要关注指标
CPU密集型 r高,us高,或者sy高,id很低
I/O密集型 b高,wa高
内存不足型 swpd高,si高(最关键),so高

/proc/meminfo

img

  • 上图来自 极客时间-Linux内核技术实战课
参数 说明 异常情况的值或者范围
MemTotal 物理内存总量 小于实际内存容量
MemFree 空闲内存 持续为 0 或非常低
MemAvailable 可用内存 持续为 0 或非常低
Buffers 块设备缓冲区 持续为 0
Cached 文件缓存内存 持续为 0
SwapCached 从交换区恢复的缓存内存 持续为 0
Active 活跃的内存 持续为 0 或与 MemTotal 差距过大
Inactive 不活跃的内存 异常大或异常小
Active(anon) 活跃的匿名内存 异常大,接近 MemTotal
Inactive(anon) 不活跃的匿名内存 异常大
Active(file) 活跃的文件缓存内存 持续为 0 或非常低
Inactive(file) 不活跃的文件缓存内存 持续为 0 或非常低
Unevictable 无法被回收的内存 持续为高值
Mlocked 被锁定的内存 持续为高值
SwapTotal 交换空间总量 持续为 0(未配置交换空间时)
SwapFree 可用的交换空间 持续为 0 或持续减少
Dirty 等待写入磁盘的内存 持续为高值
Writeback 正在写入磁盘的内存 持续为高值
AnonPages 匿名内存页 持续为高值
Mapped 映射到用户空间的内存 异常高或异常低
Shmem 共享内存 异常大
KReclaimable 可回收的内核缓存内存 持续为 0
Slab 内核数据结构使用的内存.kmalloc申请的内存则是体现在Slab这一项中,它又分为两部分,其中SReclaimable是指在内存紧张的时候可以被回收的内存,而SUnreclaim则是不可以被回收只能主动释放的内存 异常大
SReclaimable 可回收的 Slab 内存 持续为 0 或非常低
SUnreclaim 不可回收的 Slab 内存 异常大
KernelStack 内核栈的内存使用量 异常大
PageTables 内存分页表的内存使用量 异常大
NFS_Unstable 未提交到稳定存储的 NFS 页 异常大
Bounce Bounce 缓冲区内存 异常高(极少见)
WritebackTmp 写回临时存储的内存 异常高
CommitLimit 系统内存承诺限制 与 MemTotal 差距过大
Committed_AS 系统已承诺分配的内存 大于 CommitLimit 或异常大
VmallocTotal 可供分配的虚拟地址空间总量 异常小
VmallocUsed 已使用的虚拟地址空间.vmalloc申请的内存会体现在VmallocUsed这一项中 异常大
VmallocChunk 可用的最大连续虚拟地址空间块 异常小
Percpu 每个 CPU 使用的内存 异常大
HardwareCorrupted 被检测为硬件损坏的内存 异常大
AnonHugePages 匿名巨大页的内存 异常高
ShmemHugePages 共享内存中的巨大页数量 异常高
ShmemPmdMapped 使用 PMD 映射的共享内存页面数量 异常高
FileHugePages 文件映射中的巨大页数量 异常高
FilePmdMapped 使用 PMD 映射的文件页面数量 异常高
CmaTotal 预留给 CMA 的内存总量 异常大
CmaFree CMA 可用内存量 异常小
HugePages_Total 巨大页总数 异常小
HugePages_Free 未使用的巨大页数量 异常小
HugePages_Rsvd 保留但未使用的巨大页数量 异常小
HugePages_Surp 超额分配的巨大页数量 异常大
Hugepagesize 每个巨大页的大小 异常小
Hugetlb 使用的巨大页总量 异常大
DirectMap4k 4 KB 页大小映射的内存 异常小或为 0
DirectMap2M 2 MB 页大小映射的内存 异常小或为 0
DirectMap1G 1 GB 页大小映射的内存 异常小或为 0
1
2
3
4
5
6
7
8
9
awk '{
if ($2 >= 1048576) {
printf "%s: %.2f GB\n", $1, $2/1048576
} else if ($2 >= 1024) {
printf "%s: %.2f MB\n", $1, $2/1024
} else {
printf "%s: %s kB\n", $1, $2
}
}' /proc/meminfo
内存泄漏判定
  • 如果/proc/meminfo中内核内存(比如VmallocUsedSUnreclaim)太大,那很有可能发生了内核内存泄漏;
  • 另外,也可以周期性地观察VmallocUsed和SUnreclaim的变化,如果它们持续增长而不下降,也可能是发生了内核内存泄漏

Swap

  • 检查进程使用swap情况
1
2
3
for i in $(cd /proc;ls |grep "^[0-9]"|awk ' $0 >100'); \
do awk '/Swap:/{a=a+$2}END{print '"$i"',a/1024"M"}' /proc/$i/smaps 2>/dev/null; \
done |sort -k2nr |head
  • sort -k2nr 表示按照第二列数字逆序排序.-k 用来指定排序的键值,2 表示第二列,n 表示按照数字而不是字典顺序排序,r 表示逆序.
  • linux查找占用swap的进程的脚本
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
#!/bin/bash
########################################
# 脚本功能 : 列出正在占用swap的进程.
########################################
echo -e "PID\tSwap\tProc_Name"

# 拿出/proc目录下所有以数字为名的目录(进程名是数字才是进程,其他如sys,net等存放的是其他信息)
for pid in `ls -l /proc|awk '/^d/ {print $NF}'|grep ^[0-9]`
do
# Do not check init process
if [ $pid -eq 1 ];then continue;fi
# 判断改进程是否占用了swap
grep -q "Swap" /proc/$pid/smaps 2>/dev/null
if [ $? -eq 0 ];then # 如果占用了swap
swap=$(grep Swap /proc/$pid/smaps| gawk '{ sum+=$2} END{ print sum }')
# 进程名
#proc_name=$(ps aux | grep -w "$pid" | grep -v grep
proc_name=$(ps -eo pid,comm | grep -w "$pid" | grep -v grep|awk '{print $NF}')
if [ $swap -ge 0 ];then # 如果占用了swap则输出其信息
echo -e "$pid\t${swap}\t$proc_name"
fi
fi
done | sort -k2 -n | gawk -F'\t' '{
pid[NR]=$1;
size[NR]=$2;
name[NR]=$3;
}
END{
for(id=1;id<=length(pid);id++)
{
if(size[id]<1024)
printf("%-10s\t%10sKB\t%s\n",pid[id],size[id],name[id]);
else if(size[id]<1048576)
printf("%-10s\t%10.2fMB\t%s\n",pid[id],size[id]/1024,name[id]);
else
printf("%-10s\t%10.2fGB\t%s\n",pid[id],size[id]/1048576,name[id]);
}
}'

swapoff

swapon

smem

  • smem是一个专门用来查看内存和 Swap 使用情况的工具

    1
    smem -s swap -r

I/O

iostat

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
iostat <options> <device name>

常用选项:
-c 只显示 CPU 的信息
-d 只显示设备信息
--human 以友好的方式显示结果
-j { ID | LABEL | PATH | UUID | ... } 显示设备的持久化名称
-k 以 k 为单位显示
-m 以 m 为单位显示
-N 显示任何设备映射器设备的注册设备映射器名称,用于查看LVM2统计数据
-p [ { device [,...] | ALL } ] 显示块设备及其分区的信息
-t 显示每次输出的时间
-V 显示 iostat 的版本信息
-x 显示更多的设备列
-z 如果没有变化就不重复输出信息
interval 连续输出,每 interval 秒输出一次
count 与 interval 连用,指定一共输出多少次
  • %util ,磁盘I/O使用率;
  • r/s+ w/s ,就是IOPS;
  • rkB/s+wkB/s ,就是吞吐量;
  • r_await+w_await ,就是响应时间.

img

1
2
3
4
5
6
7
8
9
10
iostat: Get report and statistic.
iostat -x: Show more details statistics information.
iostat -c: Show only the cpu statistic.
iostat -d: Display only the device report.
iostat -xd: Show extended I/O statistic for device only.
iostat -k: Capture the statistics in kilobytes or megabytes.
iostat -k 2 3: Display cpu and device statistics with delay.
iostat -j ID mmcbkl0 sda6 -x -m 2 2: Display persistent device name statistics.
iostat -p: Display statistics for block devices.
iostat -N: Display lvm2 statistic information.

iotop

1
2
3
4
Total DISK READ :       0.00 B/s | Total DISK WRITE :       0.00 B/s
Actual DISK READ: 0.00 B/s | Actual DISK WRITE: 0.00 B/s
TID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND

  • 前两行分别表示,进程的磁盘读写大小总数和磁盘真实的读写大小总数.因为缓存、缓冲区、I/O 合并等因素的影响,它们可能并不相等.
  • 剩下的部分,则是从各个角度来分别表示进程的 I/O 情况,包括线程 ID、I/O 优先级、每秒读磁盘的大小、每秒写磁盘的大小、换入和等待 I/O 的时钟百分比等

dstat

  • 默认情况下分五个区域

    1
    2
    --total-cpu-usage-- 
    usr sys idl wai stl
    • usr: 用户空间的程序所占百分比;
    • sys: 系统空间程序所占百分比;
    • idel: 空闲百分比;
    • wai: 等待磁盘I/O所消耗的百分比;
    • hiq: 硬中断次数;
    • siq: 软中断次数;
    1
    2
    -dsk/total-
    | read writ|
    • read: 读总数
    • writ: 写总数
    1
    2
    -net/total- 
    | recv send|
    • recv: 网络收包总数
    • send: 网络发包总数
    1
    2
    ---paging-- 
    | in out |
    • in: pagein(换入)
    • out: page out(换出)
    1
    2
    ---system--
    int csw
    • int: 中断次数
    • csw: 上下文切换
  • 参数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    -l : 显示负载统计量
    -m : 显示内存使用率(包括used,buffer,cache,free值)
    -r : 显示I/O统计
    -s : 显示交换分区使用情况
    -t : 将当前时间显示在第一行
    –fs : 显示文件系统统计数据(包括文件总数量和inodes值)
    –nocolor : 不显示颜色(有时候有用)
    –socket : 显示网络统计数据
    –tcp : 显示常用的TCP统计
    –udp : 显示监听的UDP接口及其当前用量的一些动态数据

CPU

/proc/cpuinfo

  • 查看CPU信息

    1
    # cat /proc/cpuinfo

mpstat

  • mpstat 是一个常用的多核 CPU 性能分析工具,用来实时查看每个 CPU 的性能指标,以及所有 CPU 的平均指标.
1
mpstat -P ALL 60

sysrq

  • 分析内核问题的工具,用它可以观察当前的内存快照、任务快照,可以构造vmcore把系统的所有信息都保存下来,甚至还可以在内存紧张的时候用它杀掉内存开销最大的那个进程

    1
    $ sysctl -w kernel.sysrq=1
  • 使用它的-t选项把当前的任务快照保存下来,看看系统中都有哪些任务,以及这些任务都在干什么.使用方式如下

    1
    $ echo t > /proc/sysrq-trigger
  • 然后任务快照就会被打印到内核缓冲区,这些任务快照信息你可以通过dmesg命令来查看:

    1
    $ dmesg

磁盘

du

1
2
3
4
5
# 列出当前目录里最大的10个文件
du -s * | sort -n | tail

# 统计处当前目录下文件所占容量
du -sh .

lsof

strace

1
2
3
4
# -f 表示跟踪子进程和子线程,-T 表示显示系统调用的时长,-tt 表示显示跟踪时间
$ strace -f -T -tt -p 9085

$ strace -f -e trace=file /bin/ls

ldd

  • 可以对任何程序文件显示其共享库

fio

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
# 测试磁盘或存储设备的随机读取性能
# fio -direct=1 -iodepth=64 -rw=read -ioengine=libaio -size=10G -numjobs=1 -name=./fio.test
./fio.test: (g=0): rw=read, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=libaio, iodepth=64
fio-3.1
Starting 1 process
./fio.test: Laying out IO file (1 file / 10240MiB)
Jobs: 1 (f=1): [R(1)][100.0%][r=414MiB/s,w=0KiB/s][r=106k,w=0 IOPS][eta 00m:00s]
./fio.test: (groupid=0, jobs=1): err= 0: pid=21480: Fri Aug 9 16:51:39 2024
read: IOPS=65.2k, BW=255MiB/s (267MB/s)(10.0GiB/40211msec)
slat (nsec): min=1899, max=200529, avg=3972.55, stdev=3542.87
clat (usec): min=25, max=2273.3k, avg=977.16, stdev=9984.34
lat (usec): min=32, max=2273.4k, avg=981.24, stdev=9984.34
clat percentiles (usec):
| 1.00th=[ 70], 5.00th=[ 91], 10.00th=[ 97], 20.00th=[ 112],
| 30.00th=[ 143], 40.00th=[ 194], 50.00th=[ 412], 60.00th=[ 457],
| 70.00th=[ 506], 80.00th=[ 586], 90.00th=[ 832], 95.00th=[ 1795],
| 99.00th=[ 17695], 99.50th=[ 21890], 99.90th=[ 41157], 99.95th=[ 57410],
| 99.99th=[206570]
bw ( KiB/s): min=208784, max=474504, per=99.68%, avg=259940.67, stdev=46812.37, samples=80
iops : min=52196, max=118626, avg=64985.15, stdev=11703.09, samples=80
lat (usec) : 50=0.03%, 100=13.90%, 250=28.10%, 500=26.53%, 750=19.23%
lat (usec) : 1000=4.68%
lat (msec) : 2=2.75%, 4=1.16%, 10=1.48%, 20=1.44%, 50=0.62%
lat (msec) : 100=0.05%, 250=0.01%, 500=0.01%, 750=0.01%, 1000=0.01%
lat (msec) : 2000=0.01%, >=2000=0.01%
cpu : usr=6.61%, sys=31.64%, ctx=1193303, majf=0, minf=103
IO depths : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=0.1%, >=64=100.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.1%, >=64=0.0%
issued rwt: total=2621440,0,0, short=0,0,0, dropped=0,0,0
latency : target=0, window=0, percentile=100.00%, depth=64

Run status group 0 (all jobs):
READ: bw=255MiB/s (267MB/s), 255MiB/s-255MiB/s (267MB/s-267MB/s), io=10.0GiB (10.7GB), run=40211-40211msec

Disk stats (read/write):
sdb: ios=2605434/174, merge=0/240, ticks=2505276/50, in_queue=1386964, util=99.82%
  • -direct=1: 直接 I/O 模式.数据不会经过操作系统的缓存,直接从磁盘读写数据,通常用于模拟真实的硬件 I/O 性能.
  • -iodepth=64: I/O 队列深度,表示在任何时间点最多可以有 64 个 I/O 操作同时进行.较大的队列深度有助于测试设备在高并发场景下的性能.
  • -rw=read: 指定 I/O 模式为纯读取操作.fio 只会执行读取操作,不会进行写入.
  • -ioengine=libaio: I/O 引擎选择为 libaio(Linux异步I/O).这种引擎允许在 Linux 系统上进行异步 I/O 操作,通常用于测试高性能存储设备的 I/O 能力.
  • -size=10G: 测试文件的大小为 10 GB.这个文件将被创建并用于读取操作.
  • -numjobs=1: 指定同时运行的作业数为 1,意味着只有一个测试线程在运行.
  • -name=./fio.test: 指定测试任务的名称为 fio.test,同时该名称也将作为测试生成的文件名.

strings

进程

ps

  • Linux上进程有5种状态:

    • 运行(正在运行或在运行队列中等待)
    • 中断(休眠中, 受阻, 在等待某个条件的形成或接受到信号)
    • 不可中断(收到信号不唤醒和不可运行, 进程必须等待直到有中断发生)
    • 僵死(进程已终止, 但进程描述符存在, 直到父进程调用wait4()系统调用后释放)
    • 停止(进程收到SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU信号后停止运行运行)
  • ps工具标识进程的5种状态码:

    • D 不可中断 uninterruptible sleep (usually IO)
    • R 运行 runnable (on run queue)
    • S 中断 sleeping
    • T 停止 traced or stopped
    • Z 僵死 a defunct (”zombie”) process
  • 命令参数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    a 显示所有进程
    -a 显示同一终端下的所有程序
    -A 显示所有进程
    c 显示进程的真实名称
    -N 反向选择
    -e 等于“-A”
    e 显示环境变量
    f 显示程序间的关系
    -H 显示树状结构
    r 显示当前终端的进程
    T 显示当前终端的所有程序
    u 指定用户的所有进程
    -au 显示较详细的资讯
    -aux 显示所有包含其他使用者的行程
    -C<命令> 列出指定命令的状况
    –lines<行数> 每页显示的行数
    –width<字符数> 每页显示的字符数
    –help 显示帮助信息
    –version 显示版本显示
  • 输出列的含义

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    F 代表这个程序的旗标 (flag), 4 代表使用者为 super user
    S 代表这个程序的状态 (STAT),关于各 STAT 的意义将在内文介绍
    UID 程序被该 UID 所拥有
    PID 进程的ID
    PPID 则是其上级父程序的ID
    C CPU 使用的资源百分比
    PRI 这个是 Priority (优先执行序) 的缩写,详细后面介绍
    NI 这个是 Nice 值,在下一小节我们会持续介绍
    ADDR 这个是 kernel function,指出该程序在内存的那个部分.如果是个 running的程序,一般就是 “-“
    SZ 使用掉的内存大小
    WCHAN 目前这个程序是否正在运作当中,若为 - 表示正在运作
    TTY 登入者的终端机位置
    TIME 使用掉的 CPU 时间.
    CMD 所下达的指令为何
  • 示例

    1
    2
    3
    4
    # 列出头十个最耗内存的进程
    ps aux | sort -nk +4 | tail

    ps -eo cmd,pcpu,pid,user --sort -pcpu | head
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # ps -ef
    UID PID PPID C STIME TTY TIME CMD
    root 1 0 0 12月08 ? 00:00:09 /sbin/init recovery dis_ucode_ldr --startup-event=recovery
    root 2 0 0 12月08 ? 00:00:00 [kthreadd]
    root 3 2 0 12月08 ? 00:00:00 [rcu_gp]
    root 4 2 0 12月08 ? 00:00:00 [rcu_par_gp]
    root 6 2 0 12月08 ? 00:00:00 [kworker/0:0H-kb]
    root 8 2 0 12月08 ? 00:00:04 [kworker/u80:0-p]
    root 9 2 0 12月08 ? 00:00:00 [mm_percpu_wq]
    root 10 2 0 12月08 ? 00:00:00 [ksoftirqd/0]
    root 11 2 0 12月08 ? 00:05:35 [rcu_sched]
    • PID1的进程就是init进程systemd,PID2的进程是内核线程kthreadd,其中用户态的不带中括号,内核态的带中括号.
    • 进程号依次增大,但是会看所有带中括号的内核态的进程,祖先都是2号进程.而用户态的进程,祖先都是1 号进程.tty那一列,是问号的,说明不是前台启动的,一般都是后台的服务
    1
    ps auxefw

pgrep

1
2
# 用进程名字查找PID号
pgrep -l ssh

pstree

1
2
# 显示进程树
pstree -p

pmap

1
2
3
# 查看PID对应的内存映射
pmap PID

killall

1
2
3
# 杀死httpd进程
killall -1 httpd

pkill

1
2
3
4
# 杀死http进程
pkill -9 http
# 杀死所有www用户的进程
pkill -TERM -u www

sar

top

pidstat

  • pidstat是一个常用的进程性能分析工具,用来实时查看进程的 CPU、内存、I/O 以及上下文切换等性能指标.

    1
    2
    3
    4
    5
    6
    7
    # pidstat 1 5
    Linux 5.4.0-77-generic (skyward-dev-aliyun) 08/30/2023 _x86_64_ (4 CPU)

    05:11:43 PM UID PID %usr %system %guest %wait %CPU CPU Command
    05:11:44 PM 0 732418 0.00 0.99 0.00 0.00 0.99 1 AliYunDunMonito
    05:11:44 PM 0 850211 0.99 0.99 0.00 0.00 1.98 3 pidstat

    • 用户态 CPU 使用率 (%usr);

    • 内核态 CPU 使用率(%system);

    • 运行虚拟机 CPU 使用率(%guest);

    • 等待 CPU 使用率(%wait);

    • 以及总的 CPU 使用率(%CPU)

    1
    2
    3
    4
    pidstat -d 1
    Linux 4.15.0-156-generic 08/31/2023 _x86_64_ (4 CPU)

    04:00:34 PM UID PID kB_rd/s kB_wr/s kB_ccwr/s iodelay Command
    • 用户 ID(UID)和进程 ID(PID) .

    • 每秒读取的数据大小(kB_rd/s) ,单位是 KB.

    • 每秒发出的写请求数据大小(kB_wr/s) ,单位是 KB.

    • 每秒取消的写请求数据大小(kB_ccwr/s) ,单位是 KB.

    • 块 I/O 延迟(iodelay),包括等待同步块 I/O 和换入块 I/O 结束的时间,单位是时钟周期.

unhide

网络

网络问题排查思路

  • dstat --> dstat --tcp --> ss -natp / netstat -natp
    1. 先使用dstat观察一下系统整体的信息
    2. 再使用dstat --tcp 关注一下TCP情况
    3. 再使用ss -natp查看一下具体网络连接

流量监控

ifstat
  • ifstat 是一个简单的工具,可以显示网络接口的实时流量统计信息.它会显示每个网络接口的入站(接收)和出站(发送)流量,以及总的流量统计.通过运行 ifstat 命令即可查看当前网络接口的流量统计信息.
nethogs
iftop

netstat

  • 不推荐,推荐使用ss代替.netstat属于net-tools这个比较古老的工具集,而ss属于iproute2这个工具集.net-tools中的常用命令,几乎都可以用iproute2中的新命令来代替
net-tools iproute2 作用
ifconfig ip addr; ip link 网络接口具体配置信息
route; netstat -r ip route 路由信息,看看是否有不合理的路由
netstat ss 网络连接统计信息
netstat -s nstat 网络状态统计信息

ss

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
-a	显示所有套接字(包括监听的)
-e 显示扩展信息
-h 显示帮助信息
-i 显示内部TCP信息
-l 仅显示监听状态的套接字
-n 不解析服务名称,直接显示IP和端口号
-o 显示计时器信息
-p 显示进程使用的套接字
-r 解析主机名
-s 显示套接字统计信息
-t 仅显示TCP套接字
-u 仅显示UDP套接字
-v 显示详细信息
-w 显示RAW套接字
-x 显示UNIX域套接字
-4 仅显示IPv4套接字
-6 仅显示IPv6套接字
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 列出所有打开的套接字
ss -a

# 列出所有TCP套接字
ss -t -a

# 列出所有监听状态的TCP端口
ss -lt

# 列出所有监听状态的UDP端口
ss -lu

# 显示每个套接字的进程信息
ss -lp

# 查找监听特定端口(例如80端口)的进程
ss -lntp | grep ':80'

# 仅显示有关TCP套接字的统计信息
ss -s

# 显示所有处于TIME-WAIT状态的TCP连接
ss -o state time-wait

nslookup

1
nslookup www.holelin.cn

unhide-tcp

/proc/net/snmp

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
cat /proc/net/snmp | awk '
BEGIN {
FS=":";
protocol = "";
header = "";
}
{
if (NR % 2 == 1) {
protocol = $1; # 获取协议名称
header = $2;
gsub(/[ ]+/, " ", header);
} else {
data = $2;
gsub(/[ ]+/, " ", data);
split(header, headerArray, " ");
split(data, dataArray, " ");

# 输出协议名称作为表头的前一行
print protocol;

# 输出表头和对应的数据
for (i = 1; i <= length(headerArray); i++) {
printf "%-15s %-15s\n", headerArray[i], dataArray[i];
}
printf "\n";
}
}'
  • TCP重传率是通过解析/proc/net/snmp这个文件里的指标计算出来的

    指标 说明
    ActiveOpens 主动打开的TCP连接数量
    PassiveOpens 被动打开的TCP连接数量
    InSegs 收到的TCP报文数量
    OutSegs 发出的TCP报文数量
    EstabRests TCP连接处于ESTABLISHED时发生的Reset数量
    AttemptFails 连接失败的数量
    CurrEstab 当前状态为ESTABLISHEDTCP连接数
    RetransSegs 重传的报文数量
  • TCP重传率的计算公式如下:

    retrans=(RetransSegslastRetransSegs)/(OutSegslastOutSegs)100retrans = (RetransSegs - last RetransSegs) / (OutSegs - last OutSegs) * 100

  • 单位时间内TCP重传包的数量除以TCP总的发包数量,就是TCP重传率

nstat

  • 查看丢包信息.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # nstat -z | grep -i drop
    TcpExtLockDroppedIcmps 0 0.0
    TcpExtListenDrops 0 0.0
    TcpExtTCPBacklogDrop 0 0.0
    TcpExtPFMemallocDrop 0 0.0
    TcpExtTCPMinTTLDrop 0 0.0
    TcpExtTCPDeferAcceptDrop 0 0.0
    TcpExtTCPReqQFullDrop 0 0.0
    TcpExtTCPOFODrop 0 0.0
    TcpExtTCPZeroWindowDrop 0 0.0
    TcpExtTCPRcvQDrop 0 0.0

TCP Tracepoints

内核

dmesg

ulimit

  • /etc/security/limits.conf

  • 修改打开文件句柄限制

    1
    ulimit -HSn 65535
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 128240
max locked memory (kbytes, -l) 65536
max memory size (kbytes, -m) unlimited
open files (-n) 65535
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 128240
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
  • core file size (blocks, -c) unlimited
    • 表示进程产生的核心转储文件大小限制.其中,-c 选项表示要查询或修改的资源类型为 core file size;unlimited 表示在不受任何限制的情况下,可产生任何大小的核心转储文件.0则表示当程序崩溃后,不转储核心文件
  • data seg size (kbytes, -d) unlimited
    • 表示进程数据段(Data Segment)大小限制.其中,-d 选项表示要查询或修改的资源类型为 data seg size;unlimited 表示不受限制.
  • scheduling priority (-e) 0
    • 表示进程可设置的调度优先级限制.其中,-e 选项表示要查询或修改的资源类型为 scheduling priority;0 表示没有优先级的限制
  • file size (blocks, -f) unlimited
    • 表示进程可创建的文件大小限制.其中,-f 选项表示要查询或修改的资源类型为 file size;unlimited 表示没有大小的限制.
  • pending signals (-i) 128240
    • 表示进程可排队等待处理的信号数量限制.其中,-i 选项表示要查询或修改的资源类型为 pending signals;unlimited 表示不受限制.
  • max locked memory (kbytes, -l) 65536
    • 表示进程可锁定的内存大小限制.其中,-l 选项表示要查询或修改的资源类型为 max locked memory;16384 表示最大可锁定内存大小为 16MB.
  • max memory size (kbytes, -m) unlimited
    • 表示进程可使用的最大内存大小限制,即进程的内存占用量限制.其中,-m 选项表示要查询或修改的资源类型为 max memory size;unlimited 表示没有内存大小限制.
  • open files (-n) 65535
    • 表示进程可同时打开的最大文件数量限制.其中,-n 选项表示要查询或修改的资源类型为 open files;65535表示最大可同时打开文件数限制为 65535.
  • pipe size (512 bytes, -p) 8
    • 表示进程可创建的管道(Pipe)大小限制.其中,-p 选项表示要查询或修改的资源类型为 pipe size;8 表示管道缓冲区大小为 8*512=4096 Bytes.
  • POSIX message queues (bytes, -q) 819200
    • 表示进程可创建的 POSIX 消息队列大小限制.其中,-q 选项表示要查询或修改的资源类型为 POSIX message queues;819200 表示最大可用消息队列大小为 819200 Bytes.
  • real-time priority (-r) 0
    • 表示进程可设置的实时优先级限制.其中,-r 选项表示要查询或修改的资源类型为 real-time priority;0 表示没有优先级的限制.
  • stack size (kbytes, -s) 8192
    • 表示进程栈空间大小限制.其中,-s 选项表示要查询或修改的资源类型为 stack size;8192 表示默认栈空间大小为 8MB.
  • cpu time (seconds, -t) unlimited
    • 表示进程可使用的 CPU 时间限制.其中,-t 选项表示要查询或修改的资源类型为 cpu time;unlimited 表示没有时间限制.
  • max user processes (-u) 128240
    • 表示用户可同时创建的最大进程数量限制.其中,-u 选项表示要查询或修改的资源类型为 max user processes;128240表示最大可同时创建的进程数限制为 128240个.
  • virtual memory (kbytes, -v) unlimited
    • 表示进程可使用的虚拟内存大小限制.其中,-v 选项表示要查询或修改的资源类型为 virtual memory;unlimited 表示不受限制.
  • file locks (-x) unlimited
    • 表示进程可使用的文件锁的数量限制.其中,-x 选项表示要查询或修改的资源类型为 file locks;unlimited 表示不受限制.

安全防护

clamav

hm

Linux Check

案例分析

磁盘空间不足,需快速定位日志目录

1
du -x --max-depth=1 / |sort -k1 -nr
  • -x 参数表示跳过其他文件系统,也就是只分析本文件系统里的文件,它可以帮助我们排除一些非本文件系统的统计信息,这样执行速度会更快也不容易出现一些额外的干扰项
  • -k 参数指明具体按照哪一列进行排序
  • -n 参数表示只对数值进行排序
  • -r 参数表示反向排序

系统产生很多碎片文件,导致 inode 资源不足

1
find -type f|awk -F / -v OFS=/ '{$NF="";dir[$0]++}END{for(i in dir)print dir[i]""i}'|sort -k1 -nr |head

找出当前系统内存使用量较高的进程

1
ps -aux | sort -rnk 4 | head -20
  • 输出的第 4 列就是内存的耗用百分比.最后一列就是相对应的进程.

找出当前系统CPU使用量较高的进程

1
ps -aux | sort -rnk 3 | head -20
  • 输出的第 3 列为 CPU 的耗用百分比,最后一列就是对应的进程.

查看TCP连接状态

1
netstat -nat |awk '{print $6}'|sort|uniq -c|sort -rn

查找 80 端口请求数最高的前 20 个 IP

1
netstat -anlp|grep 80|grep tcp|awk '{print $5}'|awk -F: '{print $1}'|sort|uniq -c|sort -nr|head -n2

Linux进程被杀掉(OOM killer),查看系统日志

  • Linux 操作系统有特定的内存管理方法.其中一项策略是过度使用,它允许应用程序提前预订所需的内存.然而,承诺的内存在实际使用时可能并不可用.然后,系统必须提供一种特殊的手段来避免内存不足.
  • 为了让OOM killer发挥作用,系统必须允许过度使用.然后,根据系统从消除该进程中获得的收益来对每个进程进行评分.最后,当遇到低内存状态时,内核会杀死分数最高的进程.
  • 可以通过/proc/PID/oom_score文件中的 PID 找到进程的分数
  • 杀掉“某个进程”的选择标准,涉及到内核函数oom_badness().具体的计算方法是: 系统总的可用页面数乘以进程的 OOM 校准值 oom_score_adj,再加上进程已经使用的物理页面数,计算出来的值越大,那么这个进程被 OOM Kill 的几率也就越大
查看方法
使用journalctl
1
journalctl -k -p err

img

  • 查看特定时间范围内的日志,请使用以下命令(替换<START_TIME>和<END_TIME>为实际的起始时间和结束时间)

    1
    2
    3
    4
    sudo journalctl -k -p err --since="<START_TIME>" --until="<END_TIME>"

    # 查看过去一小时的日志
    sudo journalctl -k -p err --since="1 hour ago"
使用dmesg
1
2
3
dmesg --level=err

dmesg | grep "Out of memory" | awk '{print systime() - $1, $0}' | awk '{print strftime("%Y-%m-%d %H:%M:%S", $1) " " substr($0, index($0,$2))}'

img

  • 查看特定时间范围内的日志,请使用以下命令(替换<START_TIME>和<END_TIME>为实际的起始时间和结束时间)

    1
    2
    3
    4
    dmesg --level=err --time-format=iso --ctime --human --since="<START_TIME>" --until="<END_TIME>"

    # 要查看过去一小时的日志
    dmesg --level=err --time-format=iso --ctime --human --since="$(date -d '1 hour ago' +'%Y-%m-%dT%H:%M:%S')"
  • 通过查看/var/log下文件中的信息

    1
    egrep -i -r 'killed process' /var/log
  • 列出所有进程及其 PID 和名称,按oom_score从最低到最高排序

1
2
3
4
5
6
#!/bin/bash

while read -r pid comm
do
printf '%d\t%d\t%s\n' "$pid" "$(cat /proc/$pid/oom_score)" "$comm"
done < <(ps -e -o pid= -o comm=) | sort -k2 -n

查看CPU是否开启高性能模式

1
cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor

查看CPU温度

1
cat /sys/class/thermal/thermal_zone*/temp

查询系统中正在等待IO的进程

1
ps aux|awk '$8 ~ /D/ {print $0}'

查看Linux系统是何时安装的

1
sudo tune2fs -l /dev/sdaX | grep "Filesystem created"
  • /dev/sdaX替换为Linux系统所在的分区

查看所有用户的定时任务

1
cat /etc/passwd | cut -f 1 -d : |xargs -I {} crontab -l -u {}

查找异常定时任务

1
2
3
# ls -al /etc/cron*

# ls -al /var/spool/cron/crontabs/

查找异常预加载动态库

  • Linux/etc/ld.so.preload配置,可以自定义程序运行前优先加载的动态链接库.部分木马病毒通过修改该文件,添加恶意文件,从而实现挖矿进程的隐藏等恶意功能.
  • 该文件默认为空
1
2
3
4
cat /etc/ld.so.preload

# 暂时禁用预加载动态库功能
mv /etc/ld.so.preload /etc/ld.so.preload.bak

查杀木马常用命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
1. ps,top
查看运行的进程和进程系统资源占用情况,查找异常进程.

2. pstree
以树状图的形式显示进程间的关系.

3. lsof
可以查看进程打开的文件、文件或目录被哪个进程占用、打开某个端口的进程、系统所有打开的端口等等.

4. netstat
可以查看系统监听的所有端口、网络连接情况、查找连接数过多的IP地址等.

5. iftop
监控TCP连接实时网络流量,可分别分析出入流量并进行排序,查找出流量异常的IP地址.

6. nethogs
监控每个进程使用的网络流量,并从高到低排序,方便查找出流量异常的进程.

7. strace
追踪一个进程所执行的系统调用,可分析木马进程的运行情况.

8. strings
输出文件中可打印的字符串,可用来分析木马程序

根据PID查看进程具体监听的是哪个端口

  • 使用lsof

    1
    sudo lsof -nP -iTCP -sTCP:LISTEN -a -p <PID>
    • -nP: 不解析主机名和端口号,显示 IP 和端口.

    • -iTCP: 只显示 TCP 连接.

    • -sTCP:LISTEN: 过滤出监听状态的连接.

    • -a: 逻辑与操作,组合多个条件.

    • -p <PID>: 根据进程 PID 过滤.

  • 使用netstat/ss

    1
    2
    3
    sudo netstat -tuln | grep <PID>

    sudo ss -tulnp | grep <PID>

名词解释

平均负载

1
2
$ uptime
15:37:04 up 280 days, 47 min, 1 user, load average: 0.06, 0.07, 0.02
  • 最后三个数字依次则是过去 1 分钟、5 分钟、15 分钟的平均负载(Load Average)

    • 如果 1 分钟、5 分钟、15 分钟的三个值基本相同,或者相差不大,那就说明系统负载很平稳.
    • 但如果 1 分钟的值远小于 15 分钟的值,就说明系统最近 1 分钟的负载在减少,而过去 15 分钟内却有很大的负载.
    • 反过来,如果 1 分钟的值远大于 15 分钟的值,就说明最近 1 分钟的负载在增加,这种增加有可能只是临时性的,也有可能还会持续增加下去,所以就需要持续观察.一旦 1 分钟的平均负载接近或超过了 CPU 的个数,就意味着系统正在发生过载的问题,这时就得分析调查是哪里导致的问题,并要想办法优化了.
  • 平均负载是指单位时间内,系统处于可运行状态TASK_RUNNING和不可中断状态TASK_UNINTERRUPTIBLE的平均进程数,也就是平均活跃进程数,它和 CPU 使用率并没有直接关系.它不仅包括了正在使用 CPU 的进程,还包括等待 CPU等待 I/O的进程

  • 平均负载统计了这两种情况的进程:

    • 第一种是 Linux 进程调度器中可运行队列(Running Queue)一段时间(1 分钟,5 分钟,15 分钟)的进程平均数.

    • 第二种是 Linux 进程调度器中休眠队列(Sleeping Queue)里的一段时间的TASK_UNINTERRUPTIBLE状态下的进程平均数.

    1
    Load Average= 可运行队列进程平均数 + 休眠队列中不可打断的进程平均数
  • 平均负载最理想的情况是等于 CPU 个数.

    • 获取CPU个数方法:

      1
      2
      3
      4
      5
      # 方法一
      grep 'model name' /proc/cpuinfo | wc -l

      # 方法二
      lscpu
  • 当平均负载高于 CPU 数量 70% 的时候,就应该分析排查负载高的问题了.一旦负载过高,就可能导致进程响应变慢,进而影响服务的正常功能.

CPU使用率

  • Linux 作为一个多任务操作系统,将每个 CPU 的时间划分为很短的时间片,再通过调度器轮流分配给各个任务使用,因此造成多任务同时运行的错觉.

  • 为了维护 CPU 时间,Linux 通过事先定义的节拍率(内核中表示为 HZ),触发时间中断,并使用全局变量 Jiffies 记录了开机以来的节拍数.每发生一次时间中断,Jiffies 的值就加 1.

  • 节拍率 HZ 是内核的可配选项,可以设置为 100、250、1000 等.不同的系统可能设置不同数值,你可以通过查询 /boot/config内核选项来查看它的配置值

    1
    2
    # grep 'CONFIG_HZ=' /boot/config-$(uname -r)
    CONFIG_HZ=250
  • 正因为节拍率 HZ 是内核选项,所以用户空间程序并不能直接访问.为了方便用户空间程序,内核还提供了一个用户空间节拍率 USER_HZ,它总是固定为 100,也就是 1⁄100 秒.这样,用户空间程序并不需要关心内核中 HZ 被设置成了多少,因为它看到的总是固定值 USER_HZ.

  • Linux 通过 /proc 虚拟文件系统,向用户空间提供了系统内部状态的信息,而 /proc/stat 提供的就是系统的 CPU 和任务统计信息.比方说,如果只关注 CPU 的话,可以执行下面的命令:

    1
    2
    3
    4
    5
    6
    # cat /proc/stat | grep ^cpu
    cpu 59103830 9113 31804093 9506491595 28595015 0 2307763 0 0 0
    cpu0 17966575 2045 9334852 2369152739 8861122 0 791352 0 0 0
    cpu1 12085692 1916 6763948 2383057321 5553224 0 170553 0 0 0
    cpu2 17474766 2713 9045814 2369158238 9175479 0 1142654 0 0 0
    cpu3 11576796 2439 6659477 2385123295 5005189 0 203203 0 0 0
    • 这里的输出结果是一个表格.其中,第一列表示的是 CPU 编号,如 cpu0、cpu1 ,而第一行没有编号的 cpu ,表示的是所有 CPU 的累加.其他列则表示不同场景下 CPU 的累加节拍数,它的单位是 USER_HZ,也就是 10 ms(1/100 秒),所以这其实就是不同场景下的 CPU 时间.
  • CPU 使用率相关的重要指标

    • user(通常缩写为 us),代表用户态 CPU 时间.注意,它不包括下面的 nice 时间,但包括了 guest 时间.
    • nice(通常缩写为 ni),代表低优先级用户态 CPU 时间,也就是进程的 nice 值被调整为 1-19 之间时的 CPU 时间.这里注意,nice 可取值范围是 -20 到 19,数值越大,优先级反而越低.
    • system(通常缩写为 sys),代表内核态 CPU 时间.
    • idle(通常缩写为 id),代表空闲时间.注意,它不包括等待 I/O 的时间(iowait).
    • iowait(通常缩写为 wa),代表等待 I/O 的 CPU 时间.
    • irq(通常缩写为 hi),代表处理硬中断的 CPU 时间.
    • softirq(通常缩写为 si),代表处理软中断的 CPU 时间.
    • steal(通常缩写为 st),代表当系统运行在虚拟机中的时候,被其他虚拟机占用的 CPU 时间.
    • guest(通常缩写为 guest),代表通过虚拟化运行其他操作系统的时间,也就是运行虚拟机的 CPU 时间.
    • guest_nice(通常缩写为 gnice),代表以低优先级运行虚拟机的时间.
  • CPU 使用率,就是除了空闲时间外的其他时间占总 CPU 时间的百分比,用公式来表示就是

    CPU使用率=1空闲时间CPU时间CPU使用率=1-\frac{空闲时间}{总CPU时间}

  • 平均CPU使用率

    平均CPU使用率=1空闲时new空闲时oldCPUnewCPUold平均CPU使用率=1-\frac{空闲时间_{new}-空闲时间_{old} }{总CPU时间_{new}-总CPU时间_{old}}

查看CPU使用率
  • top 显示了系统总体的 CPU 和内存使用情况,以及各个进程的资源使用情况.
  • ps 则只显示了每个进程的资源使用情况.

中断

  • 中断其实是一种异步的事件处理机制,可以提高系统的并发处理能力
  • 由于中断处理程序会打断其他进程的运行,所以,为了减少对正常进程运行调度的影响,中断处理程序就需要尽可能快地运行
  • 特别是,中断处理程序在响应中断时,还会临时关闭中断.这就会导致上一次中断处理完成之前,其他中断都不能响应,也就是说中断有可能会丢失
软中断
  • 为了解决中断处理程序执行过长和中断丢失的问题,Linux 将中断处理过程分成了两个阶段,也就是上半部和下半部:
    • 上半部用来快速处理中断,它在中断禁止模式下运行,主要处理跟硬件紧密相关的或时间敏感的工作.
      • 上半部直接处理硬件请求,也就是我们常说的硬中断,特点是快速执行;
    • 下半部用来延迟处理上半部未完成的工作,通常以内核线程的方式运行.
      • 而下半部则是由内核触发,也就是我们常说的软中断,特点是延迟执行.
  • 实际上,上半部会打断 CPU 正在执行的任务,然后立即执行中断处理程序.而下半部以内核线程的方式执行,并且每个 CPU 都对应一个软中断内核线程,名字为 “ksoftirqd/CPU 编号”,比如说, 0 号 CPU 对应的软中断内核线程的名字就是 ksoftirqd/0.
  • 不过要注意的是,软中断不只包括了刚刚所讲的硬件设备中断处理程序的下半部,一些内核自定义的事件也属于软中断,比如内核调度和 RCU 锁(Read-Copy Update 的缩写,RCU 是 Linux 内核中最常用的锁之一)等.
查看方法
  • /proc/softirqs 提供了软中断的运行情况;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    # cat /proc/softirqs
    CPU0 CPU1
    HI: 0 0
    TIMER: 1767310814 1981790179
    NET_TX: 21 22
    NET_RX: 180258835 14781962
    BLOCK: 0 56877414
    IRQ_POLL: 0 0
    TASKLET: 1883 254
    SCHED: 2112808147 2040670866
    HRTIMER: 173929 228
    RCU: 1921421919 1902663659
    • 注意软中断的类型,也就是这个界面中第一列的内容.从第一列你可以看到,软中断包括了 10 个类别,分别对应不同的工作类型.比如 NET_RX 表示网络接收中断,而 NET_TX 表示网络发送中断.

    • 要注意同一种软中断在不同 CPU 上的分布情况,也就是同一行的内容.正常情况下,同一种中断在不同 CPU 上的累积次数应该差不多.

    • 查看ksoftirqd/CPU 编号线程运行状态

      1
      ps aux|grep softirq
  • /proc/interrupts 提供了硬中断的运行情况.

    1
    cat /proc/interrupts | awk '{printf "%-8s %-15s %-8s %-8s %-15s\n", $1, $2, $3, $4, $5}'

CPU性能指标

CPU 使用率
  • CPU 使用率描述了非空闲时间占总 CPU 时间的百分比,根据 CPU 上运行任务的不同,又被分为用户 CPU、系统 CPU、等待 I/O CPU、软中断和硬中断等.
    • 用户 CPU 使用率,包括用户态 CPU 使用率(user)和低优先级用户态 CPU 使用率(nice),表示 CPU 在用户态运行的时间百分比.用户 CPU 使用率高,通常说明有应用程序比较繁忙.
    • 系统 CPU 使用率,表示 CPU 在内核态运行的时间百分比(不包括中断).系统 CPU 使用率高,说明内核比较繁忙.
    • 等待 I/O 的 CPU 使用率,通常也称为 iowait,表示等待 I/O 的时间百分比.iowait 高,通常说明系统与硬件设备的 I/O 交互时间比较长.
    • 软中断和硬中断的 CPU 使用率,分别表示内核调用软中断处理程序、硬中断处理程序的时间百分比.它们的使用率高,通常说明系统发生了大量的中断.
    • 除了上面这些,还有在虚拟化环境中会用到的窃取 CPU 使用率(steal)和客户 CPU 使用率(guest),分别表示被其他虚拟机占用的 CPU 时间百分比,和运行客户虚拟机的 CPU 时间百分比.
平均负载(Load Average)
  • Linux平均负载是一个指标,显示CPU当前执行的任务数量和队列中等待的任务数量.

  • 与衡量特定时间点的系统性能的 CPU 使用率不同,负载平均值显示特定时间段内的性能.系统上运行的进程数不断变化,平均负载显示该变化.

  • 也就是系统的平均活跃进程数.它反应了系统的整体负载情况,主要包括三个数值,分别指过去 1 分钟、过去 5 分钟和过去 15 分钟的平均负载.

    • 平均负载越高表示资源使用率越高
  • 理想情况下,平均负载等于逻辑 CPU 个数,这表示每个 CPU 都恰好被充分利用.如果平均负载大于逻辑 CPU 个数,就表示负载比较重了.

进程上下文切换
  • 无法获取资源而导致的自愿上下文切换;
  • 被系统强制调度导致的非自愿上下文切换.
  • 上下文切换,本身是保证 Linux 正常运行的一项核心功能.但过多的上下文切换,会将原本运行进程的 CPU 时间,消耗在寄存器、内核栈以及虚拟内存等数据的保存和恢复上,缩短进程真正运行的时间,成为性能瓶颈.
CPU 缓存的命中率
img img img
  • 上述图片来自极客时间-Linux性能优化 倪朋飞
物理CPU数量查看方法
  • 实际机器中插槽上的CPU个数,物理CPU数量

    1
    2
    # cat /proc/cpuinfo | grep "physical id" | sort | uniq | wc -l
    2
CPU核数查看方法
  • 一块物理CPU上能处理数据的芯片组数量.也就是说一个物理CPU上可能会有多个核心,日常中说的双核,四核就是指的CPU核心

    1
    2
    # cat /proc/cpuinfo | grep  "cores" | uniq
    cpu cores : 10
逻辑CPU数量查看方法
  • 逻辑CPU数量 = 物理CPU数量 x CPU CORES x 2(如果支持并开启HT)

    • 逻辑CPU数量 (4个)=物理cpu数量(1个) x CPU CORES(4) x 1(不支持ht超线程技术)
  • 一般情况,我们认为一颗cpu可以有多核,加上intel的超线程技术(HT),可以在逻辑上再分一倍数量的cpu core出来;所以逻辑CPU的值理论上是可以超过100%的.

    1
    2
    # cat /proc/cpuinfo | grep  "processor" | wc -l
    40

内存性能指标

img
  • 上述图片来自极客时间-Linux性能优化 倪朋飞

  • 系统内存使用情况,比如已用内存、剩余内存、共享内存、可用内存、缓存和缓冲区的用量等.

    • 已用内存和剩余内存很容易理解,就是已经使用和还未使用的内存.
    • 共享内存是通过 tmpfs 实现的,所以它的大小也就是 tmpfs 使用的内存大小.tmpfs 其实也是一种特殊的缓存.
    • 可用内存是新进程可以使用的最大内存,它包括剩余内存和可回收缓存.
    • 缓存包括两部分,一部分是磁盘读取文件的页缓存,用来缓存从磁盘读取的数据,可以加快以后再次访问的速度.另一部分,则是 Slab 分配器中的可回收内存.
    • 缓冲区是对原始磁盘块的临时存储,用来缓存将要写入磁盘的数据.这样,内核就可以把分散的写集中起来,统一优化磁盘写入.
  • 进程内存使用情况,比如进程的虚拟内存、常驻内存、共享内存以及 Swap 内存等.

    • 虚拟内存,包括了进程代码段、数据段、共享内存、已经申请的堆内存和已经换出的内存等.这里要注意,已经申请的内存,即使还没有分配物理内存,也算作虚拟内存.
    • 常驻内存是进程实际使用的物理内存,不过,它不包括 Swap 和共享内存.
    • 共享内存,既包括与其他进程共同使用的真实的共享内存,还包括了加载的动态链接库以及程序的代码段等.
    • Swap 内存,是指通过 Swap 换出到磁盘的内存.
    • 当然,这些指标中,常驻内存一般会换算成占系统总内存的百分比,也就是进程的内存使用率.
  • 系统调用内存分配请求后,并不会立刻为其分配物理内存,而是在请求首次访问时,通过缺页异常来分配.缺页异常又分为下面两种场景.

    • 可以直接从物理内存中分配时,被称为次缺页异常.
    • 需要磁盘 I/O 介入(比如 Swap)时,被称为主缺页异常.
    • 显然,主缺页异常升高,就意味着需要磁盘 I/O,那么内存访问也会慢很多.
  • Swap 的使用情况,比如 Swap 的已用空间、剩余空间、换入速度和换出速度等.

    • 已用空间和剩余空间很好理解,就是字面上的意思,已经使用和没有使用的内存空间.
    • 换入和换出速度,则表示每秒钟换入和换出内存的大小.
img img

img

  • 上述图片来自极客时间-Linux性能优化 倪朋飞

磁盘性能指标

  • 使用率: 是指磁盘处理 I/O 的时间百分比.过高的使用率(比如超过 80%),通常意味着磁盘 I/O 存在性能瓶颈.

    • 这里要注意的是,使用率只考虑有没有 I/O,而不考虑 I/O 的大小.换句话说,当使用率是 100% 的时候,磁盘依然有可能接受新的 I/O 请求.
  • 饱和度,是指磁盘处理 I/O 的繁忙程度.过高的饱和度,意味着磁盘存在严重的性能瓶颈.当饱和度为 100% 时,磁盘无法接受新的 I/O 请求.

  • **IOPS(Input/Output Per Second): **是指每秒钟磁盘读写的次数,这个数值越大,当然也就表示性能越好.

  • 吞吐量: 是指每秒钟磁盘中数据的读取量,一般以 MB/s 为单位.这个读取量可以叫作吞吐量,有时候也被称为带宽(Bandwidth)

    • 在 IOPS 固定的情况下,如果读写的每一个数据块越大,那么吞吐量也越大.吞吐量 = 数据块大小*IOPS
  • 响应时间: 是指 I/O 请求从发出到收到响应的间隔时间.

img img

img

  • 上述图片来自极客时间-Linux性能优化 倪朋飞

网络性能指标

  • 带宽,表示链路的最大传输速率,单位通常为 b/s (比特 / 秒).
  • 吞吐量(Throughput),表示单位时间内成功传输的数据量,单位通常为 b/s(比特 / 秒)或者 B/s(字节 / 秒).吞吐量受带宽限制,而吞吐量 / 带宽,也就是该网络的使用率.
  • 延时(Latency),表示从网络请求发出后,一直到收到远端响应,所需要的时间延迟.在不同场景中,这一指标可能会有不同含义.比如,它可以表示,建立连接需要的时间(比如 TCP 握手延时),或一个数据包往返所需的时间(比如 RTT).
  • PPS,是 Packet Per Second(包 / 秒)的缩写,表示以网络包为单位的传输速率.PPS 通常用来评估网络的转发能力,比如硬件交换机,通常可以达到线性转发(即 PPS 可以达到或者接近理论最大值).而基于 Linux 服务器的转发,则容易受网络包大小的影响.
  • 除了这些指标,网络的可用性(网络能否正常通信)、并发连接数(TCP 连接数量)、丢包率(丢包百分比)、重传率(重新传输的网络包比例)等也是常用的性能指标.