[TOC]

第1章 进程管理

1.进程介绍

1.1 程序/进程的关系

1.开发写好的代码,没有运行的时候,只是静态的文件,我们称之为程序,程序是数据和指令的集合。

2.当我们把开发好的代码程序运行起来的时候,我们称之为进程。

3.程序运行的时候系统会为进程分配PID,运行用户,分配内存等资源。

1.2 进程的生命周期

1.当程序运行的时候会由父进程通过fock创建子进程来处理任务。

2.子进程被创建后开始处理任务,当任务处理完毕后就会退出,然后子进程会通知父进程来回收资源。

3.如果子进程处理任务期间,父进程意外终止了,那么这个子进程就变成了僵尸进程。

1.3 如何查看当前中端的进程号和父进程号

查看当前进程号:echo $BASHPID

查看父进程号:echo $PPID

1.4 压测工具

安装:

yum install stress -y

查看帮助:

stress --help

解释:

Usage: stress [OPTION [ARG]] ...

-?, --help show this help statement

--version show version statement

-v, --verbose be verbose

-q, --quiet be quiet

-n, --dry-run show what would have been done

-t, --timeout N timeout after N seconds

--backoff N wait factor of N microseconds before work starts

-c, --cpu N spawn N workers spinning on sqrt()

-i, --io N spawn N workers spinning on sync()

-m, --vm N spawn N workers spinning on malloc()/free()

--vm-bytes B malloc B bytes per vm worker (default is 256MB)

--vm-stride B touch a byte every B bytes (default is 4096)

--vm-hang N sleep N secs before free (default none, 0 is inf)

--vm-keep redirty memory instead of freeing and reallocating

-d, --hdd N spawn N workers spinning on write()/unlink()

--hdd-bytes B write B bytes per hdd worker (default is 1GB)

压测CPU:

stress --cpu 8

压测内存:

stress --vm 4 --vm-bytes 128M

压测硬盘:

stress --io 2 --hdd 4

2.进程监控命令

那么在程序运行后,我们如何了解进程运行的各种状态呢?这就需要使用各种查看进程状态的命令来查看了。

2.1 ps 查看当前的进程状态--每天都用到

命令作用:

ps process state 进程状态

打印出进程当前运行的状态快照,并不是实时的监控,而是某一时刻系统进程的快照

常用参数:

#UNIX风格

a #显示包含所有终端中的进程

u #此选项使ps列出您拥有的所有进程(与ps相同的EUID),或与a选项一起使用时列出所有进程。

x #显示进程所有者的信息

f #显示进程树

o #属性,显示定制的信息

k #属性,对属性进行排序,属性前加-表示倒叙

--sort #同上

#使用标准语法查看系统上的每个进程

-e #显示所有进程

-f #显示完整格式程序信息

-p #显示pid的进程

-C #指定命令

-q #指定id

运行结果:

#ps aux

[root@linux ~]# ps aux

USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND

root 1 0.0 0.1 43524 3836 ? Ss 04:20 0:02 /usr/lib/systemd/

root 2 0.0 0.0 0 0 ? S 04:20 0:00 [kthreadd]

root 3 0.0 0.0 0 0 ? S 04:20 0:01 [ksoftirqd/0]

root 5 0.0 0.0 0 0 ? S< 04:20 0:00 [kworker/0:0H]

#ps -ef

[root@linux ~]# ps -ef

UID PID PPID C STIME TTY TIME CMD

root 1 0 0 04:20 ? 00:00:02 /usr/lib/systemd/systemd

root 2 0 0 04:20 ? 00:00:00 [kthreadd]

root 3 2 0 04:20 ? 00:00:01 [ksoftirqd/0]

root 5 2 0 04:20 ? 00:00:00 [kworker/0:0H]

root 6 2 0 04:20 ? 00:00:01 [kworker/u256:0]

状态解释:

USER: #启动进程的用户

PID: #进程ID号

%CPU: #进程占用的CPU百分比

%MEM: #进程占用的内存百分比

VSZ: #进程申请占用的虚拟内存大小,单位KB

RSS: #进程实际占用的物理内存实际大小,单位KB

TTY: #进程运行的终端,?表示为内核程序,与终端无关

STAT: #进程运行中个的状态,可以man ps关键词/STATE查询详细帮助手册

###进程状态

D: 不可中断睡眠

R: 正在运行

S: 可中断睡眠

T: 进程被暂停

Z: 僵尸进程

###进程字符

<: 高优先级进程 S<表示优先级较高的进程

N: 低优先级进程 SN表示优先级较低的进程

s: 子进程发起者 Ss表示父进程

l: 多线程进程 Sl表示进程以多线程运行

+: 前台进程 R+表示该进程在前台运行,一旦终止,数据丢失

START: #进程启动时间

TIME: #进程占用CPU时间

COMMAND: #程序运行的指令 []表示属于内核态的进程。没有[]表示用户态进程

案例演示:

#1.查看进程的父子关系

ps auxf

#2.查看进程的特定属性

ps axo pid,cmd,%cpu,%mem

#3.按CPU利用率排序

ps axo pid,cmd,%cpu,%mem k -%cpu

#4.按内存使用倒序排序

ps axo pid,cmd,%cpu,%mem --sort %mem

#5.列出指定用户名和或用户ID的进程

ps -fu oldboy

ps -fu 1000

#6.查看指定进程ID对应的进程

ps -fp PID

#7.查找指定父进程ID下的所有的子进程

ps -f --ppid PID

#8.按照tty显示所属进程

ps -ft pts/1

#9.根据进程名查找所属PID

ps -C sshd -o pid=

#10.根据PID查找运行的命令

ps -p PID -o comm=

2.2 pstree 以树状图查看进程状态

命令作用:

以树状图显示父进程和子进程的关系

命令格式:

pstree [选项] [pid|user]

常用参数:

-p 显示PID

-u 显示用户切换

-H pid 高亮显示指定进程

案例演示:

#1.查看指定pid的进程关系

pstree 1

#2.查看oldboy用户的进程关系

pstree oldboy

#3.显示pid

pstree -p

pstree -p 1

pstree -p oldboy

#4.显示运行用户

pstree -u

2.3 pidof 查看指定名称进程的进程号

命令作用:

显示指定程序的pid

举例:

pidof nginx

2.4 top 查看当前的进程状态

命令作用:

展示进程动态的实时数据

常用参数:

-d #指定刷新时间,默认3秒

-n #刷新多少次后退出

-p #指定pid

内置命令:

#帮助

h/? #查看帮助

q/esc #退出帮助

#排序:

P #按CPU使用百分比排序输出

M #按内存使用百分比排序输出

#显示

1 #数字1,显示所有CPU核心的负载

m #显示内存内存信息,进度条形式

t #显示CPU负载信息,进度条形式

#退出

q #退出top命令

运行结果:

[root@linux ~]# top

top - 16:42:49 up 12:22, 3 users, load average: 0.00, 0.03, 0.05

Tasks: 106 total, 1 running, 105 sleeping, 0 stopped, 0 zombie

%Cpu(s): 0.0 us, 6.2 sy, 0.0 ni, 93.8 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st

KiB Mem : 2028088 total, 465376 free, 110864 used, 1451848 buff/cache

KiB Swap: 0 total, 0 free, 0 used. 1707948 avail Mem

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND

1 root 20 0 43524 3836 2580 S 0.0 0.2 0:02.61 systemd

2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd

3 root 20 0 0 0 0 S 0.0 0.0 0:01.45 ksoftirqd/0

5 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kworker/0:0H

6 root 20 0 0 0 0 S 0.0 0.0 0:01.24 kworker/u256:0

7 root rt 0 0 0 0 S 0.0 0.0 0:00.00 migration/0

状态解释:

Tasks: 106 total, #当前进程的总数

1 running, #正在运行的进程数

105 sleeping, #睡眠中的进程数

0 stopped, #停止的进程数

0 zombie #僵尸进程数

%Cpu(s): #平均CPU使用率,按1查看每个cpu核的具体状态

0.0 us, #用户进程占用CPU百分比

6.2 sy, #系统进程占用CPU百分比

0.0 ni, #优先级进程占用cpu的百分比

