介绍
Apache Commons Daemon 可以让Java程序在linux系统上以服务器的方式运行。通过jsvc执行写好脚本,可以启动我们的java项目。
依赖
<dependency>
<groupId>commons-daemon</groupId>
<artifactId>commons-daemon</artifactId>
<version>1.1.0</version>
</dependency>
代码实现
在代码层我们需要自定义类实现Daemon接口并在其中加入自己的业务代码。并编写linux启动脚本。
自定义Daemon实现类
public class JsvcStart implements Daemon {
@Override
public void destroy() {
//释放此守护进程分配的任何资源,如文件描述符或套接字。
// 在调用stop()之后,在JVM退出之前,容器将调用此方法。如果没有对init()方法的新调用,则在调用此方法后无法重新启动守护程序。
System.out.println("JsvcStart destory method...");
}
@Override
public void init(DaemonContext ctx) throws DaemonInitException, Exception {
//一旦JVM进程被创建并且Daemon实例通过它的空公共构造函数被创建,这个方法就会被调用。
//设置和分配本机资源
System.out.println("JsvcStart init method..."+ctx.toString());
}
@Override
public void start() throws Exception {
//这里可以执行自己的代码逻辑
//启动此Daemon实例的操作。在init()方法被成功调用并且JVM的安全级别可能被删除之后,环境将调用此方法。此方法的实现者可以自由地启动任意数量的线程,但在完成之后需要返回控制,以启用stop()方法的调用。
UsulTestStartApplication.main(new String[]{}); //我的项目启动类。
System.out.println("JsvcStart start method...");
}
@Override
public void stop() throws Exception {
//释放任何已分配资源(如套接字或文件描述符)的适当位置是destroy方法,因为容器可以通过在stop()之后调用start()来重新启动守护进程
System.out.println("JsvcTest stop method...");
}
}
我的项目是一个web项目,启动类是UsulTestStartApplication
@RestController
@SpringBootApplication(scanBasePackages = "zhong.test.springbootdemo.usultestdemo")
public class UsulTestStartApplication implements CommandLineRunner {
@Value("${key1}")
String value;
@Value("${EnvironmentPostProcessor.key1}")
String value1;
@Value("${PropertySourceLocator-key}")
String value2;
@Override
public void run(String... args) throws Exception {
System.out.println("key = " + value);
System.out.println("EnvironmentPostProcessor.key1 = " + value1);
System.out.println("PropertySourceLocator-key = " + value2);
}
public static void main(String[] args) {
try {
SpringApplication.run(UsulTestStartApplication.class, args);
} catch (Exception e) {
e.printStackTrace();
}
}
@GetMapping("/test")
public String test(){
return "yes! test";
}
}
启动脚本-daemservice
#!/bin/bash
#项目名称
_ServerName=springbootdemo
#java的jdk地址
JAVA_HOME=/opt/java/jdk/jre18linux64.1
CLASSPATH=.:${JAVA_HOME}/lib/dt.jar:${JAVA_HOME}/lib/tools.jar
_Xms=100M
_Xmx=200M
_Xmn=50M
_MetaspaceSize=50M
_MaxMetaspaceSize=100M
#获取当前路径
_DIR="$( cd "$(dirname "$0")" && pwd )"
_HOME_DIR=$(dirname "$_DIR")
#jsvc地址
_JSVC=${_HOME_DIR}/bin/linux/Jsvc
#项目配置配置以及jar的路径
_Classpath=${CLASSPATH}:"${_HOME_DIR}/config":"${_HOME_DIR}/lib/*"
#Daeam的实现类的路径
_StarCLASS=zhong.test.springbootdemo.usultestdemo.JsvcStart
#pid文件路径
_pidPath=${_HOME_DIR}/temp
_Pid=${_pidPath}/${_ServerName}.pid
_LogOut=${_HOME_DIR}/logs/${_ServerName}.log
_LogErr=${_HOME_DIR}/logs/Jsvc.log
echo "service name: $_ServerName"
do_start()
{
$_JSVC -D${_ServerName} -home $JAVA_HOME -cwd ${_HOME_DIR}/config -Djava.net.preferIPv4Stack=true -Dcom.sun.jndi.ldap.connect.pool.protocol="plain ssl" -XX:MetaspaceSize=${_MetaspaceSize} -XX:MaxMetaspaceSize=${_MaxMetaspaceSize} -Xms${_Xms} -Xmx${_Xmx} -Xmn${_Xmn} -XX:SurvivorRatio=8 -XX:+UseG1GC -XX:+PrintTenuringDistribution -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintAdaptiveSizePolicy -XX:+PrintHeapAtGC -XX:+DisableExplicitGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -Xloggc:${_HOME_DIR}/logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=8M -Djava.io.tmpdir=${_HOME_DIR}/temp -Dloader.main=${_MainClass} -wait 60 -pidfile $_Pid -outfile ${_LogOut} -errfile ${_LogErr} -cp ${_Classpath} ${_StarCLASS}
echo "${_ServerName} started"
}
do_stop()
{
SERVICE_PID=`cat ${_Pid}`
kill -15 ${SERVICE_PID}
echo "${_ServerName} stopped"
find ${_pidPath} 'tomcat.*' | xargs rm -rf
}
case "$1" in
start)
do_start
chmod -R 777 ${_HOME_DIR}
;;
stop)
if [ -f "$_Pid" ]; then
do_stop
fi
;;
restart)
if [ -f "$_Pid" ]; then
do_stop
#休眠3秒,否则无法重新启动
sleep 3
do_start
echo "${_ServerName} restarted"
else
echo "service not running, will do nothing"
exit 1
fi
;;
status)
ps -ef | grep ${_ServerName}
;;
*)
echo "usage: service ${_ServerName} {start|stop|restart|status}" >&2
exit 3
;;
esac
环境准备
开发需要使用jsvc环境,所以需要安装jsvc。
我的项目是通过ideapackege出来的,直接发送到指定的linux文件下解压即可结构是:
lib:项目jar包
bin下面是启动、停止的脚本。
logs是项目的日志位置
config是配置文件application.properties等
脚本执行
启动: ./daemservice start
停止: ./daemservice stop