CnSwift - 雨燕

agile development - 敏捷开发

进程的管理

一个称职的系统管理员,必须要熟悉进程的管理流程才行。

进程的介绍

什么是进程?

在Linux系统当中,触发任何一个事件时,系统都会将它定义为一个进程,并且给予这个进程一个id,称为pid,同时依据触发这个进程的用户与相关属性关系,给予这个pid一组有效的权限设置。从此以后,这个pid能够在系统上面进行的操作,就与这个pid的权限有关了。

如何产生一个进程?

其实很简单,就是“执行一个程序或命令”就可以触发一个事件而取得一个pid,因为系统仅认识二进制文件,所以当我们让系统工作时,就需要启动一个二进制文件,这个二进制文件也就是一个程序。

程序一般是放置在磁盘当中,然后通过用户的执行触发,触发后会加载到内存中成为一个个体,也就是进程。为了让操作系统可以管理这个进程,因此进程有给予执行者的权限/属性等参数,并包括进程所需要的脚本和数据或文件数据等,最后在给予一个pid。系统就是通过这个pid来判断该process(进程)是否具有权限进行工作的。

程序和进程的区别是什么?

程序(program):通常为二进制程序放置在存储媒介中(如硬盘、光盘、软盘、磁带等),以物理文件的形式存在。

进程(process):程序被触发后,执行者的权限和属性、程序的程序代码与所需数据等都会被加载到内存中,操作系统并给予这个内存内的单元一个标识符(pid),可以说,进程就是一个正在运行中的程序。

子进程与父进程

举例说明,当我们登录系统后,会取得一个bash的shell并得到一个pid,然后我们用这个bash提供的接口去执行另一个命令,比如新建一个文件touch test.txt,执行的另一个命令也会被触发成为pid,那么后来执行的另一个命令所产生的pid就是子进程,而我们原本的bash环境下的pid就是父进程。

如何判断某个进程的父进程是哪个?

这是通过Parent PID(PPID)判断的,由以下命令可以看出,ps命令的父进程(ppid)是bash的进程(pid)。

1
2
3
4
[root@localhost test6]# ps -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 S 0 12202 12200 0 80 0 - 29209 do_wai pts/1 00:00:00 bash
0 R 0 12570 12202 0 80 0 - 37235 - pts/1 00:00:00 ps

进程的查看

进程的查看

如何查阅系统上正在运行的进程?

使用静态的ps或者动态的top,还可以使用pstree查看程序树之间的关系。

ps:将某个时间点的进程运行情况选取下来

先来说一下ps命令,常用方式有这么几种:

  • 查看系统所有的进程数据 ps aux

  • 也能够查看所有系统的数据 ps -lA

  • 连同部分进程树状态 ps axjf

参数:

-A:所有的进程都显示出来,与-e具有同样的作用。

-a:不与terminal有关的所有进程。

-u:有效用户(effective user)相关的进程。

x:通常与a参数一起使用,可以列出较完整信息。

输出格式规划:

l:较长、较详细的将pid的信息列出。

j:工作的格式(jobs format)

-f:做一个更为完整的输出。

注意:一般只需要背下来两个使用方式即可,一个是只能查阅自己bash程序的“ps -l”,另一个是可以查看所有系统正在运行的程序的“ps aux”。所以我们这里也仅通过示例来讲解一下这两个使用方式。

下面通过几个示例将显示的数据详细介绍一下:

示例1:

将目前属于你自己这次登录的pid与相关信息列出来(只和自己的bash有关)

1
2
3
4
[root@localhost test6]# ps -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 S 0 12202 12200 0 80 0 - 29209 do_wai pts/1 00:00:00 bash
0 R 0 12839 12202 0 80 0 - 37235 - pts/1 00:00:00 ps

显示数据所表示的含义:

F:代表这个进程的标志(process flags),说明这个进程的权限,常见号码有:

4:表示进程的权限为root
1:表示此子进程仅可以进行复制(fork)而无法实际执行(exec)