93.8 id, #空闲cup

0.0 wa, #CPU等待IO完成的时间,大量的io等待,会变高

0.0 hi, #硬中断,占的CPU百分比

0.0 si, #软中断,占的CPU百分比

0.0 st #虚拟机占用物理CPU的时间

什么是I/O?

I/O称为硬盘的: 写入/读取也就是硬盘的读写。

简单来说:系统发送读或写的指令,硬盘收到指令后进行读或写数据,这个过程就是一次IO。

什么是软中断和硬中断?

在Linux的实现中,有两种类型的中断。

硬中断是由请求响应的设备发出的(磁盘I/O中断、网络适配器中断、键盘中断、鼠标中断)

软中断被用于处理可以延迟的任务(TCP/IP操作,SCSI协议操作等等)

简单来说,就是中断就是告诉操作系统,停下你手里的工作,先处理我的任务。

硬中断是由硬件发出的,软中断是由正在运行的进程发出的。

案例演示:

#1.查看指定pid的进程信息

top -H -p $(pidof ping)

2.5 htop 更高级的top

命令作用:

界面更美观的增强版top

常用选项:

-d #指定刷新时间

-s #以指定列字段排序

常用指令:

t #显示进程树

运行结果:

2.6 lsof 查看进程打开文件

命令作用:

查看当前系统文件的工具。

在Linux下,一切皆文件,包括硬件及网络协议等也都可以访问,系统会为每一个程序都分配一个文件描述符。

常用参数:

-c #显示指定程序名所打开的文件

-d #显示打开这个文件的进程名

-i #显示符合条件的进程,IPv[46][proto][@host|addr][:svc_list|port_list]

-p #显示指定进程pid所打开的文件

-u #显示指定用户UID的进程

+d #列出目录下被打开的文件

+D #递归累出目录下被打开的文件

状态解释:

COMMAND 进程的名称

PID 进程标识符

USER 进程所有者

FD 文件描述符,应用程序通过文件描述符识别该文件。如cwd、txt等

TYPE 文件类型,如DIR、REG等

DEVICE 指定磁盘的名称

SIZE 文件的大小

NODE 索引节点(文件在磁盘上的标识)

NAME 打开文件的确切名称

案例演示:

#查看正在使用此文件的进程

lsof /var/log/nginx/access.log

#查看指定pid号的进程打开的文件

lsof -p $(cat /var/run/nginx.pid)

#查看指定程序打开的文件

lsof -c nginx

#查看指定用户打开的文件

lsof -u nginx

#查看指定目录下被打开的文件

lsof +d /var/log

lsof +D /var/log

#查看指定IP的连接

lsof -i@10.0.0.1

#查看指定进程打开的网络连接

lsof -i -a -n -p 8765

#查看指定TCP状态的连接

lsof -n -P -i TCP -s TCP:LISTEN

模拟误删除文件:

前提:被误删的文件还有进程在使用,并且这个进程不能重启或退出。

#1.新开一个终端使用tail查看nginx的访问日志,这里只是方便演示效果,不tail也可以恢复,只要nginx进程没有重启

[root@linux ~]# tail -f /var/log/nginx/access.log

#2.然后在另一个终端重看日志的进程信息

[root@linux ~]# lsof |grep access.log

nginx 9067 root 5w REG 253,0 0 67881734 /var/log/nginx/access.log

nginx 9068 nginx 5w REG 253,0 0 67881734 /var/log/nginx/access.log

tail 9099 root 3r REG 253,0 0 67881734 /var/log/nginx/access.log

#3.此时我们模拟误删除了日志文件

[root@linux ~]# rm -rf /var/log/nginx/access.log

[root@linux ~]# ll /var/log/nginx/access.log

ls: 无法访问/var/log/nginx/access.log: 没有那个文件或目录

#4.然后我们再次查看相关进程会发现日志文件后多了一个(deleted)字样,等得出PID以及文件描述符

[root@linux ~]# lsof |grep access.log

nginx 9067 root 5w REG 253,0 0 67881734 /var/log/nginx/access.log (deleted)

nginx 9068 nginx 5w REG 253,0 0 67881734 /var/log/nginx/access.log (deleted)

tail 9099 root 3r REG 253,0 0 67881734 /var/log/nginx/access.log (deleted)

#5.然后我们直接进入/proc/9067查看一下

[root@linux fd]# ll

总用量 0

lrwx------ 1 root root 64 4月 4 15:58 0 -> /dev/null

lrwx------ 1 root root 64 4月 4 15:58 1 -> /dev/null

l-wx------ 1 root root 64 4月 4 15:58 2 -> /var/log/nginx/error.log

lrwx------ 1 root root 64 4月 4 15:58 3 -> socket:[92536]

l-wx------ 1 root root 64 4月 4 15:58 4 -> /var/log/nginx/error.log

l-wx------ 1 root root 64 4月 4 15:58 5 -> /var/log/nginx/access.log (deleted)

lrwx------ 1 root root 64 4月 4 15:58 6 -> socket:[92525]

lrwx------ 1 root root 64 4月 4 15:58 7 -> socket:[92537]

#6.通过查看可以发现,名称为5的链接就是我们删除后的文件

[root@linux fd]# head -n 3 5

10.0.0.1 - - [04/Apr/2021:16:43:42 +0800] "GET / HTTP/1.1" 502 559 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.192 Safari/537.36" "-"

10.0.0.1 - - [04/Apr/2021:16:43:42 +0800] "GET / HTTP/1.1" 502 559 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.192 Safari/537.36" "-"

10.0.0.1 - - [04/Apr/2021:16:43:42 +0800] "GET / HTTP/1.1" 502 559 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.192 Safari/537.36" "-"

#7.接着我们就可以把数据恢复出来了

[root@linux fd]# cat 5 > /var/log/nginx/access.log

[root@linux fd]# ll /var/log/nginx/access.log

-rw-r--r-- 1 root root 1194 4月 4 16:44 /var/log/nginx/access.log

3.进程管理命令

3.1 控制信号

什么是控制信号?

简单来说,就是向进程发送控制信号,一般用于停止或杀死进程。

每个信号对应1个数字,信号名称以SIG开头,可以省略SIG头。

Linux常见控制信号

信号名称 数字编号 信号含义

HUP 1 无需关闭进程并且让其重新加载配置文件

KILL 9 强制杀死正在运行的进程

TERM 15 终止正在运行的进程,不特别指定数字信号的话,默认就是15

控制进程的命令

kill #结束指定PID的进程

killall #根据进程名杀死进程

pkill #同样是根据进程名杀死进程

3.2 kill

命令作用:

根据进程的pid号杀死指定的进程

常用参数:

kill -1 pid #重新加载配置

kill -15 pid #优雅的停止进程

kill -9 pid #强制终止进程

案例演示:

#1.安装nginx

[root@linux ~]# yum install nginx -y

#2.创建2个新的默认网页

[root@linux ~]# echo v1 > /usr/share/nginx/html/index.html

[root@linux ~]# cat /usr/share/nginx/html/index.html

v1

[root@linux ~]# echo v2 > /usr/share/nginx/html/index2.html

[root@linux ~]# cat /usr/share/nginx/html/index2.html

v2

#3.启动nginx并查看网页信息

[root@linux ~]# systemctl start nginx

[root@linux ~]# curl 127.0.0.1

v1

#4.修改nginx配置文件,将默认首先更新为index2.html

[root@linux ~]# sed -i 's#index.html#index2.html#g' /etc/nginx/conf.d/default.conf

[root@linux ~]# grep "index2" /etc/nginx/conf.d/default.conf

index index2.html index.htm;

#5.这时在访问一次。会发现依然是v1版本,为什么?因为我们虽然修改了配置文件,但是并没有重启,所以配置文件没有被加载。

[root@linux ~]# curl 127.0.0.1

v1

#6.查看nginx自带的启动文件里是如何重新加载配置文件的

[root@linux ~]# rpm -ql nginx |grep nginx.service

/usr/lib/systemd/system/nginx.service

[root@linux ~]# grep -i "reload" /usr/lib/systemd/system/nginx.service

