Java服務(wù)如何調(diào)用系統(tǒng)指令、Bat腳本記錄
前言
在項目推進過程中偶爾會涉及到調(diào)用其它組件或腳本的需求,本文重點介紹Java服務(wù)調(diào)用Bat腳本、系統(tǒng)指令。
調(diào)用Bat腳本
根據(jù)需求生成BAT腳本內(nèi)容文本,通過文件流寫入到新建的BAT文件中,然后利用ProcessBuilder執(zhí)行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"; // 批處理文件的路徑和名稱 // 創(chuàng)建一個Writer對象來寫入批處理命令 PrintWriter writer = new PrintWriter(new FileWriter(tBatFilePath)); writer.println(cCommand); // 在批處理文件中寫入命令 writer.close(); // 關(guān)閉Writer對象 // 執(zhí)行批處理文件 ProcessBuilder builder = new ProcessBuilder(tBatFilePath); // 輸出指令日志 builder.redirectOutput(ProcessBuilder.Redirect.INHERIT); builder.redirectError(ProcessBuilder.Redirect.INHERIT); // 啟動進程并后臺執(zhí)行批處理文件 builder.start(); // 刪除生成的批處理文件 File file = new File(tBatFilePath); if (file.delete()) { log.info("Batch file deleted successfully."); } }
當(dāng)前模式存在兩個問題需要手動處理:
1、設(shè)置了打印指令日志會導(dǎo)致最終服務(wù)運行的日志很多很雜,按理說Logger應(yīng)該可以配置單獨開一個日志文件,這塊暫時還沒研究到,有配置成功的同學(xué)記得評論區(qū)分享下哈。
2、執(zhí)行的BAT腳本為非阻塞型,所以針對BAT腳本運行中斷后的處理需要在BAT內(nèi)容中實現(xiàn),后面是筆者用到的BAT腳本,供大家參考。
@echo off :: 設(shè)置重試次數(shù)和計數(shù)器變量 set max_retry=3 set retry_count=0 set remote=$remote$ set local=$local$ :retry :: 檢查重試次數(shù)是否超過最大值 if %retry_count% gtr %max_retry% ( echo "Maximum retries exceeded. Quitting." goto end ) :: 調(diào)用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"
調(diào)用系統(tǒng)指令
執(zhí)行系統(tǒng)指令還是利用ProcessBuilder,包括日志打印的套路都與BAT腳本執(zhí)行一致,需要注意的一點是,針對指令中的空格分割需要通過List的集合進行拆分。
例如:
指令 rtmp-to-flv.exe -proxy 50003,50004,需要將其根據(jù)空格分為三份,分別裝進List集合中,然后使用processBuilder.command方法運行即可。
public void executeSystemCommand() { try { // 執(zhí)行批處理文件 Resource classpathResource = resourceLoader.getResource("classpath:"); String classpathPath = classpathResource.getFile().getAbsolutePath(); ProcessBuilder processBuilder = new ProcessBuilder(); //定義命令內(nèi)容 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(); // 啟動進程并后臺執(zhí)行批處理文件 } catch (Exception e) { e.printStackTrace(); } }
總結(jié)
利用JAVA服務(wù)運行系統(tǒng)指令及BAT腳本其實可以很大程度減輕JAVA的開發(fā)工總量,更容易做到功能的可插拔性,只是對開發(fā)人員的編碼要求和編程思想有一些較高的要求,當(dāng)然這也是作為研發(fā)的必經(jīng)之路,salute。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringCloud2020.0.x版UnderTow AccessLog相關(guān)配置簡介
本文詳細介紹了SpringCloud中AccessLog的相關(guān)配置,我們可以根據(jù)文中的相關(guān)數(shù)據(jù)配置出所需的AccessLog的信息以及格式,感興趣的小伙伴可以參考一下2021-08-08SpringBoot獲取yml和properties配置文件的內(nèi)容
這篇文章主要為大家詳細介紹了SpringBoot獲取yml和properties配置文件的內(nèi)容,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-04-04Java中PageHelper分頁后對list操作導(dǎo)致分頁無效
在項目中使用分頁插件的時候發(fā)現(xiàn)PageHelper插件失效了,本文就來介紹一下Java中PageHelper分頁后對list操作導(dǎo)致分頁無效的解決方法,感興趣的可以了解一下2021-05-05Mybatis多數(shù)據(jù)源切換實現(xiàn)代碼
這篇文章主要介紹了Mybatis多數(shù)據(jù)源切換實現(xiàn)代碼,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-10-10Java請求流量合并和拆分提高系統(tǒng)的并發(fā)量示例
這篇文章主要為大家介紹了Java請求流量合并和拆分提高系統(tǒng)的并發(fā)量示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步早日升職加薪2022-04-04SpringMVC處理器映射器HandlerMapping詳解
這篇文章主要介紹了SpringMVC處理器映射器HandlerMapping詳解,在SpringMVC中會有很多請求,每個請求都需要一個HandlerAdapter處理,具體接收到一個請求之后使用哪個HandlerAdapter進行處理呢,他們的過程是什么,需要的朋友可以參考下2023-09-09Java中提供synchronized后為什么還要提供Lock
這篇文章主要介紹了Java中提供synchronized后為什么還要提供Lock,在Java中提供了synchronized關(guān)鍵字來保證只有一個線程能夠訪問同步代碼塊,下文更多相關(guān)資料需要的小伙伴可以參考一下2022-03-03