一、前言

本文通过以下几个方面介绍Linux管理体系中进程管理:

  • 什么是进程
  • 常见进程分类
  • 进程监控指令
  • 进程状态
  • 前后台管理
  • 杀手三剑客
  • 负载

二、什么是进程

进程的定义和概念:

  • 进程是计算机上运行的程序的实例。每个进程都有自己的内存空间、CPU执行状态、系统资源使用情况和程序计数器。
  • 进程是操作系统进行资源分配和调度的基本单位。它可以包含程序的代码、数据、运行时栈、全局变量和其他相关信息。
  • 操作系统通过进程来实现多任务处理,允许多个程序同时在计算机上执行。每个进程都有自己的独立地址空间,不会直接访问其他进程的内存。

进程与程序的区别:

  • 程序是存储在磁盘上的可执行文件,包含计算机指令和数据。程序本身只是静态的文件,而进程是程序在内存中的动态实例。
  • 进程是程序的执行实例,包括程序的代码、数据和运行时环境。进程具有自己的运行状态和资源分配,可以与其他进程并发执行。
  • 一个程序可以在多个进程中同时运行,每个进程都有自己的进程空间,包括堆、栈、全局变量和文件描述符。因此,多个进程可以独立执行相同的程序,而不会相互干扰。
  • 进程在操作系统中拥有唯一的标识符,称为PID(进程标识符),用于在系统中唯一标识和管理每个进程。

三、常见进程分类

进程可以根据其性质、功能和用途进行不同的分类。其中常见的进程分类为:

  • 前台进程(Foreground Processes): 前台进程是与用户终端交互的进程,它们接收用户的输入并将输出显示在终端上。这包括终端会话中的命令行应用程序和图形用户界面(GUI)应用程序。
  • 后台进程(Background Processes): 后台进程是在后台运行,不与用户终端直接交互的进程。它们通常在终端会话中使用&操作符启动,允许用户在同一终端继续执行其他命令
  • 守护进程(Daemon Processes): 守护进程是在系统引导时启动的进程,通常在后台运行,并负责提供系统级服务或执行周期性任务。它们不与用户直接交互。例如,httpdsshdcron等守护进程
  • 父进程和子进程(Parent and Child Processes): 进程可以通过分叉(forking)创建子进程。父进程通常启动并监控子进程的执行,子进程可以继承父进程的资源和环境。这种层次关系形成了进程树。
  • 交互式进程(Interactive Processes): 交互式进程是需要与用户进行实时交互的进程。这包括终端会话中的命令行工具、文本编辑器等。
  • 批处理进程(Batch Processes): 批处理进程是自动执行的、无需实时交互的进程。它们通常用于执行定期或周期性任务,如数据处理、备份和自动化脚本
  • 特殊类型进程:
  • 僵尸进程(Zombie Processes): 僵尸进程是已经完成执行的进程,但其父进程尚未读取其终止状态的进程。这些进程处于一种"已终止,但未被清理"的状态。僵尸进程的存在通常是父进程没有正确处理子进程终止状态的结果。僵尸进程不会消耗系统资源,但如果父进程不及时处理,它们可能会占用系统中的进程ID。僵尸进程通常需要被清理,以释放相关资源
  • 孤儿进程(Orphan Processes): 孤儿进程是其父进程提前终止或意外终止,而使子进程成为孤儿的进程。孤儿进程将由init进程(通常具有进程ID 1)接管,并继续在系统中运行。这可以防止孤儿进程变成僵尸进程,因为init进程会及时处理子进程的终止状态

下面主要说说僵尸进程(Zombie Processes)和孤儿进程(Orphan Processes):

3.1 僵尸进程

僵尸进程是当子进程比父进程先结束,而父进程又没有回收子进程,释放子进程占用的资源,此时子进程将成为一个僵尸进程。

僵尸进程-1

3.1.1 如何查看僵尸进程

方法一:使用top命令查看僵尸进程个数

僵尸进程-2

方法二:使用ps命令查看僵尸进程ID

$ ps aux | grep Z

3.1.2 如何关闭僵尸进程

