Java执行shell遇到的各种问题
来源:互联网 发布:淘宝2016版本5.7.0下载 编辑:程序博客网 时间:2024/05/16 11:02
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;}@Overridepublic 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 blocke.printStackTrace();}}}};t1.start();t2.start();} catch (IOException e1) {// TODO Auto-generated catch blocke1.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);
- Java执行shell遇到的各种问题
- Java执行Shell遇到的各种问题
- 配置crontab定时执行调用java程序的shell脚本遇到的问题
- java发送邮件遇到的各种问题
- java web遇到的各种问题汇总
- shell的执行问题
- java编写程序遇到的各种乱码问题记录
- java编写程序遇到的各种乱码问题记录
- 新学习JAVA,记录遇到的各种奇葩问题
- java面试遇到的各种问题(不定期更新中~~)
- 上架遇到的各种问题
- 我遇到的各种问题
- 文件系统遇到的各种问题
- Mysql 遇到的各种问题
- 今天遇到的java执行sql语句的问题
- 使用Java调用shell脚本时遇到的问题
- maven打jar包,用doc命令执行jar遇到的各种问题(记录备忘)
- dos下编译执行java程序遇到的问题
- 高效开发 Android App 的 10 个建议
- listview 的Item 可点击跳转
- Android平板开发精确适配不同的dpi和屏幕尺寸
- 实现虚拟存储器的方式
- matlab中图像数据类型转换
- Java执行shell遇到的各种问题
- Hough 变换算法研究
- 导视系统设计欣赏
- 对于retain和assign属性的理解
- PostgreSQL 序列(SEQUENCE)
- 【安卓笔记】touch事件的分发和消费机制
- NYOJ45 棋盘覆盖
- android 内存溢出(oom)产生原因和内存优化
- cocos2d-x jsb 防止触摸事件传递