最近在寫一個本身的郵箱服務器裏用到java
監視及起/停 windows 中的服務,調查發現仍是得用dos來作這些事情shell
說一下遭遇戰的過程windows
首先是java裏如何執行DOS命令,查到下記函數緩存
Runtime.getRuntime().exec()服務器
(到這你能夠試着啓動個 記事本 計算器的了Runtime.getRuntime().("notepad"); Runtime.getRuntime().("calc"); )多線程
而後就是準備dos命令函數
服務啓動 sc start "服務名" this
服務中止 sc start "服務名"spa
服務狀態 sc query "服務名"線程
(引號必須)
而後是返回值的問題了 起/停 的命令執行後是有返回值的
還沒發現比較好的對應方案 如今基本上就是把本來打印在 cmd框裏的一行行輸出出來本身判斷
1 private Map<String, String> executeCmd(String cmd) { 2 Runtime rt = Runtime.getRuntime(); // 運行時系統獲取
3 Map<String, String> lineMap = new HashMap<String, String>();//存放返回值
4 try { 5 Process proc = rt.exec(cmd);// 執行命令
6 InputStream stderr = proc.getInputStream();//執行結果 獲得進程的標準輸出信息流
7 InputStreamReader isr = new InputStreamReader(stderr);//將字節流轉化成字符流
8 BufferedReader br = new BufferedReader(isr);//將字符流以緩存的形式一行一行輸出
9 String line = null; 10 while ((line = br.readLine()) != null) { 11 if (!StringUtils.isEmpty(line)) { 12 String[] strLine = line.split(":"); 13 if(strLine.length>=2) { 14 lineMap.put(strLine[0].trim(), strLine[1].trim()); 15 } 16
17 } 18 } 19 br.close(); 20 isr.close(); 21 stderr.close(); 22 } catch (IOException e) { 23 e.printStackTrace(); 24 } 25 return lineMap; 26 }
ps: L11-17 根據不一樣的命令的執行結果不一樣 相應改變的 我這裏獲得的是 xx : yy 這樣的因此這樣處理
接下來就是 如是 bat 文件 怎麼對處
一樣的方法 把命令換成你的bat路徑就行了 ,這個就很少說了想說一個關於權限的問題
bat文件的話 若是權限不夠 一般會郵件bat文件以管理員身份運行 會這樣的處理
但java裏怎麼處理?以下
1 @echo off 2 mode con lines=30 cols=60
3 %1 mshta vbscript:CreateObject("Shell.Application").ShellExecute("cmd.exe","/c %~s0 ::","","runas",1)(window.close)&&exit 4 cd /d "%~dp0"
5 rem
以後再加上你要寫的bat命令就行了
如今想一想忽然感受很可怕有 admin 權限 也能夠本身寫cmd 建立 shell 執行 ...
還有一個就是 看當網上說 因執行命令過多或者執行內容過多 會形成Runtime阻塞問題,基本解決方案是多線程處理
就是把子進程的輸出流(getInputStream)和錯誤流(getOutputStream)分給兩個線程來作處理 以下
public class StreamManage extends Thread { private final Logger logger = LoggerFactory.getLogger(this.getClass()); InputStream inputStream; String type; public StreamManage(InputStream inputStream,String type) { this.inputStream = inputStream; this.type = type; } public void run () { InputStreamReader inputStreamReader = new InputStreamReader(inputStream); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); String line = null; try { while((line = bufferedReader.readLine()) !=null ) { if(type.equals("Error")) { logger.error(line); }else { logger.debug(line); } } } catch (IOException e) { e.printStackTrace(); } } }
這裏應該沒什麼要說的就是把把輸出流穿過來作輸出處理,而後調用的地方
L8,9
1 private void startMailServer() { 2 String cmd = "sc start \"James 2.3.2.1\"";// dos 命令
3 Runtime rt = Runtime.getRuntime(); // 運行時系統獲取
4 try { 5 // Process proc = rt.exec(cmd);// 執行命令
6 File filePath = new File("src\\main\\resources\\static\\bat\\runStart.bat"); 7 Process proc = rt.exec(filePath.toString()); 8 StreamManage errorStream = new StreamManage(proc.getErrorStream(), "Error"); 9 StreamManage outputStream = new StreamManage(proc.getInputStream(), "Output"); 10 errorStream.start(); 11 outputStream.start(); 12 } catch (IOException e) { 13 e.printStackTrace(); 14 } 15 }
基本上就這些
最後說一個殘留問題
就是 cmd窗口 閃屏的問題 若是執行的的是 命令 這個問題不存在 若是是 bat 不是要獲取 admin 權限這個問題也沒有 猜想 上記 獲取權限的代碼 形成了閃屏 調查中... 有知道的請告知 🙏