Linux学习48 Linux进程管理命令top、ps、pgrep实战
一、概述
1、在当代的X86结构的CPU中,我们将指令分为了两类,普通指令和特权指令。或者说CPU运行指令分为四个不同的级别,分别在环0,环1,环2,环3上,环0上存放的为root指令,也叫特权指令。普通用户的运行程序是不能运行环0指令的。必须是运行在内核级代码的程序才能去运行环0指令,而我们要运行的其它普通程序只能运行环3上的指令,环1和环2由于历史原因没有使用。无论是我们写的任何程序要想运行在计算机上必须编译成二进制,这就是我们之前说过的我们任何的程序包都由二进制程序和相应的库文件等结合起来组成。但是现在应用程序如果本来开发时就没有直接面向过程开发而是面向操作系统的系统调用或库调用所研发的话,这些程序在真正所运行时,尤其我们所研发的应用程序在运行时他们必须要通过发起系统调用才能完成特权级操作因为一个应用程序运行中,比如我们的echo 一个字符串给grep让其把某个字符串找出来这个基本不会涉及到特权操作的,但是如果我们打算在某个文件系统的某个目录下创建一个文件或目录的话这就涉及到硬件操作了。因为我们要把创建的文件保存在磁盘上。这就意味着是特权级别的操作。所以任何想创建文件等功能都必须由内核来完成,由内核来负责通过硬件完成操作。
二、Linux系统上的进程查看及管理工具
pstree,ps,pldof,pgrep,top,htop,glances,pmap,vmstat,dstat,kill,pkill,job,bg,fg,nohup,nice,renice,killall,...
1、pstree
a、任何进程要创建子进程时都会将请求交给init进程。init程序对CentOS5 6 7都是不一样的
CentOS5叫做传统的SysV init程序,非常经典,但是这个init有一个缺陷,在系统启动和引导时,他创建各子进程我们是通过写脚本的方式借助于shell来完成的,因此执行速度非常之慢。大家知道我们shell写的脚本里面是通过堆积大量的命令来完成的。每一个命令的启动和运行其实都是创建了一个进程,也就意味着你的系统要启动完成可能要创建上千个进程才能把系统启动起来。因此启动速度会很慢
CentOS6时就叫做upstart(ubuntu系统首先使用的),他也一样是通过启动很多命令来创建进程。而后通过进程来完成系统启动的。但是upstart能够做到的是他比init优于在init所有的命令启动和运行仅能够串行方式实现,但是upstart能够做到并行启动相应的有关联性的服务。所以使得整个系统启动速度更快了一点。所以我们创建进程时我们可以多线创建进程。如果你有多颗CPU或多个核心的话启动速度会快很多。内部基于dbus的方式进行通信。其实在CentOS6上启动服务应该使用upstart的,但是为了兼容CentOS5,CentOS6上他们较好的把upstart封装了起来依然保留使用service来启动,事实上在CentOS6上对upstart作用发挥的并不是特别大
CentOS7叫做systemd:据说在upstart出现后不久红帽的另外一个程序员发明了参考MACOS的启动逻辑又重新研发了一个新版的init程序,这个init是能够一个人独立以一个程序完成整个系统启动过程,也就意味着说他只需要在开机过程中启动这一个init进程就能够负责完成把其它各服务都启动起来。把整个系统引导起来,而这背后他所需要启动的进程通过也不过数十个而已。因此CentOS7的启动速度会非常快,这个init程序就叫systemd,这就是为什么在CentOS7上我们要启动或关闭服务时我们要使用systemctl这个命令。因为他们统一接受systemd的控制。事实上在CentOS6上对upstart作用发挥的并不是特别大,但是在CentOS7上systemd基本上已经全面介入了,他们在系统上统一的称为 /sbin/init,有可能有些系统上称之为systemd
b、不同的是我们在不同的发行版上通过pstree命令查看所看到的进程树的顶级进程对不同的系统版本来讲有可能是不一样的。CentOS5和6上看到的有可能是init,CentOS7上看到的有可能是systemd。
c、pstree命令
display a tree of processes
[root@node1 ~]# pstree systemd─┬─NetworkManager───2*[{NetworkManager}] ├─VGAuthService ├─abrt-watch-log ├─abrtd ├─agetty ├─atd ├─auditd───{auditd} ├─crond ├─dbus-daemon ├─irqbalance ├─lsmd ├─lvmetad ├─master─┬─pickup │ └─qmgr ├─polkitd───5*[{polkitd}] ├─rngd ├─rsyslogd───2*[{rsyslogd}] ├─smartd ├─sshd─┬─sshd───bash │ └─sshd───bash───pstree ├─systemd-journal ├─systemd-logind ├─systemd-udevd ├─tuned───4*[{tuned}] └─vmtoolsd───{vmtoolsd}
2、ps命令:report a snapshot of the current processes.(取出并显示当前系统上所运行的这一刻所有进程状态)
a、ps命令是怎么能够查看进程状态的呢?我们说过所有进程的管理都是由内核进行的,内核为了能够让用户空间可以查看他所管理到的进程的相关功能,其实内核是通过一个接口/proc/将其内部的很多状态信息输出给用户。
(1)、/proc/:而这个状态信息就算内核参数,内核参数有两类:
1)、一类是可设置参数,可设置其值从而调整内核运行特性的参数;这些可设置的参数都在/proc/sys/目录下,但是/proc/sys/目录下不是所有都可以设置,我们只有查看拥有写权限的才可以设置。
2)、第二类叫状态参数,也可以称之为状态变量,因为我们不可以修改他,其用于输出内核中的统计信息或状态信息,因此只能用于查看来获取内核状态的目的。而这些可设置的参数
3)、为了我们Linux一切皆文件的哲学思想,我们参数也被模拟成了文件系统类型,也就意味着你的对应的参数路径,非参数本身被模拟成目录,而参数本身被模拟成文件
4)、每一个进程在/proc/目录下都有一个进程命名的参数,/proc目录下有很多数字命名的目录,这个数字就是进程号,也就是PID,因此任何一个PID或者说进程他都会在/proc目录下有一个与其进程号同名的目录,这个目录中存放了当前进程存放的所有的信息。我们的1号进程指的就是我们的init进程,他是我们所有进程的父进程。我们可以查看/proc/1这个文件夹下,我们可以发现这个文件夹下有很多文件,其实每个文件都是一个内核参数,这个内核参数就是用来保存当前这个进程的状态的。
[root@node1 proc]# ls /proc/1 attr cgroup comm cwd fd io map_files mountinfo net oom_adj pagemap root sessionid stack status timers autogroup clear_refs coredump_filter environ fdinfo limits maps mounts ns oom_score personality sched setgroups stat syscall uid_map auxv cmdline cpuset exe gid_map loginuid mem mountstats numa_maps oom_score_adj projid_map schedstat smaps statm task wchan
比如我们可以看到,我们cmdline就保存了启动这个应用程序的命令到底是谁
[root@node1 proc]# cat /proc/1/cmdline /usr/lib/systemd/systemd--switched-root--system--deserialize21[root@node1 proc]#
再比如说我们mem保存了我们内存的相关信息,这个mem是不允许被查看的,但是我们可以看maps,他保存了我们当前这个进程启动起来以后用到了我们物理内存空间中的从哪个地址开始到哪个地址结束之间的内存空间,在这段内存空间当中存放的是什么数据
[root@node1 proc]# cat /proc/1/maps 560df4234000(开始地址)-560df437e000(结束地址) r-xp 00000000 fd:00 421382 /usr/lib/systemd/systemd(存放的文件) ...
b、因此ps就是查看我们内核所输出的每一个进程的相关状态的相关参数的数据抽取出来以后进行显示的
c、命令使用格式
ps [options]
ps 命令选项有三种风格:在UNIX格式输出时必须带 - ,在BSD格式输出时必须不带 - ,在GNU 格式输出时需要用 -- 来引导,也就是长格式形式来引导
d、ps选项
(1)、启动进程的方式:
系统启动过程中自动启动:与终端无关的进程
用户通过终端启动:与终端相关的进程,通过ps a可以查看(ps a是BSD风格的查看方式,ps -a 是UNIX风格的查看方式)
[root@node1 ~]# ps a PID TTY STAT TIME COMMAND 738 tty1 Ss+ 0:00 /sbin/agetty --noclear tty1 linux 5994 pts/0 Ss 0:00 -bash 6034 pts/0 R+ 0:00 ps a
[root@node1 ~]# ps -a PID TTY TIME CMD 6035 pts/0 00:00:00 ps
PID:进程号
TTY:终端
STAT:进程状态
TIME:累计占用cpu的时间
COMMAND:表示命令启动的进程,带中括号的表示是内核的线程,我们通过pstree查看到的基本都是启动的进程而不是内核线程
(2)、相应选项
常用组合之一:aux
1)、a:所有与终端相关的进程
2)、x:所有与终端无关的进程
3)、查看所有进程可使用ax,与终端无关的在TTY处会显示一个?,表示不知道是什么,即与终端无关
4)、u:表示以用户为中心来组织进程状态信息显示
[root@node1 ~]# ps -aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.0 0.1 125352 3900 ? Ss Mar11 0:03 /usr/lib/systemd/systemd --switched-root --system --deserialize 21 root 2 0.0 0.0 0 0 ? S Mar11 0:00 [kthreadd] root 3 0.0 0.0 0 0 ? S Mar11 0:01 [ksoftirqd/0] root 5 0.0 0.0 0 0 ? S< Mar11 0:00 [kworker/0:0H]
USER:用户
PID:进程号
%CPU:累积CPU的使用时间
%MEM:内存空间占用比率
VSZ:占用的虚拟内存集,即占用的虚拟内存大小,就是前面所说到的线性地址空间
RSS:常驻内存集(Resident Size),即不能用来交换的内存。
STAT:状态
R:running,运行态
S:Interruptable sleeping,可中断睡眠
D:uninterruptable sleeping,不可中断睡眠
T:Stopped,停止态
Z:zombie,僵死态
+:前台进程,即运行在终端之上的,并且占据着你的命令提示符
l(L的小写):多线程进程
N:低优先级进程
<:高优先级进程
s:session leader,会话主导者,意思是我们在终端启动一个bash程序,这个bash程序启动好几级进程,这个bash就是整个会话领导者,我们 把它一干掉他的所有的子子孙孙就都被干掉了
常用组合之二: -ef
5)、-e:显示所有进程,相当于aux,但是这是UNIX风格的
6)、-f:显示完整格式的进程信息
[root@node1 ~]# ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 Mar11 ? 00:00:03 /usr/lib/systemd/systemd --switched-root --system --deserialize 21 root 2 0 0 Mar11 ? 00:00:00 [kthreadd] root 3 2 0 Mar11 ? 00:00:01 [ksoftirqd/0]
UID:用户
PID:进程号
PPID:父进程的进程号,我们可以发现init的父进程是0,虽然这个0进程看不到,但是其实0进程是存在的,在内核启动init进程之前是会启动0号进程的,但是一旦init进程启动起来以后0号进程就被终止了,他一般而言是idle进程,所以0号进程不是不存在,他只是一个过渡
C:CPU的运行百分比
STIME:启动时间
TTY:与其相关的终端
TIME:累计运行时间
CMD:启动此进程的命令
常用组合之三:-eFH
7)、-F:完全显示完整格式的进程信息
C:cpu utillzation CPU利用率
PSR:运行于那颗CPU之上
8)、-H:以层级结构显示进程的相关信息
[root@node1 ~]# ps -eFH UID PID PPID C SZ RSS PSR STIME TTY TIME CMD root 2 0 0 0 0 0 Mar11 ? 00:00:00 [kthreadd] root 3 2 0 0 0 0 Mar11 ? 00:00:01 [ksoftirqd/0] root 5 2 0 0 0 0 Mar11 ? 00:00:00 [kworker/0:0H] ...
常用组合之四: -eo,axo
9)、o field1,fleld2:自定义要显示的字段,以逗号分隔
常用的field:pid,ni(nice值),prl(优先级),psr(运行于哪个CPU),pcpu(CPU的利用率),stat(状态),comm(由哪个程序启动),ppid(父进程的进程号),tty(与哪个终端相关)
[root@node1 ~]# ps -axo pid,command PID COMMAND 1 /usr/lib/systemd/systemd --switched-root --system --deserialize 21 2 [kthreadd] ...
3、pgrep,pkill命令
pgrep, pkill - look up or signal processes based on name and other attributes(根据进程名或其它属性来查询进程或给进程发信号)
a、pgrep使用格式:pgrep [options] pattern
b、pgrep常用选项
(1)、-u uid:effective user。指定用户的进程,有效的用户,谁的用户运行
(2)、-U uid:read user。谁启动的进程。
指定postfix用户运行的进程
[root@node1 ~]# pgrep -U postfix 1081 6251
(3)、-t TERMINAL:与指定的终端相关的进程
(4)、-l:显示进程名
[root@node1 ~]# pgrep -U postfix -l 1081 qmgr 6251 pickup
(5)、-a 显示完整格式进程名
[root@node1 ~]# pgrep -U postfix -a 1081 qmgr -l -t unix -u 6251 pickup -l -t unix -u
(6)、-P pid:显示此进程的子进程
[root@node1 ~]# ps -axu|grep ssh root 975 0.0 0.2 106000 4124 ? Ss Mar11 0:00 /usr/sbin/sshd -D root 5992 0.0 0.2 150404 5420 ? Ss 04:47 0:00 sshd: root@pts/0 root 6258 0.0 0.2 150404 5416 ? Ss 08:55 0:00 sshd: root@pts/1 [root@node1 ~]# pgrep -P 975 -a 5992 sshd: root@pts/0 6258 sshd: root@pts/1
4、pidof命令:取指定进程的进程号,即根据进程名获取pid,有些进程可能不止一个因此我们取到的pid也不止一个
[root@node1 ~]# pidof sshd 6258 5992 975 [root@node1 ~]# ps -aux|grep sshd root 975 0.0 0.2 106000 4124 ? Ss Mar11 0:00 /usr/sbin/sshd -D root 5992 0.0 0.2 150404 5420 ? Ss 04:47 0:00 sshd: root@pts/0 root 6258 0.0 0.2 150404 5416 ? Ss 08:55 0:00 sshd: root@pts/1 root 6447 0.0 0.0 112660 968 pts/1 S+ 09:22 0:00 grep --color=auto sshd
5、top命令:他有点类似于windows中的任务管理器,可以以动态查看的方式不断刷新来查看当前系统上的进程信息
a、相应解释
[root@node1 ~]# top top - 09:31:25 up 1 day, 16:38, 2 users, load average: 0.00, 0.01, 0.05 Tasks: 111 total, 1 running, 110 sleeping, 0 stopped, 0 zombie %Cpu(s): 0.2 us, 0.0 sy, 0.0 ni, 99.8 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem : 2031912 total, 1354988 free, 238400 used, 438524 buff/cache KiB Swap: 2097148 total, 2097148 free, 0 used. 1529380 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 720 root 20 0 305096 6160 4796 S 0.3 0.3 3:24.77 vmtoolsd 5988 root 20 0 0 0 0 S 0.3 0.0 0:17.63 kworker/0:1 6448 root 20 0 157712 2172 1508 R 0.3 0.1 0:00.31 top 1 root 20 0 125352 3900 2496 S 0.0 0.2 0:03.66 systemd
第一行(相当于uptime命令,可以敲l打开或关闭显示):
09:31:25:当前系统时间
1 day:运行时长
2 users:登陆到当前系统上的用户数
load average: 0.00, 0.01, 0.05:过去一分钟,五分钟和十五分钟的平均队列长度。注意不是CPU的平均负载,而是平均在CPU上等待运行的进程的队列长度,如果一个CPU上等待运行的进程的队列很长意味着需要等待运行的进程太多,这个队列越长意味着负载越大,而且当队列超出三个的时候,如果长时间超出三个的话意味着CPU应付不了当前的负载需要了,当然,如果你有n颗CPU就另行计算了,通常来说,队列长度的总数量不能大于CPU的数量
上面这几个信息和命令uptime命令显示的信息是一样的。
uptime:显示系统时间,运行时长及平均负载
[root@node1 ~]# uptime 10:00:05 up 1 day, 17:07, 2 users, load average: 0.00, 0.01, 0.05
第二行(第二和第三行可使用t命令进行打开或关闭):
Tasks:任务数量
111 total, 1 running, 110 sleeping, 0 stopped, 0 zombie:一共111个任务,1个运行状态的,110个睡眠状态的,0个停止状态的,0个僵死状态的
第三行:
%CPU(s):CPU占用百分比
0.2 us:即用户空间的进程所占据CPU的百分比为0.2%
0.0 sy:即内核空间的内核占据CPU使用的百分比
0.0 ni:用于nice值调整以后nice调整额外占据CPU的时间
99.8 id:表示空闲cpu百分比
0.0 wa:等待IO完成所消耗的时间,如果这个时间很大则意味着你的IO系统存在性能瓶颈
0.0 hi:处理硬件中断所消耗的CPU百分比
0.0 si:软件中断所消耗的CPU百分比
0.0 st:被偷走的百分比,我们机器上面可以运行虚拟机软件,运行虚拟机软件以后他的CPU就会被CPU偷走
第四行和第五行(可以使用m命令开启或关闭):
KiB Mem : 2031912 total, 1354988 free, 238400 used, 438524 buff/cache(以KB为单位显示物理内存大小,分别是总空间,空闲空间,已经使用的空间,buff/cache表示用于缓冲和缓存的内存空间)
注意,用于缓冲和缓存的内存空间他们是可以被回收回来直接使用的。所以这一段不算真的占用,因此我们真正的free空间应该是 free+buff/cache的空间
KiB Swap: 2097148 total, 2097148 free, 0 used. 1529380 avail Mem(表示以KB为单位显示交换内存的信息,分别是总内存大小,空闲内存大小,已经使用的内存大小。后面的avail Mem应该归纳到第四行去,表示有效内存空间,也就是大概 free + buff/cache的值)
第六行:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND(进程号,用户,优先级,NICE值,虚拟内存集,常驻内存集,共享内存空间,当前状态,占据CPU百分比,占据内存百分比,运行时长,启动命令)
b、相应的排序交互式命令。
M:根据内存占用百分比排序
P:根据CPU占用百分比排序
T:累积占用CPU时间排序
1:分散显示每一颗CPU,再按1又可以统一显示
c、相应操作
q:退出命令
s:我们可以修改相应的刷新时间,默认是3秒刷新一次,敲s后会显示Change delay from 3.0 to 信息,在后面设置相应的需要刷新的时长即可
[root@node1 ~]# top top - 10:53:44 up 1 day, 18:00, 1 user, load average: 0.00, 0.01, 0.05 Tasks: 108 total, 1 running, 107 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 : 2031912 total, 1359072 free, 234376 used, 438464 buff/cache KiB Swap: 2097148 total, 2097148 free, 0 used. 1533532 avail Mem Change delay from 3.0 to PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
k:如果我们要终止某个进程,我们输入k键,然后输入进程号敲回车即可,接下来会让你输入相应的信号,默认为15,选择默认15即可,然后再enter就可以了
d、启动常用选项
-d #:指定刷新时间间隔,比如设置为1秒
-b:以批次方式显示
-n #:显示多少批次
因此我们用top只显示一批我们可以这样来玩:
[root@node1 ~]# top -b -n 1
...