Unix/Linux 系统自动化管理: 进程管理篇





Unix/Linux 系统自动化管理: 进程管理篇

    本文是 Unix/Linux 系统管理自动化系列中的一篇,主要讲述如何实现自动化监控进程状态和性能并及时通知系统管理员。

进程监控是 Unix/Linux 系统管理中一个非常重要的组成部分。它可以监控进程状态、进程的 CPU 利用率等信息,并且可以在发现进程出现异常情况的时候,发送告警信息给系统管理员或者做出指定的反应。我们可以使用系统进程监控信息进行合理的进程调度从而优化系统性能,或者根据这些信息调整系统的行为。

不同的操作系统监控进程的命令可能略有不同。本文将介绍 Unix/Linux 操作系统进程管理命令及相关信息,并论述 Unix/Linux 操作系统上进程监控的自动化脚本实现。

Unix/Linux 进程管理相关命令介绍

进程是操作系统用于控制系统资源使用的实体。Unix/Linux 进程管理相关的命令主要有以下几个,在后面的脚本实现中会用到部分命令。

显示进程属性命令

ps 命令:该命令是最基本同时也是非常强大的进程查看命令,用于报告进程标识、用户、CPU 时间消耗以及其他属性。利用它可以确定有哪些进程正在运行及运行的状态、进程是否结束、进程有没有僵死、哪些进程占用了过多的资源等。ps 命令可以监控后台进程的工作情况,因为后台进程是不和屏幕键盘这些标准输入 / 输出设备进行通信的,如果需要检测其情况,可以使用 ps 命令。

单独使用 ps 命令所看到的进程列表,都是在前台执行的进程,但并非所有进程都在前台执行,也有不少进程隐藏在后台执行。使用命令 ps -e 可以显示所有进程。

进程性能检测命令

top 命令:Linux 使用 top 命令来显示 CPU 占用率为前几位的进程。该命令可以按 CPU 使用率、内存使用率、执行时间对任务进行排序,而且该命令的很多特性都可以通过交互式命令或者在个人定制文件中进行设定。top 主要字段的含义如下:

表 1. top 字段含义
列名 含义
PID 进程 ID
USER 进程所有者的用户名
PR 任务优先级
NI nice 值。数值越小表示优先级越高,数值越大表示优先级越低
VIRT 进程使用的虚拟内存总量,单位:kb。VIRT=SWAP+RES
RES 进程使用的、未被换出的物理内存大小,单位:kb。RES=CODE+DATA
SHR 共享内存大小,单位:kb
S 进程状态。
D= 不可中断的睡眠状态
R= 运行
S= 睡眠
T= 跟踪 / 停止
Z= 僵尸进程
%CPU 上次更新到现在的 CPU 时间占用百分比
TIME+ 进程使用的 CPU 时间总计,精确到 1/100 秒
COMMAND 命令名 / 命令行

topas 命令:AIX 使用 topas 命令在字符终端上报告有关本地系统上的活动的至关重要的统计信息,包括显示 CPU 占用率为前几位的进程。topas 命令以缺省的两秒间隔从系统中提取并显示统计信息。通过命令 topas -P 可以进入 topas 的 process 子部分,显示活动进程的列表。各进程将按它们在监视间隔期间的 CPU 使用率进行排序。topas 针对每个进程所显示的字段含义如下:

表 2. topas 字段含义
列名 含义
Name 在该进程中执行的可执行程序的名称。此名称将剥离任何路径
名称和参数信息,并将长度截断为 9 个字符。
Process ID 进程 ID
% CPU Utilization 该进程在监视间隔期间的平均 CPU 利用率。在第一次显示某个进
程时,此值是该进程在生存期中的平均 CPU 利用率。
Paging Space Used 分配给该进程的分页空间大小。可将这视为该进程的内存占用空间
大小,但是不包括用于保存可执行程序及其依赖的任何共享库的内存。
Process Owner 拥有该进程的用户的用户名

控制进程争用 CPU 的优先级级别的命令

nice 命令:nice 命令允许您以比命令的正常优先级更低的优先级运行命令。

语法:nice [  - Increment|  -n Increment ] Command [ Argument ... ]

如果您没有指定 Increment 值,nice 命令缺省为递增值 10。您必须有 root 用户权限以在更高的优先级运行命令。进程的优先级通常被称作它的 nice 值。Linux 操作系统的 nice 值范围是 -20 到 19,19 是最低优先级。AIX 操作系统 nice 值的范围是 0 到 39,39 是最低优先级。如果您没有适当的权限就试图增加命令的优先级,nice 命令不会返回错误消息。相反,命令的优先级不会更改,并且系统以它通常的优先级启动命令。

