17-Linux进程管理

1. 进程介绍

1.1什么是进程

开发写的代码, 称为程序.
开发的代码运行起来, 称为进程.  
总结一句话就是: 当我们运行一个程序, 那么我们将运行的程序叫进程.  
PS1: 当程序运行为进程后, 系统会为该进程分配内存, 以及进程运行的身份和权限.  
PS2: 在进程运行的过程中, 系统会有各种指标来表示当前运行的状态.

1.2 程序和进程的区别

1. 程序是数据和指令的集合, 是一个静态的概念.
   比如/bin/ls、/bin/cp等二进制文件, 同时程序可以长期存在系统中.  
2. 进程是程序运行的过程, 是一个动态的概念.
   进程是存在生命周期的概念的, 也就是说进程会随着程序的终止而销毁,
   不会永久存在系统中.

1.3 进程的生命周期

生命周期就是指一个对象的生老病死.

17-Linux进程管理_第1张图片

当父进程接收到任务调度时, 会通过fock派生子进程来处理, 那么子进程会继承父进程属性.  
1.子进程在处理任务代码时, 父进程会进入等待状态中…  
2.子进程在处理任务代码后, 会执行退出, 然后唤醒父进程来回收子进程的资源.  
3.如果子进程在处理任务过程中, 父进程退出了, 子进程没有退出, 那么这些子进程就没有父进程来管理了, 就变成僵尸进程.  
PS: 每个进程都父进程的PPID, 子进程则叫PID.

2. 监控进程状态

程序在运行后, 需要了解进程的运行状态.
查看进程的状态分为: 静态和动态两种方式

2.1 静态查看进程状态

使用ps命令查看当前的进程状态(静态)
ps -aux常用组合, 查看进程 用户、PID、占用cpu百分比、占用内存百分比、状态、执行的命t

17-Linux进程管理_第2张图片

2.2 进程信息

状态 描述
USER 启动进程的用户
PID 进程运行的ID号
%CPU 进程占用CPU百分比
%MEM 进程占用内存百分比
VSZ 进程占用虚拟内存大小 (单位KB)
RSS 进程占用物理内存实际大小 (单位KB)
TTY 进程是由哪个终端运行启动的tty1、pts/0等 ?表示内核程序与终端无关(远程连接会通过tty打开一个bash:tty)
STAT 进程运行过程中的状态 man ps (/STATE)
START 进程的启动时间
TIME 进程占用 CPU 的总时间(为0表示还没超过秒)
COMMAND 程序的运行指令, [ 方括号 ] 属于内核态的进程. 没有 [ ] 的是用户态进程.systemctl status 指令

2.3 进程的STAT信息

17-Linux进程管理_第3张图片

STAT基本状态 描述 STAT状态+符号 描述
R 进程运行 s 进程是控制进程, Ss进程的领导者, 父进程
S 可中断睡眠 < 进程运行在高优先级上, S<优先级较高的进程
T 进程被暂停 N 进程运行在低优先级上, SN优先级较低的进程
D 不可中断睡眠 + 当前进程运行在前台, R+该表示进程在前台运行(正在io操作, 一旦停止, 数据丢失)
Z 僵尸进程 l 进程是多线程的, Sl表示进程是以线程方式运行

3.5 查看进程暂停状态

使用ps命令查询切换的进程状态.(使用xshell连接两次, 一个终端1, 一个终端2)
# 在终端1上运行vim  
[root@kid ~]# vim 1.txt  

# 在终端2上运行ps命令查看状态  
[root@kid ~]# ps aux|grep 1.txt
# 这个时终端1执行的命令
root       3914  0.4  0.4 149244  4940 pts/1    S+   17:03   0:00 vim 1.txt
# 这个是终端2当前执行的命令
root       3916  0.0  0.0 112808   980 pts/0    R+   17:03   0:00 grep --color=auto 1.txt
[root@kid ~]# 

17-Linux进程管理_第4张图片

# 在终端1上挂起vim命令, 按下:ctrl+z  
[root@kid ~]# vim 1.txt  # 已经输入过了

[1]+  Stopped                 vim 1.txt
[root@kid ~]# 

# 回到终端2再次运行ps命令查看状态  
[root@kid ~]# ps aux|grep 1.txt
# T表示程序被暂停
root       3914  0.0  0.4 149244  4940 pts/1    T    17:03   0:00 vim 1.txt
root       3919  0.0  0.0 112808   980 pts/0    R+   17:05   0:00 grep --color=auto 1.txt

3.6 查看不可中断进程状态

# 使用tar打包文件时, 可以通过终端不断查看状态, 由S+, R+变为D+  
[root@kid ~]# tar -czf etc.tar.gz /etc/ /usr/ /var/  

[root@kid ~]# ps aux|grep tar|grep -v grep  
root      58467  5.5  0.2 127924  5456 pts/1    R+   22:22   0:04 tar -czf etc.tar.gz /etc/   
[root@kid ~]# ps aux|grep tar|grep -v grep  
root      58467  5.5  0.2 127088  4708 pts/1    S+   22:22   0:03 tar -czf etc.tar.gz /etc/   
[root@kid ~]# ps aux|grep tar|grep -v grep  
root      58467  5.6  0.2 127232  4708 pts/1    D+   22:22   0:03 tar -czf etc.tar.gz /etc/  

3.7 动态查看进程状态

使用top命令查看当前的进程状态(动态)

17-Linux进程管理_第5张图片

任务 含义
top - 17:12:53 up 2:28 top命令执行时间, 系统运行时间2:28分
load average 平均负载 一分钟, 5分钟, 15分钟 的负载状态
Tasks: 104 total 当然进程的总数
3 running 正在运行的进程数
98sleeping 睡眠的进程数
3 stopped 停止的进程数
0 zombie 僵尸进程数
%Cpu(s) 平均cpu使用率, 按1 查看每个cup具体状态
0.0 us 用户进程占用cpu百分比
0.0 sys 内核进程占用百分比
0.0 ni 优先级进程占用cpu的百分比
100.0 id 空闲cup
0.0 wa CPU等待IO完成的时间, 大量的io等待, 会变高
0.0 hi 硬中断, 占的CPU百分比
0.0 si 软中断, 占的CPU百分比
0.0 st 虚拟机占用物理CPU的时间
# 显示Linux系统中当前登录用户的信息以及该用户正在执行的进程信息
[root@kid ~]# w
 17:20:11 up  2:35,  2 users,  load average: 0.02, 0.07, 0.10
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0    10.0.0.1         17:18    3.00s  0.18s  0.00s w
root     pts/1    10.0.0.1         17:02   10:03  39.37s  0.01s -bash

# 用于显示系统总共运行了多长时间和系统的平均负载
[root@kid ~]# uptime
 17:21:23 up  2:36,  2 users,  load average: 0.01, 0.06, 0.09
了解中断: https://www.cnblogs.com/xuliangwei/p/10789270.html
top常见指令, 在输入top命令之后, 出现了top展示的信息再按下面按键使用对应的功能.
字母 含义
h 查看帮出
1 数字1, 显示所有CPU核心的负载
z 以高亮显示数据
b 高亮显示处于R(进行中)状态的进程
M 按内存使用百分比排序输出
P 按CPU使用百分比排序输出
q 退出top
第三方top  
htop, 高级版本的top:
    先安装epel源:  yum -y install  epel-release 
    安装htop: yum install htop -y  
    使用htop: htop

iftop, 网卡流量: 
    安装iftop: yum install iftop -y  
    使用iftop: iftop
    
glances, 提供监视和分析性能数据的功能(更加直观的显示)
	安装glances:yum install glances -y  
      -rz上传文件, 可以动态看到, 网卡情况  

3. 管理进程状态

当程序运行为进程后, 如果希望停止进程, 怎么办呢?
那么此时我们可以使用linux的kill命令对进程发送关闭信号.
当然除了kill、还有killall, pkill

3.1 查看系统支持的信号

 使用kill -l列出当前系统所支持的信号

17-Linux进程管理_第6张图片

虽然linux支持信号很多, 但是我们仅列出我们最为常用的3个信号
数字编号 信号含义 信号翻译
1 SIGHUP 通常用来重新加载配置文件,重新读取一次参数的配置文件 (类似 reload)
9 SIGKILL 强制杀死进程(有状态的服务(存磁盘的, 如mysql)强制停止可能会导致下次起不来)
15 SIGTERM 终止进程, 默认kill使用该信号

3.2 通过进程号杀死进程

使用kill命令杀死指定PID的进程.
# 安装vsftpd服务
[root@kid ~]# yum -y install vsftpd  
# 启动vsftpd服务
[root@kid ~]# systemctl start vsftpd  
# 查看vsftpd服务的进程 (进程id 2609)
[root@kid ~]# ps aux|grep vsftpd  
root       2609  0.0  0.0  53292   576 ?        Ss   18:04   0:00 /usr/sbin/vsftpd /etc/vsftpd/vsftpd.conf
root       2611  0.0  0.0 112808   968 pts/1    R+   18:04   0:00 grep --color=auto vsftpd

# 2.发送重载信号, 例如 vsftpd 的配置文件发生改变, 希望重新加载  
[root@kid ~]# kill -1 2609 
  
# 3.发送停止信号, 当然vsftpd 服务有停止的脚本 systemctl stop vsftpd  
[root@kid ~]# kill 2609  
  
#4.发送强制停止信号, 当无法停止服务时, 可强制终止信号  
[root@kid ~]# kill -9 2609  

3.3 杀死子进程

子进程被杀死很快被父进程从新启动, 只有杀死父进程, 子进程才会完全杀死.
# 安装nginx
[root@kid ~]# yum install nginx -y
# nginx的配置文件/etc/nginx/nginx.conf 

# 启动 nginx
[root@kid ~]# systemctl start nginx 
# 查看nginx进程
[root@kid ~]# ps aux|grep nginx
# 主进程
root       2723  0.0  0.0  39308   936 ?        Ss   18:22   0:00 nginx: master process /usr/sbin/nginx
# 网络服务(子进程)
nginx      2725  0.0  0.1  39696  1820 ?        S    18:22   0:00 nginx: worker process
root       2739  0.0  0.0 112808   964 pts/1    R+   18:28   0:00 grep --color=auto nginx

# 修改为worker_processes  10; 
[root@kid ~]# vim /etc/nginx/nginx.conf   

[root@kid ~]# kill -1 26093    # 平滑reload nginx, 进程会发生变化
[root@kid ~]# ps aux|grep nginx
root       2723  0.0  0.2  39424  2016 ?        Ss   18:22   0:00 nginx: master process /usr/sbin/nginx
nginx      2745  0.0  0.1  39428  1464 ?        S    18:31   0:00 nginx: worker process
...
 # 杀掉一个子进程, 会迅速的被master启动起来, 只是id号不一致了  
[root@kid ~]# kill 2745  
[root@kid ~]# ps aux|grep nginx
root       2723  0.0  0.2  39424  2016 ?        Ss   18:22   0:00 nginx: master process /usr/sbin/nginx
# 子进程还存在, pid号换了
nginx      2751  0.0  0.1  39428  1464 ?        S    18:33   0:00 nginx: worker process

# 杀死主进程, 子进程都会被杀掉  
[root@kid ~]# ps aux|grep nginx
# nginx的进程都没了, 只有查询nginx的进程存在
root       2758  0.0  0.0 112808   968 pts/1    R+   18:35   0:00 grep --color=auto nginx

3.4 通过服务名称杀掉进程

Linux系统中的killall、pkill命令用于杀死指定名字的进程.
可以使用kill命令杀死指定进程PID的进程, 如果要找到我们需要杀死的进程, 
还需要在之前使用ps等命令再配合grep来查找进程, 
而killall、pkill把这两个过程合二为一.
# 启动nginx服务
[root@kid ~]#  systemctl start nginx
# 查看nginx进程
[root@kid ~]# ps aux|grep nginx
root       2773  0.0  0.0  39308   936 ?        Ss   18:39   0:00 nginx: master process /usr/sbin/nginx
nginx      2775  0.0  0.1  39312  1324 ?        S    18:39   0:00 nginx: worker process
...

# 例通过服务名称杀掉进程  
[root@kid ~]# pkill nginx  

# 下载killall
[root@kid ~]# yum install psmisc -y
# 重复上面的启动nginx步骤
[root@kid ~]# killall nginx  

# 一般程序都会有自己的启动和停止
/usr/local/nginx/sbin/nginx -h 
# 二进制安装会有这个目录, yum安装没用)
[root@kid ~]# rpm -qc nginx
/etc/logrotate.d/nginx
/etc/nginx/fastcgi.conf
...

3.5 终止远程连接的进程

使用pkill踢出从远程登录到本机的用户, 终止pts/0上所有进程, 
并且bash也结束, 用户被强制退出.
# 结束远程用户的bash
[root@kid ~]# pkill -9 bash  

4. 管理后台进程

4.1 什么是后台进程

后台进程(Background Process): 
是一种在不需用户干预的情况下运行于操作系统后台的计算机进程.
通常进程都会在终端前台运行, 一旦关闭终端, 进程也会随着结束, 
那么此时我们就希望进程能在后台运行, 就是将在前台运行的进程放入后台运行,
这样及时我们关闭了终端也不影响进程的正常运行.

4.2 为什么要将进程放入后台运行

比如:此前在国内服务器往国外服务器传输大文件时,由于网络的问题需要传输很久,
如果在传输的过程中出现网络抖动或者不小心关闭了终端则会导致传输失败, 
如果能将传输的进程放入后台, 是不是就能解决此类问题了.

