主备配置值检查脚本
上一篇讲了方法论,关于主备环境的一致性问题。 热备双机中备机处理业务异常故障引发的思考 这周终于要写脚本了。 一、背景: 主备双机环境下,备机作为热备主机,只在有故障情况下使用。在备机启动业务前,需检查备机环境是否与主机完全一致,主要包括启动程序、启动配置,以及jar包。 二、功能及配置说明 (一)功能说明: 1、可配置多个程序模块。通过[NAME XXX] ..... [/NAME]来标记。 2、对city中的配置值,以逗号为分隔符,对制定配置sh,para项,替换XX。 3、对配置项sh、para中,主备机相同结构文件进行核对。 4、可以对本地文件进行核对,配置:local即可。 5、可以自行扩展配置项,并写配置分支函数,来实现扩展功能。如:检查文件目录、检查MQ状态等。 (二)配置说明:其中[NAME XXXX]可以自行配置 [NAME abcd] #abcd为模块名 Hostname=node1 #对比文件所在主机,ssh无密码登录 city=zs,zh,sz #替换下面配置中的XX地市,注意XX为大写,以逗号为分隔符。 sh=/home/hadoop/*/_perl/_1403/ms/XX/XX.sh para=/home/hadoop/*/_perl/_1403/ms/XX.txt local=/home/hadoop/*/_perl/_1403/ms/zh.txt,/home/hadoop/*/_perl/_1403/ms/t7.txt #本地文件比较,以逗号为分隔符 jar_lib_chk=1 #1表示核对$jar_lib,0表示不核对,源自*-background.jar 这个jar包是否依赖公共lib下面的包,如果依赖的话那些也需要一致。 jar_lib=/home/hadoop/*/_perl/_1403/ms/zs [/NAME] #固定格式作为该段配置结束 三、使用方法: 1、主备之间需可以ssh无密码登录,即可从运行主机ssh到对照主机执行命令。 2、各类文件: # ?程序运行的主目录 my $rundir = '/home/hadoop/*/_perl/_1403/ms'; # 运行日志 my $log_file = $rundir. "/chk_ms.log"; # 错误报告 my $log_error = $rundir. "/chk_ms.err"; # ?配置文件 my $cfg_file = $rundir . "/chk_ms.cfg"; 3、运行方式:修改配置文件chk_ms.cfg,以及运行目录$rundir。主要脚本和配置文件需在同一级目录。直接启动即可。如: ../chk_ms.pl 四、源码: #!/usr/bin/perl ######################### ##chk_ms.pl,核查主备一致性 ##主要功能: ##1、可配置多个程序模块。通过[NAME XXX] ..... [/NAME]来标记。 ##2、对city中的配置值,以逗号为分隔符,对制定配置sh,para项,替换XX。 ##3、对配置项sh、para中,主备机相同结构文件进行核对。 ##4、可以对本地文件进行核对,配置:local即可。 ##5、可以自行扩展配置项,并写配置分支函数,来实现扩展功能。如:检查文件目录、检查MQ状态等。 ##lanfity@126.com ##version v1.0 ########################## use strict; use Fcntl qw(:DEFAULT :flock); # 程序运行的主目录 my $rundir = '/home/hadoop/*/_perl/_1403/ms'; # 运行日志 my $log_file = $rundir. "/chk_ms.log"; # 错误报告 my $log_error = $rundir. "/chk_ms.err"; # 配置文件 my $cfg_file = $rundir . "/chk_ms.cfg"; sub write_log { my $time=scalar localtime; open (HDW,">>",$log_file); flock (HDW,LOCK_EX); print HDW $time," ",join ' ',@_,"n"; flock (HDW,LOCK_UN); close HDW; } sub write_err { my $time=scalar localtime; open (HDW,$log_error); flock (HDW,LOCK_EX); print HDW "ERROR: ",$time,"n"; print "ERROR: ",LOCK_UN); close HDW; } #获取文件的序列号,使用cksum sub get_sn { my $file=$_[0]; chomp(my $sn=`cksum $file 2>/dev/null|awk '{print $1" "$2}' `); if ($sn eq "") { write_err "local $file not exist"; write_log "ERR:local $file not exist"; } return $sn; } #获取其他主机文件的序列号,使用ssh信任机制,以及cksum sub ssh_sn { my ($file,$host)=@_; chomp(my $sn=`ssh $host "cksum $file 2>/dev/null"|awk '{print $1" "$2}'`); if ($sn eq "") { write_err "remote $file not exist"; write_log "ERR:remote $file not exist"; } return $sn; } #对多个地市的配置进行对比,参数为$0:对比的文件名;$1:"city"字段;$2:对比的远端ip。输出:对比结果,print或写入$log_err sub mult_city { my $hostname=$_[2]; my $city=$_[1]; my @city=split /,/,$city; foreach $city(@city){ my $char=$_[0]; $char =~ s/XX/$city/g; #所有XX替换 write_log " mult_city start $city is $char"; my $loc=get_sn($char); my $rem=ssh_sn($char,$hostname); ###待调试ssh后再测试 if ( $loc ne $rem ){ write_err "$city $char is differentn"; write_log "ERR:$city $char is differentn"; } } } #获取对应目录的文件名。参数为:$1:对比的目录。输出:数组,文件名。 sub get_file { my ($dir_file,$catch)=@_; my $path=$dir_file."/*.".$catch; my @dir=glob($path); return @dir; } # 扫描函数 sub do_scan { # 先读取配置文件,获取要扫描的程序,以及扫描哪些选项 my $scan_cfg = get_config(); # 在 for循环里逐个程序项扫描 for my $hid (keys %{$scan_cfg}) { write_log "Checking $hid ...."; print "Checking $hid ....n"; my $hostname=$$scan_cfg{$hid}{"Hostname"}; my $city=$$scan_cfg{$hid}{"city"}; for my $cfg_key (keys %{$$scan_cfg{$hid}}) { my $value=$$scan_cfg{$hid}{$cfg_key}; next if $cfg_key eq "jar_lib"; write_log "$hid start $cfg_key is $value"; # 检查本地文件是否一致 if ($cfg_key eq 'local') { my ($file1,$file2)=split /,$value; if ( &get_sn($file1) ne &get_sn($file2) ) {write_err "$cfg_key is different,$file1 : $file2"; write_log "$cfg_key is different,$file1 : $file2"; } # 检查启动shell是否一致 } elsif ($cfg_key eq 'sh'){ mult_city($value,$city,$hostname); # 检查启动配置是否一致 } elsif ($cfg_key eq 'para'){ mult_city($value,$hostname); # 检查jar库是否一致 }elsif ($cfg_key eq 'jar_lib_chk'){ if ( $value == "1" ){ my $dir=$$scan_cfg{$hid}{"jar_lib"}; write_log " now checking jar_lib $dir"; foreach my $file(get_file($dir,"jar")){ #匹配关键字jar my $loc=get_sn($file); my $rem=ssh_sn($file,$hostname); if ( $loc ne $rem ){ write_err "jar_lib $dir is different,please sync. "; write_log "jar_lib $dir is different,please sync. "; next; } } } } } print "Checking $hid ENDn"; write_log "Checking $hid END."; } } # 该函数用来读取配置文件,并将结果放入一个 Hash。 sub get_config { my %config; open (HDR,$cfg_file) or die "[EMERG] can't open cfg_file: $!n"; #[NAME XXXX] #Hostname=XXX #city=fs,zs,st,sw,cz,jy,zq,qy,sg,yf,sz #替换下面配置中的XX地市,注意XX为大写,逗号为分隔符 #sh=/crmapp/_run/_market/_bin/_XX/SubsStatusSynToBillMain_XX.sh #para=/crmapp/_conf/_XX/_market/SubsStatusSynToBillMain.properties # #jar_lib_chk=1 #1表示核对$jar_lib,0表示不核对,源自ngcrm-background.jar 这个jar包 是否依赖公共lib下面的包, 如果依赖的话 那些也需要一致。 #jar_lib=/crmapp/_run/_lib # #local=/crmapp/_run/_lib/qloader.jar,/crmapp/_run/_lib/ngcrm-background.jar #本地文件比较,以逗号为分隔符 #[/NAME] #本节配置结束 while(<HDR>) { next if /^$/; next if /^s*#/; if ( my ($hid) = /[NAMEs+(w+)]/ ) { while (<HDR>) { next if /^$/; next if /^s*#/; last if /[/NAME]/; chomp; my ($cfg_key,$cfg_value) = split /=/; $cfg_key =~ s/^s+|s+$//g; $cfg_value =~ s/#.*$//; $cfg_value =~ s/^s+|s+$//g; $cfg_value =~ s/^"|"$//g; $cfg_value =~ s/^'|'$//g; $config{$hid}->{$cfg_key} = $cfg_value; } } } close HDR; return %config; } do_scan; (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |