掘金 后端 ( ) • 2024-04-19 16:14

一、 安装JDK环境

路径:/usr/lib/jdk/jdk1.8.0_201

添加环境变量:

JAVA_HOME=/usr/lib/jdk/jdk1.8.0_201
PATH=$JAVA_HOME/bin:$PATH
CLASSPATH=.:$JAVA_HOME/jre/lib/ext:$JAVA_HOME/lib/tools.jar
export PATH JAVA_HOME CLASSPATH

二、 安装Maven环境

maven路径:/usr/lib/maven/apache-maven-3.5.3

maven仓库路径:/usr/lib/maven/repos

  1. 需要修改配置文件:
<mirror>
<id>alimaven</id>
<mirrorOf>*</mirrorOf>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
</mirror>
<localRepository>/usr/lib/maven/repos</localRepository>
  1. 添加环境变量
vim /etc/profile

#在profile中添加如下配置:
export M2_HOME=/usr/lib/maven/apache-maven-3.5.3
export PATH=${PATH}:$JAVA_HOME/bin:$M2_HOME/bin

source /etc/profile        #重新加载配置文件

三、安装Jenkins、配置

1. 拉取镜像

docker pull jenkins/jenkins:lts

2. 构建容器运行

docker run \
--name jenkins \
--memory=2048m \
-d \
-p 10240:8080 \
-u root \
-v /var/jenkins_mount:/var/jenkins_home \
-v /usr/lib/maven/apache-maven-3.5.3:/usr/local/maven \
-v /usr/lib/jdk/jdk1.8.0_201:/usr/local/jdk \
-v /etc/localtime:/etc/localtime \
jenkins/jenkins:lts

3. 初始登录密码

docker logs jenkins

4. 安装推荐插件 (失败重试)

单独安装

SSH :用来系统配置SSH remote hosts

Git Parameter :用来构建时选择分支

Publish Over SSH:用来远端发布

5. 添加全局Credentials凭据

5.1 服务器登录凭据

1689347783782.png

5.2 Git凭据

使用用户名密码或sshkey

1689347911739.png

6. 系统配置 SSH remote hosts

1689349174357.png

7.系统配置Publish over SSH(远端发布使用)

1689921622186.png

1689921741545.png

8.全局工具配置

Git不需要配置

8.1 JDK

1689348181240.png

8.2 MAVEN

1689348246271.png

四、项目构建

1689646759983.png

1. General 参数化构建

构建之后参数可以作为环境变量使用

1.1 Git参数(选择分支)

下载插件Git Parameter

1689645510936.png

1.2 profile(选择运行环境)

添加参数,选择选项参数

1689645627665.png

1.3 module(选择打包模块)

添加参数,选择选项参数

image.png

1.4 选择构建后执行位置

添加参数,选择选项参数

1689920257451.png

2. 源码管理 git

image.png

3. Build Steps

3.1 调用顶层 Maven 目标

1689646241817.png

-U
-pl ${module}
-am
-P ${env}
clean
-Dmaven.test.skip=true
package 
install
参数 全称 说明 -pl –projects 选项后可跟随{groupId}:{artifactId}或者所选模块的相对路径(多个模块以逗号分隔) -am –also-make 表示同时处理选定模块所依赖的模块,向下处理 -amd –also-make-dependents 表示同时处理依赖选定模块的模块,向上处理 -N –Non-recursive 表示不递归子模块 -rf –resume-from 表示从指定模块开始继续处理 -DskipTests 跳过测试 -U 全部更新代码

3.2 Execute shell script on remote host using ssh

执行服务器中脚本

/home/../shell/run.sh ${module} ${env} ${location}

image.png

3.3 Send files or execute commands over SSH

需要提前安装插件Publish Over SSH

1689920680845.png

Source files:准备发送的文件,该文件是相对于这个项目的workspace目录,也就是$JENKINS_HOME/workspace/xxxx/
例如要发送$JENKINS_HOME/workspace/lumitech-dev/shumiweb/target/shumiweb-1.0.0-SNAPSHOT.jar到目标目录,则设置Source files为shumiweb/target/shumiweb-1.0.0-SNAPSHOT.jar

Remove prefix:例如设置为shumiweb/target,如果不填会创建shumiweb/target/目录层级。

更多示例见官网:https://wiki.jenkins.io/display/JENKINS/Publish+Over#PublishOver-examples

4. 构建

1689922036191.png

★5. 说明

打包都是在Jenkins服务器进行的,

选择local代表在Jenkins所在服务器发布,

选择remote代表在把jar包发送到远端服务器,在远端服务器进行发布。

需要在服务器上提前准备好shell脚本

脚本位置:/home/../shell/run.sh

/home/../shell/rollback.sh

/home/../shell/backup.sh

jar包位置:/home/../xxx-${env}/web-jar/

备份jar包位置:/home/../xxx-${env}/backup/

五、shell脚本

1. run.sh

module=$1                              #模块名
env=$2                                 #运行环境
location=$3                            #执行位置 local本地执行 remote远端执行
WEB_PATH='/home/../xxx-'$env           #项目根路径(路径自行定义)
JAR_PATH=$WEB_PATH'/web-jar/'          #jar包路径
LOG_PATH=$WEB_PATH'/web-jar/'          #log路径
SHELL_PATH=$WEB_PATH'/shell/'          #shell脚本路径
BACKUP_PATH=$WEB_PATH'/backup/'        #备份jar包路径
APP_NAME=$module'-1.0.0-SNAPSHOT.jar'  #当前项目名称
DES_APP=$JAR_PATH$APP_NAME             #jar包全路径
DES_LOG=$LOG_PATH'nohup-'$module'.out' #nohup全路径
PROJECT_NAME="xxxxx"                   #项目名称

#打印路径
echo [INFO]'$APP_NAME':$APP_NAME
echo [INFO]'$WEB_PATH:'$WEB_PATH
echo [INFO]'$BACKUP_PATH:'$BACKUP_PATH
echo [INFO]'$DES_APP:'$DES_APP
echo [INFO]'$DES_LOG:'$DES_LOG

# 创建目录
mkdir -p $WEB_PATH
mkdir -p $JAR_PATH
mkdir -p $LOG_PATH
mkdir -p $BACKUP_PATH

#kill进程
killProgress() {
  pid=$(ps -ef | grep $DES_APP | grep -v grep | awk '{print $2}')
  if [ -n "$pid" ]; then
    kill -9 $pid
    echo [INFO] ">>>>>>>>>> "$DES_APP" "$pid" has bean killed <<<<<<<<<<"
  fi
}

