java 執行shell命令遇到的坑


正常來說java調用shell命令就是用

String[] cmdAry = new String[]{"/bin/bash","-c",cmd}
Runtime.getRuntime().exec(cmdAry);

實際上就是創建個子進程去執行這個命令。

 

問題來了: 如果我執行下面這句命令

exp system/manager buffer=64000  file=/home/oracle/beifen/beifen.dmp  FULL=Y

這種輸出日志量特別大的命令,就會出現卡死,一直不動,后來了解到 子進程產生的輸出日志都會寫到窗口里,因為窗口有緩存大小限制,

到達一定程度時就會卡死,導致死鎖,后來百度了其他作者的資料才發現,這種直接調用exec用法是不好的,數據量小可能體現不出來,

數據量大的時候 就會直接緩存爆滿 子進程就會卡死,所以我們可以創建2個線程來消費子進程運行shell命令產生的日志,正確用法如下

public class TestController {

    @GetMapping("/exp")
    public void addHomePage(String cmd) throws InterruptedException, IOException {
        //創建子進程調用shell命令
        new MyThread(cmd).start();
    }
}

class MyThread extends Thread {
    String cmd;
    MyThread(String cmd)
    {
        this.cmd = cmd;
    }
public void run(){ Process proc = null; try {
       String[] cmdAry = new String[]{"/bin/bash","-c",cmd} proc
= Runtime.getRuntime().exec(cmdAry); } catch (IOException e) { e.printStackTrace(); } //接收子進程的匯報信息和錯誤信息,避免阻塞 new StreamGobbler(proc.getInputStream(),"INFO").start(); new StreamGobbler(proc.getErrorStream(),"ERROR").start(); //獲取子進程執行結果狀態 int status= 0; try { status = proc.waitFor(); } catch (InterruptedException e) { e.printStackTrace(); } if (status == 0){ System.out.println("執行完畢"); }else System.out.println("執行失敗"); //銷毀子進程 proc.destroy(); } } class StreamGobbler extends Thread { InputStream is; String type; StreamGobbler(InputStream is, String type) { this.is = is; this.type = type; } public void run() { try { InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr); String line=null; while ( (line = br.readLine()) != null) System.out.println(type + ">" + line); } catch (IOException ioe) { ioe.printStackTrace(); } } }

這樣就可以了  記得以后調用shell命令都用這種形式


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM