1. 程式人生 > 程式設計 >Spring Boot呼叫 Shell 指令碼實現看門狗功能

Spring Boot呼叫 Shell 指令碼實現看門狗功能

需要實現看門狗功能,定時檢測另外一個程式是否在執行,使用 crontab 僅可以實現檢測程式是否正在執行,無法做到擴充套件,如:手動重啟、程序升級(如果只需要實現自動升級功能可以使用 inotify)等功能;最後決定使用 Spring Boot 呼叫 Shell 指令碼來實現

一、指令碼

1.1 啟動指令碼

#!/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!"

二、功能實現

將指令碼放置在程式的資源目錄下,每次程式啟動時將指令碼讀取到指定位置,然後再通過定時任務執行指令碼

配置內容:

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 啟動時將指令碼讀取到指定位置

@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;
  }

  // 如果檔案已存在,FileWriter 會先刪除再新建
  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();

  // 設定許可權,否則會報 Permission denied
  file.setReadable(true);
  file.setWritable(true);
  file.setExecutable(true);
 }
}

2.2 定時任務定時任務執行指令碼

@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 擴充套件

本例只實現了定時檢測程式是否執行,如果沒有執行則啟動程式;如有需要可以新增介面,呼叫介面重啟程式;或者新增定時任務定時檢測程式是否有更新,如果有更新則下載新的 jar 包然後重啟程式

看門狗程式自己可以使用 crontab 定時檢測是否正在執行,模仿上面的啟動指令碼編寫看門狗的啟動指令碼,然後新增定時任務:

crontab -e
*/10 * * * * /project/watchdog/watchdog.sh
sudo systemctl reload crond.service

完整程式碼:GitHub

參考:java去呼叫並執行shell指令碼以及問題總結

總結

到此這篇關於Spring Boot呼叫 Shell 指令碼實現看門狗功能的文章就介紹到這了,更多相關spring boot 看門狗內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!