# 备份
fileSize=$(du -s $BACKUP_PATH) #项目所在路径的大小
if [[ ${fileSize%%/*} -ne 0 ]]; then
  echo [INFO] ">>>>>>>>>> 开始备份 <<<<<<<<<<"
  echo 'backup file ->'$BACKUP_PATH$APP_NAME
  cp -r $DES_APP $BACKUP_PATH
  echo [INFO] ">>>>>>>>>> 结束备份 <<<<<<<<<<"
fi

#本地才执行该操作
if [[ $location = "local" ]]; then
  # 删除应用服务器旧的代码
  rm -rf $DES_APP
  echo [INFO] ">>>>>>>>>> 原jar包已删除 <<<<<<<<<<"

  # 拷贝jar包
  cp /var/jenkins_mount/workspace/$PROJECT_NAME/$module/target/$APP_NAME $JAR_PATH
  echo [INFO] ">>>>>>>>>> jar包拷贝成功 <<<<<<<<<<"
fi

#kill进程
killProgress

#运行jar包
echo [INFO] ">>>>>>>>>> 开始启动项目 <<<<<<<<<<"
source /etc/profile
echo "" >$DES_LOG
nohup java -jar $DES_APP >>$DES_LOG 2>&1 &

# 日志监测部分
echo [INFO] ">>>>>>>>>>> 日志所在位置"$DES_LOG" 开始输出日志<<<<<<<<<<"
sleep 2
second=0
lastShellRow=0
while true; do
  nowShellRow=$(cat $DES_LOG | wc -l)
  showRow=$((nowShellRow - lastShellRow))
  if [[ $showRow -ge 0 ]]; then
    tail -n$showRow $DES_LOG
  fi
  sum=$(cat $DES_LOG | grep 'Started application in' | wc -l)
  sum_jvm=$(cat $DES_LOG | grep 'JVM running for' | wc -l)
  failed_sign=$(cat $DES_LOG | grep 'Application run failed\|APPLICATION FAILED TO START' | wc -l)
  if [ $second -ge 800 ]; then
    echo [ERROR] ">>>>>>>>>> 部署等待时间过长 退出部署 <<<<<<<<<<<"
    killProgress

    echo [INFO] ">>>>>>>>>> 准备回退版本 <<<<<<<<<<"
    bash /home/shumi/shell/rollback.sh $APP_NAME $JAR_PATH $BACKUP_PATH $DES_LOG

    exit 1
    break
  fi
  if [ $sum -gt 0 ] || [ $sum_jvm -gt 0 ]; then
    echo [INFO] ">>>>>>>>>> 项目启动花费 $second 秒 <<<<<<<<<<"
    break
  fi
  if [[ $failed_sign -gt 0 ]]; then
    echo [INFO] ">>>>>>>>>> 项目启动花费 $second 秒 <<<<<<<<<<"
    echo [ERROR] ">>>>>>>>>>> 项目启动失败 <<<<<<<<<<<"
    killProgress

    echo [INFO] ">>>>>>>>>> 准备回退版本 <<<<<<<<<<"
    bash /home/shumi/shell/rollback.sh $APP_NAME $JAR_PATH $BACKUP_PATH $DES_LOG

    exit 1
    break
  fi
  second=$((second + 2))
  lastShellRow=$nowShellRow
  sleep 2
done

2.rollback.sh

APP_NAME=$1    #jar包名
JAR_PATH=$2    #web-jar路径
BACKUP_PATH=$3 #备份路径
DES_LOG=$4     #nohup.out位置

echo [INFO]'$APP_NAME':$APP_NAME
echo [INFO]'$JAR_PATH:'$JAR_PATH
echo [INFO]'$BACKUP_PATH:'$BACKUP_PATH
echo [INFO]'$DES_LOG:'$DES_LOG

#kill进程
killProgress(){
pid=$(ps -ef | grep $DES_APP | grep -v grep | awk '{print $2}')
if [ -n "$pid" ]; then
  kill -9 $pid
  echo [INFO] ">>>>>>>>>> "$DES_APP" "$pid" has bean killed <<<<<<<<<<"
fi
}

#备份jar包移动回去
rm -rf $JAR_PATH$APP_NAME
cp $BACKUP_PATH$APP_NAME $JAR_PATH


echo [INFO] ">>>>>>>>>>> 开始回滚 <<<<<<<<<<"
source /etc/profile
echo "" >$DES_LOG
nohup java -jar $JAR_PATH$APP_NAME >>$DES_LOG 2>&1 &

echo [INFO] ">>>>>>>>>>> 日志所在位置"$DES_LOG" 开始输出日志<<<<<<<<<<"
# 日志监测部分
sleep 2
second=0
lastShellRow=0
while true; do
  nowShellRow=$(cat $DES_LOG | wc -l)
  showRow=$((nowShellRow - lastShellRow))
  if [[ $showRow -ge 0 ]]; then
    tail -n$showRow $DES_LOG
  fi
  sum=$(cat $DES_LOG | grep 'Started application in' | wc -l)
  sum_jvm=$(cat $DES_LOG | grep 'JVM running for' | wc -l)
  failed_sign=$(cat $DES_LOG | grep 'Application run failed\|Failed to\|APPLICATION FAILED TO START' | wc -l)
  if [ $second -ge 800 ]; then
    echo [ERROR] ">>>>>>>>>> 部署等待时间过长 退出部署 <<<<<<<<<<<"
    killProgress
    exit 1
    break
  fi
  if [ $sum -gt 0 ] || [ $sum_jvm -gt 0 ]; then
    echo [INFO] ">>>>>>>>>> 项目回退版本启动花费 $second 秒 <<<<<<<<<<"
    echo [INFO] ">>>>>>>>>> 项目回退版本启动成功 <<<<<<<<<<"
    break
  fi
  if [[ $failed_sign -gt 0 ]]; then
    echo [INFO] ">>>>>>>>>> 项目回退版本启动花费 $second 秒 <<<<<<<<<<"
    echo [ERROR] ">>>>>>>>>> 项目回退版本启动失败 <<<<<<<<<<"
    echo [INFO] ">>>>>>>>>> 请手动操作回退版本!<<<<<<<<<<"
    killProgress
    exit 1
    break
  fi
  second=$((second + 2))
  lastShellRow=$nowShellRow
  sleep 2
done

3.backup.sh

module=$1                              #模块名
env=$2                                 #运行环境
WEB_PATH='/home/../xxx-'$env      #项目根路径
JAR_PATH=$WEB_PATH'/web-jar/'          #jar包路径
LOG_PATH=$WEB_PATH'/web-jar/'          #log路径
SHELL_PATH=$WEB_PATH'/shell/'          #shell脚本路径
BACKUP_PATH=$WEB_PATH'/backup/'        #备份jar包路径
APP_NAME=$module'-1.0.0-SNAPSHOT.jar'  #当前项目名称
DES_APP=$JAR_PATH$APP_NAME             #jar包全路径

# 创建目录
mkdir -p $WEB_PATH
mkdir -p $JAR_PATH
mkdir -p $BACKUP_PATH

# 备份
fileSize=$(du -s $BACKUP_PATH) #项目所在路径的大小
if [[ ${fileSize%%/*} -ne 0 ]]; then
  echo [INFO] ">>>>>>>>>> 开始备份 <<<<<<<<<<"
  echo 'backup file ->'$BACKUP_PATH$APP_NAME
  cp -r $DES_APP $BACKUP_PATH
  echo [INFO] ">>>>>>>>>> 结束备份 <<<<<<<<<<"
fi

六、使用方法

http://ip:10240/

用户名:admin 密码:xxx

1. 选择项目

image.png

2. 构建

image.png

3. 选择参数

image.png

4. 查看构建日志

image.png

image.png

PS

shell脚本或者其他地方,涉及到路径相关,灵活修改即可。

使用docker-compose部署springcloud项目,后续更新...