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

}

}

}

3、shell脚本中有关联脚本,注意路径

就是shell脚本中还要执行其他脚本,这时候就是注意一个路径的问题,这个问题也是我找了好长时间的一个问题。

Process p=Runtime.getRuntime().exec(“/etc/a.sh”)

在Test.java类调用了etc目录下的a.sh脚本, a.sh脚本中执行etc目录下的b.sh脚本,原来我在a.sh脚本中写的是./b.sh。其实这样linux是找不到b.sh的,因为我们执行是在

Test.class目录下调用的/etc/a.sh  所以当a.sh中执行./b.sh的时候他会在Test.class目录下寻找,所以找不到,所以a.sh中要写成/etc/b.sh

4、java连续调用多个脚本

String[] cmd = { "/bin/sh", "-c", "rm -rf /installation/upgrade/ ; mkdir /installation/upgrade/" };

Process p = Runtime.getRuntime().exec(cmd);

p.waitFor();

就是这种数组的方式。

5、java执行.sh脚本文件的时候直接写目录就行,例如这样:Runtime.getRuntime().exec(“/etc/a.sh”)

java 直接执行语句的时候需要加上"/bin/sh"  例如这样:

String name="/bin/sh cd /installation/upgrade/ip89_install_packet";

Process p = Runtime.getRuntime().exec(name);

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值