需要实现看门狗功能,定时检测另外一个程序是否在运行,使用 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 扩展

  1. 本例只实现了定时检测程序是否运行,如果没有运行则启动程序;如有需要可以添加接口,调用接口重启程序;或者添加定时任务定时检测程序是否有更新,如果有更新则下载新的 jar 包然后重启程序
  2. 看门狗程序自己可以使用 crontab 定时检测是否正在运行,模仿上面的启动脚本编写看门狗的启动脚本,然后添加定时任务:
crontab -e
*/10 * * * * /project/watchdog/watchdog.sh
sudo systemctl reload crond.service

完整代码:GitHub

参考:java去调用并执行shell脚本以及问题总结

Spring Boot 实现看门狗功能 (调用 Shell 脚本)的更多相关文章

  1. spring boot实现ssm(2)功能

    spring 和 mybatis 整合的那篇: ssm(2) . 配置文件比ssm(1) 更多, 在做项目的时候, 配置文件是一个让人头大的事情. 那么在spring boot中, 实现相同功能, 需 ...

  2. Java 调用 shell 脚本详解

    这一年的项目中,有大量的场景需要Java 进程调用 Linux的bash shell 脚本实现相关功能. 从之前的项目中拷贝的相关模块和网上的例子来看,有个别的“陷阱”造成调用shell 脚本在某些特 ...

  3. 【原】Gradle调用shell脚本和python脚本并传参

    最近由于项目自动化构建的需要,研究了下gradle调用脚本并传参的用法,在此作个总结. Pre build.gradle中定义了$jenkinsJobName $jenkinsBuild两个Jenki ...

  4. 调用shell脚本,IP处理

    //调用shell脚本,IP处理 package com.letv.sdns.web.utils; import org.slf4j.Logger; import org.slf4j.LoggerFa ...

  5. C程序调用shell脚本共有三种方法

    C程序调用shell脚本共有三种法子 :system().popen().exec系列函数call_exec1.c ,内容为:system() 不用你自己去产生进程,它已经封装了,直接加入自己的命令e ...

  6. python调用shell脚本时需要切换目录

    最近遇到了一个问题,就是python代码调用shell脚本时,发现输入输出的文件,总是和自己预想的有偏差,但是单独在linux下执行命令的时候,却没有错误.后来发现是相对路径的问题,因为执行pytho ...

  7. python调用shell脚本

    # coding=utf-8   //设置文本格式import os            //导入os方法print('hello')n=os.system('/home/csliyb/kjqy_x ...

  8. Centos下使用php调用shell脚本

    我们在实际项目中或许会遇到php调用shell脚本的需求.下面就用简单案例在Centos环境下实践 准备 查看php.ini中配置是否打开安全模式 //php.ini safe_mode = //这个 ...

  9. Android应用程序如何调用shell脚本(一)

    转自: Android应用程序如何调用shell脚本(一) 一般来说, Android 下的应用程序可以“直接”得到的最大的权限为 system ,但是如果我们需要在程序中执行某些需要 root 权限 ...

随机推荐

  1. 关于||和&&运算符及表达式的执行

    ++a || ++b && ++c表达式中++a,--b,++c三者执行与否的判断 在||运算符前的表达式为真,则其后的表达式不执行 eg:执行前 a=2,  b=2,  c=2 执行 ...

  2. 分布式文档存储数据库之MongoDB副本集

    前文我们聊到了mongodb的索引的相关作用和介绍以及索引的管理,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/13950287.html:今天我们来聊下mon ...

  3. ASP.NET MVC过滤器粗略总结

    mvc的过滤器总共分为:授权认证过滤器.行为过滤器.异常过滤器.自定义行为过滤器 授权认证过滤器: 异常过滤器: 行为过滤器的调用顺序: 几个过滤器在Controler的使用

  4. martini-md参数(mdp文件)

    输入参数:一个典型的mdp文件 1 ; 2 ; STANDARD MD INPUT OPTIONS FOR MARTINI 2.x 3 ; Updated 02 feb 2013 by DdJ 4 ; ...

  5. RPC协议实践入门

    RPC 是什么 RPC(Remote Procedure Call) 是一个计算机通信协议.该协议允许运行与一台计算机的程序调用另一个地址空间的程序,是一个通过发送请求-接受回应进行信息交互的系统. ...

  6. “”.length()与“”.split(",").length

    public class test { public static void main(String[] args){ String str = ""; System.out.pr ...

  7. Android状态栏与布局重叠解决方案

    问题起因: 同组的同事将项目全局设置成了沉浸式,对于我这个半路过来开发的人 可真是头疼呵~ 没办法,那就我自己添加一个头吧.也可以在布局中取消沉浸式,不过我这个是在fragment中,为了不修改之前的 ...

  8. WSL2:我在原生的Win10玩转Linux系统

    原文地址:梁桂钊的博客 博客地址:http://blog.720ui.com 欢迎关注公众号:「服务端思维」.一群同频者,一起成长,一起精进,打破认知的局限性. WSL2:我在原生的Win10玩转Li ...

  9. python执行rados命令例子

    前言 我们以前的管理平台在python平台下面做的,内部做的一些操作采用的是命令执行,然后解析的方式去做的,ceph自身有python的rados接口,可以直接调用原生接口,然后直接解析json的方式 ...

  10. classmethod、staticclassmethod内置装饰器函数

    # method 英文是方法的意思 # classmethod 类方法 # 当一个类中的方法中只涉及操作类的静态属性时,此时在逻辑上,我们想要直接通过类名就可以调用这个方法去修改类的静态属性,此时可以 ...