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 {
}
}
}