ExecReload=/bin/sh -c "/bin/kill -s HUP $(/bin/cat /var/run/nginx.pid)"

#可以发现nginx重新加载配置是分为了2步操作:

1.找出正在运行的nginx的pid号

2.向nginx进程发送HUP信号,也就是0型号以使其重新加载配置

#7.发送控制信号重新加载配置

[root@linux ~]# pidof nginx

20951 20950

[root@linux ~]# cat /var/run/nginx.pid

20950

[root@linux ~]# kill -1 20950

#8.重新查看网页可以发现已经切换到了v2版本,说明配置被重新加载了

[root@linux ~]# curl 127.0.0.1

v2

#9.使用kill杀死进程

[root@linux ~]# kill 20950

[root@linux ~]# ps -ef|grep nginx

3.3 pkill和killall

命令作用:

类似于kill,只不过kill需要先找出pid号,然后再杀掉进程

而pkill则可以将kill的两步操作合二为一,只需要根据进程名就可以杀死进程

不过要注意的是pkill的优势也有可能会造成误杀,因为是根据进程名杀死进程,那么只要匹配上进程名的进程,哪怕只是名称里包含了匹配的,也会被杀掉。

案例演示:

#1.启动并查看nginx

[root@linux ~]# systemctl start nginx

[root@linux ~]# ps -ef|grep nginx|grep -v grep

root 21088 1 0 16:49 ? 00:00:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf

nginx 21089 21088 0 16:49 ? 00:00:00 nginx: worker process

#2.使用pkill杀死进程

[root@linux ~]# pkill nginx

[root@linux ~]# ps -ef|grep nginx|grep -v grep

#3.重新启动nginx并查看进程

[root@linux ~]# systemctl start nginx

[root@linux ~]# ps -ef|grep nginx|grep -v grep

root 21141 1 0 16:51 ? 00:00:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf

nginx 21142 21141 0 16:51 ? 00:00:00 nginx: worker process

#4.使用killall杀死nginx进程

[root@linux ~]# killall nginx

[root@linux ~]# ps -ef|grep nginx|grep -v grep

4.进程后台管理

前台运行与后台运行

1.前台进程就是运行在当前的终端,并且运行中的信息都会输出到屏幕上,会一直占用终端的使用。如果当前终端关闭了,则进程就自动退出了。

2.而后台进程则可以在终端的后台继续运行,但是并不会占用当前的终端使用。即使当前终端关闭了,进程也不会退出。

&,jobs,bg,fg -- 了解即可

命令作用:

& #把未启动的进程放在后台执行

jobs #查看后台进程

ctrl + z #将运行中的进程放在后台.但是暂停

bg #将暂停的进程放在后台继续运行

fg #将后台进程调回到前台

案例演示:

[root@linux ~]# sleep 3000 &

[1] 22125

[root@linux ~]# sleep 4000

^Z

[2]+ 已停止 sleep 4000

[root@linux ~]# ps aux|grep sleep

root 22125 0.0 0.0 108052 612 pts/0 S 20:41 0:00 sleep 3000

root 22127 0.0 0.0 108052 616 pts/0 T 20:41 0:00 sleep 4000

[root@linux ~]# jobs

[1]- 运行中 sleep 3000 &

[2]+ 已停止 sleep 4000

[root@linux ~]# bg %2

[2]+ sleep 4000 &

[root@linux ~]# jobs

[1]- 运行中 sleep 3000 &

[2]+ 运行中 sleep 4000 &

[root@linux ~]# fg %1

sleep 3000

[root@linux ~]# kill %2

[root@linux ~]# jobs

[2]- 已终止 sleep 4000

[3]+ 运行中 sleep 3000 &

screen -- 重点推荐

命令作用:

工作中非常推荐使用的后台进程管理工具,作用是可以将进程放在后台运行,并且可以随时切换到前台。

常用参数:

screen -S 终端名称 #新建一个指定名称的终端

Ctrl + a + d #切换到前台,但是保持后台运行的进程

screen -ls #查看已经放在后台的进程名称列表

screen -r 名称或ID号 #进入指定名称的后台程序

案例演示:

#1.创建名为ping的终端

