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: %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;
}