4.3 使用什么工具将进程放入后台

早期的时候大家都选择使用&符号将进程放入后台,
然后在使用jobs、bg、fg等方式查看进程状态, 但太麻烦了.
也不直观, 所以我们推荐使用screen.
jobs、bg、fg的使用(强烈不推荐, 了解即可)
# 睡3000秒 & 在后台
[root@kid ~]# sleep 3000 &  
[root@kid ~]# ps aux | grep sleep
root       5291  0.0  0.0 108052   356 pts/0    S    19:30   0:00 sleep 3000
...

# 将前台的程序挂起(暂停)到后台
[root@kid ~]# sleep 4000 
^Z
[2]+  Stopped                 sleep 4000
 
[root@kid ~]# ps aux |grep sleep  
root       5298  0.0  0.0 108052   356 pts/0    T    19:31   0:00 sleep 4000
...

# 查看后台作业 Running正在运行  Stopped暂停
[root@kid ~]# jobs  
[1]   Running                 sleep 3000 &
[2]+  Stopped                 sleep 4000
每个bash都要自己独立的后台, 连接两个xshell找不到彼此的后台程序.
# 运行程序(时), 让其在后台执行  
# 在命令后面加上&, 程序执行都是有时间的,
# 一般一秒就执行结束的命令执行了看不出效果
[root@kid ~]# sleep 5 &
[2] 1496
# 查看后台
[root@kid ~]# jobs
[1]+  Running                 sleep 5 &
[root@kid ~]# jobs
[1]+  Running                 sleep 5 &
# 到这里都停止了
[root@kid ~]# jobs
[1]+  Done                    sleep 5

#  将作业 1 调回到前台  
[root@kid ~]# fg %1 
sleep 3000
# 光闭停在这里等3000秒, ctrl + z 暂停程序
[1]+  Stopped                 sleep 3000

# 让作业 1 在后台运行  
[root@kid ~]# bg %1 
[1]+ sleep 3000 &

# 
[root@kid ~]# jobs
# []中的序号是后台进程的pid
[1]-  Running                 sleep 3000 &
[2]+  Stopped                 sleep 4000

# 终止后台程序 PID 为 1 的进程  
[root@kid ~]# kill %1  
# 查看后台程序, Terminated 停止
[root@kid ~]# jobs
[1]-  Terminated              sleep 3000
[2]+  Stopped                 sleep 4000

# 进程在后台运行, 但输出依然在当前终端  
[root@kid ~]# (while :; do date; sleep 2; done) & 
Thu Sep  8 19:45:08 CST 2022
Thu Sep  8 19:45:10 CST 2022
Thu Sep  8 19:45:12 CST 2022
...
# 快速按下回车等出现终端的时候输入kill %3, 不然会自动输入date并回车
# 要趁他还还没输入的时候抢先输入终止运行
[root@kid ~]#  kill %3
# 输出信息丢入黑洞
[root@kid ~]# (while :; do date; sleep 2; done) &> /dev/null &  
screen的使用(强烈推荐, 生产必用)
# 1. 安装  
[root@oldboy ~]# yum install screen -y  
# 2. 开启一个screen窗口,指定名称  
[root@oldboy ~]# screen -S wget_mysql  
  
# 3. 在screen窗口中执行任务即可  (下载mysql)
[root@oldboy ~]# wget https://downloads.mysql.com/archives/get/p/23/file/mysql-5.7.30-linux-glibc2.12-x86_64.tar.gz --no-check-certificate  
  
# 4.平滑的退出screen,但不会终止screen中的任务. 
# 注意: 如果使用exit 才算真的关闭screen窗口  
# 快捷键: ctrl+a+d  输入之后出现下行提示
[detached from 1527.wget_mysql]

# 5.查看当前正在运行的screen有哪些  
[root@kid ~]# screen -list  
There is a screen on:
	1527.wget_mysql	(Detached)
1 Socket in /var/run/screen/S-root.

  
# 6.进入正在运行的screen  
[root@oldboy ~]# screen -r wget_mysql  
# 获取通过编号进入screen  
[root@oldboy ~]# screen -r 1527  
  
# 7 终止(ctrl+z), 退出才能停止screen  
....
[1]+  Stopped                 wget https://downloads.mysql.com/archives/get/p/23/file/mysql-5.7.30-linux-glibc2.12-x86_64.tar.gz --no-check-certificate
[root@kid ~]# exit
exit
There are stopped jobs.
[root@kid ~]# 

5. 进程的优先级

