Unix/Linux 系统自动化管理之进程管理篇(2)

来源:developerWorks 中国 作者:方 正
  

必须为每个字段指定一个值。除了 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;
}

时间:2009-07-23 13:47 来源:developerWorks 中国 作者:方 正 原文链接

好文,顶一下
(5)
100%
文章真差,踩一下
(0)
0%
------分隔线----------------------------


把开源带在你的身边-精美linux小纪念品
无觅相关文章插件,快速提升流量