写在前面
这是一个在Jenkins
下使用shell
脚本发布一个java
项目的过程,其中打包好的jar
是直接跑在运行服务器上的,下次有空可以写一个docker
方式的(当然也有必要探讨一下jar
有没有必要在docker
中运行)
一、在Jenkins
项目中增加参数化构建
之所以有这么多详细参数是为了更加灵活的定制化,来适应运行服务器的各种情况
结构说明:
- 变量名
- 变量默认值
- 变量说明
详细的参数:
-
branch
master
- 要操作的分支
-
projectName
test-milk
- 项目名(磁盘上的文件夹)
-
jenkinsProjectName
test-milk
- jenkins项目名(jenkins工作空间的文件夹)
-
mavenCmd
clean package install -DskipTests --settings ${JENKINS_HOME}/workspace/deployment-init/aliyun/jenkins/settings.xml
- maven 的运行命令
-
jarName
a-crawler-w-0.0.1-SNAPSHOT.jar
- jar包名称
-
runServer
root@xxx.xxx.xxx.xxx
- jar运行的目标服务器
-
shellDeployment
/root/shell-deployment
- runServer 服务器的脚本根路径
-
javaHome
/usr/java/jdk1.8.0_111
- runServer 服务器的jdk javahome位置
-
source
/root/source
- runServer 服务器 jar包存放的根目录
-
logs
/root/logs
- runServer 服务器 日志文件根目录
-
javaParameter
-Xmx512m -Xms256m -Duser.timezone=Asia/Shanghai
- runServer 服务器 java 命令启动参数
-
arguments
- runServer 服务器 -jar 启动的额外参数 比如 --spring.profiles.active=dev
部分截图:
二、在Jenkins
项目中增加代码源
如果有多个项目组合编译,建议使用Jenkins
触发构建的模式来按顺序编译其他依赖项目,不要直接在这里配置多个代码源(会增加编译脚本编写的复杂度,且定制程度太强,没有复用性了)
三、在Jenkins
项目中配置构建相关设置
四、在Jenkins
项目中配置编译工具
五、在Jenkins
项目中配置shell
脚本来完成主要功能
此过程分为3步:
- 第一步
- 更新远程运行服务的部署脚本
- 检查远程服务器上必要的资源文件夹及文件情况,不符合要求就开始创建
git-pull.sh 脚本:
#!/usr/bin/env bash
resource_dir=$1
# backup_dir检测
if test -d ${resource_dir};then
echo ${resource_dir}" 资源目录已存在"
cd ${resource_dir}
git pull
else
cd "/root"
git clone git@code.aliyun.com:lc-private/shell-deployment.git
fi
# 第一个参数是当前部署脚本存放的位置
source-init.sh 脚本:
#!/usr/bin/env bash
root_source=$1
root_logs=$2
# /root/source检测
if test -d ${root_source};then
echo ${root_source}" 资源目录已存在"
else
mkdir ${root_source}
fi
# /root/logs检测
if test -d ${root_logs};then
echo ${root_logs}" 日志目录已存在"
else
mkdir ${root_logs}
fi
#要构建的项目名称
project_name=$3
# 运行环境的jar存放位置
source=${root_source}/${project_name}
if test -d ${source};then
echo ${source}" 运行目录已存在"
else
mkdir ${source}
fi
# 第一个参数是当前运行环境的jar包存放根位置 /root/source
# 第二个参数是当前运行环境的日志存放位置 /root/logs
# 第三个参数是当前运行环境的jar包存放位置 test-config
# 这个脚本应该在当前运行环境上的服务器执行执行顺序为1
- 第二步
- 在
Jenkins
下寻找执行文件拷贝到远程运行服务器上
- 在
source-init.sh 脚本:
#!/usr/bin/env bash
# !/bin/sh
jenkins_home=${JENKINS_HOME}
# Jenkins的工作目录
jenkins_workspace=${jenkins_home}"/workspace"
#要构建的项目名称
project_name=$1
#Jenkins项目名称
jenkins_project_name=$2
#Jenkins编译项目相对路径
jenkins_project_target=${project_name}/"target"
if [[ "$project_name" = "$jenkins_project_name" ]];then
echo "Jenkins忽略当前project_name属性寻址 :"${project_name}
else
jenkins_project_target=${jenkins_project_name}/${jenkins_project_target}
fi
# Jenkins编译生成的jar包中间的相对路径 /root/data/jenkins_home/workspace/test-eureka/target/
jenkins_target=${jenkins_workspace}/${jenkins_project_target}
# jar全名,带后缀
jar_name=$3
# 运行服务器位置 root@172.16.10.211
server_domain=$4
# 运行环境的jar文件存放根目录
root_source=$5
# 运行环境的jar存放位置
source=${root_source}/${project_name}
scp -C -o StrictHostKeyChecking=no -r ${jenkins_target}/${jar_name} ${server_domain}:${source}
# 第一个参数为项目名称 account-server
# 第二个参数为Jenkins项目名称 production-account-server
# 第三个参数是jar包的名称带后缀 sn-eureka-0.0.1-SNAPSHOT.jar
# 第四个参数是当前运行环境的服务器位置 root@xxx.xxx.xxx.xxx
# 执行顺序为2 这个脚本需要配置第四个参数所对应的服务器ssh pubkey 需要放到 jenkins /var/jenkins_home
- 第三步
- 检查并启动服务,反馈过程及结果给
Jenkins
控制台
- 检查并启动服务,反馈过程及结果给
java.sh 脚本:
#!/usr/bin/env bash
JAVA_HOME=$1
JRE_HOME=${JAVA_HOME}/jre
JAVA_BIN=${JAVA_HOME}/bin
CLASSPATH=.:${JAVA_HOME}/lib/dt.jar:${JAVA_HOME}/lib/tools.jar:${JRE_HOME}/lib
PATH=$PATH:${JAVA_HOME}/bin:${JRE_HOME}/bin
export JAVA_HOME JRE_HOME PATH CLASSPATH
echo "path "${PATH}
echo "java_home "${JAVA_HOME}
echo "jre_home "${JRE_HOME}
echo "classpath "${CLASSPATH}
RUNNING_USER=${USER}
#要运行的项目名称
project_name=$2
# 运行环境的jar文件存放根目录
root_source=$3
# 运行环境的jar存放位置
source=${root_source}/${project_name}
# jar全名,带后缀
jar_name=$4
log_root=$5
shell_root=$6
# 参数有空格 需要用引号引起来 显示当做字符串传递
java_parameter=${7//","/" "}
arguments=${8//","/" "}
echo "参数=>>> start >>>>>>>>>>>>>>>>>>>>>"
echo "JAVA_HOME:"${JAVA_HOME}
echo "project_name:"${project_name}
echo "root_source:"${root_source}
echo "jar_name:"${jar_name}
echo "log_root:"${log_root}
echo "shell_root:"${shell_root}
echo "java_parameter:"${java_parameter}
echo "arguments:"${arguments}
echo "参数=>>> end >>>>>>>>>>>>>>>>>>>>>"
log_file=${log_root}"/"${project_name}".log"
psid=0
function initPsid(){
javaps=`jps -l | grep "${project_name}/${jar_name}"`
if [[ -n "$javaps" ]]; then
psid=`echo ${javaps} | awk '{ print $1}'`
else
psid=0
fi
}
function main(){
initPsid
if [[ ${psid} -ne 0 ]]; then
kill -s 9 ${psid}
echo "已杀死 "${psid}
fi
#有内核不兼容
# JAVA_CMD="nohup java -Xmx1024m -Xms512m -Duser.timezone=Asia/Shanghai -jar ${source}/${jar_name} &> /dev/null &"
# su - ${RUNNING_USER} -c "${JAVA_CMD}"
JAVA_CMD="java ${java_parameter} -jar ${source}/${jar_name} ${arguments}"
echo "JAVA_CMD:"${JAVA_CMD}
nohup ${JAVA_CMD} &> ${log_file} &
initPsid
if [[ ${psid} -ne 0 ]]; then
${shell_root}"/exec-java/java-log.sh" ${log_file}
echo -e "\n===================== start [OK] pid=${psid} ====================="
exit 0
else
echo -e "\n===================== start [FAILED], $? ====================="
fi
}
main
# 第一个参数是java的环境变量 JAVA_HOME
# 第二个参数是当前运行环境的jar包存放位置 eureka
# 第三个参数是当前运行环境的jar包存放位置根目录 /root/source
# 第四个参数是jar包的名称带后缀 sn-eureka-0.0.1-SNAPSHOT.jar
# 第五个参数是日志根目录 /root/logs
# 第六个参数是脚本执行根目录 /root/shell-deployment
# 第七1个参数是 java 命令启动参数 比如 -Xmx1024m
# 第七2个参数是 java 命令启动参数 比如 -Xms512m
# 第七3个参数是 java 命令启动参数 比如 -Duser.timezone=Asia/Shanghai
# 第八个参数是 -jar 启动的额外参数 比如 --spring.profiles.active=dev
#/root/shell-deployment/exec-java/java-log.sh ${logRoot}/${projectName}.log
#nohup java -Xmx1024m -Xms512m -Duser.timezone=Asia/Shanghai -jar /root/source/flow-dashboard-server/a-flow-dashboard-0.0.1-SNAPSHOT.jar | tee /root/logs/flow-dashboard-server.log
#java -Duser.timezone=Asia/Shanghai -jar a-crawler-w-0.0.1-SNAPSHOT.jar --spring.profiles.active=pod
java.sh 脚本中应用了一个 java-log.sh脚本,以下是 java-log.sh脚本内容:
#!/usr/bin/env bash
log_file=$1
echo ">>>>>>>>>>>>>>>>>>>> 启动日志输出 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
echo ">>>>>>>>>>>>>>>>>>>> 预祝一切正常 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
/usr/bin/expect <<EOF
set timeout 120
spawn tail -f ${log_file}
expect "JVM running for"
exit
#wait
EOF
需要说明一下:
这个脚本使用了 expect
来做交互式通知,需要在远程运行服务器上安装此组件,当然这个工作会在发布系统客户端初次启动的时候完成这个工作
到此,java
项目的发布部署完成,还有一种将项目发布到没有公网ip的服务器的方案,限于篇幅,这里就不介绍了。
评论区