我的编程空间,编程开发者的网络收藏夹
学习永远不晚

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

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

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

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

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

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Linux中如何连续执行多条命令

这篇文章主要为大家展示了“Linux中如何连续执行多条命令”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Linux中如何连续执行多条命令”这篇文章吧。每条命令使用";"隔开,则无论前边的命令执行
2023-06-09

在Laravel中如何执行Shell命令

这篇文章主要介绍在Laravel中如何执行Shell命令,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!shell_exec() 和 exec() 都可以执行 shell 命令。如果你的命令不知道因为什么原因而崩溃,你
2023-06-21

java如何执行(命令执行)

执行java文件方法:(相关视频教程推荐:java视频教程)使用环境:jdk1.6文件目录:javac *.java会生成对应的*.class文件java *.class就可以执行了,.class可以省略1、t.java中是没有包的public class t
java如何执行(命令执行)
2019-10-16

java在linux本地如何执行shell命令

这篇文章主要讲解了“java在linux本地如何执行shell命令”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“java在linux本地如何执行shell命令”吧!一.以springboot
2023-06-29

linux下如何执行shell命令

这篇文章将为大家详细讲解有关linux下如何执行shell命令,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。linux下执行shell命令有两种方法 在当前shell中执行shell命令在当前shell中
2023-06-09

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

android中执行java命令的方法大家都晓得吗,下面一段内容给大家带来了具体解析。android的程序基于java开发,当我们接上调试器,执行adb shell,就可以执行linux命令,但是却并不能执行java命令。 那么在andro
2022-06-06

dos、bat批处理如何延时执行命令

这篇文章给大家分享的是有关dos、bat批处理如何延时执行命令的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。第一种方法:ping 127.0.0.1 -n 5000>nul dir c:\ >c:\1.txt延时
2023-06-09

Java如何执行cmd命令

这篇文章主要介绍了Java如何执行cmd命令问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
2023-01-09

如何实现shell中嵌套执行expect命令

本篇内容主要讲解“如何实现shell中嵌套执行expect命令”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何实现shell中嵌套执行expect命令”吧!1.先安装expect代码如下:yu
2023-06-09

如何用shell脚本执行hadoop命令

要使用shell脚本执行Hadoop命令,可以按照以下步骤操作:1. 创建一个新的文本文件,并使用任何文本编辑器打开它(如vi、nano等)。2. 在文件的第一行添加以下内容,以告知操作系统要使用哪个解释器来执行该脚本:```bash#!/
2023-10-11

如何用java执行redis命令

本指南详细介绍了如何使用Java执行Redis命令。它涵盖了从连接到Redis服务器到执行高级操作,例如发布/订阅和事务。文章还讨论了监控和Lua脚本等最佳实践。通过遵循这些步骤,开发人员可以有效地利用Java与Redis交互。
如何用java执行redis命令
2024-04-02

如何在shell中使用expect命令进行远程执行命令脚本

如何在shell中使用expect命令进行远程执行命令脚本?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。expect是用来实现自动交互功能的工具之一,使用expect-send
2023-06-09

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录