S:代表这个进程的状态(STAT),主要状态有:

R(Running):该进程正在运行中
S(Sleep):该进程目前正在睡眠状态(idle),但可以被唤醒(signal)
D:不可被唤醒的睡眠状态,通常这个进程可能在等待I/O的情况(ex>打印)
T:停止状态(stop),可能在工作控制(后台暂停)或除错(traced)状态
Z(Zombie):“僵尸”状态,进程已经终止但无法被删除到内存外

UID:代表此进程被该UID所拥有

PID:进程的PID号码

PPID:此进程的父进程PID号码

C:代表CPU使用率,单位是百分比

PRI:Priority的缩写

NI:Nice的缩写

ADDR:kernel function,指出该进程在内存的哪个部分,如果是个running的进程,一般就会显示”-“

SZ:代表此进程用掉多少内存

WCHAN:表示目前进程是否运行中,若为”-“,表示正在运行中

TTY:登录者的终端机位置,若为远程登录则使用动态终端接口(pts/n)

TIME:使用掉的CPU时间,注意,是此进程实际花费CPU运行的时间,不是系统时间

CMD:是command的缩写,造成此程序的触发进程命令是什么

示例2:

列出目前所有正在内存当中的进程。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[root@localhost test6]# ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.1 125540 3464 ? Ss 4月19 0:01 /usr/lib/systemd/systemd --switched-root --system --deserialize 21
root 2 0.0 0.0 0 0 ? S 4月19 0:00 [kthreadd]
root 3 0.0 0.0 0 0 ? S 4月19 0:02 [ksoftirqd/0]
root 5 0.0 0.0 0 0 ? S< 4月19 0:00 [kworker/0:0H]

中间部分省略...

root 11609 0.0 0.1 116704 3304 pts/0 Ss+ 09:31 0:00 -bash
root 12015 0.0 0.1 101172 2352 ? Ss 09:47 0:00 sendmail: accepting connections
smmsp 12034 0.0 0.1 84120 2036 ? Ss 09:47 0:00 sendmail: Queue runner@01:00:00 for /var/spool/clientmqueue
root 12062 0.0 0.8 113372 15948 ? S 09:48 0:00 /sbin/dhclient -d -q -sf /usr/libexec/nm-dhcp-helper -pf /var/run/dhclient-enp0s3.pid -lf /var/lib/NetworkManager/dhclient-b9e01253-6fc8-
root 12200 0.0 0.3 150444 5992 ? Ss 09:53 0:00 sshd: root@pts/1
root 12202 0.0 0.1 116836 3584 pts/1 Ss 09:53 0:00 -bash
root 12245 0.0 0.0 0 0 ? S 09:53 0:00 [kworker/u2:1]
root 12518 0.0 0.0 0 0 ? R 10:20 0:00 [kworker/0:3]
root 12829 0.0 0.0 0 0 ? S 10:52 0:00 [kworker/0:0]
root 12873 0.0 0.0 0 0 ? S 10:57 0:00 [kworker/0:1]
root 12910 0.0 0.0 107904 612 ? S 11:00 0:00 sleep 60
root 12911 0.0 0.0 151064 1824 pts/1 R+ 11:00 0:00 ps aux

说一下各个字段的意义:

USER:该进程属于哪个用户帐号的

PID:该进程的进程标识符

%CPU:该进程使用掉的CPU资源百分比

%MEM:该进程所占用物理内存百分比

VSZ:该进程使用掉的虚拟内存量(KB)

RSS:该进程占用的固定内存量(KB)

TTY:该进程是在哪个终端机上面运行,如果与终端机无关,则显示”?“。另外,tty1-tty6是本机上面的登录者程序,如果为pts/0等,则表示由网络连接进主机的进程。

STAT:该进程目前的状态,状态显示与ps -l的S标识相同(R/S/T/Z)

START:该进程被触发启动的时间

TIME:该进程实际使用CPU运行的时间

COMMAND:该进程的实际命令

top:动态查看进程的变化