[root@linux ~]# screen -S ping

#2.切换到后台后执行前台命令

[root@linux ~]# ping 127.0.0.1

PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.

64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.012 ms

64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.038 ms

#3.切出后台,切换到前台

Ctrl + a + d

#4.查看已经在运行的后台进程列表

[root@linux ~]# screen -ls

There is a screen on:

22237.ping (Detached)

1 Socket in /var/run/screen/S-root.

#5.重新进入指定名称的后台进程

[root@linux ~]# screen -r ping

nohub &

命令作用:

将进程放在后台执行,并且把运行过程输出到日志里。

常用参数:

nohup 命令 >> 日志 2>&1 &

案例演示:

nohup /usr/sbin/nginx >> /var/log/nginx/access.log 2>&1 &

第2章 系统平均负载监控

uptime 查看系统平均负载

什么是系统负载?

系统负载是指单位时间内,系统处于可运行状态和不可中断状态的平均进程数,也就是平均活跃进程数。

简单来说就是可以被分配给CPU处理的活动进程数。

注意,平均负载指的并不是系统CPU使用率。

什么是可运行状态和不可中断状态?

1.可运行状态进程,是指正在使用 CPU 或者正在等待 CPU 的进程,也就是我们ps命令看到处于R状态的进程。

2.不可中断进程,系统中最常见的是等待硬件设备的I/O响应,也就是我们ps命令中看到的D状态(也称为 Disk Sleep)的进程。

例如: 当一个进程向磁盘读写数据时,为了保证数据的一致性,在得到磁盘回复前,它是不能被其他进程或者中断打断的,这个时候的进程就处于不可中断状态。如果此时的进程被打断了,就容易出现磁盘数据与进程数据不一致的问题。所以,不可中断状态实际上是系统对进程和硬件设备的一种保护机制。

在Linux的实现中,有两种类型的中断。

硬中断是由请求响应的设备发出的(磁盘I/O中断、网络适配器中断、键盘中断、鼠标中断)。

软中断被用于处理可以延迟的任务(TCP/IP操作,SCSI协议操作等等)

平均负载为多少合适?

最理想的状态是每个CPU核上都刚好运行着一个进程,这样每个CPU都得到了充分利用。

所以首先你需要知道你的服务器上有几个CPU,可以通过lscpu命令或top交互模式按1查看有几核。

假如有以下核数的CPU,负载为2时,说明了什么?

CPU核数 负载 说明

1 2 表示有一半的进程需要等待

2 2 表示刚好所有的CPU都被使用了

4 2 表示有一半的CPU处于空闲状态

uptime命令有三个数值,分别为1,5,15分钟的平均负载,那么该如何理解这三个数值呢?或者说更应该关注哪个值?

简单来说,三个数值都要看,但是一定要分析变化的趋势,虽然三个值是数字,但是他们表达的是1到15分钟CPU负载变化的趋势。

例如如下几种情况:

1.三个数值差不多一样,这表示了系统运行很稳定,15分钟内系统没有特别繁忙。

2.如果1分钟的值大于15分钟的值,那表示系统负载1分钟内有上升的趋势。但是并不能立即下结论,因为有可能只是临时的升高,所以要持续的观察一段时间,结合这段时间的趋势分析。

3.如果1分钟负载低于15分钟的值,那表示系统负载是在下降的趋势。

如何监控系统负载的趋势呢?

实际工作中我们不可能实时的使用uptime命令来监控系统负载,那么我们如何随时系统平均的负载呢?

1.自己编写脚本然后配合定时任务周期性的运行uptime命令并输出到文本里

2.推荐使用成熟的监控工具,比如zabbix,Prometheus等监控平台,因为他们具有丰富的图形报表功能,更容易观察变化趋势。

假如平均负载变高了,应该如何处理?

虽然理想情况是每个CPU核数都被使用,但是也不是说如果平均负载超过了CPU核数系统就不正常了。

如果只是短暂的超过了CPU核数,并且平均负载有下降的趋势,那可以理解为刚才系统只是暂时的繁忙,现在已经恢复正常。