5.1 什么优先级

优先级(priority)是一种约定, 是计算机分时操作系统在处理多个作业程序时, 
决定各个作业程序接受系统资源的优先等级的参数, 优先级高的先做, 优先级低的后做.

5.2 为什么要有系统优先级

因为在很多情况下, 总会有优先级特别高的事件出现.
例如: 在医院中有急诊病例,交通道路中有应急车道等, 这些情况发生时,
事件优先级会提升到“极高”.

5.3 查看优先级

在启动进程时, 为不同的进程使用不同的调度策略.  
nice 值越高: 表示优先级越低, 例如+19, 该进程容易将CPU 使用量让给其他进程.  
nice 值越低: 表示优先级越高, 例如-20, 该进程更不倾向于让出CPU.
* 使用top或ps命令查看进程的优先级
使用top可以查看nice优先级.    
NI: 实际nice级别, 默认是0.   
PR: 显示nice值, -20映射到0, +19映射到39  

17-Linux进程管理_第7张图片

# 使用ps查看进程优先级(auo以指定格式展示 终端 nice, 过滤sshd相关信息)
# grep -v grep 排查grep本身这个命令的展示
[root@kid ~]# ps axo command,nice |grep sshd|grep -v grep
/usr/sbin/sshd -D             0
sshd: root@pts/0              0

5.4 系统中如何给进程配置优先级?

nice指定程序的优先级.
语法格式 nice -n 优先级数字 进程名称
# 开启vim并且指定程序优先级为-5 
[root@kid ~]# nice -n -5 vim & 
[3] 1454

# 查看该进程的优先级情况
[root@kid ~]# ps axo pid,command,nice |grep 1454| grep -v grep
  1454 vim                          -5

renice命令修改一个正在运行的进程优先级.
语法格式 renice -n 优先级数字 进程pid
# 查看sshd进程当前的优先级状态  
[root@kid ~]# ps axo pid,command,nice |grep sshd |grep -v grep
  1103 /usr/sbin/sshd -D             0
  1152 sshd: root@pts/0              0
# 调整sshd主进程的优先级 
[root@kid ~]#  renice -n -20 1103
1103 (process ID) old priority 0, new priority -20

# 查看调整的结果
[root@kid ~]# ps axo pid,command,nice |grep sshd |grep -v grep
  1103 /usr/sbin/sshd -D           -20
  1152 sshd: root@pts/0              0

# 退出终端(我使用xshell连接的, 退出再重连)
[root@kid ~]# exit
logout

Connection closed.
...

Last login: Fri Sep  9 16:44:13 2022 from 10.0.0.1
# 当再次登陆sshd服务, 会由主进程fork子进程(那么子进程会继承主进程的优先级)
[root@kid ~]#  ps axo pid,command,nice |grep sshd |grep -v grep
  1103 /usr/sbin/sshd -D           -20
  1497 sshd: root@pts/0            -20

6. 系统平均负载

每次发现系统变慢时, 通常做的第一件事, 
就是执行top或者uptime命令, 来了解系统的负载情况.
比如像下面这样, 在命令行里输入了 uptime命令, 系统也随即给出了结果.
[root@kid ~]# uptime
 17:17:16 up 33 min,  1 user,  load average: 0.00, 0.01, 0.04
 
# 前面几列, 它们分别是当前时间、系统运行时间以及正在登录用户数.     
# 而最后三个数字, 依次则是过去 1 分钟、5 分钟、15 分钟的平均负载(Load Average).

6.1 什么是平均负载

单位时间: 一般是指一个时间单位的时间, 具体情况具体分析, 可以是1, 1小时, 1天等等.
平均负载: 是指单位时间内, 系统处于可运行状态和不可中断状态的平均进程数, 
也就是单位时间内的活跃进程数.
PS: 平均负载与 CPU使用率并没有直接关系.

6.2 可运行状态和不可中断状态

可运行状态进程:是指正在使用 CPU 或者正在等待 CPU 的进程, ps命令看到处于R状态的进程.  
(你做什么事情的时候是不能打断的?) 
不可中断进程: 系统中最常见的是等待硬件设备的I/O响应, 
也就是我们 ps 命令中看到的 D 状态(也称为Disk Sleep)的进程.  

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

6.3 那平均负载为多少时合理

最理想的状态是每个CPU上都刚好运行着一个进程, 这样每个CPU都得到了充分利用.
所以在评判平均负载时, 首先你要知道计算机CPU的运行核心有几核.
# 从 /proc/cpuinfo 中查看设备名称 获取cpu的信息
[root@kid ~]# grep 'model name' /proc/cpuinfo
model name	: 12th Gen Intel(R) Core(TM) i7-12700H

# 获取cpu的信息
[root@kid ~]# cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c
      1  12th Gen Intel(R) Core(TM) i7-12700H
      
# 查看物理CPU个数
[root@kid ~]# cat /proc/cpuinfo| grep "physical id"| sort| uniq| wc -l
1


# 查看CPU核心数
[root@kid ~]# cat /proc/cpuinfo| grep "cpu cores"| uniq
cpu cores	: 1

# 查看逻辑CPU个数(核心 * 线程)
[root@kid ~]# cat /proc/cpuinfo| grep "processor"| wc -l
1

# 查看cpu的信息
[root@kid ~]# lscpu
Architecture:          x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                1
On-line CPU(s) list:   0
Thread(s) per core:    1
Core(s) per socket:    1
Socket(s):             1
NUMA node(s):          1
...

# 自己是在虚拟机上运行的, 分配的cpu与内核数都是一个.
# 总核数 = 物理CPU个数 *每颗物理CPU的核数
# 总逻辑CPU数 = 物理CPU个数 * 每颗物理CPU的核数 * 超线程数
假设现在在 421核的CPU上, 如果平均负载为2, 意味着什么呢?  
Q1. 在CPU有4个运算核心的系统上, 意味 CPU有50%的空闲.  
Q2. 在CPU有2个运算核心的系统上, 意味着所有的CPU都刚好被完全占用.  
Q3. 在CPU有2个运算核心的系统上, 则意味着有一半的进程竞争不到 CPU.
平均负载有三个数值, 我们应该关注哪个呢?  
实际上, 我们都需要关注.

如果1分钟、5分钟、15分钟的三个值基本相同, 或者相差不大, 那就说明系统负载很平稳. 
但如果1分钟的值远小于15分钟的值, 就说明系统最近1分钟的负载在减少,
而过去15分钟内却有很大的负载.  

反过来,如果1分钟的值远大于15分钟的值, 就说明最近1分钟的负载在增加, 
这种增加有可能只是临时性的, 也有可能还会持续上升, 所以就需要持续观察.  
一旦1分钟的平均负载接近或超过了CPU的运算核心个数, 就意味着系统正在发生过载的问题, 
这时就得分析问题, 并要想办法优化了.
假设我们在CPU有2个运算核心的系统上看到平均负载为 2.73, 6.90, 12.98  
那么说明在过去1 分钟内, 系统有 136% 的超载 (2.73/2=136%)  
而在过去5分钟内, 345%的超载 (6.90/2=345%)  
而在过去15分钟内, 649%的超载, (12.98/2=649%)  
但从整体趋势来看, 系统的负载是在逐步的降低.

6.4 生产环境中的负载

实际生产环境中,当平均负载高于CPU数量 70% 的时候, 你就应该分析排查负载高的问题了.
一旦负载过高, 就可能导致进程响应变慢, 进而影响服务的正常功能.  
 70%这个数字并不是绝对的, 最推荐的方法, 还是把系统的平均负载监控起来, 
然后根据更多的历史数据, 判断负载的变化趋势.
当发现负载有明显升高趋势时, 比如说负载翻倍了, 你再去做分析和调查.

6.5 平均负载与 CPU 使用率

在实际工作中, 经常容易把平均负载和CPU使用率混淆, 所以在这里做一个区分.
可能你会疑惑, 既然平均负载代表的是活跃进程数, 那平均负载高了,
不就意味着CPU使用率高吗?  

我们还是要回到平均负载的含义上来, 平均负载是指单位时间内,
处于可运行状态和不可中断状态的进程数.
所以, 它不仅包括了正在使用CPU的进程, 还包括等待CPU和等待I/O的进程.
而CPU使用率, 是单位时间内CPU繁忙情况的统计, 跟平均负载并不一定完全对应.

比如:  
CPU密集型进程, 大量使用CPU会导致平均负载升高, 此时这两者是一致的;  
I/O密集型进程, 等待I/O也会导致平均负载升高, 但CPU使用率不一定很高;  
大量等待CPU的进程调度也会导致平均负载升高, 此时的CPU使用率也会比较高.

总结: 平均负载与CPU 使用率并不一定完全对应.

6.6 平均负载案例分析

下面, 我们以三个示例分别来看这三种情况, 
并用 stress、mpstat、pidstat 等工具, 找出平均负载升高的根源.

stress是Linux 统压力测试工具, 这里我们用作异常进程模拟平均负载升高的场景. 
stress工具使用参考: https://www.cnblogs.com/muahao/p/6346775.html