关于如何关闭僵尸进程有两种情况:

  • 一、 如果上级进程不是主进程,则找出僵尸进程的上级进程,结束即可
  • 二、 如果上级进程是主进程(PID为1),则需要重启Linux系统

3.2 孤儿进程

孤儿进程指的是在其父进程执行完成或被终止后仍继续运行的一类进程。孤儿进程会被系统直接接管.(systemd进程)。

孤儿进程

3.3 演示僵尸进程

3.3.1 准备模拟环境

1、使用文本编辑器创建一个名为zombie.c的文件,将下面C代码粘贴到文件中。

$ vim zombie.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main() {
    pid_t child_pid;

    // 创建一个子进程
    child_pid = fork();

    if (child_pid > 0) {
        // 这是父进程,在这里等待10分钟
        sleep(600);
    } else if (child_pid == 0) {
        // 这是子进程,在这里退出
        exit(0);
    } else {
        // fork失败
        perror("Fork failed");
        return 1;
    }

    return 0;
}

2、打开终端,使用以下命令编译程序

$ gcc zombie.c -o zombie

3、运行程序

$ ./zombie

3.3.2 排查并解决僵尸进程

1、使用top命令简单查看是否存在僵尸进程

演示僵尸进程-1

2、查看僵尸进程的PID为21313

$ ps aux | grep Z

USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root      21313  0.0  0.0      0     0 pts/1    Z+   15:17   0:00 [zombie] <defunct>
root      21319  0.0  0.0 112812   944 pts/0    S+   15:18   0:00 grep --color=auto Z

3、安装psmisc软件包并使用pstree命令查看僵尸进程的父进程PPID为21312

$ yum install -y psmisc
$ pstree -ap

上面pstree命令参数说明:

  • -a:显示完整信息
  • -p:显示进程号码

演示僵尸进程-2

4、直接结束僵尸进程的父进程

$ kill -9 21312

四、进程监控指令

Linux中查询进程信息的命令:

监控命令 含义
ps 静态:ps查看当前瞬间进程状态,一般用于临时检查或取值
top 动态:top动态,交互,整体查看系统状态,负载,僵尸进程,cpu,内存. 类似于windows任务管理器

4.1 ps

ps命令常用用法

ps命令选项 命令说明
ps -ef 显示当前系统运行状态中进程信息,其中命令选项说明:
-e:显示环境变量信息
-f:用ASCII字符显示树状结构
ps auxf 查看系统中全部的进程信息,含详细信息,其中命令选项说明:
-a:显示所有进程信息
-u:使用用户为主的格式来显示程序状态
-x:不区分终端机
-f:用ASCII字符显示树状结构

4.1.1 ps -ef每一列含义

每一列 每一列代表含义
第1列:UID 进程所属的用户标识符(User ID),通常是一个数字。这表示启动进程的用户
第2列:PID 进程标识符(Process ID),是一个唯一的数字,用于标识每个正在运行的进程
第3列:PPID 父进程标识符(Parent Process ID),表示启动当前进程的父进程的PID。每个进程都有一个父进程,除了初始进程(通常是PID为1的init或systemd进程)
第4列:C 进程的CPU使用情况。通常是CPU占用百分比。0%表示进程没有占用CPU时间,100%表示进程一直在占用CPU。
第5列:STIME 进程的启动时间,即进程开始运行的时间点
第6列:TTY 进程关联的终端设备。如果进程与终端相关联,这个字段会显示终端的名称(如tty1、pts/0等)。如果进程没有与终端相关联,它会显示 ?
第7列:TIME 进程已经运行的CPU时间。通常以小时(h)和分钟(m)表示
第8列:CMD 启动进程的完整命令行。这个字段包含了启动进程的命令及其参数

4.1.2 ps aux每一列含义

每一列 每一列代表含义
第1列: User 进程属于用户
第2列: PID 进程号(子进程号)
第3列: %CPU cpu使用率
第4列: %MEM 内存使用率
第5列: VSZ 进程占用虚拟内存大小 (KB)
第6列: RSS 进程占用物理内存大小 (KB)
第7列: TTY 用户使用终端(用户连接进来后,系统创建)
第8列: STAT 进程状态
第9列: START 进程启动时间
第10列: TIME 进程占用CPU时间
第11列及最后: COMMAND 进程名字(命令,选项...) []括起来的是内核进程, 其他是系统进程 systemd(pid是1)的第 1个进程