相对于ps是选取一个时间点的进程状态,top则可以持续检测进程运行的状态,使用方式如下:

top [-d 数字] | top [-bnp]

参数:

-d:后面可以接秒数,就是整个进程界面更新的秒数,默认是5秒

-b:以批次的方式执行top,还有更多的参数可以使用。通常会搭配数据流重定向来将批处理的结果输出成为文件。

-n:与-b搭配,意义是,需要进行几次top的输出结果。

-p:指定某些个pid来进行查看监测

在top执行过程当中,可以使用的按键命令:

?:显示在top当中可以输入的按键命令

P:以CPU的使用资源排序显示

M:以内存的使用资源排序显示

N:以PID来排序显示

T:由该进程使用的CPU时间累积(TIME+)排序

k:给予某个pid一个信号(signal)

r:给予某个pid重新制定一个nice值

q:离开top软件的按键

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
top - 14:26:44 up 15:17,  2 users,  load average: 0.00, 0.01, 0.05
Tasks: 197 total, 1 running, 196 sleeping, 0 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 : 1883516 total, 130896 free, 960040 used, 792580 buff/cache
KiB Swap: 2097148 total, 2088552 free, 8596 used. 707652 avail Mem

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1034 root 20 0 145260 7136 688 S 1.0 0.4 0:57.43 redis-server
1 root 20 0 125540 3468 2084 S 0.0 0.2 0:01.84 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:02.67 ksoftirqd/0
5 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kworker/0:0H
7 root rt 0 0 0 0 S 0.0 0.0 0:00.00 migration/0
8 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_bh
9 root 20 0 0 0 0 S 0.0 0.0 0:17.09 rcu_sched
10 root rt 0 0 0 0 S 0.0 0.0 0:00.35 watchdog/0
省略...

top分为两个界面,上面的界面为整个系统的资源使用状态,基本上总共有六行,显示的内容依序是:

第一行(top…):这一行显示的信息分别为:目前的时间,即是14:26:44那个选项;开机到目前为止所经过的时间,即使up 15:17那个选项;已经登录系统的用户人数,即是2 users那个选项;系统在1,5,15分钟的平均工作负载,即是load average: 0.00, 0.01, 0.05那个选项,代表的是1,5,15分钟,系统平均要负责运行几个进程(工作)的意思,越小代表系统越闲置,如果高于1,就要注意你的系统压力是否太高了。

第二行(Tasks…):显示的是目前进程的总量与个别进程在什么状态(running,sleeping,stopped,zombie)。比较需要注意的是最后的zombie那个数值,如果不是0,就要好好看到底是哪个进程变成僵尸进程了。

第三行(%Cpu…):显示的是CPU的整体负载,每个选项可使用”?“查阅。需要特别注意的是wa,那个选项代表的是I/O wait,通常你的系统会变慢都是I/O产生的问题比较大,因此这里要注意这个选项耗用CPU的资源,另外,如果是多内核设备,可以按下数字键”1“来切换成不同CPU的负载率。

第四行与第五行:表示目前的物理内存与虚拟内存(Mem/Swap)的使用情况。特别强调一下,要注意的是Swap的使用量要尽量少,如果Swap被大量使用,表示系统物理内存不足。

第六行:这个是当在top进程当中输入命令时显示状态的地方。

top下半部分的界面,则是每个进程使用资源的情况。比较需要注意的是:

PID:每个进程的id

USER:该进程所属的用户

PR:Priority的简写,进程的优先执行顺序,越小越早被执行

NI:Nice的缩写,与Priority有关,也是越小越早被执行

%CPU:CPU的使用率

%MEM:内存的使用率

TIME+:CPU使用时间的累加

top默认使用CPU使用率(%CPU)作为排序的重点,如果你想要使用内存使用率排序,则可按下”M“按键,若要恢复则按下”P“按键,如果想离开top,则按下”q“按键。

如果你想将top的结果输出成为文件,可以看下面这个示例。

示例3:

将top的信息进行2次,然后将结果输出到/tmp/top.txt

top -b -n 2 > /tmp/top.txt

仅查看单一进程,请看下面示例。

示例4:

我们自己的bash PID 可由 $$ 变量取得,请使用top持续查看该PID

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@localhost test6]# echo $$
12202
[root@localhost test6]# top -d 2 -p 12202

top - 15:00:09 up 15:50, 2 users, load average: 0.00, 0.01, 0.05
Tasks: 1 total, 0 running, 1 sleeping, 0 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 : 1883516 total, 130988 free, 959904 used, 792624 buff/cache
KiB Swap: 2097148 total, 2088580 free, 8568 used. 707760 avail Mem

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
12202 root 20 0 116836 3584 1832 S 0.0 0.2 0:00.06 bash

这样就只会显示你指定的pid

示例5:

承接上例,上面的NI值为0,想要修改为10

在top界面中,按下”r“按键,显示”PID to renice [default pid = 12202]”如下:

1
2
3
4
5
6
7
8
top - 15:03:35 up 15:53,  2 users,  load average: 0.00, 0.01, 0.05
Tasks: 1 total, 0 running, 1 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.5 us, 0.0 sy, 0.0 ni, 99.5 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 1883516 total, 131300 free, 959588 used, 792628 buff/cache
KiB Swap: 2097148 total, 2088584 free, 8564 used. 708072 avail Mem
PID to renice [default pid = 12202]
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
12202 root 20 0 116836 3584 1832 S 0.0 0.2 0:00.06 bash

输入进程号pid,显示”Renice PID 12202 to value“如下:

1
2
3
4
5
6
7
8
top - 15:03:35 up 15:53,  2 users,  load average: 0.00, 0.01, 0.05
Tasks: 1 total, 0 running, 1 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.5 us, 0.0 sy, 0.0 ni, 99.5 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 1883516 total, 131300 free, 959588 used, 792628 buff/cache
KiB Swap: 2097148 total, 2088584 free, 8564 used. 708072 avail Mem
Renice PID 12202 to value
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
12202 root 20 0 116836 3584 1832 S 0.0 0.2 0:00.06 bash

输入新Nice值10,显示如下:

1
2
3
4
5
6
7
8
top - 15:07:47 up 15:58,  2 users,  load average: 0.00, 0.01, 0.05
Tasks: 1 total, 0 running, 1 sleeping, 0 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 : 1883516 total, 130988 free, 959900 used, 792628 buff/cache
KiB Swap: 2097148 total, 2088584 free, 8564 used. 707760 avail Mem

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
12202 root 30 10 116836 3584 1832 S 0.0 0.2 0:00.06 bash

一般如果想找出最损耗CPU资源的进程,就是使用top,然后强制使用CPU使用资源来排序(在top当中按下”P“按键),就可以很快知道结果。

pstree

格式:

pstree [-A|U] [-up]

参数:

-A:各进程树之间的连接以ASCII字符来连接

-U:各进程树之间的连接以utf8码的字符连接,在某些终端接口下可能会有错误

-p:同时列出每个进程的pid

-u:同时列出每个进程的所属帐户名称

进程的管理

进程之间是可以互相控制的,比如我们可以关闭、重启服务器软件,服务器软件本身是个程序,我们既然可以关闭或启动程序,当然就可以控制程序,每个运行的程序都有一个进程号(pid),如果我们想控制程序,我们只需要给该进程号发送一个信号(signal)告诉该程序,我们想让它干什么。所以这个信号很重要,到底有多少信号呢?我们可以通过命令kill -l查看。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@localhost ~]# 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 启动被终止的进程,可以让该pid重新读取自己的配置文件,类似重新启动
2 SIGINT 相当于键盘输入[ctrl] + c中断一个进程的进行
9 SIGKILL 代表强制中断一个进程的进行,如果该进程进行到一半,那么尚未完成的部分可能会有”半产品“产生,类似vim会有.filename.swp保留下来
15 SIGTERM 以正常的结束进程来终止该进程。由于是正常的终止,所以后续的操作会将它完成。不过,如果该进程已经发生问题,就是无法使用正常的方法终止时,输入这个SIGTERM也是无用的
17 SIGCHLD 相当于用键盘输入[ctrl] + z暂停一个进程的进行

