使用java代码关闭指定端口的程序-windows下

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

一:问题由史

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

二:基础知识

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<Integer> 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<Integer> 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<String> 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<String> data){
        Set<Integer> 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<Integer> 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<String> read(InputStream in,String charset) throws IOException{
        List<String> 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();
    }
}
时间: 2024-10-29 10:44:30

使用java代码关闭指定端口的程序-windows下的相关文章

如何用dat批处理文件关闭某端口对应程序-Windows自动化命令

如何用dat批处理文件关闭某端口对应程序? 网上找到的大部分都是手动操作,第一步先查出端口,第二步在根据上一步查到的端口手动去关闭进程.但我的需求不是这样的,我需要全自动处理.用于 dubbo 服务进程在 Windows 环境下的关闭.如果 Linux 环境,则不需那么辛苦了. 找了大半天,终于在百度知道上得到参考案例(或许是我使用的关键词不对),并成功试验,感谢相关贡献者. 答案一: for /f "tokens=1-5 delims= " %%a in ('"netsta

windows下关闭指定端口服务,解决tomcat端口占用问题

http://blog.aizhet.com/Server/640.html 在windows下做java EE的开发时:搭建 Eclipse+tomcat的java web开发环境:在应用之中经常遇到 tomcat在重新启动服务时,端口占用问题:导致无法启动服务: 错误提示: Several ports (8005, 8080, 8009) required by Tomcat v7.0 Server at localhost are already in use. The server ma

Java如何在指定端口创建套接字?

在Java编程中,如何在指定端口创建套接字并连接到指定服务器的端口? 下面的例子演示了Socket类的Socket构造函数,并且使用getLocalPort(),getLocalAddress(),getInetAddress()以及getPort()方法获取Socket细节. package com.yiibai; import java.io.IOException; import java.net.InetAddress; import java.net.Socket; import ja

Qt5 发布的exe应用程序Windows下无法执行的问题解决方案

本解决方案着重解决报错为: This application has requested the Runtime to terminate it in an unusual way. 的错误. 即: 错误是由于一个Qt5应用程序发布时,要自带一些.dll文件到该exe所在的文件路径当中,比如: 尤其是platforms文件夹,要在Windows系统下运行,必须要加这个文件夹,而且名称必须是platforms,里面应包含:qminimald.dll和qwindowsd.dll 两个文件,这些.dl

如何关闭指定端口占用的进程

1.查找对应的端口占用的进程,找到占用端口对应的程序的PID号: netstat  -aon|findstr  "9001" 2.根据PID号找到对应的程序 ,找到对应的程序名: tasklist|findstr "6676" 3.结束该进程: taskkill /f /t /im java.exe

OS端口占用,如何排查平关闭占用端口的程序?

环境:Windows 10 1.查看OS端口占用情况 2.打开任务管理器,查找PID为15116的程序"mysqld",强行关闭即可.

windows 10中使用命令行关掉占用指定端口的程序

通过netstat -ano与findstr命令结合查询到带有9080端口的监听信息,图中最后一列为监听程序的PID 通过tasklist命令与findstr命令结合查询到指定PID对应的应用程序 使用taskkill强制终止指定PID的进程 原文地址:https://www.cnblogs.com/alonely/p/12008205.html

windows如何关闭指定端口

关闭windows中被占用的端口,比如我们常见的8080端口被占用了 1.查找端口的PID netstat -aon|findstr "8080" 如图 PID为3888 2.关闭PID进程 结束进程

查询并关闭指定端口进程

windows环境: 检查8080端口是否被占用 netstat -nao | findstr "8080" tasklist | findstr "3640" taskkill /pid 3640 /f Linux环境: 检查8080端口是否被占用 netstat -anp | grep 8080 查看是那个程序占用的端口 lsof -i:8080 查看该应用程序的进程信息 ps PID(进程号) 查看该进程的状态 pidstat -p PID(进程号) pid: