【CI/CD】Jenkins 部署前后端项目Demo
前置环境准备:
参考尚硅谷最新发布的Jenkins教程
同样准备了三台服务器:
1 2 3 | 192.168.124.34 Centos7 8G内存 用于安装GitLab 192.168.124.35 Centos7 4G内存 用于搭建Jenkins 192.168.124.36 Centos7 4G内存 用于测试环境 |
正好前面把尚学堂云医疗的项目搞完了,可以作为上手的材料
项目部署环境都写的很详细
Gitee开源仓库地址:
1 | https: //gitee .com /daizhizhou/open-his .git |
前端工程的路径是
1 | ${仓库地址} /code/Open-His-Web |
后端工程的路径是
1 | ${仓库地址} /code/Open-His |
也就是所有代码都放在同一个仓库下面存放
在安装Jenkins的机器上需要安装项目构建的环境
git,NodeJS和Npm,新版NodeJS和NPM拆分开了,得单独再安装npm
1 2 3 | sudo yum install git -y sudo yum install nodejs -y sudo yum install npm -y |
Maven需要从官网上下载,以Tar包方式安装
配置Jenkins
1、搭建后台Java工程部署需要使用[Maven集成插件],首先进入[插件管理]菜单
然后在[可选安装]的导航中,搜索: Maven Integration
勾选插件的[ 复选框 ],然后点击下面的 [ 不重启Jenkins安装插件 ]
回到[全局配置],配置Maven的环境
检查一下
一、搭建Open-His后台部署配置
安装完成后,可以发现构建新项目时多一个Maven项目的选项:
输入后台项目名称,点击Maven选项,然后确定项目创建
所有项目都需要配置Git的远程仓库地址和对应的分支:
没有搭建GitLab,可以使用公开的Github或者Gitee
勾选构建触发器这个选项
保存后,在全局配置中,配置远程服务器地址
这个服务器就是我们测试环境的机器
然后回到配置的项目中,可以在[构建前]配置测试服务器的地址:
用于构建的前置处理
【Maven集成】插件的作用在[ 构建 ]部分这里
只需要配置工程总pom文件的位置,就可以帮助用户进行自动构建
构建完成时的后续步骤配置:
保存后,回到主面板,就可以开始进行项目的构建:
可以点击项目名称,翻看构建历史:
如果构建失败,在控制台菜单查看输出日志找到问题原因:
若构建成功,可以在测试环境的目录中检查生成的项目文件:
jenkins默认发送到配置的用户目录下
1 2 3 4 | [root@centos7- ~] # ll 总用量 0 drwxr-xr-x 6 root root 268 8月 10 21:44 Open-His drwxr-xr-x 7 root root 281 8月 13 13:49 Open-His-Web |
可以安装tree命令,速览全部内容:
1 | yum install tree -y |
命令使用:
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 60 61 62 | [root@centos7- ~] # tree code/Open-His code /Open-His ├── His-Commons │ └── target │ └── His-Commons-1.0.jar ├── His-Doctor │ ├── His-Doctor-API │ │ └── target │ │ └── His-Doctor-API-1.0.jar │ ├── His-Doctor-Domain │ │ └── target │ │ └── His-Doctor-Domain-1.0.jar │ ├── His-Doctor-Mapper │ │ └── target │ │ └── His-Doctor-Mapper-1.0.jar │ └── His-Doctor-Service │ └── target │ └── His-Doctor-Service-1.0.jar ├── His-ERP │ ├── His-ERP-API │ │ └── target │ │ └── His-ERP-API-1.0.jar │ ├── His-ERP-Domain │ │ └── target │ │ └── His-ERP-Domain-1.0.jar │ ├── His-ERP-Mapper │ │ └── target │ │ └── His-ERP-Mapper-1.0.jar │ └── His-ERP-Service │ └── target │ └── His-ERP-Service-1.0.jar ├── His-Statistic │ ├── His-Statistic-API │ │ └── target │ │ └── His-Statistic-API-1.0.jar │ ├── His-Statistic-Domain │ │ └── target │ │ └── His-Statistic-Domain-1.0.jar │ ├── His-Statistic-Mapper │ │ └── target │ │ └── His-Statistic-Mapper-1.0.jar │ └── His-Statistic-Service │ └── target │ └── His-Statistic-Service-1.0.jar └── His-System ├── His-System-API │ └── target │ └── His-System-API-1.0.jar ├── His-System-Domain │ └── target │ └── His-System-Domain-1.0.jar ├── His-System-Mapper │ └── target │ └── His-System-Mapper-1.0.jar ├── His-System-Service │ └── target │ └── His-System-Service-1.0.jar └── His-System-Web └── target └── His-System-Web-1.0.jar 40 directories, 18 files |
实现Jenkins自动化部署的关键是在于Shell脚本
Jenkins本身只是帮助我们从仓库拉取最新代码并打包,其他的事情交给我们自己来决定
第一个问题的是打包成功之后立即启动项目:
jar包启动命令:
1 | nohup java -jar jar包位置 >日志文件位置 2>&1 & |
但是现在大多数项目不再是单体架构,需要启动若干个jar包
所以视频演示的项目不能满足我的要求,于是看了Shell脚本怎么写遍历
为了实现批量启动Jar包,这是我写的批量启动脚本:
appStart.sh,对应Jenkins的[ PostStep ]的执行脚本,在构建成功后直接运行项目
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 | #!/bin/bash # 应用名称数组 APPLICATIONS=( 'His-ERP-Service-1.0.jar' 'His-Doctor-Service-1.0.jar' 'His-Statistic-Service-1.0.jar' 'His-System-Web-1.0.jar' ) # 应用位置数组 APPLICATIONS_PATH=( './code/Open-His/His-ERP/His-ERP-Service/target/His-ERP-Service-1.0.jar' './code/Open-His/His-Doctor/His-Doctor-Service/target/His-Doctor-Service-1.0.jar' './code/Open-His/His-Statistic/His-Statistic-Service/target/His-Statistic-Service-1.0.jar' './code/Open-His/His-System/His-System-Web/target/His-System-Web-1.0.jar' ) # ${#APPLICATIONS_PATH[@]} 表示数组长度 for ((i=0; i<${ #APPLICATIONS_PATH[@]}; i++ )) do # 启动jar包 ` nohup java -jar ${APPLICATIONS_PATH[i]} >./${APPLICATIONS[i]}.log 2>&1 &` # 休息3秒 sleep 3s # 检查进程是否存在 pid=` ps -ef | grep ${APPLICATIONS[i]} | grep 'java -jar' | awk '{printf $2}' ` if [ -z $pid ]; then echo "应用:${APPLICATIONS[i]} 没有运行!" else echo "应用:${APPLICATIONS[i]} 正在运行... 进程:$pid " fi done ; |
同样,在项目构建之前,需要清除生成的文件
在清除之前,还要关闭正在运行的项目
首先,先编写停止脚本:
单个程序停止脚本的编写演变:
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 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | # 1、展示所有进程信息 [root@centos7- ~] # ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 19:42 ? 00:00:03 /usr/lib/systemd/systemd --switched-root --system --deserialize 22 root 2 0 0 19:42 ? 00:00:00 [kthreadd] root 4 2 0 19:42 ? 00:00:00 [kworker /0 :0H] root 6 2 0 19:42 ? 00:00:00 [ksoftirqd /0 ] root 7 2 0 19:42 ? 00:00:00 [migration /0 ] root 8 2 0 19:42 ? 00:00:00 [rcu_bh] root 9 2 0 19:42 ? 00:00:03 [rcu_sched] root 10 2 0 19:42 ? 00:00:00 [lru-add-drain] root 11 2 0 19:42 ? 00:00:00 [watchdog /0 ] root 12 2 0 19:42 ? 00:00:00 [watchdog /1 ] root 13 2 0 19:42 ? 00:00:00 [migration /1 ] root 14 2 0 19:42 ? 00:00:01 [ksoftirqd /1 ] root 16 2 0 19:42 ? 00:00:00 [kworker /1 :0H] root 18 2 0 19:42 ? 00:00:00 [kdevtmpfs] root 19 2 0 19:42 ? 00:00:00 [netns] root 20 2 0 19:42 ? 00:00:00 [khungtaskd] root 21 2 0 19:42 ? 00:00:00 [writeback] root 22 2 0 19:42 ? 00:00:00 [kintegrityd] root 23 2 0 19:42 ? 00:00:00 [bioset] root 24 2 0 19:42 ? 00:00:00 [bioset] root 25 2 0 19:42 ? 00:00:00 [bioset] root 26 2 0 19:42 ? 00:00:00 [kblockd] root 27 2 0 19:42 ? 00:00:00 [md] # 2、过滤,筛选带有指定字符的进程信息 # 例如过滤出带有java字符的进程[java] [root@centos7- ~] # ps -ef | grep java root 66255 1492 0 23:07 pts /0 00:00:00 grep --color=auto java # 3、剔除指定字符 # 因为grep命令本身也占用一个进程来处理执行 # 这里剔除grep自身 # 剔除之前 [root@centos7- ~] # ps -ef | grep java root 21320 1 1 17:16 ? 00:05:16 java -jar jenkins.war root 75765 63565 0 23:09 pts /1 00:00:00 grep --color=auto java # 剔除之后 [root@centos7- ~] # ps -ef | grep java | grep -v grep root 21320 1 1 17:16 ? 00:05:16 java -jar jenkins.war # 4、二次筛选(筛选执行命令中带有”Open-His“字符的进程),二次筛选,指定是[java -jar]命令启动的 [root@centos7- ~] # ps -ef | grep "Open-His" root 66487 1492 30 23:12 pts /0 00:00:27 java -jar /root/code/Open-His/His-System/His-System-Web/target/His-System-Web-1 .0.jar root 66654 66511 0 23:13 pts /1 00:00:00 grep --color=auto Open-His [root@centos7- ~] # ps -ef | grep "Open-His" | grep "java -jar" root 66487 1492 27 23:12 pts /0 00:00:27 java -jar /root/code/Open-His/His-System/His-System-Web/target/His-System-Web-1 .0.jar # 5、获取指定非空串的字符 # awk命令必须使用单引号修饰 awk '{printf $游标的下标值}' ps -ef | grep 'Open-His' | grep 'java -jar' | awk '{printf $2}' # 6、把执行的命令输出的值赋值给shell变量 变量名=`执行的命令` pid=` ps -ef | grep 'Open-His' | grep 'java -jar' | awk '{printf $2}' ` # 7、打印变量 echo '结果是 -> $变量名' echo '结果是 -> $pid' # 8、执行进程杀死命令 pid=` ps -ef | grep 'Open-His' | grep 'java -jar' | awk '{printf $2}' ` kill -9 $pid # 9、获取shell脚本执行时附带的参数 $参数下标 echo $1 附加的第一个参数 . /demo .sh param1 echo $2 附加的第二个参数 . /demo .sh param1 param2 echo $3 附加的第三个参数 . /demo .sh param1 param2 param3 ... # 10、指定脚本的第一个参数为自定义进程结束参数 . /demo .sh "Open-His" # 11、shell判断控制 if [ 表达式,逻辑 ]; then # 执行部分 else # 不成立则执行的部分 # 使用fi结束判断 fi # 12、在杀死进程之前先做判断处理,防止脚本误杀进程 # -z 表示 判断右侧变量是否为空, pid=` ps -ef | grep $1 | grep 'java -jar' | awk '{printf $2}' ` if [ -z $pid ]; then echo "程序:$1 进程:pid 没有运行!" else kill -9 $pid echo "程序:$1 进程:pid 正在停止" fi # 13、杀死进程后检查是否还在运行 pid=` ps -ef | grep $1 | grep 'java -jar' | awk '{printf $2}' ` if [ -z $pid ]; then echo "程序:$1 进程:pid 没有运行!" else kill -9 $pid echo "程序:$1 进程:pid 正在停止" fi check=` ps -ef | grep -w $pid | grep java` if [ -z $check ]; then echo "程序:$1 进程:pid 已经停止" else echo "程序:$1 进程:pid 停止失败,仍在执行" fi |
然后改变成批量停止:
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 | #!/bin/bash # 应用名称数组 APPLICATIONS=( 'His-System-Web-1.0.jar' 'His-Doctor-Service-1.0.jar' 'His-Statistic-Service-1.0.jar' 'His-ERP-Service-1.0.jar' ) # 遍历执行 for ((i=0; i<${ #APPLICATIONS[@]}; i++ )) do # 获取pid进程号 pid=` ps -ef | grep ${APPLICATIONS[i]} | grep 'java -jar' | awk '{printf $2}' ` # 判断进程号是否存在 if [ -z $pid ]; then # 不存在则输出提示信息 echo "应用:${APPLICATIONS[i]} 没有运行!" else # 存在则杀死进程 echo "应用:${APPLICATIONS[i]} 进程:$pid 正在停止..." ` sudo kill -9 $pid` fi done ; |
然后再编写前置操作脚本:
1 2 3 4 5 6 7 8 9 10 11 12 | #!/bin/bash # 1、停止进程执行 echo '正在停止jar服务...' sudo . /appStop .sh # 2、清除代码和日志 sudo sleep 3s sudo rm -rf . /code/Open-His echo 'jar包已被清除...' sudo rm -rf ./*.log echo '日志已被清除...' |
二、搭建Open-His前台部署配置
参考博客:
1 | https: //blog .csdn.net /m0_61452987/article/details/123194604 |
Vue构建时需要Node和NPM,在一开始就使用yum进行了安装
1、点选[ 自定义风格 ] 的项目构建,就是第一个
2、和后台一样,配置仓库地址和分支,还有测试环境地址
3、然后保存,直接点击构建,让Jenkins有一个工作空间,里面存放拉取的远程代码
4、Jenkins在构建时会拉取代码,之后通过命令,来完成前端的构建
贴上我写的命令内容:
- 显示node和npm版本,如果在这个位置报错,说明前端环境搭建有问题
- 切换到工作区里的前端代码目录
- 删除之前构建的dist目录
- 执行构建命令
1 2 3 4 5 | node - v npm - v cd /root/ .jenkins /workspace/Open-His-Web/code/Open-His-Web rm -rf /root/ .jenkins /workspace/Open-His-Web/code/Open-His-Web/dist npm run build:prod |
注意,在这里没有添加npm install命令,因为前端的依赖只需要执行一次即可,而且依赖安装的时间非常长
需要自己手动去工作区中添加
同样构建后的操作,就是把生成的文件传到测试机上面
构建前删除项目文件:
Dist目录的文件只是静态文件,需要交给Nginx进行代理
在测试环境中需要安装Nginx
1 | yum install nginx -y |
启动、停止、重启:
1 2 3 | systemctl start nginx systemctl stop nginx systemctl restart nginx |
找到nginx的配置文件:
除了docker的,第一个就是
1 2 3 4 5 6 7 8 9 | [root@centos7- ~] # find / -name nginx.conf /etc/nginx/nginx .conf /var/lib/docker/overlay2/2505bed6ad4b8728ab2689e684765af529f0508888e349cb6054adcfa2264639/diff/root/nginx-1 .13.6 /conf/nginx .conf /var/lib/docker/overlay2/2505bed6ad4b8728ab2689e684765af529f0508888e349cb6054adcfa2264639/diff/usr/local/nginx/conf/nginx .conf /var/lib/docker/overlay2/89313592c0297e779ac25bab4758ef5fc8403dd12e335e3594576958fa133ff7/diff/usr/local/nginx/conf/nginx .conf /var/lib/docker/overlay2/8d9dfa9ccc325c9ab916851d939794604c03fabb790633e691429b05984630bb/diff/usr/local/nginx/conf/nginx .conf /var/lib/docker/overlay2/1954e83a87a7ad5cdfadeebb0cab0a4a74e232738a7253eedb4fda4bf71f1c5b/diff/usr/local/nginx/conf/nginx .conf /var/lib/docker/overlay2/1954e83a87a7ad5cdfadeebb0cab0a4a74e232738a7253eedb4fda4bf71f1c5b/merged/usr/local/nginx/conf/nginx .conf [root@centos7- ~] # |
在配置文件中添加前端和后端的接口配置:
之后重启Nginx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | # 后台服务的地址 upstream his-server { server 127.0.0.1:8081; } # 一个新的静态资源代理的服务配置 server { # 监听哪一个端口 (vue配置的) listen 8088; # 服务名称 server_name localhost; # 配置首页访问的资源位置 location / { # 根目录 root /root/code/Open-His-Web/dist ; # 首页文件 index index.html index.htm; } # 配置后台服务接口的代理 (路径是vue的环境配置) location /prod-api {<br> # 注意下面要补上/ 不然会被vue的拦截器一直拦截,无法登录 proxy_pass http: //his-server/ ; } } |
检查后台和前台是否正常访问:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· 因为Apifox不支持离线,我果断选择了Apipost!
2020-08-13 【FastDFS】06 SpringBoot实现上传
2020-08-13 【FastDFS】05 Java程序测试上传
2020-08-13 【FastDFS】04 Docker搭建
2020-08-13 【FastDFS】环境搭建 03 FastDFS & Nginx整合
2020-08-13 【FastDFS】环境搭建 02 测试
2020-08-13 【FastDFS】环境搭建 01 跟踪器和存储节点