转载请请在页首注明作者与出处

一:问题由史

今天遇到一个问题,就是在实现自动化灾备的时候,发现原有死掉的程序没有完全关闭,当然这都不是本文的重点,重点是这个时候,我得把它完全关闭,所以才有了这篇文章。

二:基础知识

2.1:java要怎么实现

java可以获取并删除JAVA虚拟机启动的应用,但是却并没有提供API获取操作系统中其它的进程的API。

但是java可以执行操作系统的脚本命令。

2.2:根据端口查找进程

windows中有这样的命令

netstat -ano 查看操作系统所有占用端口的进程

netstat -ano | findstr "8080" 获取占用了80端口的进程

得到的结果如下

TCP 127.0.0.1:51846 127.0.0.1:5037 TIME_WAIT 0

TCP 127.0.0.1:51847 127.0.0.1:5037 TIME_WAIT 0

UDP 0.0.0.0:4500 *:* 444

UDP 0.0.0.0:5355 *:* 1232

可以看到TCP/UPD是所使用的协议,后面的是绑定IP与端口,最后一列,是占用的进程号(pid)。

2.3:根据进程号删除进程

再来看一条命令

taskkill /pid 123

我们可以关闭进程号为123的进程,当然,我试上面的这条命令的时候,系统提示无法终止这个进程,那我们可以加一个/F,如下,就能强行关闭。

taskkill /F /pid 123

三:java实现,支持一次性杀死多个端口

之前有说过,java可以执行操作系统的脚本,不论是什么操作,系统,那么我们就可以用这个方法,来直接执行这些命令来达到相应的效果。

package kill.window;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.util.ArrayList;

import java.util.HashSet;

import java.util.List;

import java.util.Scanner;

import java.util.Set;

import java.util.regex.Matcher;

import java.util.regex.Pattern;

public class KillServer {

private Set ports;

public static void main(String[] args) throws InterruptedException {

System.out.println("请输入要杀掉的windows进程的端口号,如果有多个,则以逗号相隔");

System.out.println("Please input kill port");

Scanner scanner = new Scanner(System.in);

String input = scanner.next();

scanner.close();

String[] split = input.split(",");

Set ports = new HashSet<>();

for (String spid : split) {

try{

int pid = Integer.parseInt(spid);

ports.add(pid);

}catch(Exception e){

System.out.println("错误的端口号,请输入一个或者多个端口,以英文逗号隔开");

try {

Thread.sleep(5000);

} catch (InterruptedException e1) {

e1.printStackTrace();

}

System.exit(0);

}

}

KillServer kill = new KillServer();

kill.ports = ports;

System.out.println("need kill " + ports.size() + " num");

for (Integer pid : ports) {

kill.start(pid);

}

System.out.println("清理完毕,程序即将退出");

System.out.println("SUCCESS");

Thread.sleep(5000);

System.exit(0);

}

public void start(int port){

Runtime runtime = Runtime.getRuntime();

try {

//查找进程号

Process p = runtime.exec("cmd /c netstat -ano | findstr \""+port+"\"");

InputStream inputStream = p.getInputStream();

List read = read(inputStream, "UTF-8");

if(read.size() == 0){

System.out.println("找不到该端口的进程");

try {

Thread.sleep(6000);

System.exit(0);

} catch (InterruptedException e) {

e.printStackTrace();

}

}else{

for (String string : read) {

System.out.println(string);

}

System.out.println("找到"+read.size()+"个进程,正在准备清理");

kill(read);

}

} catch (IOException e) {

e.printStackTrace();

}

}

/**

* 验证此行是否为指定的端口,因为 findstr命令会是把包含的找出来,例如查找80端口,但是会把8099查找出来

* @param str

* @return

*/

private boolean validPort(String str){

Pattern pattern = Pattern.compile("^ *[a-zA-Z]+ +\\S+");

Matcher matcher = pattern.matcher(str);

matcher.find();

String find = matcher.group();

int spstart = find.lastIndexOf(":");

find = find.substring(spstart + 1);

int port = 0;

try {

port = Integer.parseInt(find);

} catch (NumberFormatException e) {

System.out.println("查找到错误的端口:" + find);

return false;

}

if(this.ports.contains(port)){

return true;

}else{

return false;

}

}

/**

* 更换为一个Set,去掉重复的pid值

* @param data

*/

public void kill(List data){

Set pids = new HashSet<>();

for (String line : data) {

int offset = line.lastIndexOf(" ");

String spid = line.substring(offset);

spid = spid.replaceAll(" ", "");

int pid = 0;

try {

pid = Integer.parseInt(spid);

} catch (NumberFormatException e) {

System.out.println("获取的进程号错误:" + spid);

}

pids.add(pid);

}

killWithPid(pids);

}

/**

* 一次性杀除所有的端口

* @param pids

*/

public void killWithPid(Set pids){

for (Integer pid : pids) {

try {

Process process = Runtime.getRuntime().exec("taskkill /F /pid "+pid+"");

InputStream inputStream = process.getInputStream();

String txt = readTxt(inputStream, "GBK");

System.out.println(txt);

} catch (IOException e) {

e.printStackTrace();

}

}

}

private List read(InputStream in,String charset) throws IOException{

List data = new ArrayList<>();

BufferedReader reader = new BufferedReader(new InputStreamReader(in, charset));

String line;

while((line = reader.readLine()) != null){

boolean validPort = validPort(line);

if(validPort){

data.add(line);

}

}

reader.close();

return data;

}

public String readTxt(InputStream in,String charset) throws IOException{

BufferedReader reader = new BufferedReader(new InputStreamReader(in, charset));

StringBuffer sb = new StringBuffer();

String line;

while((line = reader.readLine()) != null){

sb.append(line);

}

reader.close();

return sb.toString();

}

}

https://www.cnblogs.com/zhuxiaojie/category/669086.html

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