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;
    }
}

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

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

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);
    }
}

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

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

public class ExecuteShell {
    public static void main (String[] args){
        String command1 = "some command" ;
        String command2 = "some command" ;
        String command = command1 + " && " + command2;
        String message = ShellUtil.runShell(command);
        System. out .println(message);
    }
}

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)

相关推荐

  • 关于protected修饰符详解-源于Cloneable接口

    目录 今天在做对象拷贝的时候发现一个问题 接下来按照我们的思路写代码实现 为什么应用了Cloneable接口的类 通常还必须重写一个public的clone()方法 总结 Cloneable接口是一个空接口,仅用于标记对象,Cloneable接口里面是没有clone()方法,clone()方法是Object类里面的方法,默认实现是一个Native方法. 今天在做对象拷贝的时候发现一个问题 某类实现Cloneable接口后,还要重新实现Object类中的clone()方法: 感觉有点奇怪,这个类里

  • Java执行cmd命令两种实现方法解析

    一般java在执行CMD命令时,通常是使用Runtime.getRuntime.exec(command)来执行的,这个方法有两种细节要注意: 1.一般执行方法,代码如下,这种方法有时执行exe时会卡在那里. //一般的执行方法,有时执行exe会卡在那 stmt要执行的命令 public static void executive(String stmt) throws IOException, InterruptedException { Runtime runtime = Runtime.g

  • java如何连续执行多条cmd命令

    java连续执行多条cmd命令 命令之间用&连接 例如: Process p = Runtime.getRuntime().exec("cmd /c d: & cd bin/"); java ssh登录执行多条cmd命令 java登录ssh执行多条命令,解决出现more自动回车的问题 import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import ja

  • Java基于Runtime调用外部程序出现阻塞的解决方法

    本文实例讲述了Java基于Runtime调用外部程序出现阻塞的解决方法, 是一个很实用的技巧.分享给大家供大家参考.具体分析如下: 有时候在java代码中会调用一些外部程序,比如SwfTools来转换swf.ffmpeg来转换视频等.如果你的代码这样写:Runtime.getRuntime().exec(command),会发现程序一下就执行完毕,而在命令行里要执行一会,是因为java没有等待外部程序的执行完毕,此时就需要使用阻塞,来等待外部程序执行结果: InputStream stderr

  • 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

  • 在python 中实现运行多条shell命令

    使用py时可能需要连续运行多条shell 命令 1. # coding: UTF-8 import sys reload(sys) sys.setdefaultencoding('utf8') import subprocess import os import commands #os.system('cmd1 && cmd2') cmd1 = "cd ../" cmd2 = "ls" cmd = cmd1 + " &&

  • java Runtime如何执行多条命令

    目录 java Runtime如何执行多条命令 Runtime.getRuntime().exec 执行多条 java Runtime如何执行多条命令 使用 && 分隔命令 public static void cmd() { String ls = " cd /home/ && dir "; Process process = null; String cmd = getOsCmd()+ ls; try { process = Runtime.getR

  • Java中try-catch-finally执行顺序你知道吗

    目录 引言 正文 try块中有return catch块中有return try块和finally块中有return catch块和finally块中有return try块.catch块和finally块中都有return 总结 引言 java异常处理中,try.catch.finally的执行顺序,大家都知道是按顺序执行的,这里我就不废话了.但是当try.catch.finally中加入return之后,就会有几种不同的情况出现,下面分别来说明一下.也可以跳到最后直接看总结. 正文 这里共列

  • java中如何执行xshell命令

    目录 java执行xshell命令 实例 Xshell启动java项目脚本(标本参考) 项目启动脚本 java执行xshell命令 实例 import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class Lin { public static void main(String[] args) { Process process =null; //chm

  • 详解如何在Java中调用Python程序

    Java中调用Python程序 1.新建一个Maven工程,导入如下依赖 <dependency> <groupId>org.python</groupId> <artifactId>jython-standalone</artifactId> <version>2.7.0</version> </dependency> 2.在java中直接执行python代码片段 import org.python.util

  • Android中执行java命令的方法及java代码执行并解析shell命令

    android中执行java命令的方法大家都晓得吗,下面一段内容给大家带来了具体解析. android的程序基于java开发,当我们接上调试器,执行adb shell,就可以执行linux命令,但是却并不能执行java命令. 那么在android的shell中是否就不能执行java程序了呢. 答案是否定的.我们可以通过app_process来执行java程序. 写一个hello world吧,就是刚开始学java的时候 写得那个hello world,这次要在android上运行. 用记事本新建

  • Java JSch远程执行Shell命令的方法

    目录 背景 JSch简介 使用示例 需要注意的点 参考文档 背景 项目需求,需要远程 ssh 登录到某个节点执行 shell 命令来完成任务.对于这种需求,如果不用 java 程序,直接 linux 的 ssh 命令就可以完成,但是在编码到程序中时需要相关的程序包来完成,本文主要介绍在 java 中如何使用 JSch 包实现 ssh 远程连接并执行命令. JSch 简介 JSch是Java Secure Channel的缩写.JSch是一个SSH2的纯Java实现.它允许你连接到一个SSH服务器

  • Java中16条的代码规范

    目录 一.MyBatis 不要为了多个查询条件而写 1 = 1 二. 迭代entrySet() 获取Map 的key 和value 三.使用Collection.isEmpty() 检测空 四.初始化集合时尽量指定其大小 五.使用StringBuilder 拼接字符串 六.若需频繁调用Collection.contains 方法则使用Set 七.使用静态代码块实现赋值静态成员变量 八.删除未使用的局部变量.方法参数.私有方法.字段和多余的括号. 九.工具类中屏蔽构造函数 十.删除多余的异常捕获并

随机推荐