• 使用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();
        }
    }
  • 相关阅读:
    Mantis安装过程笔记
    Python脚本文件中使用中文
    String.trim的作用
    Ivy入门笔记
    Groovy正则表达式复杂逻辑判断实例
    Build a ZenTao Server on Linux
    Ubuntu上安装gevent
    Install Redmine Server with Bitnami Installer
    Semi-automation Script Based on Sleep
    关于MySQL的事务处理及隔离级别
  • 原文地址:https://www.cnblogs.com/zhuxiaojie/p/6055298.html
Copyright © 2020-2023  润新知