renice 命令:renice 命令改变系统中已经在运行的一个或多个进程的 nice 值,因此改变了优先级。进程可由进程标识、进程组标识或拥有该进程的用户名识别。如果不具有 root 用户权限,则仅可以重新设置自己拥有的进程的优先级。

终止进程的命令

kill 命令:kill 命令发送一个信号(缺省,SIGTERM 信号)到一个正运行的程序。缺省操作一般是停止进程。root 用户可用 kill 命令来停止任何进程。如果不是 root 用户,必须已经启动了要停止的进程。

进程定时启动命令 crontab

为了定期执行命令,可以利用 crontab 定义命令执行的间隔和顺序。crontab 命令用于提交、编辑、列出或删除 cron 作业。一个 cron 作业是一个命令,其运行是由 cron 守护程序在规则的调度间隔执行的。要编辑提交一个 cron 作业,可以使用 crontab -e 命令。crontab -e 命令调用一个编辑会话,允许创建一个 crontab 文件。crontab 文件中的条目必须是一种 cron 守护程序可接受的格式。编辑完成后,

RedHat 系统会自动在 /var/spool/cron 下生成一个与此用户同名的文件,此用户的 cron 信息都记录在这个文件中。

SUSE 系统会自动在 /var/spool/cron/tabs 下生成一个与此用户同名的文件,此用户的 cron 信息都记录在这个文件中。

AIX 系统会自动在 /var/spool/cron/crontabs 下生成一个与此用户同名的文件,此用户的 cron 信息都记录在这个文件中。

以 RedHat 操作系统为例,cron 服务每分钟不仅要读一次 /var/spool/cron 内的所有文件,还需要读一次 /etc/crontab,因此我们配置这个文件也能运用 cron 服务做一些事情。用 crontab 配置是针对某个用户的,而编辑 /etc/crontab 是针对系统的任务。此文件的文件格式如下:

清单 1. /etc/crontab 文件内容

SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root // 如果出现错误,或者有数据输出,数据作为邮件发给这个帐号
HOME=/  // 使用者运行的路径
# run-parts
01 * * * * root run-parts /etc/cron.hourly // 每小时执行 /etc/cron.hourly 目录下的脚本
02 4 * * * root run-parts /etc/cron.daily // 每天执行 /etc/cron.daily 目录下的脚本
22 4 * * 0 root run-parts /etc/cron.weekly // 每星期执行 /etc/cron.weekly 目录下的脚本
42 4 1 * * root run-parts /etc/cron.monthly // 每月去执行 /etc/cron.monthly 目录下的脚本


列出用户目前的 crontab 可以使用命令:crontab -l UserName

删除用户目前的 crontab 可以使用命令:crontab -r UserName

一个 crontab 文件包含若干个 cron 作业的条目。每个 crontab 文件条目包括 6 个字段,它们被空格或制表符以以下格式分开:

minute hour day_of_month month weekday command

这些字段接收以下值:

表 3. 字段含义
字段 值
minute 0 到 59
hour 0 到 23
day_of_month 1 到 31
month 1 到 12
weekday 0 到 6(星期日到星期六)
command shell 命令

必须为每个字段指定一个值。除了 command 字段,这些字段可以包含以下内容:

    * 指定范围内的一个数。要在 5 月运行一个命令,在 month 字段指定 5。
    * 两个被破折号分开的数目表明了包含的范围。要从星期二到星期五运行 cron 作业,把 2-5 放到 weekday 字段中。
    * 由逗号隔开的数字列表。要在一月第一天和最后一天的运行命令,在 day_of_month 字段中可指定 1,31。
    * 由两个被破折号分开的数字组成的组合表明了包含的范围,可与由逗号格开的数字列表一起使用。要在一月的第 10 天到第 16 天和最后一天首次运行命令,应该在 day_of_month 字段中指定 1,10-16,31。以上两种也可组合使用。

*(星号),意味着所有的允许值。要每个小时运行一个作业,在小时字段指定一个星号。




Unix/Linux 进程管理自动化实现

在这篇文章里,我们将给出两个比较常见的进程自动化管理示范实例,分别用来进行进程状态自动化管理和进程性能监控自动化管理。用户可以根据自身需求,在这些脚本的基础上进行扩展,实现更加复杂的管理功能。

实现这两个自动化脚本,我们需要三个文件,主要脚本文件,实现进程自动化管理的主要程序;操作定义文件,定义进程名称以及相关信息和指定操作;用户自定义的 action 文件,定义系统采取的一系列操作。具体实现将在下面详细描述。

进程状态管理自动化实现

服务器中的一些服务进程可能不稳定,偶尔会异常终止,因此需要一个监控程序来对这些进程进行监控,当发现被监控的服务进程异常终止时,将其重新启动或者实行一系列操作。

该监控程序的基本实现思路是,编写一个监控脚本,然后在系统的 crontab 中将该脚本配置为定期自动执行(例如可以配置为每 2 分钟执行一次),监控脚本通过监控服务进程的状态来判断服务进程是否已终止,当监控条件成立时,执行指定的命令或者脚本。

本实例的具体实现方法如下:

脚本 CheckProcLive 实现了监控指定进程状态并在发现进程终止时采取指定的响应操作的功能。该脚本在 RedHatEL-Server 5.3、SLES 10 SP2 和 AIX 5.3 操作系统上测试通过,可以正常执行,使用 perl 的版本为 v5.8.8。默认情况下,保存进程名称以及对应操作的操作定义文件为 /root/StartProc,该文件位置也可以通过参数指定。代码如下:

清单 2. /root/CheckProcLive 文件内容

#!/usr/bin/perl
use strict;
my $StartProcFile = $ARGV[0];
if( $StartProcFile eq "" )
{
  $StartProcFile = "/root/StartProc";
}

my %StartProcHash = GetStartProc($StartProcFile);
my %PsHash = &GetPs;

while (my($key,$value) = each %StartProcHash)
{
  if(!defined($PsHash{$key}))
   {
     system "$value";
   }
}

