进程管理
1、什么是进程和程序
进程是正在执行的一个程序或命令,每个进程都是一个运行的实体,都有自己的地址空间,并占用一定的系统资源。程序是人使用计算机语言编写的可以实现特定目标或解决特定问题的代码集合。
这么讲很难理解,那我们换一种说法。程序是人使用计算机语言编写的,可以实现一定功能,并且可以执行的代码集合。而进程是正在执行中的程序。当程序被执行时,执行人的权限和属性,以及程序的代码都会被加载入内存,操作系统给这个进程分配一个 ID,称为 PID(进程 ID)。
也就是说,在操作系统中,所有可以执行的程序与命令都会产生进程。只是有些程序和命令非常简单,如 ls 命令、touch 命令等,它们在执行完后就会结束,相应的进程也就会终结,所以我们很难捕捉到这些进程。但是还有一些程和命令,比如 httpd 进程,启动之后就会一直驻留在系统当中,我们把这样的进程称作常驻内存进程。
某些进程会产生一些新的进程,我们把这些进程称作子进程,而把这个进程本身称作父进程。比如,我们必须正常登录到 Shell 环境中才能执行系统命令,而 Linux 的标准 Shell 是 bash。我们在 bash 当中执行了 ls 命令,那么 bash 就是父进程,而 ls 命令是在 bash 进程中产生的进程,所以 ls 进程是 bash 进程的子进程。也就是说,子进程是依赖父进程而产生的,如果父进程不存在,那么子进程也不存在了。
2、 进程管理的作用
在使用 Windows 系统的过程中,使用任务管理器,很大程度上是为了强制关闭“未反应”的软件,也就是杀死进程。的确,这是很多使用进程管理工具或进程管理命令的人最常见的使用方法。不过,杀死进程(强制中止进程)只是进程管理工作中最不常用的手段,因为每个进程都有自己正确的结束方法,而杀死进程是在正常方法已经失效的情况下的后备手段。
那么,进程管理到底应该是做什么的呢?进程管理主要有以下 3 个作用。
1) 判断服务器的健康状态
运维工程师最主要的工作就是保证服务器安全、稳定地运行。理想的状态是,在服务器出现问题,但是还没有造成服务器宕机或停止服务时,就人为干预解决了问题。
进程管理最主要的工作就是判断服务器当前运行是否健康,是否需要人为干预。如果服务器的 CPU 占用率、内存占用率过高,就需要人为介入解决问题了。这又出现了一个问题,我们发现服务器的 CPU 或内存占用率很高,该如何介入呢?是直接终止高负载的进程吗?
当然不是,应该判断这个进程是否是正常进程,如果是正常进程,则说明你的服务器已经不能满足应用需求,你需要更好的硬件或搭建集群了;如果是非法进程占用了系统资源,则更不能直接中止进程,而要判断非法进程的来源、作用和所在位置,从而把它彻底清除。
当然,如果服务器数量很少,我们完全可以人为通过进程管理命令来进行监控与干预,但如果服务器数量较多,那么人为手工监控就变得非常困难了,这时我们就需要相应的监控服务,如 cacti 或 nagios。总之,进程管理工作中最重要的工作就是判断服务器的健康状 态,最理想的状态是服务器宕机之前就解决问题,从而避免服务器的宕机。
2) 查看系统中所有的进程
我们需要查看看系统中所有正在运行的进程,通过这些进程可以判断系统中运行了哪些服务、是否有非法服务在运行。
3) 杀死进程
这是进程管理中最不常用的手段。当需要停止服务时,会通过正确关闭命令来停止服务(如 apache 服务可以通过 service httpd stop 命令来关闭)。只有在正确终止进程的手段失效的情况下,才会考虑使用 kill 命令杀死进程
在 Linux 系统中,每个进程都有一个唯一的进程号(PID),方便系统识别和调度进程。通过简单地输出运行程序的程序名,就可以运行该程序,其实也就是启动了一个进程。
总体来说,启动一个进程主要有 2 种途径,分别是通过手工启动和通过调度启动(事先进行设置,根据用户要求,进程可以自行启动),接下来就一一介绍这 2 中方式。
3、Linux手工启动进程
手工启动进程指的是由用户输入命令直接启动一个进程,根据所启动的进程类型和性质的不同,其又可以细分为前台启动和后台启动 2 种方式。
3.1 前台启动进程
这是手工启动进程最常用的方式,因为当用户输入一个命令并运行,就已经启动了一个进程,而且是一个前台的进程,此时系统其实已经处于一个多进程的状态(一个是 Shell 进程,另一个是新启动的进程)。
假如启动一个比较耗时的进程,然后再把该进程挂起,并使用 ps 命令查看,就会看到该进程在 ps 显示列表中,将进程挂起,指的是将前台运行的进程放到后台,并且暂停其运行
[root@localhost tmp]# ping www.baidu.com
PING www.a.shifen.com (112.80.248.75) 56(84) bytes of data.
64 bytes from 112.80.248.75 (112.80.248.75): icmp_seq=1 ttl=128 time=24.2 ms
64 bytes from 112.80.248.75 (112.80.248.75): icmp_seq=2 ttl=128 time=20.4 ms
64 bytes from 112.80.248.75 (112.80.248.75): icmp_seq=3 ttl=128 time=21.1 ms
64 bytes from 112.80.248.75 (112.80.248.75): icmp_seq=4 ttl=128 time=46.2 ms
64 bytes from 112.80.248.75 (112.80.248.75): icmp_seq=5 ttl=128 time=21.3 ms
^Z
[1]+ Stopped ping www.baidu.com
[root@localhost tmp]# ps
PID TTY TIME CMD
1464 pts/0 00:00:00 bash
4518 pts/0 00:00:00 ping
4529 pts/0 00:00:00 ps
通过运行 ps 命令查看进程信息,可以看到,刚刚执行的 ping命令的进程号为 4518,同时 ps 进程的进程号为 4529
3.2 后台启动进程
进程直接从后台运行,用的相对较少,除非该进程非常耗时,且用户也不急着需要其运行结果的时候,例如,用户需要启动一个需要长时间运行的格式化文本文件的进程,为了不使整个 Shell 在格式化过程中都处于“被占用”状态,从后台启动这个进程是比较明智的选择。
从后台启动进程,其实就是在命令结尾处添加一个 " &" 符号(注意,& 前面有空格)。输入命令并运行之后,Shell 会提供给我们一个数字,此数字就是该进程的进程号。然后直接就会出现提示符,用户就可以继续完成其他工作,例如:
[root@localhost tmp]# nohup ping www.baidu.com &
[3] 4759
其中【3】是工作号,4759是进程号
以上介绍了手工启动的 2 种方式,实际上它们有个共同的特点,就是新进程都是由当前 Shell 这个进程产生的,换句话说,是 Shell 创建了新进程,于是称这种关系为进程间的父子关系,其中 Shell 是父进程,新进程是子进程。
值得一提的是,一个父进程可以有多个子进程,通常子进程结束后才能继续父进程;当然,如果是从后台启动,父进程就不用等待子进程了。
4 、查看正在运行的进程
ps 命令是最常用的监控进程的命令,通过此命令可以查看系统中所有运行进程的详细信息。
ps 命令有多种不同的使用方法,这常常给初学者带来困惑。在各种 Linux 论坛上,询问 ps 命令语法的帖子屡见不鲜,而出现这样的情况,还要归咎于 UNIX 悠久的历史和庞大的派系。在不同的 Linux 发行版上,ps 命令的语法各不相同,为此,Linux 采取了一个折中的方法,即融合各种不同的风格,兼顾那些已经习惯了其它系统上使用 ps 命令的用户。
ps 命令的基本格式如下:
[root@localhost ~]# ps -aux
#查看系统中所有的进程,使用 BSD 操作系统格式
[root@localhost ~]# ps -le
#查看系统中所有的进程,使用 Linux 标准命令格式
[root@localhost ~]# ps -ef
选项:
a:显示一个终端的所有进程,除会话引线外;
u:显示进程的归属用户及内存的使用情况;
x:显示没有控制终端的进程;
l:长格式显示更加详细的信息;
e:显示所有进程;
大家如果执行 “man ps” 命令,则会发现 ps 命令的帮助为了适应不同的类 UNIX 系统,可用格式非常多,不方便记忆。所以,我建议大家记忆几个固定选项即可。比如:
① "ps aux" 可以查看系统中所有的进程;
② "ps -le" 可以查看系统中所有的进程,而且还能看到进程的父进程的 PID 和进程优先级;
③ "ps -l" 只能看到当前 Shell 产生的进程;
有这三个命令就足够了,下面分别来查看。
4.1、ps -aux查看
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.4 193980 8536 ? Ss 19:50 0:01 /usr/lib/systemd/systemd --switched-root --system --deserialize 22
root 2 0.0 0.0 0 0 ? S 19:50 0:00 [kthreadd]
root 3 0.0 0.0 0 0 ? I< 19:50 0:00 [rcu_gp]
root 4 0.0 0.0 0 0 ? I< 19:50 0:00 [rcu_par_gp]
root 6 0.0 0.0 0 0 ? I< 19:50 0:00 [kworker/0:0H-kb]
root 8 0.0 0.0 0 0 ? I< 19:50 0:00 [mm_percpu_wq]
root 9 0.0 0.0 0 0 ? S 19:50 0:00 [rcu_tasks_rude_]
root 10 0.0 0.0 0 0 ? S 19:50 0:00 [rcu_tasks_trace]
root 11 0.0 0.0 0 0 ? S 19:50 0:00 [ksoftirqd/0]
root 12 0.0 0.0 0 0 ? I 19:50 0:03 [rcu_sched]
root 13 0.0 0.0 0 0 ? S 19:50 0:00 [migration/0]
root 15 0.0 0.0 0 0 ? S 19:50 0:00 [cpuhp/0]
root 16 0.0 0.0 0 0 ? S 19:50 0:00 [cpuhp/1]
root 17 0.0 0.0 0 0 ? S 19:50 0:00 [migration/1]
root 18 0.0 0.0 0 0 ? S 19:50 0:00 [ksoftirqd/1]
root 20 0.0 0.0 0 0 ? I< 19:50 0:00 [kworker/1:0H-ev]
root 21 0.0 0.0 0 0 ? S 19:50 0:00 [cpuhp/2]
root 22 0.0 0.0 0 0 ? S 19:50 0:00 [migration/2]
root 23 0.0 0.0 0 0 ? S 19:50 0:00 [ksoftirqd/2]
root 25 0.0 0.0 0 0 ? I< 19:50 0:00 [kworker/2:0H-ev]
root 26 0.0 0.0 0 0 ? S 19:50 0:00 [cpuhp/3]
root 27 0.0 0.0 0 0 ? S 19:50 0:00 [migration/3]
4.2、ps -le
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 S 0 1 0 0 80 0 - 48495 - ? 00:00:01 systemd
1 S 0 2 0 0 80 0 - 0 - ? 00:00:00 kthreadd
1 I 0 3 2 0 60 -20 - 0 - ? 00:00:00 rcu_gp
1 I 0 4 2 0 60 -20 - 0 - ? 00:00:00 rcu_par_gp
1 I 0 6 2 0 60 -20 - 0 - ? 00:00:00 kworker/0:0H-kb
1 I 0 8 2 0 60 -20 - 0 - ? 00:00:00 mm_percpu_wq
1 S 0 9 2 0 80 0 - 0 - ? 00:00:00 rcu_tasks_rude_
1 S 0 10 2 0 80 0 - 0 - ? 00:00:00 rcu_tasks_trace
1 S 0 11 2 0 80 0 - 0 - ? 00:00:00 ksoftirqd/0
1 I 0 12 2 0 80 0 - 0 - ? 00:00:04 rcu_sched
1 S 0 13 2 0 -40 - - 0 - ? 00:00:00 migration/0
1 S 0 15 2 0 80 0 - 0 - ? 00:00:00 cpuhp/0
1 S 0 16 2 0 80 0 - 0 - ? 00:00:00 cpuhp/1
1 S 0 17 2 0 -40 - - 0 - ? 00:00:00 migration/1
1 S 0 18 2 0 80 0 - 0 - ? 00:00:00 ksoftirqd/1
1 I 0 20 2 0 60 -20 - 0 - ? 00:00:00 kworker/1:0H-ev
1 S 0 21 2 0 80 0 - 0 - ? 00:00:00 cpuhp/2
1 S 0 22 2 0 -40 - - 0 - ? 00:00:00 migration/2
1 S 0 23 2 0 80 0 - 0 - ? 00:00:00 ksoftirqd/2
1 I 0 25 2 0 60 -20 - 0 - ? 00:00:00 kworker/2:0H-ev
1 S 0 26 2 0 80 0 - 0 - ? 00:00:00 cpuhp/3
1 S 0 27 2 0 -40 - - 0 - ? 00:00:00 migration/3
常见选项:
4.3、ps -l
如果不想看到所有的进程,只想查看一下当前登录产生了哪些进程,那只需使用 “ps -l” 命令就足够了
[root@localhost tmp]# ps -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 S 0 1464 1460 0 80 0 - 28916 0xffff pts/0 00:00:00 bash
4 T 0 4518 1464 0 80 0 - 37527 - pts/0 00:00:00 ping
4 S 0 4759 1464 0 80 0 - 37527 - pts/0 00:00:00 ping
0 T 0 4905 1464 0 80 0 - 27607 - pts/0 00:00:00 less
0 T 0 4998 1464 0 80 0 - 27607 - pts/0 00:00:00 less
4 R 0 5089 1464 0 80 0 - 38336 - pts/0 00:00:00 ps
5、 持续监听进程运行状态
ps 命令可以一次性给出当前系统中进程状态,但使用此方式得到的信息缺乏时效性,并且,如果管理员需要实时监控进程运行情况,就必须不停地执行 ps 命令,这显然是缺乏效率的。
为此,Linux 提供了 top 命令。top 命令可以动态地持续监听进程地运行状态,与此同时,该命令还提供了一个交互界面,用户可以根据需要,人性化地定制自己的输出,进而更清楚地了进程的运行状态。
top 命令的基本格式如下:
[root@localhost ~]#top [选项]
选项:
-d: 秒数:指定 top 命令每隔几秒更新。默认是 3 秒;
-b:使用批处理模式输出。一般和"-n"选项合用,用于把 top 命令重定向到文件中;
-n: 次数:指定 top 命令执行的次数。一般和"-"选项合用;
-p: 进程PID:仅查看指定 ID 的进程;
-s:使 top 命令在安全模式中运行,避免在交互模式中出现错误;
-u: 用户名:只监听某个用户的进程;
在 top 命令的显示窗口中,还可以使用如下按键,进行一下交互操作:
- ? 或 h:显示交互模式的帮助;
- P:按照 CPU 的使用率排序,默认就是此选项;
- M:按照内存的使用率排序;
- N:按照 PID 排序;
- T:按照 CPU 的累积运算时间排序,也就是按照 TIME+ 项排序;
- k:按照 PID 给予某个进程一个信号。一般用于中止某个进程,信号 9 是强制中止的信号;
- r:按照 PID 给某个进程重设优先级(Nice)值;
- q:退出 top 命令;
执行top看下信息
top - 21:13:03 up 1:22, 2 users, load average: 0.00, 0.00, 0.00
Tasks: 217 total, 1 running, 117 sleeping, 3 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 1992496 total, 1193020 free, 339108 used, 460368 buff/cache
KiB Swap: 4095996 total, 4095996 free, 0 used. 1456924 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
455 root 20 0 0 0 0 S 0.3 0.0 0:01.00 xfsaild/sda2
638 root 20 0 0 0 0 S 0.3 0.0 0:03.86 xfsaild/sda6
4295 root 20 0 0 0 0 I 0.3 0.0 0:04.23 kworker/4:0-eve
5191 root 20 0 162120 4484 3708 R 0.3 0.2 0:00.01 top
1 root 20 0 193980 8536 5592 S 0.0 0.4 0:01.41 systemd
我们解释一下命令的输出。top 命令的输出内容是动态的,默认每隔 3 秒刷新一次。命令的输出主要分为两部分:
-
第一部分是前五行,显示的是整个系统的资源使用状况,我们就是通过这些输出来判断服务器的资源使用状态的;
-
第二部分从第六行开始,显示的是系统中进程的信息;
第一行为任务队列信息,具体内容如表 1 所示
内 容 | 说 明 |
---|---|
1:22 | 系统的运行时间.本机己经运行 1个小时22分支 |
21:13:03 | 系统当前时间 |
2 users | 当前登录了两个用户 |
load average: 0.00,0.00,0.00 | 系统在之前 1 分钟、5 分钟、15 分钟的平均负载。如果 CPU 是单核的,则这个数值超过 1 就是高负载:如果 CPU 是四核的,则这个数值超过 4 就是高负载 (这个平均负载完全是依据个人经验来进行判断的,一般认为不应该超过服务器 CPU 的核数) |
第二行为进程信息,具体内容如表 2 所示
内 容 | 说 明 |
---|---|
Tasks: 217 total | 系统中的进程总数 |
1 running | 正在运行的进程数 |
117 sleeping | 睡眠的进程数 |
3 stopped | 正在停止的进程数 |
0 zombie | 僵尸进程数。如果不是 0,则需要手工检查僵尸进程 |
僵尸程序
僵尸进程的产生一般是由于进程非正常停止或程序编写错误,导致子进程先于父进程结束,而父进程又没有正确地回收子进程,从而造成子进程一直存在于内存当中,这就是僵尸进程。
僵尸进程会对主机的稳定性产生影响,所以,在产生僵尸进程后,一定要对产生僵尸进程的软件进行优化,避免一直产生僵尸进程;对于已经产生的僵尸进程,可以在查找出来之后强制中止。
第三行为 CPU 信息,具体内容如表 3 所示。
内 容 | 说 明 |
---|---|
Cpu(s): 0.1 %us | 用户模式占用的 CPU 百分比 |
0.1%sy | 系统模式占用的 CPU 百分比 |
0.0%ni | 改变过优先级的用户进程占用的 CPU 百分比 |
99.7%id | 空闲 CPU 占用的 CPU 百分比 |
0.1%wa | 等待输入/输出的进程占用的 CPU 百分比 |
0.0%hi | 硬中断请求服务占用的 CPU 百分比 |
0.1%si | 软中断请求服务占用的 CPU 百分比,如果事件在处理时需要大量时间,就交由软终端处理 |
0.0%st | st(steal time)意为虚拟时间百分比,就是当有虚拟机时,虚拟 CPU 等待实际 CPU 的时间百分比 |
第四行为物理内存信息,具体内容如表 4 所示
-
内 容 说 明 Mem: 1992496 total 物理内存的总量,单位为KB 339108 used 己经使用的物理内存数量 1193020 free 空闲的物理内存数量。 460368 buffers 作为缓冲的内存数量
第五行为交换分区(swap)信息,如表 5 所示
-
内 容 说 明 Swap: 4095996 total 交换分区(虚拟内存)的总大小 0 used 已经使用的交换分区的大小 4095996 free 空闲交换分区的大小 1456924 avail Mem 代表可用内存大小
我们通过 top 命令的第一部分就可以判断服务器的健康状态。如果 1 分钟、5 分钟、15 分钟的平均负载高于 1,则证明系统压力较大。如果 CPU 的使用率过高或空闲率过低,则证明系统压力较大。如果物理内存的空闲内存过小,则也证明系统压力较大。
这时,我们就应该判断是什么进程占用了系统资源。如果是不必要的进程,就应该结束这些进程;如果是必需进程,那么我们该増加服务器资源(比如増加虚拟机内存),或者建立集群服务器。
我们还要解释一下缓冲(buffer)和缓存(cache)的区别:
- 缓存(cache)是在读取硬盘中的数据时,把最常用的数据保存在内存的缓存区中,再次读取该数据时,就不去硬盘中读取了,而在缓存中读取。
- 缓冲(buffer)是在向硬盘写入数据时,先把数据放入缓冲区,然后再一起向硬盘写入,把分散的写操作集中进行,减少磁盘碎片和硬盘的反复寻道,从而提高系统性能。
简单来说,缓存(cache)是用来加速数据从硬盘中"读取"的,而缓冲(buffer)是用来加速数据"写入"硬盘的。
再来看 top 命令的第二部分输出,主要是系统进程信息,各个字段的含义如下:
- PID:进程的 ID。
- USER:该进程所属的用户。
- PR:优先级,数值越小优先级越高。
- NI:优先级,数值越小、优先级越高。
- VIRT:该进程使用的虚拟内存的大小,单位为 KB。
- RES:该进程使用的物理内存的大小,单位为 KB。
- SHR:共享内存大小,单位为 KB。
- S:进程状态。
- %CPU:该进程占用 CPU 的百分比。
- %MEM:该进程占用内存的百分比。
- TIME+:该进程共占用的 CPU 时间。
- COMMAND:进程的命令名。
范例1:通过top查看某一个进程
[root@localhost tmp]# top -p 4759
top - 21:21:52 up 1:30, 2 users, load average: 0.00, 0.01, 0.00
Tasks: 1 total, 0 running, 1 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.0 sy, 0.0 ni, 99.9 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 1992496 total, 1192788 free, 339440 used, 460268 buff/cache
KiB Swap: 4095996 total, 4095996 free, 0 used. 1456720 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
4759 root 20 0 150108 4396 3908 S 0.0 0.2 0:00.41 ping
范例2:top 命令如果不正确退出,则会持续运行。在 top 命令的交互界面中按 “q” 键会退出 top 命令;也可以按 “?” 或 “h” 键得到 top 命令交互界面的帮助信息;还可以按键中止某个进程。比如:
范例3:设置进程的优先级,优先级的范围是【-20-19】,-20最高,19最低,
PRI也还是比较好理解的,即进程的优先级,或者通俗点说就是程序被CPU执行的先后顺序,此值越小进程的优先级别越高。那NI呢?就是我们所要说的nice值了,其表示进程可被执行的优先级的修正数值。如前面所说,PRI值越小越快被执行,那么加入nice值后,将会使得PRI变为:PRI(new)=PRI(old)+nice。这样,当nice值为负值的时候,那么该程序将会优先级值将变小,即其优先级会变高,则其越快被执行。
修改进程优先级的命令主要有两个:nice,renice
nice是程序开始时指定的,比如:
nice -n -5 /usr/local/mysql/bin/mysqld_safe &
renice是修改已经存在的进程的的nice值
[root@localhost proc]# renice -n 5 -p 6093
6093 (process ID) old priority 0, new priority 5
6、 Linux常用信号(进程间通信)及其含义
进程的管理主要是指进程的关闭与重启。我们一般关闭或重启软件,都是关闭或重启它的程序,而不是直接操作进程的。比如,要重启 apache 服务,一般使用命令"service httpd restart"重启 apache的程序。
那么,可以通过直接管理进程来关闭或重启 apache 吗?答案是肯定的,这时就要依赖进程的信号(Signal)了。我们需要给予该进程号,告诉进程我们想要让它做什么。
系统中可以识别的信号较多,我们可以使用命令"kill -l"或"man 7 signal"来查询。命令如下
[root@ali01 ~]# kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX
常见信号说明:
信号代号 | 信号名称 | 说 明 |
---|---|---|
1 | SIGHUP | 该信号让进程立即关闭.然后重新读取配置文件之后重启 |
2 | SIGINT | 程序中止信号,用于中止前台进程。相当于输出 Ctrl+C 快捷键 |
8 | SIGFPE | 在发生致命的算术运算错误时发出。不仅包括浮点运算错误,还包括溢出及除数为 0 等其他所有的算术运算错误 |
9 | SIGKILL | 用来立即结束程序的运行。本信号不能被阻塞、处理和忽略。般用于强制中止进程 |
14 | SIGALRM | 时钟定时信号,计算的是实际的时间或时钟时间。alarm 函数使用该信号 |
15 | SIGTERM | 正常结束进程的信号,kill 命令的默认信号。如果进程已经发生了问题,那么这 个信号是无法正常中止进程的,这时我们才会尝试 SIGKILL 信号,也就是信号 9 |
18 | SIGCONT | 该信号可以让暂停的进程恢复执行。本信号不能被阻断 |
19 | SIGSTOP | 该信号可以暂停前台进程,相当于输入 Ctrl+Z 快捷键。本信号不能被阻断 |
其中最重要的就是 “1”、“9”、"15"这三个信号,我们只需要记住这三个信号即可。
7、 终止进程
kill 从字面来看,就是用来杀死进程的命令,但事实上,这个或多或少带有一定的误导性。从本质上讲,kill 命令只是用来向进程发送一个信号,至于这个信号是什么,是用户指定的。
也就是说,kill 命令的执行原理是这样的,kill 命令会向操作系统内核发送一个信号(多是终止信号)和目标进程的 PID,然后系统内核根据收到的信号类型,对指定进程进行相应的操作。
kill 命令的基本格式如下:
[root@localhost ~]# kill [信号] PID
kill 命令是按照 PID 来确定进程的,所以 kill 命令只能识别 PID,而不能识别进程名。Linux 定义了几十种不同类型的信号,读者可以使用 kill -l 命令查看所有信号及其编号,这里仅列出几个常用的信号,如表 1 所示。
信号编号 | 信号名 | 含义 |
---|---|---|
0 | EXIT | 程序退出时收到该信息。 |
1 | HUP | 挂掉电话线或终端连接的挂起信号,这个信号也会造成某些进程在没有终止的情况下重新初始化。 |
2 | INT | 表示结束进程,但并不是强制性的,常用的 “Ctrl+C” 组合键发出就是一个 kill -2 的信号。 |
3 | QUIT | 退出。 |
9 | KILL | 杀死进程,即强制结束进程。 |
11 | SEGV | 段错误。 |
15 | TERM | 正常结束进程,是 kill 命令的默认信号。 |
需要注意的是,表中省略了各个信号名称的前缀 SIG,也就是说,SIGTERM 和 TERM 这两种写法都对,kill 命令都可以理解。
范例1:kill掉vsftpd进程
[root@ali01 ~]# yum -y install vsftpd
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
Package vsftpd-3.0.2-29.el7_9.x86_64 already installed and latest version
Nothing to do
[root@ali01 ~]# systemctl start vsftpd
[root@ali01 ~]# ps -aux |grep vsftpd
root 1681 0.0 0.1 112812 976 pts/0 S+ 21:01 0:00 grep --color=auto vsftpd
root 31876 0.0 0.1 53292 696 ? Ss Sep23 0:00 /usr/sbin/vsftpd /etc/vsftpd/vsftpd.conf
[root@ali01 ~]# kill -9 31876
[root@ali01 ~]# ps -aux |grep vsftpd
root 1692 0.
可以看到31876进程不存在了。
8 、终止特定的一类进程:killall
killall 也是用于关闭进程的一个命令,但和 kill 不同的是,killall 命令不再依靠 PID 来杀死单个进程,而是通过程序的进程名来杀死一类进程,也正是由于这一点,该命令常与 ps、pstree 等命令配合使用。
killall 命令的基本格式如下:
[root@localhost ~]# killall [选项] [信号] 进程名
注意,此命令的信号类型同 kill 命令一样,因此这里不再赘述,此命令常用的选项有如下 2 个:
- -i:交互式,询问是否要杀死某个进程;
- -I:忽略进程名的大小写;
[root@ali01 ~]# systemctl start httpd
[root@ali01 ~]# ps -aux |grep httpd
root 1760 0.4 1.0 230440 5216 ? Ss 21:03 0:00 /usr/sbin/httpd -DFOREGROUND
apache 1761 0.0 0.6 230440 2992 ? S 21:03 0:00 /usr/sbin/httpd -DFOREGROUND
apache 1762 0.0 0.6 230440 2992 ? S 21:03 0:00 /usr/sbin/httpd -DFOREGROUND
apache 1763 0.0 0.6 230440 2992 ? S 21:03 0:00 /usr/sbin/httpd -DFOREGROUND
apache 1764 0.0 0.6 230440 2992 ? S 21:03 0:00 /usr/sbin/httpd -DFOREGROUND
apache 1765 0.0 0.6 230440 2992 ? S 21:03 0:00 /usr/sbin/httpd -DFOREGROUND
root 1773 0.0 0.1 112812 976 pts/0 S+ 21:03 0:00 grep --color=auto httpd
[root@ali01 ~]# killall httpd
[root@ali01 ~]# ps -aux |grep httpd
root 1791 0.0 0.1 112812 976 pts/0 S+ 21:03 0:00 grep --color=auto httpd
9、终止进程,按终端号踢出用户:pkill
当作于管理进程时,pkill 命令和 killall 命令的用法相同,都是通过进程名杀死一类进程,该命令的基本格式如下:
[root@localhost ~]# pkill [信号] 进程名
表 1 罗列了此命令常用的信号及其含义。
信号编号 | 信号名 | 含义 |
---|---|---|
0 | EXIT | 程序退出时收到该信息。 |
1 | HUP | 挂掉电话线或终端连接的挂起信号,这个信号也会造成某些进程在没有终止的情况下重新初始化。 |
2 | INT | 表示结束进程,但并不是强制性的,常用的 “Ctrl+C” 组合键发出就是一个 kill -2 的信号。 |
3 | QUIT | 退出。 |
9 | KILL | 杀死进程,即强制结束进程。 |
11 | SEGV | 段错误。 |
15 | TERM | 正常结束进程,是 kill 命令的默认信号。 |
范例1:kill掉http进程
[root@ali01 ~]# systemctl start httpd
[root@ali01 ~]# ps -aux |grep httpd
root 1939 0.5 1.0 230440 5208 ? Ss 21:06 0:00 /usr/sbin/httpd -DFOREGROUND
apache 1940 0.0 0.5 230440 2984 ? S 21:06 0:00 /usr/sbin/httpd -DFOREGROUND
apache 1941 0.0 0.5 230440 2984 ? S 21:06 0:00 /usr/sbin/httpd -DFOREGROUND
apache 1942 0.0 0.5 230440 2984 ? S 21:06 0:00 /usr/sbin/httpd -DFOREGROUND
apache 1943 0.0 0.5 230440 2984 ? S 21:06 0:00 /usr/sbin/httpd -DFOREGROUND
apache 1944 0.0 0.5 230440 2984 ? S 21:06 0:00 /usr/sbin/httpd -DFOREGROUND
root 1953 0.0 0.1 112812 976 pts/0 S+ 21:06 0:00 grep --color=auto httpd
[root@ali01 ~]# pkill -9 httpd
[root@ali01 ~]# ps -aux |grep httpd
root 1966 0.0 0.1 112812 976 pts/0 S+ 21:06 0:00 grep --color=auto httpd
pkill命令踢出登陆用户
除此之外,pkill 还有一个更重要的功能,即按照终端号来踢出用户登录,此时的 pkill 命令的基本格式如下:
[root@localhost ~]# pkill [-t 终端号] 进程名
[-t 终端号] 选项用于按照终端号踢出用户;
学习 killall 命令时,不知道大家发现没有,通过 killall 命令杀死 sshd 进程的方式来踢出用户,非常容易误杀死进程,要么会把 sshd 服务杀死,要么会把自己的登录终端杀死。
所以,不管是使用 kill 命令按照 PID 杀死登录进程,还是使用 killall 命令按照进程名杀死登录进程,都是非常容易误杀死进程的,而使用 pkill 命令则不会,举个例子:
[root@ali01 ~]# w
21:07:46 up 21 days, 7:40, 2 users, load average: 0.00, 0.03, 0.05
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
root pts/0 58.19.101.143 20:51 2.00s 0.03s 0.00s w
root pts/1 58.19.101.143 21:07 1.00s 0.00s 0.00s -bash
[root@ali01 ~]# pkill -9 -t pts/1
可以看到我的pts/1这个终端时被我Kill掉了
号] 选项用于按照终端号踢出用户;
学习 killall 命令时,不知道大家发现没有,通过 killall 命令杀死 sshd 进程的方式来踢出用户,非常容易误杀死进程,要么会把 sshd 服务杀死,要么会把自己的登录终端杀死。
所以,不管是使用 kill 命令按照 PID 杀死登录进程,还是使用 killall 命令按照进程名杀死登录进程,都是非常容易误杀死进程的,而使用 pkill 命令则不会,举个例子:
[root@ali01 ~]# w
21:07:46 up 21 days, 7:40, 2 users, load average: 0.00, 0.03, 0.05
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
root pts/0 58.19.101.143 20:51 2.00s 0.03s 0.00s w
root pts/1 58.19.101.143 21:07 1.00s 0.00s 0.00s -bash
[root@ali01 ~]# pkill -9 -t pts/1
可以看到我的pts/1这个终端时被我Kill掉了