第九章进程管理
8学习目标:
l 理解进程的概念
l 理解子进程、父进程
l 熟练掌握ps、pstree、top命令查看进程
l 熟练掌握free、uname、uptime、netstat监控进程活动
9.1.、进程的概述
9.1.1进程,究竟什么是进程呢?
在 Linux 系统当中:触发任何一个事件时,系统都会将他定义成为一个程序,并且给予这个程序一个 ID ,称为 PID,同时依据启发这个程序的使用者与相关属性关系,给予这个 PID 一组有效的权限设定。从此以后,这个 PID 能够在系统上面进行的动作,就与这个 PID 的权限有关了。
一个应用程序被触发(执行),就会对这个程序产生相对应的进程。也就是已启动可执行程序的运行中实例。一个进程被触发,那么该进程的拥有者就是触发该进程的用户,进程的权限也就是触发进程用户的权限。
9.1.2程序与执行文件
我们如何产生一个 Process ID (PID) 呢?其实很简单啦,就是执行一个程序或指令就可以触发一个事件了而取得一个PID。系统仅认识 binary file (二进制文件),系统工作的时候启动的binaryfile,就是一个程序。
9.2、父进程和子进程
在我们登入系统后,会取得一个 bash 的 shell ,然后,我们用这个 bash 提供的接口去执行另一个指令,例如 /usr/bin/passwd 或者是 touch 等等,那些另外执行的指令也会被触发成为PID,这个PID 就是子程序,而在我们的 bash 环境下,就称为父程序了。
在系统上面的各个程序可能是有相关性,也就是有所谓的父程序与子程序的关系,至于程序的相关性,我们可以使用 pstree 程序去查验,就能知道彼此之间的关系了。如何pstree使用查验进程间的关系,在本章后面将会在详细的说明。
9.3、在linux系统中进程的四种状态
名称 |
标志 |
描述 |
运行中 |
R |
TASK_RUNNING:进程正在CPU上执行,或者正在等待运行 |
睡眠 |
S |
TASK_INTERRUPTIBLE:进程等待某一条件:硬件请求、系统资源访问或信号。 |
D |
TASK_UNINTERRUPTITBLE:此进程处于不会响应传递信号的睡眠状态。 |
|
K |
TASK_KILLABLE:允许等待中的任务通过响应信号而被中断(彻底退出)。 |
|
已停止 |
T |
TASK_STOPPED:进程已被停止或暂停 |
T |
TASK_TRACED:正在被调试的进程也会临时停止,并且共享同一个T状态标志。 |
|
僵停 |
Z |
EXIT_ZOMBIE:子进程在退出时向父进程发出信号。除PID外的所有资源都已释放。 |
X |
EXIT_DEAD:当父进程清理剩余的子进程的结构时,进程现在已彻底释放。 |
注意:
在linux系统的四种进程状态中,有以下几个算是比较危险的。分别是Z、K、D、X;当出现这四种情况的时候你就需要特别注意了。
9.4、在linux系统中使用ps、pstree、top去查看进程
9.4.1、ps命令:
当需要查看系统中执行的的程序时,ps虽然不是唯一的命令,但是绝对是使用最频繁的命令。
下面表格是与ps结合使用的一些参数:
参数 |
含义 |
a |
显示在终端机下的所有程序 |
-A |
显示所有程序 |
c |
列出程序时,显示每个程序的真正指令名称 |
-e |
与-A相同 |
e |
列出程序时,显示每个程序所使用的环境变量 |
f |
用ASCII字符显示树状结构 |
u |
以用户为主的格式来显示程序状况 |
s |
采用程序信号的格式来显示程序状况 |
-l |
长格式 |
-m |
显示所有的线程 |
案列1:
利用ps –l来查看进程
F |
代表这个程序的旗标(flag);4代表的是超级用户 |
S |
代表这个程序的状态 |
PID |
程序的ID |
C |
CPU使用的资源百分比 |
PRI |
Priority的缩写,优先级;数值越小越早被执行 |
NI |
Nice值 |
ADDR |
Kernelfunction,指出该程序在内存的那个部分;如果程序running,一般是“-“ |
SZ |
使用掉的内存大小 |
WCHAH |
程序是否正在运行,“-” 表示正在运行 |
TTY |
登入者的终端机位置 |
TIME |
使用掉的CPU时间 |
案列2:
多个参数与ps结合使用
案例3:
管道“|”和more与ps的结合使用
[root@server ~]# ps -elf | more F S UID PID PPID C PRI NI ADDR SZ WCHAN STIME TTY TIME CMD 4 S root 1 0 0 80 0 - 31484 ep_pol 06:42 ? 00:00:07 /usr/lib/system d/systemd --system --deserialize 25 1 S root 2 0 0 80 0 - 0 kthrea 06:42 ? 00:00:00 [kthreadd] 1 S root 3 2 0 80 0 - 0 smpboo 06:42 ? 00:00:03 [ksoftirqd/0] 1 S root 7 2 0 -40 - - 0 smpboo 06:42 ? 00:00:00 [migration/0] 1 S root 8 2 0 80 0 - 0 rcu_gp 06:42 ? 00:00:00 [rcu_bh] 1 S root 9 2 0 80 0 - 0 rcu_no 06:42 ? 00:00:00 [rcuob/0] 1 S root 10 2 0 80 0 - 0 rcu_no 06:42 ? 00:00:00 [rcuob/1] 1 S root 11 2 0 80 0 - 0 rcu_no 06:42 ? 00:00:00 [rcuob/2] 1 S root 12 2 0 80 0 - 0 rcu_no 06:42 ? 00:00:00 [rcuob/3] 1 S root 13 2 0 80 0 - 0 rcu_no 06:42 ? 00:00:00 [rcuob/4] --More-- |
9.4.2、pstree命令
功能:以树状图的形式来显示进程之间的关系
语法:pstree [-acGhlnpuUV][-H <程序识别码>][<程序识别码>/<用户名称>]
注意:
pstree指令用ASCII字符显示树状结构,清楚地表达程序间的相互关系。如果不指定程序识别码或用户名称,则会把系统启动时的第一个程序视为基层,并显示之后的所有程序。若指定用户名称,便会以隶属该用户的第一个程序当作基层,然后显示该用户的所有程序。
参数:
-a |
显示每个程序的完整指令,包含路径,参数或是常驻服务的标示 |
-c |
不使用精简标示法 |
-G |
使用VT100终端机的列绘图字符。 |
-h |
列出树状图时,特别标明现在执行的程序 |
-H |
<程序识别码> 此参数的效果和指定”-h”参数类似,但特别标明指定的程序。 |
-l |
采用长列格式显示树状图。 |
-n |
用程序识别码排序。预设是以程序名称来排序。 |
-p |
显示程序识别码。 |
-u |
显示用户名称。 |
-U |
使用UTF-8列绘图字符。 |
-V |
显示版本信息。 |
-A |
各程序树之间的连接以ASCII字符来连接 |
案例1:
在本章的开头有提到子进程与父进程,那么如何清楚地查验子进程和父进程的关系呢?没错,我们可以使用pstree这个程序来查验,让其以树状图的形式更直观地告诉我们子进程和父进程的关系。
[root@server ~]# pstree -A |grep ping |-sshd---sshd-+-bash---ping |
我们用一个简单的ping进程来描述,ping这个子进程的父进程就是前方的bash进程。
案例2:
多个参数与pstree同时使用,通过pstree程序的树状图,我们能够更加清楚地看到进程与进程之间的关系;通过多个参数的结合使用,不仅看到了进程间的关系,同时也看到了PID,如括号内的845、906等等。
[root@server ~]# pstree -Aup systemd(1)-+-NetworkManager(845)-+-{NetworkManager}(906) | |-{NetworkManager}(917) | `-{NetworkManager}(920) |-abrt-watch-log(848) |-abrt-watch-log(851) |-abrtd(847) |-accounts-daemon(890)-+-{accounts-daemon}(899) | `-{accounts-daemon}(919) |-at-spi-bus-laun(1451,kiosk)-+-dbus-daemon(1455)---{dbus-daemon}(1457) | |-{at-spi-bus-laun}(1452) | |-{at-spi-bus-laun}(1454) | `-{at-spi-bus-laun}(1456) |-at-spi2-registr(1460,kiosk)---{at-spi2-registr}(1461) |-atd(1145) |-auditd(821)-+-audispd(829)-+-sedispatch(832) | | `-{audispd}(833) | `-{auditd}(828) |-avahi-daemon(869,avahi)---avahi-daemon(883) |-bluetoothd(1633) |-chronyd(868,chrony) |-colord(1586,colord)-+-{colord}(1591) | `-{colord}(1592) |
9.4.3、top命令
简介:
top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器
top显示系统当前的进程和其他状况,是一个动态显示过程,即可以通过用户按键来不断刷新当前状态.如果在前台执行该命令,它将独占前台,直到用户终止该程序为止. 比较准确的说,top命令提供了实时的对系统处理器的状态监视.它将显示系统中CPU最“敏感”的任务列表.该命令可以按CPU使用.内存使用和执行时间对任务进行排序;而且该命令的很多特性都可以通过交互式命令或者在个人定制文件中进行设定。
1、top命令的格式
top [-] [d] [p] [q] [c] [C] [S] [n]
2、参数说明
d |
指定每两次屏幕信息刷新之间的时间间隔。当然用户可以使用s交互命令来改变之 |
p |
通过指定监控进程ID来仅仅监控某个进程的状态。 |
q |
该选项将使top没有任何延迟的进行刷新。如果调用程序有超级用户权限,那么top将以尽可能高的优先级运行。 |
S |
指定累计模式 |
s |
使top命令在安全模式中运行。这将去除交互命令所带来的潜在危险。 |
i |
使top不显示任何闲置或者僵死进程。 |
c |
显示整个命令行而不只是显示命令名 |
3、在top命令的显示窗口,我们还可以输入以下字母,进行一些交互
M |
根据驻留内存大小进行排序。 |
P |
根据CPU使用百分比大小进行排序 |
T |
根据时间/累计时间进行排序。 |
W |
将当前设置写入~/.toprc文件中。这是写top配置文件的推荐方法。 |
I |
切换显示平均负载和启动时间信息。即显示影藏第一行 |
q |
退出程序。 |
i |
忽略闲置和僵死进程。这是一个开关式命令。 |
k |
终止一个进程。系统将提示用户输入需要终止的进程PID,以及需要发送给该进程什么样的信号。 |
t |
切换显示进程和CPU状态信息。即显示影藏CPU行 |
一般来说,如果你想找出那个最损耗 CPU 资源的那个程序时,,大多使用的就是 top 这个程序。然后强制以 CPU 使用资源来排序 (在 top 当中按下 P 即可)。你能够清楚的看到进程最损耗CPU的为%1.3;如下所示:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 36647 root 20 0 146408 2340 1424 R 1.3 0.1 0:00.25 top 532 root 20 0 0 0 0 S 0.3 0.0 0:09.00 xfsaild/sda3 3554 loveq 20 0 378020 18836 14564 S 0.3 0.5 0:54.86 vmtoolsd |
案例1:
单纯用top命令动态监测进程的状况
TOP前五行统计信息:统计信息区前五行是系统整体的统计信息
4、第一行是任务队列信息:同 uptime 命令的执行结果
[root@server ~]# uptime |
其内容如下:
07:58:04 |
当前时间 |
up 13:27 |
系统运行时间,格式为时:分 |
6 users |
当前登录用户数 |
load average: 0.01, 0.02, 0.05 |
系统负载,即任务队列的平均长度。三个数值分别为 1分钟、5分钟、15分钟前到现在的平均值 |
5、 第二、三行为进程和CPU的信息
当有多个CPU时,这些内容可能会超过两行。内容如下:
Tasks: 521 total |
进程总数 |
2 running |
正在运行的进程数 |
512 sleeping |
睡眠的进程数 |
7 stopped |
停止的进程数 |
0 zombie |
僵尸进程数 |
%Cpu(s): 2.7 us |
用户空间占用CPU百分比 |
2.7 sy |
内核空间占用CPU百分比 |
0.0 ni |
用户进程空间内改变过优先级的进程占用CPU百分比 |
94.7 id |
空闲CPU百分比 |
0.0 wa |
等待输入输出的CPU时间百分比 |
6、 第四五行为内存信息。
Mem : 8162368 total |
物理内存总量 |
260496 free |
空闲内存总量 |
3809580 used, |
空闲内存总量 |
4092292 buff/cache |
用作内核缓存的内存量 |
Swap: 8257532 total |
交换区总量 |
8253348 free |
使用的交换区总量 |
4184 used |
空闲交换区总量 |
4021496 avail Mem |
缓冲的交换区总量。内存中的内容被换出到交换区,而后又被换入到内存,但使用过的交换区尚未被覆盖,该数值即为这些内容已存在于内存中的交换区的大小。相应的内存再次被换出时可不必再对交换区写入。 |
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 36251 root 20 0 146408 2332 1424 R 1.3 0.1 0:01.98 top 1428 root 20 0 553036 16404 5732 S 0.3 0.4 0:06.49 tuned 17554 root 20 0 288596 9796 4024 S 0.3 0.3 0:01.46 docker-containe 1 root 20 0 125936 6516 3856 S 0.0 0.2 0:07.81 systemd |
进程信息区统计信息区域的下方显示了各个进程的详细信息,具体如下表所示:
列名 |
含义 |
PID |
进程id |
PPID |
父进程id |
RUSER |
Real user name |
UID |
进程所有者的用户id |
USER |
进程所有者的用户名 |
GROUP |
进程所有者的组名 |
TTY |
启动进程的终端名.不是从终端启动的进程则显示为 ? |
PR |
优先级 |
NI |
nice值.负值表示高优先级,正值表示低优先级 |
P |
最后使用的CPU,仅在多CPU环境下有意义 |
%CPU |
上次更新到现在的CPU时间占用百分比 |
TIME |
进程使用的CPU时间总计,单位秒 |
TIME+ |
进程使用的CPU时间总计,单位1/100秒 |
%MEM |
进程使用的物理内存百分比 |
VIRT |
进程使用的虚拟内存总量,单位kb,VIRT=SWAP+RES |
SWAP |
进程使用的虚拟内存中,被换出的大小,单位kb. |
RES |
进程使用的、未被换出的物理内存大小,单位kb,RES=CODE+DATA |
COMMAND |
命令名/命令行 |
WCHAN |
若该进程在睡眠,则显示睡眠中的系统函数名 |
Flags |
任务标志 |
SHR |
共享内存大小,单位kb |
7、 top –d n<n表示多少刷新一次>
案例:这里的案例刷新的时间的单位是秒(s),所以表示每个3s刷新一次
[root@server0 ~]# top -d 3 |
8、 top -n n<n表示总共刷新几次>
案例:此案例表示总共刷新3次,而且刷新三次后就不然刷新了。
root@server0 ~]# top -n 3 |
9.5、bash环境下的工作管理
这个工作管理 (job control) 是用在 bash 环境下的,也就是说:当我们登入系统取得 bash shell 之后,在单一终端机接口下同时进行多个工作的行为管理。
终端(前景):您可以控制的这个工作称为终端的工作
后台(后景):在内存内可以自行运作的工作,您无法直接控制他,除非以 bg/fg 等指令将该工作调到终端上来。
如果想要同时进行多个工作,那么可以将某些工作丢到后台环境当中,让我们可以继续操作终端的工作。那么如何将工作丢到背景中?最简单的方法就是利用[ &]。
案例1:
[root@server ~]# cp /tmp/test /root/ & [3] 38158 |
上面的例子就是把复制一个test文件的操作放到后台,从而我们不必等待指令结束才能在终端上操作。
9.5.1、观察目前的后台工作状态: jobs
jobs [-lrs]
参数:
-l :除了列出 job number 之外,同时列出 PID
-r :仅列出正在后台 run 的工作;
-s :仅列出正在后台当中暂停 (stop) 的工作。
案例2:
[root@server ~]# jobs -l [1]+ 24988 Stopped [2]- 25006 Stopped |
9.5.2、将后台工作拿到终端来处理:fg
语法: fg %jobnumber
案例3:
[root@server ~]# fg %2 |
让一个工作在背景底下运行,我们可以在底下这个案例当中来测试。不过在底下的测试要进行的快一点。
案例4:
[root@server ~]# jobs ; bg %1 ; jobs [1]+ Stopped find / -perm +7000 [1]+ find / -perm +7000 & [1]+ Running find / -perm +7000 & |
9.6、控制作业
刚刚我们可以让一个已经在背景当中的工作继续工作,也可以让该工作以 fg 拿到前景来,那么,如果想要将该工作直接移除呢?或者是将该工作重新启动呢?这个时候就得需要给予该工作一个讯号 (signal) ,此时,就要用到kill/killall了。
9.6.1、kill/killall
语法:kill -signal %jobnumber
-l :这个是 L 的小写,列出目前 kill 能够使用的讯号 (signal) 有哪些?
参数 |
含义 |
-1 |
重新读取一次参数的设定档 (类似 reload); |
-2 |
代表与由键盘输入 [ctrl]-c 同样的动作; |
-9 |
立刻强制删除一个工作 |
-15 |
以正常的结束程序来终止该程序。由于是正常的终止,所以后续的动作会将他完成。不过,如果该程序已经发生问题,就是无法使用正常的方法终止时,输入这个 signal 也是没有用的。 |
案例1:
[root@server ~]# jobs [1]+ Stopped vim bashrc [root@linux ~]# kill -9 %1 [1]+ 已砍掉 vim bashrc |
案例2:
root@server ~]# killall -9 httpd [root@server ~]# ps -ef |grep httpd root 21306 19015 0 04:12 pts/0 00:00:00 grep --color=auto httpd |
[root@server ~]# kill -9 21520 |
Killall后面跟的是关键字,kill后面跟的是PID.
注意:
kill与killall的比较,用killall终止httpd进程,是一次性就所有含有httpd的进程都中断了;而用kill中断进程的时候,因为后面跟的是PID(进程ID),所以只能后一次一个进程的中断
9.7、监控进程活动
系统的程序之外,我们还必须就系统的一些资源进行检查。举例来说,我们使用 top 可以看到很多系统的资源。那么,还有没有其它的工具可以查阅的?底下这些工具指令也可以
9.7.1、free命令
语法:free [-b|-k|-m|-g] [-t]
参数:
-b :直接输入 free 时,显示的单位是 Kbytes,我们可以使用 b(bytes), m(Mbytes)、k(Kbytes), 及 g(Gbytes) 来显示单位。
-t :在输出的最终结果,显示物理内存与 swap 的总量。
案例:
[root@server ~]# free -m total used free shared buffers cached Mem: 376 366 10 0 129 94 -/+ buffers/cache: 141 235 Swap: 996 0 995 |
我的 swap 有 1GB 左右,那我使用 free -m 以 MBytes 来显示时,就会出现上面的信息。Mem 那一行显示的是物理内存的量, Swap 则是虚拟内存的量。 total 是总量, used 是已被使用的量, free 则是剩余可用的量。后面的 shared/buffers/cached 则是在已被使用的量当中,用来作为缓冲及快取的量。
一般来说, swap 最好不要被使用,尤其 swap 最好不要被使用超过 20% 以上,如果您发现 swap 的用量超过 20% ,那么,最好还是买物理内存来插吧。因为, Swap 的效能跟物理内存实在差很多,而系统会使用到 swap ,绝对是因为物理内存不足了才会这样做的。
9.7.2、uname命令
语法:uname [-asrmpi]
参数 |
含义 |
-a |
所有系统相关的信息 |
-s |
系统核心名称 |
-r |
核心的版本 |
-m |
本系统的硬件名称 |
-p |
CPU 的类型 |
-i |
硬件的平台 (ix86) |
案例:输出系统的基本信息
[root@server~]# uname -a Linux linux.site 2.6.12-1.1398_FC4 #1 Fri Jul 15 00:52:32 EDT 2005 i686 i686 i386 GNU/Linux |
9.7.3、uptime命令
这个指令很单纯,就是显示出目前系统已经开机多久的时间,以及 1, 5, 15 分钟的平均负载就是了。
案例:
[root@server ~]# uptime 18:06:30 up 52 days, 6:40, 1 user, load average: 0.00, 0.00, 0.00 # 上面表示,目前是 18:06 ,本系统已经开机 52 天又 6:40 ,有 1 个使用者在在线, # 平均负载很低,所以都是 0 。 |
9.7.4、netstat命令
其实,这个指令比较常被用在网络的监控方面,不过,在程序管理方面也是需要了解的。这个指令的执行如下所示:基本上, netstat 的输出分为两大部分,上面是网络接口相关的联机,下方则是与 unix 程序有关的项目。
语法:netstat -[atunlp]
参数:
参数 |
含义 |
-a |
将目前系统上所有的联机、监听、Socket 数据都列出来 |
-t |
列出 tcp 网络封包的数据 |
-u |
列出 udp 网络封包的数据 |
-n |
不已程序的服务名称,以埠号 (port number) 来显示 |
-l |
列出目前正在网络监听 (listen) 的服务 |
-p |
列出该网络服务的程序 PID |
案例:列出目前系统已经建立的网络联机与 unix socket 状态
[root@server~]# netstat Active Internet connections (w/o servers) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 256 59-125-83-224.ad:ssh linux.test.s:52679 ESTABLISHED Active UNIX domain sockets (w/o servers) Proto RefCnt Flags Type State I-Node Path unix 16 [ ] DGRAM 4870 /dev/log unix 2 [ ] DGRAM 3561 @udevd unix 3 [ ] STREAM CONNECTED 509237 |
在上面的结果当中,显示了两个部分,分别是网络的联机以及 linux 上面的 socket
联机状态。在网络联机的部分主要内容为:
Proto :网络的封包协议,主要分为 TCP 与 UDP 封包,相关数据请参考服务器篇;
Recv-Q:非由使用者程序连结到此 socket 的复制的总 bytes 数;
Send-Q:非由远程主机传送过来的 acknowledged 总 bytes 数;
Local Address :本地端的 IP
Foreign Address:远程主机的 IP;
State :联机状态,主要有建立(ESTABLISED)及监听(LISTEN);
至于 unix 传统的 socket 连接状态则是:
Proto :一般就是 unix 啦;
RefCnt:连接到此 socket 的程序数量;
Flags :联机的旗标;
Type :socket 存取的类型。主要有确认联机的 STREM 与不需确认的 DGRAM 两种;
State :CONNECTED 表示已经联机建立。
Path :连接到此 socket 的相关程序的路径!或者是相关数据输出的路径
案例2:找出目前系统上已在监听的网络联机及其 PID
[root@linux ~]# netstat -tulnp Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:21 0.0.0.0:* LISTEN 1598/vsftpd tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1666/master tcp 0 0 :::22 :::* LISTEN 5281/sshd udp 0 0 0.0.0.0:68 0.0.0.0:* 21339/dhclient |