Java - Get pid of process and kill it

這邊主要探討的是,如何用Java去查詢OS內正在運行的process pid,利用所執行的command進行篩選,之後再將其kill掉,主要會分成Windows and Linux進行示範!
流程如下:
1. 撰寫一支程式(BackgroundProgram.java),執行後進行等待直到強制kill掉它為止
2. Export it to Runnable JAR file (命名為reader.jar)
3. 撰寫另一支程式(ProcessManager.java)來進行查詢、刪除的操作

#BackgroundProgram.java
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class BackgroundProgram {

	public static void main(String args[]){
		// TODO Auto-generated method stub
		if(args.length != 1) {
			System.out.println("Please assign a txt file!!");
			System.exit(-1);
		}
		
		File file = null;
		if(args.length == 1) {
			file = new File(args[0]);
			if(!file.exists()) {
				System.out.println("File non-exist!!");
				System.exit(-1);
			}
		}
		
		try(BufferedReader br = new BufferedReader(new FileReader(file))){
			String line = null;
			while((line = br.readLine()) != null) {
				System.out.println(line);
			}
			while(true) {
				try {
					Thread.sleep(5000);
					System.out.println("...");
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

程式執行時assign一檔案進行讀取與顯示,之後進行等待~
將該程式打包成reader.jar(透過eclipse輸出在此略過),等等執行語法如下:
$ java -jar reader.jar [file path]

#ProcessManager.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

import org.apache.commons.lang3.SystemUtils;

public class ProcessManager {

	public static void main(String args[]){
		// TODO Auto-generated method stub
		Scanner input = new Scanner(System.in);
		boolean flag = true;
		while(flag) {
			System.out.println("(1)List executed 'reader.jar' process (2)Clear executed 'reader.jar' process (3)exit");
			int option = input.nextInt();
			switch(option) {
				case 1:{
					getProcessInfo();
					break;
				}
				case 2:{
					String killCmd = "";
					List<ProcInfo> procLists = getProcessInfo();
		                        for(int i = 0 ; i < procLists.size() ; i++) {
		            	           ProcInfo info = procLists.get(i);
    		            	           String pid = info.getPid();
	            		           if(SystemUtils.IS_OS_WINDOWS) {
	            			      String windir = System.getenv("windir");
	            			      killCmd = windir + "\\System32\\taskkill.exe /F /PID "+pid;
	            		           }else
	            			      killCmd = "kill -9 "+pid;
	            		           Process pp;
					   try {
					      pp = Runtime.getRuntime().exec(killCmd);
					      int exitValue = pp.waitFor();
					      System.out.println("Exec cmd: "+killCmd+", Status: "+exitValue);
					   } catch (IOException | InterruptedException e1) {
					      // TODO Auto-generated catch block
					      e1.printStackTrace();
					   }
		                        }
				        break;
				}
				case 3:{
					flag = false;
					input.close();
					break;
				}
				default:{
					System.out.println("Option non-exist!!");
				}
			}
		}
	}
	
	private static List<ProcInfo> getProcessInfo(){
		List<ProcInfo> procLists = new ArrayList<>();
		try {
			List<String> cmds = new ArrayList<>();
			if(SystemUtils.IS_OS_WINDOWS) {
				String windir = System.getenv("windir");
				cmds.add(windir + "\\System32\\wbem\\WMIC.exe");
				cmds.add("process");
				cmds.add("where");
				cmds.add("caption='java.exe'");
				cmds.add("get");
				cmds.add("processid,commandline");
			}else if(SystemUtils.IS_OS_LINUX) {
				cmds.add("/bin/sh");
				cmds.add("-c");
				cmds.add("ps -eo pid,args | grep java");
			}
			Process p = Runtime.getRuntime().exec(cmds.toArray(new String[0]));
			BufferedReader input2 = new BufferedReader(new InputStreamReader(p.getInputStream()));
			
			String sp = SystemUtils.IS_OS_WINDOWS ? "  " : " ";
	                String line;
	                while ((line = input2.readLine()) != null) {
	        	   line = line.trim();
	        	   String spLine[] = line.trim().split(sp);
	        	   for(int i = 0 ; i < spLine.length ; i++) {
		        	if(spLine[i].indexOf("reader.jar") > -1) {
		        		String pid = SystemUtils.IS_OS_WINDOWS ? spLine[spLine.length - 1] : spLine[0];
		        		int index = line.indexOf(pid);
		        		String cmd = SystemUtils.IS_OS_WINDOWS ? line.substring(0, index) : line.substring(index + 1);
		        		procLists.add(new ProcInfo(pid, cmd.trim()));
		        	}
	        	   }	
	                }
	                input2.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		if(procLists.size() > 0) {
			System.out.println("=============Process Lists=============");
			System.out.println(procLists);
		}else {
			System.out.println("None");
		}
		return procLists;
	}
}
class ProcInfo{
	private String pid;
	private String cmd;
	
	public ProcInfo(String pid, String cmd) {
		this.pid = pid;
		this.cmd = cmd;
	}

	public String getPid() {
		return pid;
	}

	public String getCmd() {
		return cmd;
	}

	@Override
	public String toString() {
		return "Process Info [pid = " + pid + ", executed cmd => " + cmd + "]";
	}
}

這支程式重點在getProcessInfo function,區分成Windows and Linux兩種查詢語法
針對主程序為java進行過濾
#Windwos → WMIC.exe process where caption='java.exe' get processid,commandline
回覆結果如下:
CommandLine                     ProcessId
java  -jar reader.jar word.txt  12976
Note: 即使先針對processid但結果還是先印command line

#Linux → /bin/sh -c ps -eo pid,args | grep java
回覆結果如下:
   2190 java -jar reader.jar word.txt
   2282 grep --color=auto java

過濾後會得到pid and commands,再去過濾commands是否有相關keyword,如reader.jar
最後再進行kill
#Windwos → taskkill.exe /F /PID [pid]
#Linux → kill -9 [pid]

DEMO如下:
#Windows - 上: command line執行;中: 查看工作管理員;下: Eclipse執行ProcessManager操作

#Linux - 上: command line執行;中: top;下: command line執行

留言