perl 批量执行命令脚本
一、环境描述
监控发现多台服务器负载异常,登陆服务器查看,发现salt-minion进程狂多(>100个),而且cpu占用100%。从而导致服务器负责也飙上去。
二、原因
通过分析,应该是由于slat-master进程关闭,各个服务器的salt-minion客服端无法与服务端进行交互,导致客户端堆积需求salt-minion进程,消耗大量内存和cpu资源。
三、处理步骤
1、重启服务端salt-master进程,结果发现:服务端网卡及负载波动太大,并且执行salt命令会超时,无返回接口。
2、查询salt-minion日志,发现大量如下报错:
[salt.crypt ][ERROR ] The Salt Master has cached the public key for this node, this salt minion will wait for 10 seconds before attempting to re-authenticate
经核实,该问题在salt 0.7.1版本中确实存在,主要时由于mine模块功能不全导致,后期版本已经修复这个bug。我们可以通过修改mine模块代码,限制salt-minion开启进程数。
3,面对salt相关命令执行无效的问题,采用将服务端和客服端的/etc/salt/kpi目录下缓存文件删除,并重新salt-key -A所有客户端minion连接。但服务器比较多,需要批量处理。
4、批量脚步采用了网上现成代码进行修改,主要逻辑是:使用perl的Net::SSH::Expect模块,模拟ssh到各个服务器执行一系列命令,从而达到解决问题的目的。
5、脚步包括一个perl脚步salt_minion_batch_restart.pl + 命令列表 commend_list.txt + 服务器ip_port列表 ip_list.txt
6、执行完脚步之后,slat-key -A 。然后,通过salt命令检查,如:salt ‘*’ cmd .run ‘uptime’。
四、代码展示
1、salt_minion_batch_restart.pl
#!/usr/bin/perl
#use strict;
use Net::SSH::Expect;
use Net::SCP::Expect;
my @ssh_list;
my $ip_list=’ip_list.txt’;
my $command_txt=’command_list.txt’;
open FH,$ip_list;
while(<FH>){
if (!($_ =~ m/\#|^$/)) #删除注释和空行
{
@ssh_list=split;
print “======= “,$ssh_list[0],” =======\n”;
print “开始时间:”,get_time(),”\n”;
print “正在登陆”,$ssh_list[0],”…\n”;
&salt_minion_restart(“$ssh_list[0]“,”$ssh_list[1]“);
print “结束时间:”,get_time().”\n”;
}
}
close FH;
sub salt_minion_restart(){
my($host,$port)=@_;
my $ssh= Net::SSH::Expect->new(
host => $host,
port => $port,
user => “root”,
no_terminal =>0,
raw_pty=>1,
timeout=> 3,
);
$ssh->debug(0);
$ssh->run_ssh or die “SSH process cann’t start :$!”;
my $line;
if ($line=$ssh->read_line()){
print $line .”\n”;
if ($line =~ /Last/)
{
print “$ssh_list[0] has logined\n”;
}
else {
$ssh->send(“yes\n”);
print “$ssh_list[0] send yes\n “;
}
}
open F1,$command_txt;
while(<F1>){
if (!($_ =~ m/\#|^$/)) #删除注释和空行
{
my @command=split/\n/,$_;
$result=$ssh->exec(“$command[0]“);
print $command[0],” –>”,$result,”\n”;
}
#print $ssh_list[0],”命令执行完毕\n”;
}
close F1;
$ssh->close();
}
sub get_time {
my $time = shift || time();
my ($sec,$min,$hour,$day,$mon,$year,$wday) = localtime($time);
$year += 1900;
$mon += 1;
$min = ’0′.$min if length($min) < 2;
$sec = ’0′.$sec if length($sec) < 2;
$mon = ’0′.$mon if length($mon) < 2;
$day = ’0′.$day if length($day) < 2;
$hour = ’0′.$hour if length($hour) < 2;
my $weekday = (‘Sun’,’Mon’,’Tue’,’Wed’,’Thu’,’Fri’,’Sat’)[$wday];
my $time_now = “$year-$mon-$day $hour:$min:$sec $weekday”;
return $time_now;
}
2、commend_line.txt
test -e /etc/salt/pki/minion && (cd /etc/salt/pki && rm -rf minion)|| echo ‘not exist’ #判断pki下缓存目前是否存在,存在就删除,不存在的话就输出‘not exist’
test -e /etc/init.d/salt-minion && /etc/init.d/salt-minion start #判断salt-minion是否存在,存在的话就启动
ps aux|grep salt #检查确认salt-minion是否启动成功
3、ip_list.txt
192.168.1.133 222
192.168.1.134 222
192.168.1.135 222
192.168.1.136 222
192.168.1.137 222
192.168.1.138 222
192.168.1.139 222
4、存在问题
没有完善的日志功能,从何导致执行过程中ctrl+c 终止了脚本,又要重新开始执行一遍。后期解决这个问题。