Spring Boot調(diào)用 Shell 腳本實(shí)現(xiàn)看門(mén)狗功能
需要實(shí)現(xiàn)看門(mén)狗功能,定時(shí)檢測(cè)另外一個(gè)程序是否在運(yùn)行,使用 crontab 僅可以實(shí)現(xiàn)檢測(cè)程序是否正在運(yùn)行,無(wú)法做到擴(kuò)展,如:手動(dòng)重啟、程序升級(jí)(如果只需要實(shí)現(xiàn)自動(dòng)升級(jí)功能可以使用 inotify)等功能;最后決定使用 Spring Boot 調(diào)用 Shell 腳本來(lái)實(shí)現(xiàn)
一、腳本
1.1 啟動(dòng)腳本
#!/bin/bash ps -ef | grep "demo-app-0.0.1-SNAPSHOT.jar" | grep -v "grep" if [ "$?" -eq 0 ] then # sleep echo $(date "+%Y-%m-%d %H:%M:%S") "process already started!" else nohup java -jar -server /project/watchdog/demo-app-0.0.1-SNAPSHOT.jar & echo $(date "+%Y-%m-%d %H:%M:%S") "process has been started!" fi
1.2 重啟腳本
#!/bin/bash
pid=`ps -ef | grep "demo-app-0.0.1-SNAPSHOT.jar" | grep -v "grep" | awk '{print $2}'`
for id in $pid
do
kill -9 $id
echo "killed $id"
done
nohup java -jar -server /project/watchdog/demo-app-0.0.1-SNAPSHOT.jar &
echo $(date "+%Y-%m-%d %H:%M:%S") "process has been restarted!"
二、功能實(shí)現(xiàn)
將腳本放置在程序的資源目錄下,每次程序啟動(dòng)時(shí)將腳本讀取到指定位置,然后再通過(guò)定時(shí)任務(wù)執(zhí)行腳本
配置內(nèi)容:
shell:
directory: /project/watchdog
startupFileName: startup.sh
restartFileName: restart.sh
@Configuration
@ConfigurationProperties(prefix = "shell")
public class ShellProperties {
private String directory;
private String startupFileName;
private String restartFileName;
/* getter & setter */
public String getFullName(String fileName) {
return directory + File.separator + fileName;
}
}
2.1 啟動(dòng)時(shí)將腳本讀取到指定位置
@Component
public class InitRunner implements CommandLineRunner {
@Autowired
private ShellProperties shellProperties;
@Autowired
ResourceLoader resourceLoader;
@Override
public void run(String... args) throws Exception {
generateFile(shellProperties.getStartupFileName());
generateFile(shellProperties.getRestartFileName());
}
private void generateFile(String fileName) throws IOException {
String fileFullName = shellProperties.getFullName(fileName);
File file = new File(fileFullName);
if(file.exists()) {
return;
}
// 如果文件已存在,F(xiàn)ileWriter 會(huì)先刪除再新建
FileWriter fileWriter = new FileWriter(fileFullName);
Resource resource = resourceLoader.getResource("classpath:" + fileName);
InputStream inputStream = resource.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String data;
while ((data = bufferedReader.readLine()) != null) {
fileWriter.write(data + "\n");
}
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
fileWriter.close();
// 設(shè)置權(quán)限,否則會(huì)報(bào) Permission denied
file.setReadable(true);
file.setWritable(true);
file.setExecutable(true);
}
}
2.2 定時(shí)任務(wù)定時(shí)任務(wù)執(zhí)行腳本
@Component
public class ShellTask {
private static final Logger logger = LoggerFactory.getLogger(ShellTask.class);
@Autowired
private ShellProperties shellProperties;
@Scheduled(cron = "0/10 * * * * ? ")
public void start() throws IOException {
executeShell(shellProperties.getStartupFileName());
}
private void executeShell(String fileName) throws IOException {
String fileFullName = shellProperties.getFullName(fileName);
File file = new File(fileFullName);
if(!file.exists()) {
logger.error("file {} not existed!", fileFullName);
return;
}
ProcessBuilder processBuilder = new ProcessBuilder(fileFullName);
processBuilder.directory(new File(shellProperties.getDirectory()));
Process process = processBuilder.start();
// String input;
// BufferedReader stdInput = new BufferedReader(new InputStreamReader(process.getInputStream()));
// BufferedReader stdError = new BufferedReader(new InputStreamReader(process.getErrorStream()));
// while ((input = stdInput.readLine()) != null) {
// logger.info(input);
// }
// while ((input = stdError.readLine()) != null) {
// logger.error(input);
// }
int runningStatus = 0;
try {
runningStatus = process.waitFor();
} catch (InterruptedException e) {
logger.error("shell", e);
}
if(runningStatus != 0) {
logger.error("failed.");
}else {
logger.info("success.");
}
}
}
2.3 擴(kuò)展
本例只實(shí)現(xiàn)了定時(shí)檢測(cè)程序是否運(yùn)行,如果沒(méi)有運(yùn)行則啟動(dòng)程序;如有需要可以添加接口,調(diào)用接口重啟程序;或者添加定時(shí)任務(wù)定時(shí)檢測(cè)程序是否有更新,如果有更新則下載新的 jar 包然后重啟程序
看門(mén)狗程序自己可以使用 crontab 定時(shí)檢測(cè)是否正在運(yùn)行,模仿上面的啟動(dòng)腳本編寫(xiě)看門(mén)狗的啟動(dòng)腳本,然后添加定時(shí)任務(wù):
crontab -e */10 * * * * /project/watchdog/watchdog.sh sudo systemctl reload crond.service
完整代碼:GitHub
參考:java去調(diào)用并執(zhí)行shell腳本以及問(wèn)題總結(jié)
總結(jié)
到此這篇關(guān)于Spring Boot調(diào)用 Shell 腳本實(shí)現(xiàn)看門(mén)狗功能的文章就介紹到這了,更多相關(guān)spring boot 看門(mén)狗內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java運(yùn)行時(shí)動(dòng)態(tài)生成類實(shí)現(xiàn)過(guò)程詳解
這篇文章主要介紹了Java運(yùn)行時(shí)動(dòng)態(tài)生成類實(shí)現(xiàn)過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07
java int類型二維數(shù)組實(shí)現(xiàn)“楊輝三角”的完整實(shí)例
這篇文章主要給大家介紹了關(guān)于java int類型二維數(shù)組實(shí)現(xiàn)“楊輝三角”的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12
詳解springBoot啟動(dòng)時(shí)找不到或無(wú)法加載主類解決辦法
這篇文章主要介紹了詳解springBoot啟動(dòng)時(shí)找不到或無(wú)法加載主類解決辦法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09
SpringBoot 設(shè)置傳入?yún)?shù)非必要的操作
這篇文章主要介紹了SpringBoot 設(shè)置傳入?yún)?shù)非必要的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-02-02
Java實(shí)現(xiàn)word/pdf轉(zhuǎn)html并在線預(yù)覽
這篇文章主要為大家詳細(xì)介紹了如何利用Java語(yǔ)言實(shí)現(xiàn)word、pdf文件轉(zhuǎn)html并在線預(yù)覽的功能,文中的示例代碼講解詳細(xì),需要的可以參考一下2023-05-05

