Java工程在Linux中部署
java启动的命令
- 1.java -jar ${JAR_NAME}
- 2(推荐).java -cp ${CLASSPATH} ${MAIN_CLASS_PATH}
第一种方式执行时,jar包中必须设置主函数(maven在pom中配置主函数),执行成功后进程名为jar,进程多了进程名不好分辨,不推荐使用。
在我的工作当中,很多人写启动脚本只写java一条命令,这样很不安全,很多不懂代码的运维人员不杀进程就启动,会造成启动多个进程的情况。
启动程序需要注意事项:
- 设置GC输出日志,方便GC调优
- 设置dump输出日志,当程序内存溢出时转储的镜像文件,打开工具推荐mat、ha
- 设置CLASSPATH,除了jar包,程序主目录也要加上
-
java参数
- -Xms 堆内存初始大小
- -Xmx 堆内存最大值
- -Xmn 堆内存年轻代大小
- -Dlog4j.configuration 设置日志配置文件,注意日志配置文件不要打到jar里面,在外面方便DEBUG调试
- 使用nohup启动时,除了生成程序日志外,还有nohup日志,建议把nohup日志输出到/dev/null(linux黑洞)
- 做程序启动是否成功的判断
停止程序需要注意事项:
- 使用kill pid,建议不要加-9强制停止,否则ShutdownHook不会执行
下面附上我的启动、停止进程的脚本,有重复代码,可以适当修改
startup.sh
#!/bin/sh
# 加载JAVA_HOME环境变量
source /etc/profile
if [[ -z "${JAVA_HOME}" ]]
then
echo "JAVA_HOME is empty"
exit 1
fi
JAVA_EXEC=${JAVA_HOME}/bin/java
JPS_EXEC=${JAVA_HOME}/bin/jps
# 当前文件所在目录,这里是相对路径
LOCAL_PATH=`dirname $0`
# 当前文件所在目录转为绝对路径(脚本我放在bin目录下)
LOCAL_PATH=`cd ${LOCAL_PATH}/../;pwd`
# 进程名(main函数类名,也是进程名)
APP_NAME="BootstrapStratup"
# 主函数路径
CLASS_NAME="com.zhysunny.main.${APP_NAME}"
# 日志目录(可以放程序目录下的logs目录,需要和log4j配置的路径一致)
LOG_PATH="/var/log/myapp"
if [[ ! -d ${LOG_PATH} ]]
then
mkdir -p ${LOG_PATH}
fi
# 保留gc日志文件(用于生成GC日志,启动时保留上一次的GC日志)
GC_FILE="${LOG_PATH}/gc.${APP_NAME}.log"
GC_LOG_OPTS="-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:${GC_FILE} "
if [[ -e ${GC_FILE} ]]
then
mv ${GC_FILE} ${LOG_PATH}/gc.${APP_NAME}_$(date +"%Y%m%d").log #重启程序会重置这个文件,这里做个保留
fi
# 保留hprof文件(当程序内存溢出生成dump日志,启动时保留上一次的dump日志)
DUMP_FILE="${LOG_PATH}/zhysunny-${APP_NAME}.hprof "
DUMP_LOG_OPTS="-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${DUMP_FILE} "
if [[ -e ${DUMP_FILE} ]]
then
mv ${DUMP_FILE} ${LOG_PATH}/zhysunny-${APP_NAME}_$(date +"%Y%m%d").hprof #重启程序这个文件无法覆盖,这里要重命名
fi
# 设置 classpath
# 注意必须保留环境变量中的CLASSPATH值
# 其次把LOCAL_PATH也作为classpath
# 然后添加所有依赖包,不能用通配符,只能循环
CLASSPATH=${CLASSPATH}:${LOCAL_PATH}
for f in ${LOCAL_PATH}/fss-*.jar; do
CLASSPATH=${CLASSPATH}:${f}
done
for f in ${LOCAL_PATH}/lib/*.jar; do
CLASSPATH=${CLASSPATH}:${f}
done
# java 参数
# -Xms 堆内存初始大小
# -Xmx 堆内存最大值
# -Xmn 堆内存年轻代大小
# -Dlog4j.configuration 设置日志配置文件
JAVA_OPTS="-Xmx4g -Xms4g -Xmn3g -Dlog4j.configuration=file:${LOCAL_PATH}/conf/log4j.xml "${GC_LOG_OPTS}${DUMP_LOG_OPTS}
# 启动进程
function startup() {
# pid可以写入一个文件中
PID=`${JPS_EXEC} | grep -v "grep" | grep ${APP_NAME} | awk '{print $1}'`
if [[ -z "${PID}" ]]
then
# &可以理解为shell中的并行,nohup之后需要程序终止才能走下一步,这里需要并行
{
nohup ${JAVA_EXEC} ${JAVA_OPTS} -classpath ${CLASSPATH} ${CLASS_NAME} ${HDFS_FSS_URL} 1>/dev/null 2>${LOG_PATH}/kafka-es-error.out
}&
else
echo "${APP_NAME} running as process ${PID}.Stop it first."
exit 1
fi
#判断程序是否启动
i=0
while((i<10))
do
PID=`${JPS_EXEC} | grep -v "grep" | grep ${APP_NAME} | awk '{print $1}'`
if [[ -z "${PID}" ]]
then
sleep 1s
i=$(($i+1))
else
echo "Starting ${APP_NAME} success as process ${PID}"
break
fi
done
PID=`${JPS_EXEC} | grep -v "grep" | grep ${APP_NAME} | awk '{print $1}'`
if [[ -z "${PID}" ]]
then
echo "Starting ${APP_NAME} failed!"
exit 1
fi
}
# 必须先写function,这里才能调用方法
startup
# 结束掉当前shell脚本
kill -2 $$
exit 0
shutdown.sh
#!/bin/sh
# 加载JAVA_HOME环境变量
source /etc/profile
if [[ -z "${JAVA_HOME}" ]]
then
echo "JAVA_HOME is empty"
exit 1
fi
JAVA_EXEC=${JAVA_HOME}/bin/java
JPS_EXEC=${JAVA_HOME}/bin/jps
# 当前文件所在目录,这里是相对路径
LOCAL_PATH=`dirname $0`
# 当前文件所在目录转为绝对路径(脚本我放在bin目录下)
LOCAL_PATH=`cd ${LOCAL_PATH}/../;pwd`
# 进程名(main函数类名,也是进程名)
APP_NAME="BootstrapStratup"
# 主函数路径
CLASS_NAME="com.zhysunny.main.${APP_NAME}"
# 开始杀掉进程
PID=`${JPS_EXEC} | grep -v "grep" | grep ${APP_NAME} | awk '{print $1}'`
if [[ -z "${PID}" ]]
then
echo "${APP_NAME} is not running"
else
kill ${PID}
echo "Stopping ${APP_NAME} success"
fi
kill -2 $$
exit 0
版权声明:本文为yezi1238原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。