歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> SHELL編程

Java執行Shell遇到的各種問題

1、判斷子進程是否執行結束

有的時候我們用java調用shell之後,之後的操作要在Process子進程正常執行結束的情況下才可以繼續,所以我們需要判斷Process進程什麼時候終止。

Process類提供了waitFor()方法。該方法導致當前線程等待,直到Process線程終止。

Process.waitFor()是有一個int類型返回值的,當返回值為0的時候表Process進程正常終止。否則一般是腳本執行出錯了(我遇到的一般是這種情況)。

2、Process.waitFor()導致當前線程阻塞。

有的時候我們發現調用waitFor()方法後,java主線程會一直阻塞在waitFor()處,阻塞的原因是什麼呢?分析一下:

Java在執行Runtime.getRuntime().exec(jyName)之後,Linux會創建一個進程,該進程與JVM進程建立三個管道連接,標准輸入流、標准輸出流、標准錯誤流,假設linux進程不斷

向標准輸出流和標准錯誤流寫數據,而JVM卻不讀取,數據會暫存在linux緩存區,當緩存區存滿之後導致該進程無法繼續寫數據,會僵死,導致java進程會卡死在waitFor()處,

永遠無法結束。

解決辦法:java進程在waitFor()前不斷讀取標准輸出流和標准錯誤流:

  //jyName  解壓腳本路徑
  String fileName=fileList.get(0).toString().substring(fileList.get(0).toString().lastIndexOf(File.separator)+1);
  String  jyName="/etc/zxvf.sh "+fileName;
  try {
   Process p0 = Runtime.getRuntime().exec(jyName);
   //讀取標准輸出流
   BufferedReader bufferedReader =new BufferedReader(new InputStreamReader(p0.getInputStream()));
   String line;
   while ((line=bufferedReader.readLine()) != null) {
      System.out.println(line);
   } 
   //讀取標准錯誤流
   BufferedReader brError = new BufferedReader(new InputStreamReader(p0.getErrorStream(), "gb2312"));
   String errline = null;
   while ((errline = brError.readLine()) != null) {
    System.out.println(errline);
   }
   //waitFor()判斷Process進程是否終止,通過返回值判斷是否正常終止。0代表正常終止
   int c=p0.waitFor();
   if(c!=0){
    baseRes.put("desc", "軟件升級失敗:執行zxvf.sh異常終止");
    baseRes.setReturnFlag(false);
    return baseRes;
   }
  } catch (IOException e1) {
   baseRes.put("desc", "軟件升級失敗:文件解壓失敗");
   baseRes.setReturnFlag(false);
   return baseRes;
  } catch (InterruptedException e1) {
   baseRes.put("desc", "軟件升級失敗:文件解壓失敗");
   baseRes.setReturnFlag(false);
   return baseRes;
  }

也可以在執行Runtime.getRuntime().exec(jyName)之後另外再啟動兩個線程分別讀取標准錯誤流和標准輸出流

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class ExcuteThread extends Thread {
 private String name;

 public ExcuteThread(String name) {
  this.name = name;
 }
 @Override
 public void run() {
  try {
   Process p = Runtime.getRuntime().exec(name);
   InputStream fis = p.getInputStream();
   final BufferedReader brError = new BufferedReader(
     new InputStreamReader(p.getErrorStream(), "gb2312"));
   InputStreamReader isr = new InputStreamReader(fis, "gb2312");
   final BufferedReader br = new BufferedReader(isr);
   Thread t1 = new Thread() {
    public void run() {
     String line = null;
     try {
      while ((line = brError.readLine()) != null) {
       // System.out.println(line);
      }
     } catch (IOException e) {
      e.printStackTrace();
     } finally {
      try {
       if (brError != null)
        brError.close();
      } catch (IOException e) {
       e.printStackTrace();
      }
     }
    }
   };
   Thread t2 = new Thread() {
    public void run() {
     String line = null;
     try {
      while ((line = br.readLine()) != null) {
       // System.out.println(line);
      }
     } catch (IOException e) {
      e.printStackTrace();
     } finally {
      try {
       if (br != null)
        br.close();
      } catch (IOException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
      }
     }
    }
   };
   t1.start();
   t2.start();

  } catch (IOException e1) {
   // TODO Auto-generated catch block
   e1.printStackTrace();
  } finally {
  }

 }

}

Copyright © Linux教程網 All Rights Reserved