28.Perl 脚本实战-pskill

    xiaoxiao2022-07-04  168

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

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

    1. 用法示例

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

    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: m 强制杀死成功!\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; }
    最新回复(0)