4.2 top

top命令默认是个交互式的命令,可以展示系统负载信息,进程信息,cpu,内存信息。类似于Windows任务管理器。

image-20231017192423968

4.2.1 top快捷键

top快捷键 说明
q 退出
空格键 立刻刷新,默认3秒刷新1次
P 按照CPU使用率排序(默认方式)
M 按照内存使用率排序
shift + > 向右
shift + < 向左

4.2.2 htop

top命令升级版,支持鼠标操作。在操作之前需要提前安装

$ yum install -y htop

说明: htop是epel源中的命令. 没有需要配置epel源然后安装即可

使用htop命令

$ htop

image-20231017195939827

4.3 ps和top使用案例

4.3.1 ps使用案例

1、过滤出crond进程信息

$ ps -ef |grep crond
$ ps aux |grep crond

2、按照树形结构查看进程信息并输出pid

$ pstree -p
  • pstree: 这是用于显示进程树的命令。
  • -p: 该选项指示 pstree 显示每个进程的PID。

也可以展示部分所属关系,没有pstree直观

$ ps auxf
  • ps: 显示当前进程状态的命令。
  • aux: 选项用于显示所有用户的所有进程,包括其他细节信息,例如进程的用户、CPU使用率、内存占用等。
  • f: 这个选项显示进程的树状结构,包括父进程和子进程的关系。

3、求取出ps命令结果中第一列和第三列

$ ps aux | awk  '{print $1,$3}'
  • ps aux:列出系统上所有进程的详细信息。
  • |:管道符,将 ps aux 的输出传递给下一个命令。
  • awk '{print $1,$3}':使用 Awk 命令处理 ps aux 的输出,仅打印每行的第一个(用户名)和第三个字段(CPU使用率)。

4、指定输出内容user,%cpu,stat

$ ps axo user,%cpu,stat
  • a: 显示所有用户的进程,而不仅仅是当前用户的进程。
  • x: 显示无控制终端的进程,通常是后台进程。
  • o user,%cpu,stat: 自定义输出格式,指定要显示的列,包括用户(USER)、CPU使用率(%CPU)、以及进程状态(STAT)。

5、求取出ps命令结果中第一列和第三列,并且不显示标题

$ ps aux |awk 'NR>1{print $1,$3}'
  • ps aux:列出所有进程的详细信息。
  • awk 'NR>1{print $1,$3}'awk命令用于处理ps命令的输出。NR>1 表示从第2行开始处理,以跳过标题行。然后,print $1,$3 打印每行的第1列(用户)和第3列(CPU占用率)。

6、取出某一个服务(crond)的进程信息(pid,%cpu,%mem,command)

$ ps aux |grep  'crond' |awk '{print $2,$3,$4,$11}'

同样可以使用

$ ps --no-heading  -o pid,%cpu,%mem,command  -C crond
  • --no-heading:表示不显示列标题。
  • -o pid,%cpu,%mem,command:指定显示的列,包括进程ID(pid)、CPU占用率(%cpu)、内存占用率(%mem)、以及命令行(command)。
  • -C crond:限制输出为仅包括指定名称的进程,这里是 crond

7、取出某一个服务(crond)的进程信息中最后一列

$ ps aux |grep  'crond' |awk '{print $NF}'

8、取出某一个服务(crond)的进程信息中倒数第二列

$ ps aux |grep  'crond' |awk '{print $(NF-1)}'

9、取出所有进程中内存使用率最高的前5

$ ps --no-heading aux |sort -rnk4 |head -5
  • ps: 用于显示当前系统中运行的进程信息。
  • --no-heading: 禁用了列标题,使输出更加紧凑。
  • aux: 显示所有用户的所有进程,包括不与终端相关的进程。
  • |: 将 ps 的输出通过管道传递给下一个命令。
  • -r: 表示逆序排列,即从高到低排列。
  • -n: 表示按数值进行排序,而不是字典顺序。
  • -k4: 表示按第4列进行排序,即 %MEM 列,以确定内存使用量。
  • head -5: 仅显示前5行,也就是前5个占用内存最多的进程。

4.3.2 top使用案例

1、top运行在非交互模式,显示第2行内容

$ top  -bn1 |awk 'NR ==2'
  • top: 启动系统监控工具top
  • |: 通过管道将top的输出传递给下一个命令。
  • awk 'NR == 2': 使用awk命令,NR表示记录号,这里是指行号。NR == 2表示只选择第二行的内容。

2、top运行在非交互模式,显示第2行内容中倒数第一列和倒数第二列内容

$ top -bn1 |awk 'NR ==2{print $(NF-1),$NF}'
  • top -bn1:运行 top 命令,其中 -b 选项表示以批处理模式运行,n1 表示运行一次后退出。
  • |:通过管道将 top 命令的输出传递给下一个命令。
  • awk 'NR == 2{print $(NF-1),$NF}':使用 awk 命令,NR == 2 表示只选择第二行的内容。$(NF-1) 表示倒数第二个字段,通常是系统的平均负载值之一,$NF 表示最后一个字段,通常也是平均负载值之一。这个命令的目的是提取这两个值并打印它们。

五、进程状态

在Linux中,进程可以处于不同的状态,这些状态描述了进程当前的情况和执行状态。其中进程状态为基本状态+附加组成。

STAT基本状态如下:

STAT基本状态 描述
R(running) 进程运行
S 可中断进程(可以随时停止)
T(terminate) 进程被暂停(挂起) ctrl +z
D 不可中断进程(进程正在进行IO读写)
Z(zombie) 僵尸进程,异常的进程

STAT状态+符号:

STAT状态+符号 描述
s 进程是控制进程, Ss进程的领导者,父进程/主进程
< 进程运行在高优先级上,S<优先级较高的进程
N 进程运行在低优先级上,SN优先级较低的进程
+ 当前进程运行在前台,R+该表示进程在前台运行
l(小写L) 进程是多线程的,Sl表示进程是以线程方式运行(与程序) 使用多线程可以让服务或软件支持更改的访问,但是需要软件支持。

常见的进程状态:

常见的进程状态 说明
R+ 前台运行中进程
R 后台运行进程
S 可中断进程(大部分进程)
T 后台挂起的进程
D 不可中断进程(io进程)
Ss 可中断进程(普通)管理进程
S< 可中断的高优先级进程
Ssl 可中断的多线程的管理进程
Z 僵尸进程

六、前后台管理

6.1 什么是前台和后台程序

前台程序是指在终端或命令行界面中直接运行的程序,它会占用终端窗口,通常会向终端输出信息,同时等待用户的输入。前台程序会在终端窗口启动,如果终端被关闭或该程序被终止,它也会停止运行。

后台程序是指在后台默默运行的程序,不占用当前终端窗口,并且不会向终端输出信息。通常,后台程序的运行不会受到终端窗口的状态影响,即使关闭终端窗口,它也会继续运行。

6.2 区别前台和后台程序

前台程序通常在终端窗口中运行,并会向终端输出信息。可以与其进行交互,即时查看其输出。

后台程序在后台默默运行,通常不会向终端输出信息。可以使用jobs命令查看当前终端窗口中正在运行的后台作业。或者,还可以使用ps命令来查看系统中正在运行的所有进程,后台进程通常具有不同的进程ID(PID)。

6.3 软件后台运行方法

软件后台运行方法 说明 应用场景
& 常用的后台运行方法 大部分使用
nohup 命令 & 与&类似,会记录输出到文件中默 认叫nohup.out 如果想记录输出则可以用这个方法
先运行命令,然后按下ctrl + z(后台挂起)最后按下bg进入后台 软件进入后台运行 顽固软件ctrl +c 无法结束,可以通过这个方法结束它
screen命令 通过软件创建空间,让命令在这个空间运行 稳定

6.3.1 &

1、 让sleep 999命令后台运行

$ sleep 999 &
[1] 21611

2、查看进程

$ ps aux | grep 21611

