java執(zhí)行shell并獲取shell輸出日志方式
java執(zhí)行shell并獲取shell輸出日志
獲取shell輸出日志需要java使用兩個線程分別接受shell的標準輸入流和錯誤流并打印出來
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.Charset; public class ShellLogRunTest { public static void main(String[] args) throws Exception, SecurityException { Process p = null; Runtime rt = Runtime.getRuntime(); String command = "cmd /c java -version"; command = "cmd /c ping 127.0.0.1 -n 3"; if (args != null && args.length > 0 && args[0] != null && args[0].trim().length() > 0) { command = args[0]; } try { p = rt.exec(command, null, null); // 獲取進程的標準輸入流 final InputStream is1 = p.getInputStream(); // 獲取進城的錯誤流 final InputStream is2 = p.getErrorStream(); // 啟動兩個線程,一個線程負責讀標準輸出流,另一個負責讀標準錯誤流 new Thread() { public void run() { BufferedReader br1 = new BufferedReader(new InputStreamReader(is1, Charset.forName("gb2312"))); // 這里要注意shell返回的類型,windows和linux可能不同 try { String line1 = null; while ((line1 = br1.readLine()) != null) { if (line1 != null) { System.out.println(line1); } } } catch (IOException e) { e.printStackTrace(); } finally { try { is1.close(); System.out.println("is1線程關(guān)閉"); } catch (IOException e) { e.printStackTrace(); } } } }.start(); new Thread() { public void run() { BufferedReader br2 = new BufferedReader(new InputStreamReader(is2, Charset.forName("gb2312"))); try { String line2 = null; while ((line2 = br2.readLine()) != null) { if (line2 != null) { System.out.println(line2); } } } catch (IOException e) { e.printStackTrace(); } finally { try { is2.close(); System.out.println("is2線程關(guān)閉"); } catch (IOException e) { e.printStackTrace(); } } } }.start(); p.waitFor(); p.destroy(); System.out.println("進程結(jié)束"); } catch (Exception e) { try { p.getErrorStream().close(); p.getInputStream().close(); p.getOutputStream().close(); } catch (Exception ee) { ee.printStackTrace(); } } } }
java執(zhí)行shell命令(分批 多條 走一步看一步的執(zhí)行)
說明
網(wǎng)上有很多通過java執(zhí)行命令的程序,但是只能執(zhí)行一條命令,或者是所有命令一次性執(zhí)行完畢。
而我想要的是執(zhí)行一條命令,看一看返回結(jié)果,然后在去執(zhí)行下一條命令,可惜翻遍全網(wǎng),竟然一個可行的方法都沒有?。。?/p>
沒辦法,自己想辦法解決吧。
實現(xiàn)代碼
廢話不多說,直接上代碼:
入口類
import core.CmdClient; public class Main { public static void main(String[] args) { CmdClient client = new CmdClient(); client.run("cd /"); client.run("ls"); client.run("exit"); System.out.println("主線程結(jié)束"); } }
核心代碼類:
這里就盡量不寫的太復雜,把多線程直接的交互都給砍掉了。大家可以根據(jù)自己需求去修改。
package core; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; public class CmdClient { // 中文有亂碼的可以試著改一下編碼格式。 private static final Charset charset = StandardCharsets.UTF_8; // 初始化 public CmdClient() { try { /* Runtime.getRuntime().exec()方法本質(zhì)和windows上的運行一樣,只能執(zhí)行一個命令來啟動一個程序。 這里啟動的是sh解釋器,可以根據(jù)需要改成其他shell解釋器。適用mac,linux系統(tǒng)。 對于windows,則是運行C:\Windows\System32\cmd.exe,同時執(zhí)行的也不是shell命令,而是dos命令。 */ Process process = Runtime.getRuntime().exec("/bin/sh"); // 獲取程序的輸出流和輸入流 inputStream = process.getInputStream(); errorStream = process.getErrorStream(); outputStream = process.getOutputStream(); /* 輸出數(shù)據(jù)需要,若執(zhí)行的命令沒有輸出結(jié)果,就會阻塞讀取流的線程。 為了防止主線程被阻塞,所以聲明新的線程專門盯著輸出數(shù)據(jù)。 */ new Thread(this::ReadCmdOut).start(); new Thread(this::ReadCmdError).start(); } catch (IOException e) { throw new RuntimeException("cmd初始化異常", e); } System.out.println("控制臺初始化完畢"); } private final InputStream inputStream; private final InputStream errorStream; private final OutputStream outputStream; // 運行命令 public void run(String cmd) { try { // 若執(zhí)行某些命令出現(xiàn)異常,可以嘗試更換 \n 為 \r 或 \n\r outputStream.write((cmd + "\n").getBytes(charset)); outputStream.flush(); } catch (Exception e) { throw new RuntimeException("命令執(zhí)行錯誤:" + cmd, e); } } private void ReadCmdOut() { try { print(inputStream); } catch (Exception e) { throw new RuntimeException("獲取輸出流異常", e); } System.out.println("正常輸出流結(jié)束"); } private void ReadCmdError() { try { print(errorStream); } catch (Exception e) { throw new RuntimeException("獲取錯誤流異常", e); } System.out.println("異常輸出流結(jié)束"); } /** * 這里直接把數(shù)據(jù)打印出來了,有其他需求的可以在這里寫判來確定下一步來執(zhí)行什么。 */ private void print(InputStream inputStream) throws IOException { byte[] bytes = new byte[1024]; int i; while (true) { i = inputStream.read(bytes); if (i == -1) break; System.out.print(new String(bytes, 0, i, charset)); } System.out.println(); } }
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
在Eclipse中部署Spring Boot/Spring Cloud應用到阿里云
這篇文章主要介紹了在Eclipse中部署Spring Boot/Spring Cloud應用到阿里云,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-12-12Spring IOC原理補充說明(循環(huán)依賴、Bean作用域等)
這篇文章主要介紹了Spring IOC原理補充說明(循環(huán)依賴、Bean作用域等),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-08-08java開發(fā)ShardingSphere的路由引擎類型示例詳解
這篇文章主要為大家介紹了java開發(fā)ShardingSphere的路由引擎類型示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-08-08Java將RTF轉(zhuǎn)換為PDF格式的實現(xiàn)
本文主要介紹了Java將RTF轉(zhuǎn)換為PDF格式的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-07-07springboot+mybatis plus實現(xiàn)樹形結(jié)構(gòu)查詢
實際開發(fā)過程中經(jīng)常需要查詢節(jié)點樹,根據(jù)指定節(jié)點獲取子節(jié)點列表,本文主要介紹了springboot+mybatis plus實現(xiàn)樹形結(jié)構(gòu)查詢,感興趣的可以了解一下2021-07-07