zoukankan      html  css  js  c++  java
  • 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()前不断读取标准输出流和标准错误流:

    [java] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    1. //jyName  解压脚本路径  
    2. String fileName=fileList.get(0).toString().substring(fileList.get(0).toString().lastIndexOf(File.separator)+1);  
    3. String  jyName="/etc/zxvf.sh "+fileName;  
    4. try {  
    5.     Process p0 = Runtime.getRuntime().exec(jyName);  
    6.     //读取标准输出流  
    7.     BufferedReader bufferedReader =new BufferedReader(new InputStreamReader(p0.getInputStream()));  
    8.     String line;  
    9.     while ((line=bufferedReader.readLine()) != null) {  
    10.         System.out.println(line);  
    11.     }     
    12.     //读取标准错误流  
    13.     BufferedReader brError = new BufferedReader(new InputStreamReader(p0.getErrorStream(), "gb2312"));  
    14.     String errline = null;  
    15.     while ((errline = brError.readLine()) != null) {  
    16.          System.out.println(errline);  
    17.     }  
    18.     //waitFor()判断Process进程是否终止,通过返回值判断是否正常终止。0代表正常终止  
    19.     int c=p0.waitFor();  
    20.     if(c!=0){  
    21.         baseRes.put("desc", "软件升级失败:执行zxvf.sh异常终止");  
    22.         baseRes.setReturnFlag(false);  
    23.         return baseRes;  
    24.     }  
    25. catch (IOException e1) {  
    26.     baseRes.put("desc", "软件升级失败:文件解压失败");  
    27.     baseRes.setReturnFlag(false);  
    28.     return baseRes;  
    29. catch (InterruptedException e1) {  
    30.     baseRes.put("desc", "软件升级失败:文件解压失败");  
    31.     baseRes.setReturnFlag(false);  
    32.     return baseRes;  
    33. }  


    也可以在执行Runtime.getRuntime().exec(jyName)之后另外再启动两个线程分别读取标准错误流和标准输出流

    [java] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    1. import java.io.BufferedReader;  
    2. import java.io.IOException;  
    3. import java.io.InputStream;  
    4. import java.io.InputStreamReader;  
    5.   
    6. public class ExcuteThread extends Thread {  
    7.     private String name;  
    8.   
    9.     public ExcuteThread(String name) {  
    10.         this.name = name;  
    11.     }  
    12.     @Override  
    13.     public void run() {  
    14.         try {  
    15.             Process p = Runtime.getRuntime().exec(name);  
    16.             InputStream fis = p.getInputStream();  
    17.             final BufferedReader brError = new BufferedReader(  
    18.                     new InputStreamReader(p.getErrorStream(), "gb2312"));  
    19.             InputStreamReader isr = new InputStreamReader(fis, "gb2312");  
    20.             final BufferedReader br = new BufferedReader(isr);  
    21.             Thread t1 = new Thread() {  
    22.                 public void run() {  
    23.                     String line = null;  
    24.                     try {  
    25.                         while ((line = brError.readLine()) != null) {  
    26.                             // System.out.println(line);  
    27.                         }  
    28.                     } catch (IOException e) {  
    29.                         e.printStackTrace();  
    30.                     } finally {  
    31.                         try {  
    32.                             if (brError != null)  
    33.                                 brError.close();  
    34.                         } catch (IOException e) {  
    35.                             e.printStackTrace();  
    36.                         }  
    37.                     }  
    38.                 }  
    39.             };  
    40.             Thread t2 = new Thread() {  
    41.                 public void run() {  
    42.                     String line = null;  
    43.                     try {  
    44.                         while ((line = br.readLine()) != null) {  
    45.                             // System.out.println(line);  
    46.                         }  
    47.                     } catch (IOException e) {  
    48.                         e.printStackTrace();  
    49.                     } finally {  
    50.                         try {  
    51.                             if (br != null)  
    52.                                 br.close();  
    53.                         } catch (IOException e) {  
    54.                             // TODO Auto-generated catch block  
    55.                             e.printStackTrace();  
    56.                         }  
    57.                     }  
    58.                 }  
    59.             };  
    60.             t1.start();  
    61.             t2.start();  
    62.   
    63.         } catch (IOException e1) {  
    64.             // TODO Auto-generated catch block  
    65.             e1.printStackTrace();  
    66.         } finally {  
    67.         }  
    68.   
    69.     }  
    70.   
    71. }  

    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连续调用多个脚本

    [java] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    1. String[] cmd = { "/bin/sh", "-c", "rm -rf /installation/upgrade/ ; mkdir /installation/upgrade/" };  
    2. Process p = Runtime.getRuntime().exec(cmd);  
    3. p.waitFor();  


    就是这种数组的方式。

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

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

    [java] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
      1. String name="/bin/sh cd /installation/upgrade/ip89_install_packet";  
      2. Process p = Runtime.getRuntime().exec(name);  
  • 相关阅读:
    OpenGL Pixel Linked-List
    Unity multi_compile
    Bindless Textures
    chmod递归设置文件属性
    push submodule
    NodeJS Debugger
    重载new操作符
    OpenGL瓶颈
    NGUI架构和Draw Call合并原理
    字符串哈希函数(String Hash Functions)
  • 原文地址:https://www.cnblogs.com/hanlong/p/5761662.html
Copyright © 2011-2022 走看看