我们常用的只有1,9,15,一般记住这三个的意义即可。

如何传送一个信号给某个进程呢?用kill或killall,下面分别介绍一下:

kill -signal PID

kill可以帮我们把这个signal传送给某个工作(%jobnumber)或者某个PID(直接输入数字)。需要强调的是,kill后面直接加数字和加上%number的情况是不同的!因为工作控制中有1号工作,但是PID的1号则是专指”init“这个进程。关闭”init“这个进程,你的系统就死掉了。所以一定要记得%是专门用在工作控制上的。

killall -signal 命令名称

因为kill后面必须加上pid或者%jobnumber,所以kill要配合ps,pstree等命令先找到对应的进程id,而且如果我们有多个PHP进程在运行,想要终止所有PHP进程,就需要一个一个的killPHP进程的进程号,比较麻烦。我们可以使用killall直接给进程名称发送signal。

格式:

killall [-iIe] [command name]

参数:

-i:interactive的意思,交互式的,若需要删除时,会出现提示符给用户。

-e:exact的意思,表示后面接的command name 要一致,但整个完整的命令不能超过15个字符

-I:命令名称(可能含参数)忽略大小写。

注意:如果我们想要终止某个程序的所有进程,最好使用参数-i,防止误终止不能终止的进程。

进程执行顺序

哪个进程被执行的优先序比较高,就得考虑到程序的优先执行序(Priority)与CPI调取。

Priority与Nice值

Linux给予进程一个所谓的”优先执行序“(priority,PRI),这个PRI值越低代表进程越优先的意思,不过这个PRI值是由内核动态调整的,用户无法直接调整PRI的值。

还记得我们在哪看到过PRI吗?

1
2
3
4
[root@localhost test6]# ps -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
0 R 0 3421 32449 0 80 0 - 37227 - pts/1 00:00:00 ps
4 S 0 32449 32447 0 80 0 - 29229 do_wai pts/1 00:00:00 bash

因为PRI是内核调整的,我们用户无权干涉PRI。那么如果你想要调整进程的优先执行序时,就要通过Nice值了,Nice值就是上面的NI。一般来说,PRI与NI的相关性如下:

PRI(new) = PRI (old) + nice

不过你还要特别注意,如果原本的PRI是50,并不是我们给予一个nice=5,就会让PRI变成55。因为PRI是系统”动态“决定的,所以,虽然nice值是可以影响PRI,不过,最终的PRI仍是要经过系统分析后才会决定的。另外,有几点需要注意一下:

  1. nice的值是有正负的,而既然PRI越小越早被执行,所以,当nice值为负值时,那么该程序就会降低PRI值,即会变得优先被处理的。
  2. nice的值可调整的范围是-20~19
  3. root可以随意调整自己或他人进程的Nice值,且范围是-20~19
  4. 一般用户只可以调整自己进程的Nice值,且范围是0~19(避免一般用户抢占系统资源)
  5. 一般用户仅可将nice值越调越高,例如本来nice为5,则将来仅能调整到大于5

也就是说,要调整某个进程的优先执行序,就是调整该进程的nice值。调整某个进程的nice值有两种方式:

  1. 一开始执行程序就立即给予一个特定的nice值,用nice命令
  2. 调整某个已存在的PID的nice值,用renice命令

nice:新执行的命令即给予新的nice值

格式:

nice [-n 数字] command

参数:

-n:后面接一个数字,数值的范围是-20~19

command:命令名称

renice:已存在进程的nice重新调整

格式:

renice [number] PID

参数:

PID:某个进程的pid

更多精彩内容,请关注公众号 Golang语言开发栈公众号二维码
感谢赞赏.

Welcome to my other publishing channels