Java服务如何调用系统指令、Bat脚本记录
作者:Aikes902
这篇文章主要介绍了Java服务如何调用系统指令、Bat脚本记录,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
前言
在项目推进过程中偶尔会涉及到调用其它组件或脚本的需求,本文重点介绍Java服务调用Bat脚本、系统指令。
调用Bat脚本
根据需求生成BAT脚本内容文本,通过文件流写入到新建的BAT文件中,然后利用ProcessBuilder执行BAT命令,最后判断删除生成的BAT文件。
public void executeBatScript(String cCommand, String cBatFileName, String cBasePath) throws Exception { //判断路径是否存在 File directory = new File(cBasePath); if (!directory.exists()) { directory.mkdir(); } String tBatFilePath = cBasePath + cBatFileName + ".bat"; // 批处理文件的路径和名称 // 创建一个Writer对象来写入批处理命令 PrintWriter writer = new PrintWriter(new FileWriter(tBatFilePath)); writer.println(cCommand); // 在批处理文件中写入命令 writer.close(); // 关闭Writer对象 // 执行批处理文件 ProcessBuilder builder = new ProcessBuilder(tBatFilePath); // 输出指令日志 builder.redirectOutput(ProcessBuilder.Redirect.INHERIT); builder.redirectError(ProcessBuilder.Redirect.INHERIT); // 启动进程并后台执行批处理文件 builder.start(); // 删除生成的批处理文件 File file = new File(tBatFilePath); if (file.delete()) { log.info("Batch file deleted successfully."); } }
当前模式存在两个问题需要手动处理:
1、设置了打印指令日志会导致最终服务运行的日志很多很杂,按理说Logger应该可以配置单独开一个日志文件,这块暂时还没研究到,有配置成功的同学记得评论区分享下哈。
2、执行的BAT脚本为非阻塞型,所以针对BAT脚本运行中断后的处理需要在BAT内容中实现,后面是笔者用到的BAT脚本,供大家参考。
@echo off :: 设置重试次数和计数器变量 set max_retry=3 set retry_count=0 set remote=$remote$ set local=$local$ :retry :: 检查重试次数是否超过最大值 if %retry_count% gtr %max_retry% ( echo "Maximum retries exceeded. Quitting." goto end ) :: 调用ffmpeg指令 ffmpeg -i rtmp://105if39328.51pc.cn:1935/live/0 -c copy -f flv rtmp://127.0.0.1:50001/live/aa8 ffmpeg -i %remote% -c copy -f flv %local% :: 检查上一个命令的退出代码是否为0(成功) if %errorlevel% neq nul ( echo "remote:%remote%. local:%local%. errorlevel:%errorlevel%. Retrying in 10 seconds...This is No.%retry_count% times Retry" :: 等待10秒后重试 ping -n 15 127.0.0.1 > nul set /a retry_count+=1 goto retry ) :end echo "Done"
调用系统指令
执行系统指令还是利用ProcessBuilder,包括日志打印的套路都与BAT脚本执行一致,需要注意的一点是,针对指令中的空格分割需要通过List的集合进行拆分。
例如:
指令 rtmp-to-flv.exe -proxy 50003,50004,需要将其根据空格分为三份,分别装进List集合中,然后使用processBuilder.command方法运行即可。
public void executeSystemCommand() { try { // 执行批处理文件 Resource classpathResource = resourceLoader.getResource("classpath:"); String classpathPath = classpathResource.getFile().getAbsolutePath(); ProcessBuilder processBuilder = new ProcessBuilder(); //定义命令内容 List<String> command = new ArrayList<>(); // rtmp-to-flv.exe -proxy 50003,50004 // String os= System.getProperty("os.name").toLowerCase(); if (os.contains("windows")) { command.add(classpathPath + "/rtmp-to-flv.exe"); } else { command.add(classpathPath + "/rtmp-to-flv"); } command.add("-proxy"); command.add("50003,50004"); processBuilder.command(command); //将标准输入流和错误输入流合并,通过标准输入流读取信息 processBuilder.redirectOutput(ProcessBuilder.Redirect.INHERIT); processBuilder.redirectError(ProcessBuilder.Redirect.INHERIT); processBuilder.start(); // 启动进程并后台执行批处理文件 } catch (Exception e) { e.printStackTrace(); } }
总结
利用JAVA服务运行系统指令及BAT脚本其实可以很大程度减轻JAVA的开发工总量,更容易做到功能的可插拔性,只是对开发人员的编码要求和编程思想有一些较高的要求,当然这也是作为研发的必经之路,salute。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。