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);
Java执行shell遇到的各种问题的更多相关文章
- Java执行Shell脚本
Linux 系统下采用 Java 执行 Shell 脚本,直接上代码: package com.smbea.demo; import java.io.BufferedReader; import ja ...
- Java执行shell脚本并返回结果两种方法的完整代码
Java执行shell脚本并返回结果两种方法的完整代码 简单的是直接传入String字符串,这种不能执行echo 或者需要调用其他进程的命令(比如调用postfix发送邮件命令就不起作用) 执行复杂的 ...
- 利用java执行shell脚本
BPMN中存在由系统执行的脚本任务,shell脚本任务也是该系统任务脚本中的一种,利用的也是由java执行shell脚本. 代码中的ProcessBuilder类,为java.lang.Process ...
- java 执行shell命令及日志收集避坑指南
有时候我们需要调用系统命令执行一些东西,可能是为了方便,也可能是没有办法必须要调用.涉及执行系统命令的东西,则就不能做跨平台了,这和java语言的初衷是相背的. 废话不多说,java如何执行shell ...
- Android Java执行Shell命令
最新内容建议直接访问原文:http://www.trinea.cn/android/android-java-execute-shell-commands/ 主要介绍Android或Java应用中如何 ...
- Java 执行Shell脚本指令
一.介绍 有时候我们在Linux中运行Java程序时,需要调用一些Shell命令和脚本.而Runtime.getRuntime().exec()方法给我们提供了这个功能,而且Runtime.getRu ...
- java 执行shell命令遇到的坑
正常来说java调用shell命令就是用 String[] cmdAry = new String[]{"/bin/bash","-c",cmd} Runtim ...
- java执行shell脚本并输出执行情况
1.脚本test.sh,置于/Users/hdwang目录下 #!/bin/sh cd /Users/hdwang echo ls:`ls` ;i<=;i++)); do + ); sleep ...
- [Java] Java执行Shell命令
Methods ProcessBuilder.start() 和 Runtime.exec() 方法都被用来创建一个操作系统进程(执行命令行操作),并返回 Process 子类的一个实例,该实例可用来 ...
随机推荐
- idea设置代码提示不区分大小写
idea设置代码提示不区分大小写 intellij idea默认下的代码提示是区分大小写的,例如类方法名过长.类的名字过长等,完全通过手打的话较为繁琐,这里简单的设置下即可. 把 Case sensi ...
- java001单词拼写
System.out.printIn("string"); 报错: 百度大神指点,是小写的l而不是大写的I,应该为 System.out.println("Hello S ...
- [LeetCode&Python] Problem 744. Find Smallest Letter Greater Than Target
Given a list of sorted characters letters containing only lowercase letters, and given a target lett ...
- 测试那些事儿—selenium自动化实战之登录验证码处理
登陆时经常出现验证码自动化测试如何处理呢? 一般有如下几种处理思路: 1.通过接口请求,拿到对应验证码信息 2.让开发配合把验证码改成万能验证码 3.注入cookies 如何通过注入cookies的方 ...
- Arduino SD卡 列出文件
/* SD卡测试 这个例子展示了如何使用实用程序库 sd库是基于获取您的SD卡的信息. 非常有用的测试卡,当你不确定它是否工作. 电路: *附在SPI总线上的SD卡如下: * MOSI引脚11上的Ar ...
- Nmap使用指南
一.目标指定 1.CIDR标志位 192.168.1.0/24 2.指定范围 192.168.1.1-255 192.168.1-255.1(任意位置) 3.IPv6地址只能用规范的IPv6地址或主机 ...
- 关于PostmanURL中不能传递中文的问题
众所周知,中文乱码等问题在开发过程中让人厌烦,本人最近在使用Postman插件测试web的时候,在请求中添加了中文,结果请求错误 截图如下: 原因:不能直接处理中文,需要自行转化 解决: 1.新建一个 ...
- 【java多线程】队列系统之ArrayBlockingQueue源码
1.简介 ArrayBlockingQueue,顾名思义:基于数组的阻塞队列.数组是要指定长度的,所以使用ArrayBlockingQueue时必须指定长度,也就是它是一个有界队列. 它实现了Bloc ...
- 第3章 Java数组(上): 一维数组和二维数组
3.数组及排序算法(2天) 3.1 数组的概述 2课时 3.2 一维数组的使用 3课时 3.3 多维数组的使用 3课时 3.4 数组中涉及到的常见算法 3课时 3.5 Arrays工具类的使用 3课时 ...
- 算法分析(2)——大O和大Θ
当一个软件遇到了性能瓶颈时,首要的改进是软件功能重构,适当删除可能拖垮系统的业务需求.客户对“实时”相当感兴趣,然而又有几个使用者能够真正清楚什么地方应该是实时的?这一点同样体现在其它行业,生厂商想要 ...