root      21611  0.0  0.0 108052   352 pts/0    S    22:03   0:00 sleep 999
root      21613  0.0  0.0 112808   960 pts/0    S+   22:04   0:00 grep --color=auto 21611

3、使用jobs命令手动进入后台的进程

$ jobs
[1]+  Running                 sleep 999 &

6.3.2 nohup 命令 &

可以保留输出到指定文件中,默认是nohup.out文件。其他方面与&符号一致。

1、让ping baidu.com命令后台运行并记录输出

$ nohup ping -c 2 baidu.com &

2、查看nohup.out文件

$ tail -2 nohup.out

2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 29.507/38.125/46.743/8.618 ms

6.3.3 ctrl+z

这个快捷键在Linux下面表示让当前运行的命令或服务进入后台挂起,如果转为后台运行需要再输入bg,如果是误触ctrl+z,可以通过fg让进程、命令回到前台。

6.3.4 screen

一般我们使用&,nohup方法让命令,服务进入后台运行,但是可能不稳定。这时候可以通过screen命令较为稳定的后台运行一些指令。

1、安装screen

$ yum install -y screen

2、运行screen,进入screen虚拟窗口

$ screen

3、执行命令

$ ping baidu.com

4、在一个终端会话中打开了一个 GNU Screen 会话,然后使用特定的键绑定(通常是Ctrl+A,然后按 d)将该会话切换到后台。模拟异常退出,其中Screen 会话显示Detached (分离)状态

5、列出当前系统中所有正在运行的 GNU Screen 会话

$ screen -ls

There is a screen on:
        21649.pts-0.k8s-master01        (Detached)
1 Socket in /var/run/screen/S-root.

6、恢复,使用 screen -r 命令来重新附加到一个 "Detached" 会话,以便重新获得对该会话的控制权。

$ screen -r 21649.pts-0.k8s-master01 

7、此时新开窗口再次查看screen窗口,会话状态显示Attached,也就是当前正在查看或与该会话进行交互。

$ screen -ls

There is a screen on:
        21649.pts-0.k8s-master01        (Attached)
1 Socket in /var/run/screen/S-root.

七、杀手三剑客

3个用于结束进程的命令

命令 说明
kill kill + 进程pid进行结束进程,常用
pkill pkill + 进程名字, 取你狗命(你和狗),模糊查找
killall killall + 进程名字,精确
kill命令 说明
kill pid 默认发送结束信号
kill -9 pid 发送强制结束信号(别用kill -9结束数据库)

八、负载

8.1 什么是负载

在Linux中,"负载" 是一个衡量系统繁忙程度的指标,它反映了一段时间内运行队列中的平均进程数。负载通常以三个值的形式表示,这三个值分别对应于不同的时间间隔,通常是 1 分钟、5 分钟和15 分钟。

8.2 什么是负载原理

负载是一个反映系统资源使用的度量,它代表了一定时间内的运行队列长度,即等待 CPU 时间的进程数。高负载通常表示系统中有较多的任务在排队等待 CPU 处理。负载是由内核统计并提供的。

从另一个方面理解平均负载:平均负载是指单位时间内,系统处于可运行状态(R,S)和不可中断状态(D)的平均进程数,也就是平均活跃进程数。

负载就是衡量正在运行的进程的平均数(可以中断进程和不可中断进程)

8.3 负载高如何排查

1、通过监控软件发现系统负载高,如果没有监控软件可以通过w命令人工查看

$ w

image-20231018103410388

也可以通过uptime命令进行查看

$ uptime

10:34:43 up 4 days, 18:41,  3 users,  load average: 0.00, 0.01, 0.05

2、判断是cpu还是io导致的负载高

(1)定位cpu原因

查看top命令中的us(user 用户占用cpu),sy(system 系统占用cpu)

image-20231018103835413

(2)定位io原因

查看top命令中的wa(iowait)磁盘io导致的负载高

image-20231018104046689

3、根据具体原因进一步排查

(1)如果是cpu原因导致的,排查出哪个进程导致的ps aux过滤出占用cpu较高的进程

(2)如果是io导致的,排查初级哪个进程导致的,通过iotop -o命令排查