Linux Shell之监测程序

监测程序

一、探查进程

  当程序运行在系统上时,我们称之为进程(process)。想要监测这些进程,需要熟悉ps命令的用法。ps命令好比工具中的瑞士军刀,它能输出运行在系统上的所有程序的许多信息。

  但是随着ps命令的稳健而来的还有复杂性--有数不清的参数,这或许让ps命令成了最难掌握的命令。大多数系统管理员在掌握了能提供他们需要信息的一组参数后,就一直坚持只使用这组参数。

  默认情况下,ps命令并不会提供那么多的信息:

1 xiaoyu@ubuntu:~$ ps
2    PID TTY          TIME CMD
3   2051 pts/18   00:00:00 bash
4   2162 pts/18   00:00:00 ps
5 xiaoyu@ubuntu:~$

  默认情况下,ps命令只会显示运行在当前控制台下的属于当前用户的进程,在此例中,我们只运行了bash shell(shell也只是运行在系统上的另一个程序而已)以及ps命令本身。

  上例中的基本输出显示了程序的进程ID(Process ID, PID)、它们运行在哪个终端(TTY)以及进程已用的CPU时间。

   Linux系统中使用的GNU ps命令支持3种不同类型的命令行参数:

  •   Unix风格的参数,前面加单破折线;
  •   BSD风格的参数,前面不加破折线;
  •   GNU风格的长参数,前面加双破折线。

   1、Unix风格的参数  

  Unix风格的参数是从贝尔实验室开发的AT&T Unix系统上原有的ps命令继承下来的,这些参数如下表所示

参数 m描述
-A 
显示所有进程
-N
显示与指定参数不符的所有进程
-a 显示除控制进程(session leader)和无终端进程外的所有进程
-d 显示除控制进程外的所有进程
-e 显示所有进程
-C cmdlist 显示包含在cmdlist列表中的进程
-G grplist 显示组ID在grplist列表中的进程
-U userlist 显示属主的用户ID在userlist列表中的进程
-g grplist 显示会话或组ID在grplist列表中的进程
-p pidlist 显示PID在pidlist列表中的进程
-s sesslist 显示会话ID在sesslist列表中的进程
-t ttylist 显示终端ID在ttylist列表中的进程
-u userlist 显示有效用户ID在userlist列表中的进程
-F 显示更多额外输出(相对-f参数而言)
 -O format  显示默认的输出列以及format列表指定的特定列
-M  显示进程的安全信息
-c  显示进程的额外调度器信息
-f  显示完整格式的输出
-j   显示任务信息
-l   显示长列表
 -o format  仅显示由format指定的列
 -y  不要显示进程标记(process flag,表明进程状态的标记)
 -Z  显示安全标签(security context)①信息
 -H  用层级格式来显示进程(树状,用来显示父进程)
 -n namelist  定义了WCHAN列显示的值
 -w 采用宽输出模式,不限宽度显示
-L   显示进程中的线程 
-V  显示ps命令的版本号

 上面给出的参数已经很多了,不过还有很多。使用ps命令的关键不在于记住所有可用的参数,而在于记住最有用的那些参数。大多数Linux系统管理员都有自己的一组参数,他们会牢牢记住这些用来提取有用的进程信息的参数。举个例子,如果你想查看系统上运行的所有进程,可用-ef参数组合(ps命令允许你像这样把参数组合在一起)。

 1 xiaoyu@ubuntu:~$ ps -ef
 2 UID         PID   PPID  C STIME TTY          TIME CMD
 3 root          1      0  0 05:25 ?        00:00:02 /sbin/init auto noprompt
 4 root          2      0  0 05:25 ?        00:00:00 [kthreadd]
 5 root          4      2  0 05:25 ?        00:00:00 [kworker/0:0H]
 6 root          6      2  0 05:25 ?        00:00:00 [mm_percpu_wq]
 7 root          7      2  0 05:25 ?        00:00:00 [ksoftirqd/0]
 8 root          8      2  0 05:25 ?        00:00:00 [rcu_sched]
 9 root          9      2  0 05:25 ?        00:00:00 [rcu_bh]
10 root         10      2  0 05:25 ?        00:00:00 [migration/0]
11 root         11      2  0 05:25 ?        00:00:00 [watchdog/0]
12 root         12      2  0 05:25 ?        00:00:00 [cpuhp/0]

   截取一段,Linux系统上运行着很多进程。这个例子用了两个参数:-e参数指定显示所有运行在系统上的进程;-f参数则扩展了输出,这些扩展的列包含了有用的信息。

  •   UID:启动这些进程的用户。
  •   PID:进程的进程ID。
  •   PPID:父进程的进程号(如果该进程是由另一个进程启动的)。
  •   C:进程生命周期中的CPU利用率。
  •   STIME:进程启动时的系统时间。
  •   TTY:进程启动时的终端设备。
  •   TIME:运行进程需要的累计CPU时间。
  •   CMD:启动的程序名称。

   上例子中输出了合理数量的信息,这也正是大多数系统管理员希望看到的。如果想要获得更多的信息,可采用-l参数,他会产生一个长格式输出。

1 xiaoyu@ubuntu:~$ ps -l
2 F S   UID    PID   PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
3 0 S  1000   2051   2045  0  80   0 -  7373 wait   pts/18   00:00:00 bash
4 0 R  1000   2249   2051  0  80   0 -  8996 -      pts/18   00:00:00 ps
5 xiaoyu@ubuntu:~$ 

  注意使用了-l参数之后多出的那些列。

  •   F:内核分配给进程的系统标记。
  •   S:进程的状态(O代表正在运行;S代表在休眠;R代表可运行,正等待运行;Z代表僵化--僵尸进程,进程已结束但父进程已不存在;T代表停止)。
  •   PRI:进程的优先级(越大的数字代表越低的优先级)。
  •   NI:谦让度值用来参与决定优先级。
  •   ADDR:进程的内存地址。
  •   SZ:假如进程被换出,所需交换空间的大致大小。
  •   WCHAN:进程休眠的内核函数的地址。

   2、BSD风格的参数

   了解了Unix风格的参数之后,我们来一起看一下BSD风格的参数。伯克利软件发行版(Berkeley software distribution,BSD)是加州大学伯克利分校开发的一个Unix版本。它和AT&TUnix系统有许多细小的不同,这也导致了多年的Unix争论。BSD版的ps命令参数如下表所示。
参数 描述
T 显示跟当前终端关联的所有进程
a 显示跟任意终端关联的所有进程
g 显示所有的进程,包括控制进程
r 仅显示运行中的进程
x 显示所有的进程,甚至包括未分配任何终端的进程
U userlist 显示归userlist列表中某用户ID所有的进程
p pidlist 显示PID在pidlist列表中的进程
t ttylist 显示所关联的终端在ttylist列表中的进程
O format 除了默认输出的列之外,还输出由format指定的列
X 按过去的Linux i386寄存器格式显示
Z 将安全信息添加到输出中
j 显示任务信息
l 采用长模式
o format 仅显示由format指定的列
s 采用信号格式显示
u 采用基于用户的格式显示
v 采用虚拟内存格式显示
N namelist 定义在WCHAN列中使用的值
O order 定义显示信息列的顺序
S 将数值信息从子进程加到父进程上,比如CPU和内存的使用情况
c 显示真实的命令名称(用以启动进程的程序名称)
e 显示命令使用的环境变量
f 用分层格式来显示进程,表明哪些进程启动了哪些进程
h 不显示头信息
k sort 指定用以将输出排序的列
n 和WCHAN信息一起显示出来,用数值来表示用户ID和组ID 
w 为较宽屏幕显示宽输出
H 将线程按进程来显示
m 在进程后显示线程
L 列出所有格式指定符
V  显示ps命令的版本号

  如你所见,Unix和BSD类型的参数有很多重叠的地方。使用其中某种类型参数得到的信息也同样可以使用另一种获得。大多数情况下,你只要选择自己所喜欢格式的参数类型就行了(比如你在使用Linux之前就已经习惯BSD环境了)。在使用BSD参数时,ps命令会自动改变输出以模仿BSD格式。下例是使用l参数的输出:

1 xiaoyu@ubuntu:~$ ps l
2 F   UID    PID   PPID PRI  NI    VSZ   RSS WCHAN  STAT TTY        TIME COMMAND
3 0  1000   2051   2045  20   0  29492  4936 wait   Ss   pts/18     0:00 bash
4 0  1000   2354   2051  20   0  35984  1496 -      R+   pts/18     0:00 ps l
5 xiaoyu@ubuntu:~$ 

  注意,其中大部分的输出列跟使用Unix风格参数时的输出是一样的,只有一小部分不同。

  •   VSZ:进程在内存中的大小,以千字节(KB)为单位。
  •   RSS:进程在未换出时占用的物理内存。
  •   STAT:代表当前进程状态的双字符状态码。

  许多系统管理员都喜欢BSD风格的l参数。它能输出更详细的进程状态码(STAT列)。双字符状态码能比Unix风格输出的单字符状态码更清楚地表示进程的当前状态。
  第一个字符采用了和Unix风格S列相同的值,表明进程是在休眠、运行还是等待。第二个参数进一步说明进程的状态。

  •   <:该进程运行在高优先级上。
  •   N:该进程运行在低优先级上。
  •   L:该进程有页面锁定在内存中。
  •   s:该进程是控制进程。
  •   l:该进程是多线程的。
  •   +:该进程运行在前台。

  从前面的例子可以看出,bash命令处于休眠状态,但同时它也是一个控制进程(在我的会话中,它是主要进程),而ps命令则运行在系统的前台。

   3、GNU长参数

  最后,GNU开发人员在这个新改进过的ps命令中加入了另外一些参数。其中一些GNU长参数复制了现有的Unix或BSD类型的参数,而另一些则提供了新功能。下表列出了现有的GNU长参数。

参数 描述
--deselect 显示所有进程,命令行中列出的进程
--Group grplist 显示组ID在grplist列表中的进程
--User userlist 显示用户ID在userlist列表中的进程
--group grplist 显示有效组ID在grplist列表中的进程
--pid pidlist 显示PID在pidlist列表中的进程
--ppid pidlist 显示父PID在pidlist列表中的进程
--sid sidlist 显示会话ID在sidlist列表中的进程
--tty ttylist 显示终端设备号在ttylist列表中的进程
--user userlist 显示有效用户ID在userlist列表中的进程
--format format 仅显示由format指定的列
--context 显示额外的安全信息
--cols n 将屏幕宽度设置为n列
--columns n 将屏幕宽度设置为n列
--cumulative 包含已停止的子进程的信息
--forest 用层级结构显示出进程和父进程之间的关系
--headers 在每页输出中都显示列的头
--no-headers 不显示列的头
--lines n 将屏幕高度设为n行
--rows n 将屏幕高度设为n排
--sort order 指定将输出按哪列排序
--width n 将屏幕宽度设为n列
--help 显示帮助信息
--info 显示调试信息
--version 示ps命令的版本号
   可以将GNU长参数和Unix或BSD风格的参数混用来定制输出。GNU长参数中一个着实让人喜爱的功能就是--forest参数。它会显示进程的层级信息,并用ASCII字符绘出可爱的图表。
1 xiaoyu@ubuntu:~$ ps --forest
2    PID TTY          TIME CMD
3   2051 pts/18   00:00:00 bash
4  43622 pts/18   00:00:00  \_ ps
5 xiaoyu@ubuntu:~$

 二、实时监测进程

   ps命令虽然在收集运行在系统上的进程信息时非常有用,但也有不足之处:它只能显示某个特定时间点的信息。如果想观察那些频繁换进换出的内存的进程趋势,用ps命令就不方便了。

   而top命令刚好适用这种情况。top命令跟ps命令相似,能够显示进程信息,但它是实时显示的,下图是top命令运行时输出的截图

 

   输出的第一部分显示的是系统的概况:第一行显示了当前时间、系统的运行时间、登录的用户数以及系统的平均负载。
  平均负载有3个值:最近1分钟的、最近5分钟的和最近15分钟的平均负载。值越大说明系统的负载越高。由于进程短期的突发性活动,出现最近1分钟的高负载值也很常见,但如果近15分钟内的平均负载都很高,就说明系统可能有问题。 
   说明   Linux系统管理的要点在于定义究竟到什么程度才算是高负载。这个值取决于系统的硬件配置以及系统上通常运行的程序。对某个系统来说是高负载的值可能对另一系统来说就是正常值。通常,如果系统的负载值超过了2,就说明系统比较繁忙了。

  第二行显示了进程概要信息——top命令的输出中将进程叫作任务(task):有多少进程处在运行、休眠、停止或是僵化状态(僵化状态是指进程完成了,但父进程没有响应)。

   下一行显示了CPU的概要信息。top根据进程的属主(用户还是系统)和进程的状态(运行、空闲还是等待)将CPU利用率分成几类输出。

   紧跟其后的两行说明了系统内存的状态。第一行说的是系统的物理内存:总共有多少内存,当前用了多少,还有多少空闲。后一行说的是同样的信息,不过是针对系统交换空间(如果分配了的话)的状态而言的。
   最后一部分显示了当前运行中的进程的详细列表,有些列跟ps命令的输出类似。
  •   PID:进程的ID。
  •   USER:进程属主的名字。
  •   PR:进程的优先级。
  •   NI:进程的谦让度值。
  •   VIRT:进程占用的虚拟内存总量。
  •   RES:进程占用的物理内存总量。
  •   SHR:进程和其他进程共享的内存总量。
  •   S:进程的状态(D代表可中断的休眠状态,R代表在运行状态,S代表休眠状态,T代表跟踪状态或停止状态,Z代表僵化状态)。
  •   %CPU:进程使用的CPU时间比例。
  •   %MEM:进程使用的内存占可用内存的比例。
  •   TIME+:自进程启动到目前为止的CPU时间总量。
  •   COMMAND:进程所对应的命令行名称,也就是启动的程序名。
   默认情况下,top命令在启动时会按照%CPU值对进程排序。可以在top运行时使用多种交互命令重新排序。每个交互式命令都是单字符,在top命令运行时键入可改变top的行为。键入f允许你选择对输出进行排序的字段,键入d允许你修改轮询间隔。键入q可以退出top。用户在top命令的输出上有很大的控制权。用这个工具就能经常找出占用系统大部分资源的罪魁祸首。当然了,一旦找到,下一步就是结束这些进程。

 三、结束进程

  作为系统管理员,很重要的一个技能就是知道何时以及如何结束一个进程。有时进程挂起了,只需要动动手让进程重新运行或结束就行了。但有时,有的进程会耗尽CPU且不释放资源。在这两种情景下,你就需要能控制进程的命令。Linux沿用了Unix进行进程间通信的方法。

  在Linux中,进程之间通过信号来通信。进程的信号就是预定义好的一个消息,进程能识别它并决定忽略还是作出反应。进程如何处理信号是由开发人员通过编程来决定的。大多数编写完善的程序都能接收和处理标准Unix进程信号。这些信号都列在了下表中。

信号 名称 描述
1 HUP 挂机
2 INT 中断
3 QUIT 结束运行
9 KILL 无条件终止
11 SEGV 段错误
15 TERM 尽可能终止
17 STOP 无条件停止运行,但不终止
18 TSTP 停止或暂停,但继续在后台运行
19 CONT 在STOP或TSTP之后恢复执行

   在Linux中有两个命令可以向运行中的进程发出进程信号。

  1、kill命令

  kill命令可通过进程ID(PID)给进程发信号。默认情况下,kill命令会向命令行中列出的全部PID发送一个TERM信号,遗憾的是,你只能用进程的PID而不能用命令名,所以kill命令有时并不好用。

  要发送进程信号,你必须是进程的属主或登陆为root用户。

1 xiaoyu@ubuntu:~$ kill 6447
2 bash: kill: (6447) - Operation not permitted
3 xiaoyu@ubuntu:~$ 

   TERM信号告诉进程可能的话就停止运行。不过,如果有不服管教的进程,那它通常会忽略这个请求。如果要强制终止,-s参数支持制定其他信号(用信号名或信号值)。

  从下例中看出,kill命令不会有任何输出。

1 xiaoyu@ubuntu:~$ kill 2120
2 xiaoyu@ubuntu:~$ 

   要检查kill命令是否有效,可再运行ps或top命令,看看问题进程是否已停止。

  2、killall命令

   killall命令非常强大,它支持通过进程名而不是PID来结束进程。killall命令也支持通配符,这在系统因负载过大而变得很慢时很有用。

1 xiaoyu@ubuntu:~$ killall http*
2 http*: no process found
3 xiaoyu@ubuntu:~$ 

   嗯,我这台机器没有启动任何http的进程,不过这个命令大家是可以尝试使用的

   警告   以root用户身份登录系统时,使用killall命令要特别小心,因为很容易就会误用通配符而结束了重要的系统进程。这可能会破坏文件系统。

猜你喜欢

转载自www.cnblogs.com/Reverse-xiaoyu/p/12070813.html