Java 使用Runtime在一个Java程序中启动和关闭另一个Java程序
时间:2022-07-22
本文章向大家介绍Java 使用Runtime在一个Java程序中启动和关闭另一个Java程序,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
主要使用了
Runtime.getRuntime().exec(new String[]{"/bin/bash", "-c", cmd});
调用shell命令的工具类:
public static String runShell(String cmd) throws Exception {
StringBuilder result = new StringBuilder();
Process process = null;
BufferedReader bufrIn = null;
BufferedReader bufrError = null;
try {
// 执行命令, 返回一个子进程对象(命令在子进程中执行)使用这种方式可以使用|管道符命令
process = Runtime.getRuntime().exec(new String[]{"/bin/bash", "-c", cmd});
// 方法阻塞, 等待命令执行完成(成功会返回0)
process.waitFor();
// 获取命令执行结果, 有两个结果: 正常的输出 和 错误的输出(PS: 子进程的输出就是主进程的输入)
bufrIn = new BufferedReader(new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8));
bufrError = new BufferedReader(new InputStreamReader(process.getErrorStream(), StandardCharsets.UTF_8));
// 读取输出
String line;
while ((line = bufrIn.readLine()) != null) {
result.append(line).append('n');
}
while ((line = bufrError.readLine()) != null) {
result.append(line).append('n');
}
} finally {
closeStream(bufrIn);
closeStream(bufrError);
// 销毁子进程
if (process != null) {
process.destroy();
}
}
return result.toString();
}
当有jar包上传到接口时,调用这个方法,停止正在运行的jar,并启动新jar
JAR_NAME校验自定,这里固定使用一个jar包名,方便jps时找到该进程
/**
*jar包上传及执行
*/
private ResponseVo myjarPkg(MultipartFile file) throws Exception {
//myjar目录
String myjarDir = "/data/myjar/";
File fileDir = new File(myjarDir);
fileDir.mkdirs();
//文件名校验 名称不对则不执行
if (!JAR_NAME.equals(file.getOriginalFilename())) {
return new ResponseVo(-1, "不正确的文件");
}
File myjarPkg = new File(myjarDir + file.getOriginalFilename());
//将旧的已存在的删除
if (myjarPkg.exists()) {
FileUtils.deleteQuietly(myjarPkg);
}
file.transferTo(myjarPkg);
//运行myjar程序 先停掉之前的 再启动新上传的
//由jre目录进入到父级jdk目录 不直接替换可以防止没有jre目录的情况
String javaHome = System.getProperty("java.home").replace("/jre", "") + "/bin";
final String java = javaHome + "/java";
final String jps = javaHome + "/jps";
String cmd = jps + " -l|grep " + JAR_NAME + "|awk '{print$1}'";
String pid = ShellUtil.runShell(cmd);
if (StringUtils.isNotBlank(pid)) {
cmd = "kill -9 " + pid;
String killmsg = ShellUtil.runShell(cmd);
logger.info("kill process pid:{} ,result:{}", pid, killmsg);
//杀掉之后等3s
Thread.sleep(3000);
}
cmd = "nohup " + java + " -jar " + myjarDir + JAR_NAME + " > " + myjarDir + "myjar.log 2>&1 &";
String msg = ShellUtil.runShell(cmd);
logger.info("升级程序执行结果: " + msg);
return new ResponseVo();
}
重点是Java启动的process,不能直接执行java、jps等命令,也获取不到环境变量,会报command not found
于是我使用来System.getProperty("java.home") 来获取到执行当前程序的Java路径,再把jre目录替换为jdk目录,使用jdk目录下bin目录中的java及jps命令,可以达到需求
另外需要注意命令字符串中的空格很重要,不能忽略
- 几个不常用但特别实用的PHP预定义变量
- tomcat源码解读六 tomcat中的session生命历程
- tomcat源码解读五 Tomcat中Request的生命历程
- PostQueuedCompletionStatus
- tomcat源码解读四 tomcat中的processer
- tomcat源码解读三(2) tomcat中JMX的源码分析
- 程序的入口
- tomcat源码解读三(1) tomcat的jmx管理
- 利用xinetd实现简单web服务器(镜像站)
- tomcat源码解读二 tomcat的生命周期
- IOCP反射服务器
- 给PHP开发者讲讲PHP源码-第二部分
- 给PHP开发者讲讲PHP源码-第一部分
- tomcat源码解读一 Digester的解析方式
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- python中的yield和return—迭代器和生成器
- Android studio有关侧滑的实现代码
- 图片按照宽度等比例缩放
- Android 自定义加载动画Dialog弹窗效果的示例代码
- flutter的环境安装配置问题及解决方法
- (新)关于修改window.navigator.webdriver代码失效问题
- Android底部导航栏的三种风格实现
- Android Studio3.2中导出jar包的过程详解
- Android自定义view实现标签栏功能(只支持固定两个标签)
- python 爬虫之selenium可视化爬虫
- Android Studio3.6.+ 插件搜索不到终极解决方案(图文详解)
- Spring 整合 SpringDataRedis
- Android 实现可任意拖动的悬浮窗功能(类似悬浮球)
- Android仿抖音右滑清屏左滑列表功能的实现代码
- 利用织梦CMS0day注入漏洞渗透测试