• Java中如何执行多条shell/bat命令 2023年验证通过


    Java中如何执行多条shell/bat命令

    这篇文章主要介绍了Java中如何执行多条shell/bat命令的方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

    java调用process执行命令

    public class ShellUtil {
        public static String runShell (String shStr) throws Exception {
            Process process;
            process = Runtime.getRuntime().exec( new String[]{ "/bin/sh" , "-c" ,shStr});
            process.waitFor();
            BufferedReader read = new BufferedReader( new InputStreamReader(process.getInputStream()));
            String line = null ;
            String result = "" ;
            while ((line = read.readLine())!= null ){
                result+=line;
            }
            return result;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    注意:如果是windows操作系统要改为

    Runtime.getRuntime().exec(new String[]{"**cmd** exe","-c","command"});
    
    • 1

    1.当要执行多条时且不依赖事务,可以分开多次调用

    public class ExecuteShell {
        public static void main (String[] args){
            String command1 = "some command" ;
            String command2 = "some command" ;
            String message1 = ShellUtil.runShell(command1);
            String message2 = ShellUtil.runShell(command2);
            System. out .println(message1);
            System. out .println(message2);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    2.但是当命令之间有事务依赖时

    比如一条命令是登录数据库,第二条执行查询语句,上面分开多次调用的方式就不行。需要做改动如下

    public class ExecuteShell {
        public static void main (String[] args){
            String command1 = "some command" ;
            String command2 = "some command" ;
            String message1 = ShellUtil.runShell(command1);
            String message2 = ShellUtil.runShell(command2);
            System. out .println(message1);
            System. out .println(message2);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    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;
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    也可以在执行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 {
      } 
     } 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68

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

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

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

    在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();
    
    • 1
    • 2
    • 3

    就是这种数组的方式。

    5、java执行.sh脚本文件的时候直接写目录就行

    例如这样:

    Runtime.getRuntime().exec(“/etc/a.sh”)
    
    • 1

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

       String name="/bin/sh cd /installation/upgrade/ip89_install_packet";
       Process p = Runtime.getRuntime().exec(name);
    
    • 1
    • 2

    转载

    Java中如何执行多条shell/bat命令_java_脚本之家 (jb51.net)

  • 相关阅读:
    如何使用U盘重装系统?
    微服务项目:尚融宝(14)(前端平台:尚融宝管理系统路由配置)
    MATLAB算法实战应用案例精讲-【优化算法】沙丁鱼优化算法(SOA)(附MATLAB代码实现)
    BGP——基本概念3(路由聚合)
    Python学习笔记--字符、变量、数据类型与注释
    Linux防火墙命令
    MGADA | 用于目标检测的多粒度对齐域自适应
    ubuntu在线直接升级
    69.C++多继承与纯虚函数
    Python绘图系统21:导出数据
  • 原文地址:https://blog.csdn.net/qq_46110497/article/details/126541065