mpstat 是多核 CPU 性能分析工具, 用来实时查看每个 CPU 的性能指标, 
以及所有 CPU 的平均指标.  
pidstat 是一个常用的进程性能分析工具,

用来实时查看进程的 CPU、内存、I/O 以及上下文切换等性能指标.
# 如果出现无法使用mpstat、pidstat命令, 安装软件包
[root@kid ~]# yum install sysstat -y

# 下载压力测试工具 stress
[root@kid ~]# yum install stress -y

1. CPU密集型进程
# 首先, 在第一个终端运行 stress 命令, 模拟一个 CPU 使用率 100% 的场景
[root@kid ~]# stress --cpu 1 --timeout 600  
stress: info: [1936] dispatching hogs: 1 cpu, 0 io, 0 vm, 0 hdd

# 在第二个终端运行 uptime 查看平均负载的变化情况
# 使用watch -d 参数表示高亮显示变化的区域(注意负载会持续升高)  
[root@kid ~]# watch -d uptime  
Every 2.0s: uptime                                                    Fri Sep  9 18:40:45 2022
	# 等个30s 这样
    18:40:45 up 3 min,  3 users,  load average: 1.25, 0.41, 0.17
# 最后, 在第三个终端运行 mpstat 查看 CPU 使用率的变化情况
# -P ALL 表示监控所有 CPU, 后面数字 5 表示间隔 5 秒后输出一组数据  
# 单核CPU只有一个数据all和0  
[root@kid ~]# mpstat -P ALL 5  
Linux 3.10.0-1160.el7.x86_64 (kid) 	09/09/2022 	_x86_64_	(1 CPU)

06:41:37 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
06:41:42 PM  all   99.80    0.00    0.40    0.00    0.00    0.00    0.00    0.00    0.00    0.00
06:41:42 PM    0   99.80    0.00    0.40    0.00    0.00    0.00    0.00    0.00    0.00    0.00
      
从终端二中可以看到, 1分钟的平均负载会慢慢增加到1.25, 
从终端三中可以看到, 正好有一个CPU的使用率为99.80%, 但它的iowait只有0.
这说明, 平均负载的升高正是由于CPU使用率为99.80% .
那么, 到底是哪个进程导致了 CPU 使用率 99.80%呢?可以使用 pidstat来查询.
# 开启终端5, 间隔 5 秒后输出一组数据  
[root@kid ~]# pidstat -u 5 1  
Linux 3.10.0-1160.el7.x86_64 (kid) 	09/09/2022 	_x86_64_	(1 CPU)

06:50:47 PM   UID       PID    %usr %system  %guest    %CPU   CPU  Command
06:50:52 PM     0       659    0.00    0.20    0.00    0.20     0  vmtoolsd
06:50:52 PM     0      2336   99.60    0.00    0.00   99.80     0  stress
06:50:52 PM     0      2358    0.00    0.20    0.00    0.20     0  pidstat
# 从这里可以明显看到, stress 进程的CPU使用率为 99.80%.       
2. I/O 密集型进程
# 首先还是运行 stress 命令, 但这次模拟 I/O 压力, 即不停地执行 sync
[root@kid ~]# stress  --io 1 --timeout  600s  
stress: info: [1388] dispatching hogs: 0 cpu, 1 io, 0 vm, 0 hdd

# 然后在第二个终端运行 uptime 查看平均负载的变化情况:
[root@kid ~]# watch -d uptime  

Every 2.0s: uptime                                                    Fri Sep  9 18:57:21 2022
 # 等个30s 这样 
 18:58:44 up 6 min,  3 users,  load average: 1.07, 0.41, 0.17
# 最后第三个终端运行 mpstat 查看CPU使用率的变化情况:
 # 显示所有CPU的指标, 并在间隔5秒输出一组数据  
 
[root@kid ~]# mpstat -P ALL 5  
Linux 3.10.0-1160.el7.x86_64 (kid) 	09/09/2022 	_x86_64_	(1 CPU)

06:57:47 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
06:57:47 PM  all    0.60    0.00   99.40    0.00    0.00    0.00    0.00    0.00    0.00    0.00
06:57:47 PM    0    0.60    0.00   99.40    0.00    0.00    0.00    0.00    0.00    0.00    0.00

# 会发现cpu的与内核打交道的sys占用非常高  
# 那么到底是哪个进程, 导致 iowait 这么高呢?我们还是用 pidstat 来查询
# 间隔 5 秒后输出一组数据, -u 表示 CPU 指标  

