28. Perl 脚本实战-pskill

pskill 用于通过关键字杀死当前系统正则运行的进程, 基于linux命令 ps, grep , kill 实现. 主要特性:

  • 支持通过关键字筛选进程列表, 进程列表自带序号
  • 筛选时支持使用多个关键字, 多个关键字直之间时或的关系
  • 支持通过列表序号杀死进程, 而非进程id,使用更方便
  • 支持批量杀死多个进程
  • 支持快速杀死全部进程.

1. 用法示例

  1. pskill 会查询出所有包含关键字的进程, 然后并为每个进程赋予序号
  2. 用户输入要杀死的进程序号,可支持多个,或全部

1.1 单个关键字, 选择杀死多个进程

$ pskill redis
[1 ] zongf     4435  1311  0 5月11 ?       00:49:00 redis-server 127.0.0.1:6481
[2 ] zongf     4451  1311  0 5月11 ?       01:03:21 redis-sentinel 127.0.0.1:26481 [sentinel]
[3 ] zongf     4456  1311  0 5月11 ?       01:01:07 redis-sentinel 127.0.0.1:26482 [sentinel]
[输入] 请输入您要杀死的进程序号,0表示所有:  2 3
[成功] 进程pid:   4451 强制杀死成功!
[成功] 进程pid:   4456 强制杀死成功!

1.2 多个关键字,选择杀死全部进程

$ pskill 7481 7482
[1] zongf    29081  1311  0 13:26 ?        00:00:00 redis-server 127.0.0.1:7481 [cluster]
[2] zongf    29086  1311  0 13:26 ?        00:00:00 redis-server 127.0.0.1:7482 [cluster]
[3] zongf    29208 25920  0 13:27 pts/3    00:00:00 /usr/bin/perl /home/zongf/soft/zongf/tools/pskill 7481 7482

[输入] 请输入您要杀死的进程序号,0表示所有:  0 
[成功] 进程pid:  29081 强制杀死成功!
[成功] 进程pid:  29086 强制杀死成功!

2. 命令源码

#!/usr/bin/perl
#Desc  强制杀死正在运行的进程,可同时杀死多个进程
#Auth  zonggf
#Date  2016-12-22

use warnings;
use Term::ANSIColor qw(:constants);
$Term::ANSIColor::AUTORESET = 1;

#################### 子程序  ####################
#检查是否是查询帮助
sub check_help{
  my $param = $ARGV[0];
  if("-h" eq $param || "--help" eq $param){
    print BOLD BLUE "Desc: "; print "强制杀死正在运行的进程,可同时杀死多个进程\n";
    print BOLD BLUE "Args: "; print "多个进程启动关键字,支持模糊查询\n";
    print BOLD BLUE "Exam: "; print "kill9 tomcat redis\n";
    print BOLD BLUE "Auth: "; print "zonggf\n";
    print BOLD BLUE "Date: "; print "2016-12-22\n";
    exit;
  }
}

#desc    输出有颜色的字符串
#para1  接收至少两个参数以上,第一个参数为要格式化的字符串,之后的参数为要使用颜色的字符串
sub print_color(){
  # 如果长度小于2, 那么不进行格式化输出,直接打印
  if(@_ < 2){
     print shift @_;
     return;
  }

  #获取要格式化颜色的字符串
  my $line = shift @_;

  #获取要高亮的字符串数组
  my @patterns = @_;

  #获取要高亮显示的字符串数组,拼接正则模式
  my $spectors = (shift @_) . '+';
  foreach(@_){
     $spectors .= "|$_+";
  }
  #按正则模式进行分组
  my @arrays = split(/($spectors)/, $line);

  #输出结果
  for my $item(@arrays){
      #直接使用@patterns 数组反向匹配,数组内插时,每个字符串直接会有空格
      my $pattern = "@patterns";
      
      #字符串中查找元素,如果有的话则高亮显示,否则正常显示
      my $idx = index($pattern, $item);
      if($idx > -1){
        print BOLD RED $item;
      }else{
        print $item;
      }   
  }
}

#格式化索引长度
#参数: 接收两个参数
#      para1: 需要格式化的索引
#      para2: 数组长度
#返回: [1   ]
sub fmt_idx{
    return shift @_ if @_ < 2;
    my ($str, $array_length) = @_;
    my $length = length $array_length;
    return sprintf "[%-${length}s] ", $str;
} 

#杀死进程
sub kill_ps_line{
  my $ps_line = shift @_;
  my $pid = (split/\s+/,$ps_line)[1];
  $cnt = kill 9, $pid;
  if($cnt == 1){
    printf "[成功] 进程pid: %6d 强制杀死成功!\n",$pid;
  } else {
    printf "[失败] 进程pid:%6d 强制杀死成功!\n",$pid;
  }
}

#获取用户输入,返回输入列表
sub get_user_choose{

  #print "\n[警告] 您正在试图强制杀死以上 $length 个进程,确认请输入 y:  ";
  print "\n[输入] 请输入您要杀死的进程序号,0表示所有:  ";
  chomp($choose=<STDIN>);

  #判断用户输入是否只能是数字
  unless($choose =~ /^(\s|[0-9]|\s)+$/){
    print "[错误] 只能输入正整数\n";
    exit;
  }
  
  #获取用户输入的序号列表
  @ids = split(/\s+/, $choose);
  @ids_asc = sort @ids;

  # 判断输入是否包含0,确保0 只能单独出现
  if(@ids_asc >1 && $ids_asc[0] ==0 ){
     print "[错误] 0 表示全部, 只能单独使用\n";
     exit;
  }

  #判断用户输入最大值最小值
  if($ids_asc[-1] > (@lines +1) || $ids_asc[0] < 0){
     print "[错误] 序号取值范围为 [0~ " . (@lines) . "]\n";
     exit;
  }
  
  #如果只有一个元素,且为0 
  if(@ids == 1 && $ids_asc[0] ==0){
    return (1 .. @lines);
  }else{
    return @ids;
  }
}

####################  主程序 ####################
&check_help;

#如果用户不传过滤参数,则直接退出程序
if(@ARGV <1){
  print "此命令需要至少一个参数作为筛选条件!\n";
  exit;
}

#存储匹配模式,用户高亮输出
@patterns = @ARGV;

#进行端口号拼接
$names = shift @ARGV;
foreach (@ARGV){
  $names .="|$_";
}

#如果参数不为空,则进行筛选
$ps_cmd = 'ps -ef | grep -v grep | grep -v pskill';
$ps_cmd .= " | grep -E \"" . $names ."\"" if defined $names;

@lines = `$ps_cmd`;
$length =@lines;

if($length < 1){
  #没有符合条件时,直接退出程序
  print "没有符合条件的进程运行\n";
  exit;

} else{
  #如果查出结果大于1个进程,则需要确认
  
  #遍历查询结果
  $lines_length = @lines;
  for $idx (1 ... @lines){
    print BOLD GREEN &fmt_idx($idx, $lines_length);
    &print_color($lines[$idx-1], @patterns);
  }

  #获取用户选择的序号列表
  @ids = &get_user_choose; 

  #按用户选择进行杀死进程
  &kill_ps_line($lines[$_-1]) foreach @ids;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值