# 获取正在运行的进程命令,并将其存放在一个 Hash 表中,
# 其中 key 为命令名称,值赋了同样的一个数字 1,这个值没有特殊含义和作用
sub GetPs
{
# 获取 ps -e 的第四列,即包含命令的列
my @PsArray = `ps -e |perl -ane 'print "\$F[3]\n"'`;
my %PsHash;
foreach my $cmditem(@PsArray)
  {
    chomp($cmditem);
    $PsHash{$cmditem} = 1;
  }
    return %PsHash;


# 获取参数指定的或者程序默认的操作定义文件的信息,并将其中的信息存入 Hash 表中,其中 key 值是命令名称
#value 是指发现进程终止时进行的相应操作。

sub GetStartProc
{
   my ($file) = @_;
   my $result;
   my %startproctab;

   unless(open(TABF, $file)) {
   print "Can't open file '$file'.\n";
   exit 1;
}

foreach my $line (<TABF>)
{
   chomp($line);
   #print "line = $line";
   if(!($line =~ /^#/) && $line =~ /(\S+),(.+)\s*$/)
   {
     $startproctab{$1} = $2;
   }
}
return %startproctab;
close TABF;
}


清单 2 中用到的操作定义文件是为了可以实现可定制的自动化进程监控,在检测到进程终止的时候进行指定的操作。在这里我们定义了以下一个文件,/root /StartProc,由于第二列采取指定操作和操作系统相关,因此该文件只可用于 Linux 操作系统,用户要在 AIX 系统上使用,可以修改第二列操作的值,使之适用于 AIX 系统即可。

清单 3. /root/StartProc 文件内容

# 各列的含义为:命令或者进程名称,发现进程已经终止采取的指定操作
sshd,service sshd start
dhcpd,service dhcpd start
ftpd,/root/action1


第一列是在 ps -e 中所显示的命令名称,第二列是发现该进程终止之后需要采取的操作。该操作可以是执行一个命令,也可以是执行一个响应脚本。响应脚本可以进行多个操作,例如重新启动进程,并且发送包含提示信息的邮件给管理员。

下面是一个响应脚本的简单实例,仅实现发送邮件给 root 管理员的功能。

清单 4. /root/action1 文件内容

#!/bin/bash
echo "process ftpd is not running now" | mail -s "process status warning!" root


为了实现自动化的监控,我们需要利用系统的 cron 服务。使用命令“crontab -e”编辑 crontab,添加一个条目。

在 Linux 操作系统上添加一条 crontab 条目,表示每隔两分钟运行一次 CheckProcLive 脚本,内容如下所示:

清单 5. Linux crontab 新添加的内容

*/2 * * * * /root/CheckProcLive >> /root/checkproclive.log 2>&1


在 AIX 操作系统上添加一条 crontab 条目,表示每隔两分钟运行一次 CheckProcLive 脚本,内容如下所示:

清单 6. AIX crontab 新添加的内容

0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,
46,48,50,52,54,56,58 * * * * /root/CheckProcLive >> /root/checkproclive.log 2>&1


保存退出之后,可以用“crontab -l”查看,确保任务添加成功。

上面两条 crontab 条目都表示每隔两分钟运行一次 CheckProcLive 脚本,并将其输出存储在 /root/checkproclive.log 文件中。用户可以根据自己的需求修改脚本运行的间隔时间。cron 运行命令时,其命令结果不会显示在屏幕上,而是将输出的结果通过邮件发给管理员,所以为了方便查询命令执行的结果,最好将输出重定向到文件中。以上步骤完成后,就可以实现对进程状态的自动监控了。

下面是在 /root/StartProc 中定义的进程都未启动的情况下监控程序所记录的日志信息。

清单 7. /root/checkproclive.log

Starting SSH daemon done
Starting DHCP server [chroot] done


同时因为 ftpd 服务没有启动,监控程序也执行了 /root/action1 脚本,因此 root 用户的邮箱中会收到一封标题为 process status warning!的预警邮件,如下所示:

清单 8. 预警邮件内容

From root@hv4plus_lpar2.ppd.pok.ibm.com Wed Jun 3 09:00:02 2009
X-Original-To: root
Delivered-To: root@hv4plus_lpar2.ppd.pok.ibm.com
Date: Wed, 03 Jun 2009 09:00:02 -0400
To: root@hv4plus_lpar2.ppd.pok.ibm.com
Subject: process status warning!
User-Agent: nail 11.25 7/29/05
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
From: root@hv4plus_lpar2.ppd.pok.ibm.com (root)

process ftpd is not running now


进程性能监控自动化实现

进程在正常工作过程中,会占用一定的 CPU 和内存资源。如果占用过高的 CPU 和内存资源,则有可能是进程出现异常情况,并且可能会影响其他重要进程的正常运行。因此监控进程性能并在发现异常情况的时候自动做出反应,例如 kill 掉该进程、修改进程优先级或者发送预警信息给管理员,这将会给系统管理工作带来很大的帮助。

脚本 CheckProcPerformance 可以实现对进程性能自动化监控的功能,在发现进程 CPU 或者内存资源超出预定义的阈值时,执行指定的操作。用户还可以根据自己的需求,修改该代码,以实现更加复杂的监控功能。默认的定义阈值的文件是 /root/ProcAction,该文件也可以通过参数指定。该脚本在 RedHatEL-Server 5.3、SLES 10 SP2 操作系统上测试通过,可以正常执行,使用 perl 的版本为 v5.8.8。由于该脚本使用 top 命令获取进程性能信息,因此该脚本只适用于 Linux 操作系统,不适用于 AIX 操作系统。

清单 9. /root/CheckProcPerformance 文件内容

#!/usr/bin/perl
use strict;

my $ProcActionFile = $ARGV[0];
if( $ProcActionFile eq "" )
{
  $ProcActionFile = "/root/ProcAction";
}

# 获取定义阈值文件的信息
my @ProcActionTable = &GetProcAction($ProcActionFile);

# 获取 top 信息,提取 COMMAND,%CPU,%MEM 三列信息
my %TopInfoTable = &GetTopInfo;

foreach my $line(@ProcActionTable)
{
  chomp ($line);
  my @ActionLine=split /,/,$line;
  my $value;
  #$ActionLine[0] 是 Command 名称 ;$value 是 $ActionLine[0] 进程所对应的 CPU% 和
#MEM% 值
  if (defined($TopInfoTable{$ActionLine[0]}))
  {
    $value = $TopInfoTable{$ActionLine[0]};
  }
  else
  {
     next;
  }

#$ActionLine[1] 的值是 CPU 的阈值 ; $ActionLine[2] 的值是内存阈值 ;
#$ActionLine[3] 的值是响应脚本的名称
# 如果 CPU% 或者 MEM% 超出阈值文件所定义的 CPU 或者内存阈值,将执行
#$ActionLine[3] 对应的响应脚本

  if( $ActionLine[1] < $$value[0] || $ActionLine[2] < $$value[1] )
  {
    # 将监控进程的名称,CPU 和内存利用率值作为参数传给响应脚本
    # 使脚本能提供管理员更详细预警信息
    system "$ActionLine[3] $ActionLine[0] $$value[0] $$value[1]";
   }

}

# 获取 top 信息,提取 COMMAND,%CPU,%MEM 三列信息,并以 COMMAND 为 key,#[%CPU,%MEM] 为 value,存入 Hash 表中
sub GetTopInfo
{
my @TopInfo = `top -n 1 | awk {'print \$13\" \"\$10\" \"\$11'}`;

# 去掉 top 命令所显示的系统摘要信息部分
for( my $i=0; $i<7; $i++ )
{
   shift( @TopInfo );
}
my %TopTable;
foreach my $topitem (@TopInfo)
{
   my @pair = split /\s+/,$topitem;
   $TopTable{$pair[0]} = [$pair[1], $pair[2]];
}
return %TopTable;
}

# 获取 ProcAction 信息,将非注释的行存入数组中,
sub GetProcAction
{
   my ($file) = @_;
   unless(open(TABF, $file)) {
   print "Can't open file '$file'.\n";
   exit 1;
}
my @table;
foreach my $line (<TABF>)
{
   chomp($line);
   if(!($line =~ /^#/) )
   {
     push(@table, $line);
   }
}

return @table;
close TABF;
}


为了实现自定义进程性能监控的功能,我们创建一个操作定义文件,该文件定义了要进行监控的进程名称,CPU 和内存的阈值,以及 CPU 和内存利用率超过阈值时采取的操作。这里我们将该文件命名为 /root/ProcAction,该文件适用于 Linux 和 AIX 操作系统。本实例中列出了要进行性能监控的三个进程 init、kthread 以及 migration,其中内容和格式如下所示:

清单 10. /root/ProcAction 文件内容

#command,%cpu,%memory,action
init,20,10,/root/action2
kthread,5,10,/root/action2
migration,15,20,/root/action2
java,10,10,/root/action2


以第一行内容为例,表示我们要监控 init 进程,当该进程的 CPU 利用率达到 20%或者内存利用率达到 10% 的时候,运行脚本 /root/action2 进行响应。

其中 /root/action2 脚本的内容如下所示,用户也可以根据需求进行扩充和改变。

清单 11. /root/action2 文件内容

#!/bin/bash
echo "The Process $1 Consumed too much CPU or Memory Resource:%CPU = $2% %MEM = $3%" |
mail -s "Warning for Process $1" root


在这个脚本里面,我们只做了简单的操作,发送监控进程的名称以及该进程的 CPU 和内存利用率给 root 用户。其中 $1,$2,$3 分别是 监控进程的名称,CPU 利用率和内存利用率的值。

我们的进程性能自动化监控脚本就是要监控 /root/ProcAction 文件中定义的进程,通过 top 获取到要监控的进程当前的 CPU 和内存利用率,然后将其与 /root/ProcAction 中定义的阈值进行比较,如果超出阈值,则发送警告邮件给 root 用户。

为了实现自动化的性能监控,我们利用系统的 cron 服务。使用命令“crontab -e”编辑 crontab,添加一个条目。

在 Linux 操作系统上添加一条 crontab 条目,表示每隔两分钟运行一次 CheckProcPerformance 脚本,内容如下所示:

清单 12. Linux crontab 新添加的内容

*/2 * * * * /root/CheckProcPerformance >> /root/checkprocperformance.log 2>&1


保存退出之后,可以用“crontab -l”查看,确保任务添加成功。

这里我们定义表示每隔两分钟运行一次 CheckProcPerformance 脚本,并将其输出存储在 /root/ checkprocperformance.log 文件中。用户可以根据自己的需求修改脚本运行的间隔时间。以上步骤完成后,就可以实现对进程性能的自动化监控了。

就我们这个例子来说,如果没有错误信息,checkprocperformance.log 日志中不会有信息保存,预警信息将会作为邮件发送给 root 用户。在测试的时候,java 进程占用的 CPU 值超过阈值,因此 root 用户收到一封标题为 Warning for Process java 的邮件:

清单 13. 预警邮件内容

From root@hv4plus_lpar2.ppd.pok.ibm.com Wed Jun 3 08:52:52 2009
X-Original-To: root
Delivered-To: root@hv4plus_lpar2.ppd.pok.ibm.com
Date: Wed, 03 Jun 2009 08:52:52 -0400
To: root@hv4plus_lpar2.ppd.pok.ibm.com
Subject: Warning for Process java
User-Agent: nail 11.25 7/29/05
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
From: root@hv4plus_lpar2.ppd.pok.ibm.com (root)

The Process java Consumed too much CPU or Memory Resource:%CPU = 15% %MEM = 1.3%







小结

本文介绍了 Unix/Linux 上的进程监控命令和进程定时启动命令,并通过两个自动化监控脚本详细介绍了如何实现进程状态和性能的自动化监控管理。监控系统进程会给系统管理员提供丰富的关于系统进程运行的信息,自动化监控的实现更能为系统管理员在系统发生异常时采取迅速的措施提供了方便。


你可能感兴趣的:(linux,unix,脚本,配置管理,AIX)