Jenkins保姆笔记(3)——Jenkins拉取Git代码、编译、打包、远程多服务器部署Spring Boot项目

news2024/9/26 20:48:20

前面我们介绍过:  

Jenkins保姆笔记(1)——基于Java8的Jenkins安装部署

Jenkins保姆笔记(2)——基于Java8的Jenkins插件安装

本篇主要介绍基于Java8的Jenkins第一个Hello World项目,一起实践下Jenkins拉取Git代码、编译、打包、多服务器发布的过程。涉及坑和面都较多,步骤图片有多,可以说是干货满满,希望大家能因此学会Jenkins。

S1:新建项目

工作台-新建Item,如图

取个任务名称,就可以“确定”下一步了。

S2:检查插件

新建好项目后,会看到项目构建的一些相关配置。

我们不急操作,先从上到下浏览下,看有没有红色字体的提示,然后就缺啥补啥

如果前面插件安装完整的话,这一步是不会有啥提示的。果不其然,提示我Maven有问题。

这里是说Jenkins找不到Maven,毕竟等会需要Maven干活的不是?

那么提示Jenkins needs to know where your Maven is installed.是否需要另外去服务器安装Maven呢?答案是不需要,Jenkins会帮我们自动安装的。

根据他的提示,我们点击他给的连接“the tool configuration”。进去后发现其实就是控制台——Manage Jenkins——Global Tool Configuration菜单。翻到底部

选择“新增 Maven”,写个即将新增的maven的名称,务必选择好合适的版本,我的spring boot项目的maven用了3.8.1,所以这里也选了3.8.1。

勾选“自动安装”,点击“保存”。回到刚才的项目构建的页面,发现Build的地方没有了之前Jenkins找不到maven的红色字体的警告了。

再看看还有没有其他的没有红字提示,还是按照刚才说的一步步来。大部分自动安装就行了。

S3:项目构建

一个Jenkins的项目构建过程的参数及选择项非常多,我们不一一介绍,只说下里面核心必备的一些配置。

源码管理

我们源码管理用的是Git,如果你用了SVN等也行,在开始装插件的时候,去装SVN的就行。

这里我们也需要有个3小步骤:

1,添加git地址和账号权限

选择“添加”-Jenkins就是添加git的账号权限

在我们输入完账号密码回头看,发现不对劲了,怎么又出现红色字体的警告了啊?

错误提示: 

无法连接仓库:Error performing git command: git ls-remote -h 

看意思是连接不上git服务器?排除防火墙问题后,我们首先考虑还是插件安装问题。

2,安装Git

尽管Jenkins有一些插件可以简化与Git的集成(如Git Plugin),但这些插件仍然依赖于服务器上的Git客户端来执行实际的Git命令。如果Jenkins服务器上没有安装Git,那么即使你安装了Git插件,Jenkins也无法成功执行Git操作,如克隆(clone)、拉取(pull)或推送(push)代码。

因此,如果你的Jenkins项目无法连接远程Git服务器并拉取项目代码,你首先应该检查Jenkins服务器上是否已经安装了Git。你可以通过以下命令来检查Git是否已安装:

git --version

如果系统提示Git未找到或未安装,则你需要使用包管理器(如yum、apt-get等)来安装Git。对于使用yum的CentOS系统,你可以使用以下命令来安装Git:

sudo yum -y install git

安装完成后,再次尝试配置你的Jenkins项目以连接Git服务器,发现还是红色依旧,不要气馁,还有一步。

3,修改Git路径

到之前我们修改Maven配置的那个菜单,也即是控制台——Manage Jenkins——Global Tool Configuration菜单,中间部分的Git栏目,发现也有红色提示:

提示:There's no such executable git in PATH: /usr/local/sbin, /usr/local/bin, /usr/sbin, /usr/bin. 

我们需要把这里的路径PATH修改成服务器中的Git安装目录。

找下服务中Git的安装目录:

which git

输出:

/usr/bin/git

 我们就把这个路径拷贝到上图的PATH里面

保存,刷新,回到项目构建页面,发现什么了?红色提示没了。

基本上配置完Git,下面就可以不配置了。检查下还有没有其他红色提示,没有的话,我们试着“立即构建”看看效果。

修改pom.xml的路径

这里卖个关子,因为毕竟我们是以第一次构建Jenkins项目的小白视角,并不知道这里的路径要修改。我们将在S4里介绍pom.xml的路径修改。

S4:构建项目

 试着构建看看:

很可惜,第一次构建前面出现了红色的X,代表失败了。不着急,点击#1,进去看看错误详情。

ERROR: No such file /var/lib/jenkins/workspace/First Job/pom.xml
Perhaps you need to specify the correct POM file path in the project configuration?
Finished: FAILURE 

 原来是找不到我们spring boot项目的pom路径。我们到实际路径下去看,发现在/var/lib/jenkins/workspace目录下,已经下载好了我的项目hello world了。

所以回到项目构建里,查看pom的位置,

 

在Jenkins拉取了Git的代码到本地后,他发现自己找不到spring boot项目的pom.xml文件了,也就没有办法进行编译和打包。

刚才我们也去服务看了,pom并不在workspace的根目录下,而在根目录/helloworld(我项目包名)/下,所以这里我们修改Root POM路径为helloworld/pom.xml,这里的helloworld改成你们的项目包名。

除了修改pom的路径,这里的Goals and options我们也可以加一些辅助的命令:

clean package -Dmaven.test.skip=true -U

用来在编译时做写清理、更新maven以及跳过测试代码的操作。 

保存,发现ok了吧,好,我们保存构建配置后,再去“立即构建”看看 。

这次发现构建时间有点久,告诉你,不要着急,这可能是积极的信号,因为maven首次成功使用要down好多包的,有点费时。

果不其然,不一会,我们第二次构建成功了。

S5:启动项目

既然构建成功了,启动项目无非有2种,一种是Jenkins在构建后自动给他启动,另一种是jar包都给你打包放在服务器了,你自己去手动启动也行。

Jenkins启动脚本

在项目构建的Post Steps阶段,

新增shell命令:

#!/bin/bash
# 定义变量  
JAR_PATH="$WORKSPACE/helloworld/target" # JAR 文件所在的目录  
JAR_FILE="helloworld-0.0.1-SNAPSHOT.jar" # JAR 文件名  
TARGET_DIR="/root/project/helloworld" # 目标目录,请确保您有足够的权限写入此目录  
TARGET_JAR_PATH="$TARGET_DIR/$(basename "$JAR_FILE")" # 目标目录中的JAR文件完整路径  
  
# 检查目标目录是否存在,如果不存在则创建它  
if [ ! -d "$TARGET_DIR" ]; then  
    mkdir -p "$TARGET_DIR"  
    echo "Target directory $TARGET_DIR created."  
fi  
  
# 查找并杀死已经运行的JAR文件进程(在目标目录中的JAR文件)  
echo "Stopping existing service (if any) in target directory..."  
pid=$(ps -ef | grep "java -jar $TARGET_JAR_PATH" | grep -v grep | awk '{print $2}')  
if [ -n "$pid" ]; then  
    kill -9 $pid  
    echo "Killed existing process $pid"  
else  
    echo "No existing process to kill in target directory"  
fi  
  
# 检查新的JAR文件是否存在  
if [ -f "$JAR_PATH/$JAR_FILE" ]; then  
    echo "File exists: $JAR_PATH/$JAR_FILE"  
  
    # 复制JAR文件到目标目录  
    cp "$JAR_PATH/$JAR_FILE" "$TARGET_JAR_PATH"  
    if [ $? -eq 0 ]; then  
        echo "JAR file copied to $TARGET_JAR_PATH successfully."  
  
        # 启动新的JAR服务  
        echo "Starting new Java service from target directory..."  
        BUILD_ID=dontKillMe
        nohup java -jar "$TARGET_JAR_PATH" > "$TARGET_DIR/output.log" 2>&1 & 
        sleep 3 # 等待服务启动(如果需要的话)  
  
        # 再次检查服务是否启动(可选)  
        pid=$(ps -ef | grep "java -jar $TARGET_JAR_PATH" | grep -v grep | awk '{print $2}')  
        if [ -n "$pid" ]; then  
            echo "New service process $pid started in target directory"  
            #sleep 30
        else  
            echo "Failed to start new service in target directory"  
        fi  
    else  
        echo "Failed to copy JAR file to $TARGET_JAR_PATH."  
        exit 1  
    fi  
else  
    echo "File does not exist: $JAR_PATH/$JAR_FILE"  
    exit 1 # 文件不存在时退出脚本,通常是一个错误情况  
fi
exit 0

这样可以在Jenkins打包后立刻启动项目jar服务。

里面注意有一段BUILD_ID=dontKillMe要加,否则会出现错误:Process leaked file descriptors……伴随的现象是jar程序启动后又停止。那是因为Jenkins默认会使用processTreeKiller在job build结束后杀掉了所有子进程

手动启动脚本

我们在项目目录下,做了个manage.sh的脚本:

#!/bin/bash

   JAR_NAME="helloworld-0.0.1-SNAPSHOT.jar"  # 替换为你的 JAR 文件名
   JAR_PATH="/target/"        # 替换为你的 JAR 文件路径
   LOG_FILE="helloworld.log"        # 日志文件名

   case "$1" in
       start)
           if pgrep -f $JAR_NAME > /dev/null; then
               echo "$JAR_NAME is already running."
           else
               echo "Starting $JAR_NAME..."
               nohup java -jar $JAR_PATH+$JAR_NAME > $LOG_FILE 2>&1 &
               echo "$JAR_NAME started."
               if pgrep -f $JAR_NAME > /dev/null; then
               echo "$JAR_NAME is running."
           else
               echo "$JAR_NAME is not running."
           fi
           ;;
       stop)
           if pgrep -f $JAR_NAME > /dev/null; then
               echo "Stopping $JAR_NAME..."
               pkill -f $JAR_NAME
               echo "$JAR_NAME stopped."
           else
               echo "$JAR_NAME is not running."
           fi
           ;;
       restart)
           echo "Restarting $JAR_NAME..."
           $0 stop
           sleep 2
           $0 start
           ;;
       status)
           if pgrep -f $JAR_NAME > /dev/null; then
               echo "$JAR_NAME is running."
           else
               echo "$JAR_NAME is not running."
           fi
           ;;
       *)
           echo "Usage: $0 {start|stop|restart|status}"
           exit 1
   esac

 使用前,先cd到jar项目manage.sh目录下,确认可用性。

chmod +x manage.sh

然后

./manage.sh start
./manage.sh stop
./manage.sh等等

当然,我们直接简单的java -jar命令也当然可以:

nohup java -jar helloworld/target/helloworld-0.0.1-SNAPSHOT.jar > app.log 2>&1 &

自此,Jenkins完成了我们首个打包项目算是完成的差不多了,有兴趣的也可以去看看如何编译前先clean mvn,或者打包结束后发个邮件通知当事人等等功能都是很强大的。上手后大家可以自行琢磨。这里我们再讲下最后一点,多服务器分发打包。

Jenkins远程部署

我们之前的实验,实践了往Jenkins本机部署一套jar服务的过程,但是微服务基本是分布式,需要部署在多台服务器上的,莫不是要求每台服务器都安装Jenkins,然后逐个部署吗?答案不是的。我们只需要安装一台Jenkins,就可以远程部署程序到各个远程服务器上。通常被称为Jenkins远程部署Jenkins跨服务器部署。

1,Publish Over SSH

首先我们需要检查或安装插件:Publish Over SSH,方法就略了,在本系列第二篇里有。

2,配置SSH

其次呢,我们再去Manage Jenkins——Configure System里面找到SSH单元,新增一个目标服务器的SSH连接信息,点击新增按钮,如下

照着提示填就行,Name是该SSH昵称,然后hostname是ip,username是ssh的账号,至于密码在“高级”按钮里。完事试试右下角的“Test Configuration” ,成功后进行下一步。

3,新增启动脚本

继续在本篇S5段落“Jenkins启动脚本”的后面增加一个新命令:

选择send files or execute commands over SSH

进去后大体就这么几个参数要填,主要是后面的执行脚本

#!/bin/bash  
  
# 定义变量  
JAR_PATH="project" # JAR 文件所在的目录  
JAR_FILE="helloworld-0.0.1-SNAPSHOT.jar" # JAR 文件名  
  
# 查找并杀死已经运行的 JAR 文件进程  
echo "Stopping existing service..."  
pid=$(ps -ef | grep "java -jar $JAR_PATH/$JAR_FILE" | grep -v grep | awk '{print $2}')  
if [ -n "$pid" ]; then  
    kill -9 $pid  
    echo "Killed existing process $pid"  
else  
    echo "No existing process to kill"  
fi  
  
# 检查新的 JAR 文件是否存在  
if [ -f "$JAR_PATH/$JAR_FILE" ]; then    
    echo "File exists: $JAR_PATH/$JAR_FILE"  
    # 启动新的 JAR 服务  
    echo "Starting new Java service..."  
    nohup java -jar "$JAR_PATH/$JAR_FILE" > $JAR_PATH/output.log 2>&1 &
    sleep 3 # 等待服务启动(如果需要的话)  
      
    # 再次检查服务是否启动  
    pid=$(ps -ef | grep "java -jar $JAR_PATH/$JAR_FILE" | grep -v grep | awk '{print $2}')  
    if [ -n "$pid" ]; then      
        echo "New service process $pid started"  
    else  
        echo "Failed to start new service"  
    fi  
else    
    echo "File does not exist: $JAR_PATH/$JAR_FILE"  
    exit 1 # 文件不存在时退出脚本,通常是一个错误情况  
fi

在脚本下面有个“高级”菜单按钮,里面的功能还是很实用的,安利一下,尤其是Flatten files,在拷贝文件到远程服务器时省略源服务器的冗余路径。

这样远程服务器的部署脚本就执行好了。

若还需要把该程序分发到另外的服务器上,继续Add Transfer Set就行,在此之前重复2,3步骤,就是一个新的SSH的端了。

Jenkins的实践先到这,咱们再见。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1992713.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第十九节 大语言模型与多模态大模型loss计算

文章目录 前言一、大语言模型loss计算1、loss计算代码解读2、构建模型输入内容与label标签二、多模态大模型loss计算方法1、多模态loss计算代码解读2、多模态输入内容2、大语言模型输入内容3、图像embending如何嵌入文本embeding前言 如果看了我前面文章,想必你基本对整个代码…

Java学习Day24:基础篇14:多线程

1.程序、进程和线程 程序 进程 进程(process)是程序的一次执行过程,或是一个正在执行的程序。是一个动态的过程:有它自身的产 生、存在和消亡的过程。 如: 运行中的QQ运行中的音乐播放器视频播放器等;程序是静态的&#xff0c…

写给小白程序员的一封信

文章目录 1.编程小白如何成为大神?大学新生的最佳入门攻略2.程序员的练级攻略3.编程语言的选择4.熟悉Linux5.学会git6.知道在哪寻求帮助7.多结交朋友8.参加开源项目9.坚持下去 1.编程小白如何成为大神?大学新生的最佳入门攻略 编程已成为当代大学生的必…

音视频开发,最新学习心得与感悟

音视频技术的知识海洋浩瀚无垠,自学之路显得尤为崎岖,技术门槛的存在是毋庸置疑的事实。 对于渴望踏入这一行业的初学者而言,学习资源的匮乏成为了一道难以逾越的障碍。 本次文章主要是给大家分享音视频开发进阶学习路线,虽然我…

三大口诀不一样的代码,小小的制表符和换行符玩的溜呀

# 小案例,打印输出加法口诀 for i in range(1,10):for j in range(1,10):if j>i:breakprint(f"{j}{i}{ji}".strip(),end\t)print() print(\n) for i in range(1,10):for j in range(1,10):if j>i:breakprint(f"{j}x{i}{j*i}",end\t)print…

[Spring] Spring AOP

🌸个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 🏵️热门专栏: 🧊 Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 🍕 Collection与…

【Linux】sudo提升权限(入门)

相关专栏:《Linux》 目录 1. sudo功能介绍 2. 任何人都能用 sudo 吗? (1)查看配置文件/etc/sudoers (2)修改/etc/sudoers提权 3. 改变sudo输入密码时间 4. 显示sudo 密码 5.常见 sudo 命令 -k 参数 …

ajax part4

图片上传 <!DOCTYPE html> <lang"en"><head>cmeta charset"UTF-8><meta http-equiv"X-UA-Compatibleb content" IEedge"><meta name"viewportR content" wiclthdevic6-widths initial-scalel. 0"&…

做报表用什么工具?不想再用Excel了!!!

一、什么是中国式报表&#xff1f; 不知道大家现在还是使用Excel来制作报表&#xff0c;然后跟领导汇报工作吗&#xff1f;虽然Excel功能很强大&#xff0c;但是用Excel做过中国式报表的小伙伴一定知道它的制作过程有多复杂。 中国式报表可以用一句话简单概括&#xff1a;格式…

C++笔试强训11

文章目录 一、选择题1-5题6-10题 二、编程题题目一题目二 一、选择题 1-5题 A. 不是任何一个函数都可定义成内联函数&#xff1a;这是正确的。因为内联函数需要在编译时展开&#xff0c;如果函数体过大或包含复杂的控制结构&#xff08;如循环、递归等&#xff09;&#xff0c…

Linux/C 高级——分文件编程

1.头文件&#xff1a;.h结尾的文件 头文件引用、宏定义、重命名typedef、结构体、共用体、枚举的定义、函数声明、外部引用extern。 一般全局变量不会定义在头文件中 2.源文件&#xff1a;.c结尾的文件 包含main函数的.c文件&#xff1a;main函数 包含子函数的.c文件&#xff1…

【LLM】-17-会话存储

目录 1、会话存储类型 2、版本代码说明 3、对话缓存存储 3.1、示例代码 3.2、响应response说明 3.3、流式输出 3.4、添加提示词模板 3.5、指定回答语言 4、限制令牌数存储 4.1、trim_messages 4.1.1、自定义tokens计数器 4.1.2、自定义tokens计数器 4.2、完整chat…

HookNet- 用于病理全切片图像的多分辨率语义分割模型|顶刊精析·24-08-08

小罗碎碎念 今天分享的这篇文章是关于一种名为HookNet的新型语义分割模型&#xff0c;它专为病理学全切片图像设计&#xff0c;于2021年发表于《Med Image Anal》&#xff0c;目前IF10.7。 作者角色姓名单位&#xff08;中文翻译&#xff09;第一作者Mart van Rijthoven荷兰Ra…

Spring-boot 集成 SocketIO(看这一篇就够了)

1 前言 1.1 什么是 SocketIO ? Socket.IO 是一个可以在浏览器与服务器之间实现实时、双向、基于事件的通信的工具库。 Socket.IO 能够在任何平台、浏览器或设备上运行,可靠性和速度同样出色。 1.2 websocket和socket.io区别&#xff1f; websocket a&#xff1a;一种让客户…

video标签,去除上下默认边距

不知道为什么&#xff0c;video标签上下会有空白 清除方法 style"width 100%; height100%; object-fit: fill"

校园二手物品交易网站/校园闲置物品交易系统

摘 要 本文论述了校园二手物品交易网站的设计和实现&#xff0c;该网站从实际运用的角度出发&#xff0c;运用了计算机网站设计、数据库等相关知识&#xff0c;网络和JSP技术、SSM框架Mysql数据库设计来实现的&#xff0c;网站主要包括学生注册、学生登录、浏览商品、搜索商品…

Vue+Element Plus后台管理主界面搭建实现

​ 续接Django REST Framework&#xff0c;使用Vite构建Vue3的前端项目 1. 后台管理系统主界面框架搭建 后台系统主界面搭建 新建后台管理文件目录 完成后台整体布局 // 1.主界面 index.vue<script setup lang"ts"></script><template><el-…

应用层HTTP协议

文章目录 应用层HTTP协议1、HTTP协议概念2、URL&#xff08;统一资源定位符&#xff09;2.1、URL的encode&#xff08;编码&#xff09;和decode&#xff08;解码&#xff09; 3、HTTP请求和响应报头格式3.1、请求报头3.2、响应报头 4、HTTP的方法4.1、GET方法4.2、POST方法4.3…

生成模型VAE

VAE likelihood-basedELBOVAESGVB估计器和AEVB算法重参数化 likelihood-based likelihood-based generative models是生成模型的一类范式&#xff0c;通过最大化所有观测数据的似然函数来学习模型参数。 该怎么去理解likelihood-based&#xff0c;基于似然的生成模型&#xf…

互联网重构“规则制定权”,周期性谋咒开始轮转!

周期“魔咒”又开始轮转了。 产业趋势叠加资本周期&#xff0c;使得任何产业都有其周期性规律&#xff0c;传统资源产业是如此&#xff0c;科技产业亦非例外。 刚刚迎来30周年庆的中国互联网赛道就正处于新一轮小周期的节点。随着移动用户量逐渐被开发利用至阶段性顶峰&#…