如果持续的负载高,但是业务系统并没有变慢,系统也没有进一步变糟糕的趋势,那么也不用过于担心。

如果系统确实负载高了,那么可以从以下几个角度分析:

1.运行任务是否CPU密集型

2.运行任务是不是IO密集型

命令作用:

通过uptimem命令我们可以了解到系统的CPU负载情况,当然top命令也可以。

运行结果:

[root@linux ~]# uptime

10:14:58 up 15:01, 1 user, load average: 0.01, 0.03, 0.05

状态解释:

10:14:58 #当前时间

up 15:01 #系统已启动时间

1 user #当前登陆的用户数

load average: 0.01, 0.03, 0.05 #系统 1分钟,5分钟,15分钟的平均负载

案例演示1:模拟CPU使用率100%的场景

这里我们使用三个工具来找出平均负载变高的原因

stress: 压测工具

mpstat: 多核CPU性能分析工具

pidstat: 实时查看CPU,内存,IO等指标

#1.安装性能监控工具

[root@linux ~]# wget http://pagesperso-orange.fr/sebastien.godard/sysstat-11.7.3-1.x86_64.rpm

[root@linux ~]# rpm -ivh sysstat-11.7.3-1.x86_64.rpm

#2.使用strss工具模拟CPU使用率100%

[root@linux ~]# stress --cpu 1 --timeout 600

stress: info: [18742] dispatching hogs: 1 cpu, 0 io, 0 vm, 0 hdd

#3.在第2个终端运行uptime命令实时查看系统的负载

##可以看到1分钟的负载正在升高

[root@linux ~]# watch -d uptime

16:06:47 up 20:53, 3 users, load average: 0.90, 0.67, 0.51

#4.在第3个终端运行mpstat查看CPU使用率变化情况

##可以看到CPU1使用率达到了100%,但是iowait只有0,这说明系统负载变高正是由于CPU使用率100%导致的

[root@linux ~]# mpstat -P ALL 5

Linux 3.10.0-957.el7.x86_64 (linux) 2021年04月05日 _x86_64_ (1 CPU)

15时59分32秒 CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle

15时59分37秒 all 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00

15时59分37秒 0 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00

#5.在第4个终端使用top命令查看CPU使用率

##可以看到stress进程的CPU使用率达到了100%

[root@linux ~]# top

Tasks: 104 total, 2 running, 102 sleeping, 0 stopped, 0 zombie

%Cpu(s):100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st

KiB Mem : 2028088 total, 1590216 free, 101924 used, 335948 buff/cache

KiB Swap: 0 total, 0 free, 0 used. 1735256 avail Mem

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND

18743 root 20 0 7312 100 0 R 99.7 0.0 6:55.68 stress

18712 root 20 0 0 0 0 S 0.3 0.0 0:00.06 kworker/0:2

1 root 20 0 43528 3848 2580 S 0.0 0.2 0:03.66 systemd

2 root 20 0 0 0 0 S 0.0 0.0 0:00.01 kthreadd

第3章 内存监控

free 查看内存使用状态

命令作用:

查看Linux系统的内存使用情况

常用参数:

free [选项]

-b 以b为单位输出

-k 以k为单位输出

-m 以m为单位输出

-g 以g为单位输出

-h 以人类可读友好的单位输出

-s N 间隔N秒输出一次

-c N 输出N次后退出

运行结果:

#默认以b为单位输出

[root@linux ~]# free

total used free shared buff/cache available

Mem: 2028088 85188 1807080 9720 135820 1783376

Swap: 0 0 0

#以m为单位输出

[root@linux ~]# free -m

total used free shared buff/cache available

Mem: 1980 82 1764 9 132 1741

Swap: 0 0 0

#以人类可读的单位输出

[root@linux ~]# free -h

total used free shared buff/cache available

Mem: 1.9G 82M 1.7G 9.5M 132M 1.7G

Swap: 0B 0B 0B

状态解释:

man free #free命令帮助手册

total #总计已安装的内存,统计信息来自/proc/meminfo的MemTotal和SwapTotal字段

used #已使用内存,计算公式为:used = total - free - buffers - cache

free #空闲的未使用内存,计算公式为:total - used - buff - cache

shared #共享内存,主要由tmpfs使用

buff/cache #buffers和cache的总和

buffers #缓冲区,写缓冲,目的是加快内存和硬盘之间的数据写入。存放内存需要写入到磁盘的数据。

cache #缓存区,读缓存,目的是加快CPU和内存交换数据。存放的是内存已经读完的数据。

available #估计有多少内存可用于启动新应用程序而无需交换。与cache或free字段提供的数据不同,此字段考虑了页面缓存。

swap #硬盘交换分区,目的是防止内存使用完了导致系统崩溃,临时将硬盘的一部分空间当作内存使用。

清空缓存:

echo 3 > /proc/sys/vm/drop_caches

buff/cache解释:

cache:

内存速度很快,但是CPU速度更快,所以为了提高CPU和内存之间交换数据的效率,设计了cache缓存这种技术。

CPU本身就有缓存,就是我们常听说的1级缓存2级缓存3级缓存,但是CPU内部的缓存成本太昂贵,所以设计的容量都非常小,那么就利用内存的部分空间来缓存CPU已经读过的数据,这样CPU下次访问只需要从cache里直接取就行了,不用再访问内存里的实际存储位置。

buffers:

内存速度很快,但是硬盘速度很慢,所以为了提高硬盘的写入效率,设计了buffer。

buffer主要作用是将内存写完的数据缓存起来,然后通过系统调度策略在合适的时机再定期刷新到磁盘上。

这样可以减少磁盘的寻址次数,以提高写入性能。

示意图:

第4章 磁盘监控

iostat

iotop

命令作用:

iotop用于监控磁盘的I/O使用情况,包含读和写的速率,IO百分比等信息,类似于top命令。

常用参数:

-o #只显示正在进行io操作的进程,也可以先在iotop命令运行中按o

-b #非交互模式,比较适合监控项取值或者脚本定时输出内容

-n N #默认非交互模式会一直输出信息,-n选项可以控制输出次数,常结合-b参数一起使用

-d N #设置每次数据更新的间隔,默认是1秒

-p PID #监控指定PID的进程

-u USER #监控指定用户运行程序产生的IO

-q #禁止输出头几行,一般用于非交互模式

-qq #不显示列名

-qqq #不显示IO的总揽

交互式按键:

左/右键 #切换选中的列,并且按照选中的列进行排序

p #默认显示的是线程TID,按p切换到进程PID

q #退出

运行结果:

状态解释:

#第一行 磁盘读写的速率总计

Total DISK READ :

Total DISK WRITE :

#第二行 磁盘读写的实际速率

Actual DISK READ:

Actual DISK WRITE:

#第三行 具体的进程速率信息

TID #线程ID,按p切换为进程PID

PRIO #优先级

USER #运行用户

DISK READ #磁盘读的速率

DISK WRITE #磁盘写的速率

SWAPIN #swap交换分区百分比

IO #IO等待百分比

COMMAND #运行的进程

案例演示:

[root@linux opt]# iotop -b -n 1 -a -qqq |head -n 5

1 be/4 root 0.00 B 0.00 B 0.00 % 0.00 % systemd --switched-root --system --deserialize 22

2 be/4 root 0.00 B 0.00 B 0.00 % 0.00 % [kthreadd]

3 be/4 root 0.00 B 0.00 B 0.00 % 0.00 % [ksoftirqd/0]

5 be/0 root 0.00 B 0.00 B 0.00 % 0.00 % [kworker/0:0H]

6 be/4 root 0.00 B 0.00 B 0.00 % 0.00 % [kworker/u256:0]

第5章 网络监控

iftop

命令作用:

实时显示网络流量,类似与top和iotop

常用参数:

-h #帮助说明

-B #以bytes为单位显示

-i #指定网卡

-n #不解析DNS

交互式按键:

b #显示进度条

n #打开或关闭DNS解析名称

t #切换流量显示模式

q #退出

运行结果:

状态解释:

TX transport发送的数据包速率

RX receive接收的数据包速率

TOTAL 接收和发送的数据包汇总

案例演示:

[root@linux ~]# iftop -B -n -i eth0