Java启动脚本详解

在工作的过程中,不免要遇到与服务启动相关的问题,很多问题很好解决,但是有些问题可能需要请教总部的大佬才能解决。由于最近遇到了一次nohup启动两个服务进程的问题,其中一个进程因为端口占用一直在不断重启,故深入研究一下运管的启动和启动脚本的启动。

__service脚本

__service脚本有很多种,其实作用都一样,但是因为写法不同,所以在看的过程中会感觉很痛苦,每次都会遇到新的语法。这里以Jsvc启动和nohup启动两种方式进行详细解读。

__service脚本 - Jsvc启动

  1. 什么是Jsvc

jsvc可以理解为类unix系统下的启动并守护java进程的可执行程序,属于Apache Commons Daemon项目。

简单理解,就是启动java服务,并且维护java服务的运行。

  1. Jsvc的优缺点
  • 一个java服务可能存在多个进程,通过jsvc控制不同进程
  • java进程启动、停止或者退出时,执行init stop destroy等方法,java应用能通过这些方法。执行一下必要的操作
  1. Jsvc的原理

公司使用jsvc的框架都需要引入一个laucher的依赖,这个launcher里面就是具体的启动的代码,可以看到其实是在mainClass外包装了一层,可以执行start,init,stop等操作来管理Java服务。

Jsvc __service脚本详解
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#!/bin/bash
_ServerName=placeholder
JAVA_HOME=${JDK_PATH}
CLASSPATH=.:${JAVA_HOME}/lib/dt.jar:${JAVA_HOME}/lib/tools.jar
_Xms=1024M
_Xmx=2048M
_Xmn=512M
_MetaspaceSize=512M
_MaxMetaspaceSize=1024M
_DIR="$( cd "$(dirname "$0")" && pwd )"
_HOME_DIR=$(dirname "$_DIR")
_JSVC=${_HOME_DIR}/bin/linux/Jsvc
_Classpath=${CLASSPATH}:"${_HOME_DIR}/config":"${_HOME_DIR}/lib/*":"${_HOME_DIR}/../../conf"
_MainClass=com.xx.AlarmBootstrap
_StartCLASS=com.xxx.JsvcLauncher

_Pid=${_HOME_DIR}/temp/${_ServerName}.pid
#_LogOut=${_HOME_DIR}/logs/${_ServerName}.log
_LogOut=/dev/null
_LogErr=${_HOME_DIR}/logs/Jsvc.log

echo "service name: $_ServerName"

do_exec()
{
    $_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:+HeapDumpOnOutOfMemoryError -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} $1 ${_StartCLASS}
}

case "$1" in
    start)
        do_exec
        echo "${_ServerName} started"
		chmod -R 777 ${_HOME_DIR}
		chmod -R 777 ${_HOME_DIR}/../../logs
            ;;
    stop)
        if [ -f "$_Pid" ]; then
    	    SERVICE_PID=`cat ${_Pid}`
    	    kill -15 ${SERVICE_PID}
    	fi
    	   ;;
    restart)
        if [ -f "$_Pid" ]; then
            do_exec "-stop"
            do_exec
            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
  • _ServiceName: ServiceName就是段标识的名称,也可以看到后面的Jsvc启动使用了这个ServiceName,$_JSVC -D${_ServerName},这里的-D是指 -D<name>=<value> set a Java system property

  • Java启动参数:

1
2
3
4
5
6
7
8
9
JAVA_HOME=${JDK_PATH}
CLASSPATH=.:${JAVA_HOME}/lib/dt.jar:${JAVA_HOME}/lib/tools.jar
_Xms=1024M
_Xmx=2048M
_Xmn=512M
_MetaspaceSize=512M
_MaxMetaspaceSize=1024M
_DIR="$( cd "$(dirname "$0")" && pwd )"
_HOME_DIR=$(dirname "$_DIR")

基础的参数就不过多介绍了,Java路径,启动参数,内存大小等等。

  • Jsvc启动参数
1
2
3
4
_JSVC=${_HOME_DIR}/bin/linux/Jsvc
_Classpath=${CLASSPATH}:"${_HOME_DIR}/config":"${_HOME_DIR}/lib/*":"${_HOME_DIR}/../../conf"
_MainClass=com.xxx.xxx.Bootstrap
_StartCLASS=com.xxx.JsvcLauncher
++ _JSVC为Jsvc的路径,也就是执行脚本的路径
++ _Classpath为classpath的路径,**如果有配置文件重名冲突的话,这里的顺序可以控制扫描顺序,解决文件重名导致的配置获取的失败**
++ _MainClass为Java服务的启动类,_StartClass这里是框架launcher的类。
  • Jsvc监控参数
1
2
3
4
_Pid=${_HOME_DIR}/temp/${_ServerName}.pid
#_LogOut=${_HOME_DIR}/logs/${_ServerName}.log
_LogOut=/dev/null
_LogErr=${_HOME_DIR}/logs/Jsvc.log
+ _Pid这里放Jsvc启动服务然后生成的Pid文件
+ _LogOut: Location for output from stdout (defaults to /dev/null)控制台输出的文件
+ _LogErr: ** 启动过程中错误日志存放的位置,一般如果服务没有起起来,并且没有打印业务日志,可以查看这里 ** 
  • do_exec() 启动命令

这里就是Jsvc的启动命令,把上面的参数进行了组装

  • start命令
1
2
3
4
5
6
    start)
        do_exec
        echo "${_ServerName} started"
		chmod -R 777 ${_HOME_DIR}
		chmod -R 777 ${_HOME_DIR}/../../logs
            ;;

执行do_exec()方法,启动服务,然后将文件夹设置777权限

  • stop命令
1
2
3
4
5
6
    stop)
        if [ -f "$_Pid" ]; then
    	    SERVICE_PID=`cat ${_Pid}`
    	    kill -15 ${SERVICE_PID}
    	fi
    	   ;;

stop命令,从Jsvc启动服务命令中设置的Pid文件所在的位置,找到启动的服务的进程Id,然后kill掉

  • restart: 先执行Jsvc的stop命令,然后在进行start
nohup __service脚本详解

有了上面的Jsvc脚本的经验,那么nohup模式的启动脚本的阅读也会更加轻松,除了启动命令的参数外,在Pid的处理上nohup使用ps -ef来获取启动服务的pid然后进行kill