[root@kid ~]#  pidstat -u 5 1  
Linux 3.10.0-1160.el7.x86_64 (kid) 	09/09/2022 	_x86_64_	(1 CPU)

07:00:09 PM   UID       PID    %usr %system  %guest    %CPU   CPU  Command
07:00:14 PM     0        42    0.00   10.74    0.00   10.74     0  kworker/u256:1
07:00:14 PM     0      1389    0.60   79.92    0.00   80.52     0  stress
07:00:14 PM     0      1572    0.00    7.95    0.00    7.95     0  kworker/u256:2

Average:      UID       PID    %usr %system  %guest    %CPU   CPU  Command
Average:        0        42    0.00   10.74    0.00   10.74     -  kworker/u256:1
Average:        0      1389    0.60   79.92    0.00   80.52     -  stress
Average:        0      1572    0.00    7.95    0.00    7.95     -  kworker/u256:2
  
# 可以发现, 还是 stress 进程导致的.  
3. 大量进程的场景
当系统中运行进程超出CPU运行能力时, 就会出现等待CPU的进程.
# 首先, 我们还是使用stress, 模拟的是4个进程
[root@kid ~]# stress -c 4 --timeout 600  
stress: info: [1383] dispatching hogs: 4 cpu, 0 io, 0 vm, 0 hdd

# 开启第二个终端查看, 由于系统只有 1 个 CPU, 明显比4个进程要少得多, 因而系统的CPU处于严重过载状态
[root@kid ~]#  watch -d uptime  

Every 2.0s: uptime                                                    Fri Sep  9 19:11:34 2022
 # 等个40s 这样 
 19:11:34 up 6 min,  2 users,  load average: 4.18, 1.54, 0.57

# 然后, 开启第三个终端, 再运行 pidstat 来看一下进程的情况:
# 间隔 5 秒后输出一组数据  
[root@kid ~]# pidstat -u 5 1 
Linux 3.10.0-1160.el7.x86_64 (kid) 	09/09/2022 	_x86_64_	(1 CPU)

07:12:54 PM   UID       PID    %usr %system  %guest    %CPU   CPU  Command
07:12:59 PM     0       704    0.20    0.00    0.00    0.20     0  NetworkManager
07:12:59 PM     0      1384   24.36    0.00    0.00   24.36     0  stress
07:12:59 PM     0      1385   24.55    0.00    0.00   24.55     0  stress
07:12:59 PM     0      1386   24.75    0.00    0.00   24.75     0  stress
07:12:59 PM     0      1387   24.55    0.00    0.00   24.55     0  stress

Average:      UID       PID    %usr %system  %guest    %CPU   CPU  Command
Average:        0       704    0.20    0.00    0.00    0.20     -  NetworkManager
Average:        0      1384   24.36    0.00    0.00   24.36     -  stress
Average:        0      1385   24.55    0.00    0.00   24.55     -  stress
Average:        0      1386   24.75    0.00    0.00   24.75     -  stress
Average:        0      1387   24.55    0.00    0.00   24.55     -  stress
[root@kid ~]# 

# 可以看出, 4个进程在争抢1个CPU, 这些超出 CPU计算能力的进程, 最终导致CPU过载.
4. 总结
分析完这三个案例, 再来归纳一下平均负载与CPU  
平均负载提供了一个快速查看系统整体性能的手段, 反映了整体的负载情况.
但只看平均负载本身, 我们并不能直接发现, 到底是哪里出现了瓶颈.
所以, 在理解平均负载时, 也要注意:  
平均负载高有可能是CPU密集型进程导致的;  
平均负载高并不一定代表CPU使用率高, 还有可能是I/O更繁忙了;  
当发现负载高的时候, 你可以使用mpstat、pidstat等工具, 辅助分析负载的来源...

————————————————
文章的段落全是代码块包裹的, 留言是为了避免文章提示质量低.
文章的段落全是代码块包裹的, 留言是为了避免文章提示质量低.
文章的段落全是代码块包裹的, 留言是为了避免文章提示质量低.
文章的段落全是代码块包裹的, 留言是为了避免文章提示质量低.
文章的段落全是代码块包裹的, 留言是为了避免文章提示质量低.
文章的段落全是代码块包裹的, 留言是为了避免文章提示质量低.
文章的段落全是代码块包裹的, 留言是为了避免文章提示质量低.
文章的段落全是代码块包裹的, 留言是为了避免文章提示质量低.
文章的段落全是代码块包裹的, 留言是为了避免文章提示质量低.
文章的段落全是代码块包裹的, 留言是为了避免文章提示质量低.
————————————————

你可能感兴趣的:(linux_2,linux,运维,服务器)