前言
Jenkins搭建任务的文章去年年初,刚学jenkins时其实已经记录过几篇了,但最近回过头去看,发现文章记录的不太细致,所以我决定重新梳理一篇。(特别提醒:本文篇幅比较长,但比较干货,还请耐心观看吧~)
该篇文章主要包括内容有:配置Git拉取代码、配置Maven构建代码、配置shell脚本启动代码、配置邮件通知、账号权限分配的操作。
讲解
一、Git拉取代码
拉取git代码需要做一些准备工作,便是检查是否安装Jenkins插件,其中包括:Git、Multiple SCMs 。
确认插件安装无误了,那我们便可前往任务面板,对任务进行源码管理配置。
若只需拉取单一仓库代码,可直接选用Git插件配置。
若需要同时拉取两个仓库的代码,Git插件就不适用了,我们可以采用Multiple SCMs插件进行配置。
其中jenkins与git仓库之间的连接有三种方式:
-
①、使用账号密码进行连接
-
②、使用ssh公私钥进行连接(常用、推荐)
-
③、使用私人令牌进行连接
连接方式说明:
方式①:账密连接
三种方式中最简单的了,但是通过jenkins配置可能泄露git仓库的账号密码,风险较高,故不推荐。但若忽略泄露的情况,坚持配置,具体操作如下:
任务的源码管理中,点击Credentials下的“添加”按钮。
填写完成后点击“添加”即可,后续便可以再源码管理中的Credentials下勾选了。
前面说到泄露账密,可能会好奇到底要怎么看呢?直接揭秘,操作如下:
打开jenkins管理中的脚本命令行(Script Console),在输入框内输入以下代码,遍历credentials数据。
com.cloudbees.plugins.credentials.SystemCredentialsProvider.getInstance().getCredentials().forEach{
it.properties.each { prop, val ->
println(prop + ' = "' + val + '"')
}
println("-----------------------")
}
下图中,username和password就显示出来了,所以风险就出来了。
方式②:SSH桥接
相对第一种方式,更安全,jenkins使用私钥,在git仓库上配置公钥,从而完成免密连接。具体操作如下:
- 第一步:
确认jenkins当前系统用户与linux系统用户是否保持一致,不一致则进行修改。(jenkins默认安装的用户名为Jenkins,可能会产生操作权限问题,所以建议将Jenkins用户保持与linux系统用户权限一致,避免linux上能直接操作,但jenkins上不行。)
以我为例,运维给我建了一个opser用户,权限仅次于root,那么我就要改jenkins配置文件了。
vim /etc/sysconfig/jenkins
vim /usr/lib/systemd/system/jenkins.service
刷新配置文件。
systemctl daemon-reload
systemctl restart jenkins
若启动失败,可参考我之前写的另一篇博客 – Jenkins – 踩坑记录之权限不足(切换用户)
- 第二步:
为linux系统用户opser创建ssh连接的公私钥。以gitee的推荐方式为例,生成/添加SSH公钥 。
前往linux操作系统进行如下指令操作,按提示回车三次即可。
ssh-keygen -t ed25519 -C "xxxxx@xxxxx.com"
注:其中 ed25519 表示使用的签名算法;xxxxx@xxxxx.com表示 sshkey 的名称,用邮箱只是习惯而已。
上述指令操作完成后,可前往~/.ssh/目录查看生成的公私钥。(其中 id_ed25519.pub 文件表示公钥,id_ed25519 文件表示私钥)
- 第三步:
复制私钥内容填写进jenkins的Credentials配置中。
注意:私钥的头尾也需要带上。
校验git连接仓库是否正常即可。如果遇到linux上能拉取代码,但jenkins上拉取失败,大概率还是权限问题,可参考我之前的博客 – Jenkins – 踩坑记录之权限不足(切换用户)
方式③:私人令牌
使用私人令牌和使用账密一样不太安全,容易通过jenkins泄露,但它的优势是更便捷的管理git仓库的权限,如限制用户上传、合并等操作。
以码云为例,生成私人令牌的地方如下:
使用gitee的私人令牌,推荐下载个jenkins 插件 Gitee后进行配置,这里就不展开了。
2、Maven构建代码
①、下载maven资源包
访问maven官网:maven.apache.org ,如下图提示复制资源链接。
②、在linux上使用wget指令获取资源包
# 进入用户在该系统的home目录
cd /var/lib/maven
# 拉取maven的资源压缩包
wget https://dlcdn.apache.org/maven/maven-3/3.8.5/binaries/apache-maven-3.8.5-bin.zip
③、解压maven压缩包(即安装)
unzip apache-maven-3.8.5-bin.zip
④、配置maven系统参数,验证maven是否安装成功
# 编辑linux的环境变量
vim /etc/profile
# 在文件内添加以下内容,如图:(PATH有东西的话,就用:间隔拼接)
export MAVEN_HOME=/var/lib/maven/apache-maven-3.8.5
export PATH=$MAVEN_HOME/bin:$PATH
# 修改了环境变量文件,需重新加载
. /etc/profile
# 查看maven版本校验是否安装成功
mvn -version
⑤、修改maven源,替换为阿里云的。
# 编辑maven的配置文件
vim /var/lib/maven/apache-maven-3.8.5/conf/settings.xml
# 替换掉原来的mirrot标签内容
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
3、shell脚本启动代码
在Jenkins构建中新增构建步骤“Execute shell”。
文本输入框内填写如下内容:
# jenkins默认在build结束后会kill掉所有的衍生进程,填写该配置可避免
BUILD_ID=DONTKILLME
# 重新加载配置参数
. /etc/profile
# 获取git拉取代码后存放的路径
export PROJ_PATH=`pwd`
# 执行自定义的shell脚本
source $PROJ_PATH/cmge-sdk-start.sh
上面的shell脚本中 cmge-sdk-start.sh 为启动脚本,该文件放置在当前项目的工作空间目录下,脚本中包括 mvn构建jar包、备份jar包、kill原有jar包进程、启动新jar包等系列操作,以我公司目前测试环境的脚本为例进行演示。
我司服务端拆分服务,包括网关服务、管理配置服务、第三方服务、登录服务、支付服务总计5个。那么我就需要分别构建、启动这五个服务,如下:
#!/usr/bin/env bash
# 1、查进程,有则杀,无则输出提示
killJavaGatewayProcess()
{
pid=`ps -ef | grep java | grep cmge-sdk-gateway | awk '{print $2}'`
echo "cmge-sdk-gateway PId list :$pid"
if [ "$pid" = "" ]
then
echo "no cmge-sdk-gateway pid alive!"
else
kill -9 $pid
echo "kill cmge-sdk-gateway pid success!"
fi
}
killJavaManageProcess()
{
pid=`ps -ef | grep java | grep cmge-sdk-manage | awk '{print $2}'`
echo "cmge-sdk-manage PId list :$pid"
if [ "$pid" = "" ]
then
echo "no cmge-sdk-manage pid alive!"
else
kill -9 $pid
echo "kill cmge-sdk-manage pid success!"
fi
}
killJavaThirdpartyProcess()
{
pid=`ps -ef | grep java | grep cmge-sdk-thirdparty | awk '{print $2}'`
echo "cmge-sdk-thirdparty PId list :$pid"
if [ "$pid" = "" ]
then
echo "no cmge-sdk-thirdparty pid alive!"
else
kill -9 $pid
echo "kill cmge-sdk-thirdparty pid success!"
fi
}
killJavaChargeProcess()
{
pid=`ps -ef | grep java | grep cmge-sdk-charge | awk '{print $2}'`
echo "cmge-sdk-charge PId list :$pid"
if [ "$pid" = "" ]
then
echo "no cmge-sdk-charge pid alive!"
else
kill -9 $pid
echo "kill cmge-sdk-charge pid success!"
fi
}
killJavaLoginProcess()
{
pid=`ps -ef | grep java | grep cmge-sdk-login | awk '{print $2}'`
echo "cmge-sdk-login PId list :$pid"
if [ "$pid" = "" ]
then
echo "no cmge-sdk-login pid alive!"
else
kill -9 $pid
echo "kill cmge-sdk-login pid success!"
fi
}
cd $PROJ_PATH/cmge-sdk
mvn clean install -DskipTests
#调用之前封装的方法杀掉java进程
killJavaGatewayProcess
killJavaManageProcess
killJavaThirdpartyProcess
killJavaChargeProcess
killJavaLoginProcess
# 判断是否有history文件夹,没有则创建,用于存储jar包的备份
if [ ! -d "$PROJ_PATH/history/comge-sdk" ]; then
mkdir -p $PROJ_PATH/history/cmge-sdk
fi
# 清空历史文件夹$PROJ_PATH/running/cmge-sdk/
rm -rf $PROJ_PATH/running/cmge-sdk/
# 判断是否有running文件夹和相关子文件夹,没有则创建,用于存储正在运行的jar包
if [ ! -d "$PROJ_PATH/running/cmge-sdk/cmge-sdk-gateway" ]; then
mkdir -p $PROJ_PATH/running/cmge-sdk/cmge-sdk-gateway
fi
if [ ! -d "$PROJ_PATH/running/cmge-sdk/cmge-sdk-manage" ]; then
mkdir -p $PROJ_PATH/running/cmge-sdk/cmge-sdk-manage
fi
if [ ! -d "$PROJ_PATH/running/cmge-sdk/cmge-sdk-thirdparty" ]; then
mkdir -p $PROJ_PATH/running/cmge-sdk/cmge-sdk-thirdparty
fi
if [ ! -d "$PROJ_PATH/running/cmge-sdk/cmge-sdk-login" ]; then
mkdir -p $PROJ_PATH/running/cmge-sdk/cmge-sdk-login
fi
if [ ! -d "$PROJ_PATH/running/cmge-sdk/cmge-sdk-charge" ]; then
mkdir -p $PROJ_PATH/running/cmge-sdk/cmge-sdk-charge
fi
# 移动刚通过maven install出来的jar包到running文件夹
cp $PROJ_PATH/cmge-sdk/cmge-sdk-gateway/target/cmge-sdk-gateway.jar $PROJ_PATH/running/cmge-sdk/cmge-sdk-gateway/cmge-sdk-gateway.jar
cp $PROJ_PATH/cmge-sdk/cmge-sdk-manage/target/cmge-sdk-manage.jar $PROJ_PATH/running/cmge-sdk/cmge-sdk-manage/cmge-sdk-manage.jar
cp $PROJ_PATH/cmge-sdk/cmge-sdk-thirdparty/target/cmge-sdk-thirdparty.jar $PROJ_PATH/running/cmge-sdk/cmge-sdk-thirdparty/cmge-sdk-thirdparty.jar
cp $PROJ_PATH/cmge-sdk/cmge-sdk-login/target/cmge-sdk-login.jar $PROJ_PATH/running/cmge-sdk/cmge-sdk-login/cmge-sdk-login.jar
cp $PROJ_PATH/cmge-sdk/cmge-sdk-charge/target/cmge-sdk-charge.jar $PROJ_PATH/running/cmge-sdk/cmge-sdk-charge/cmge-sdk-charge.jar
# 备份cmge-sdk部署中的jar,
cp -r $PROJ_PATH/running/cmge-sdk/ $PROJ_PATH/history/cmge-sdk_`date +%Y%m%d%H%M%S`_bak
# 依次执行java的启动指令,gateway第一,manage第二,其他随意
nohup java -Xms512m -Xmx1024m -jar $PROJ_PATH/running/cmge-sdk/cmge-sdk-gateway/cmge-sdk-gateway.jar > $PROJ_PATH/running/cmge-sdk/cmge-sdk-gateway/boot.log 2>&1 &
sleep 30
cat $PROJ_PATH/running/cmge-sdk/cmge-sdk-gateway/boot.log
echo "------------------ end ---------------------"
nohup java -Xms512m -Xmx1024m -jar $PROJ_PATH/running/cmge-sdk/cmge-sdk-manage/cmge-sdk-manage.jar > $PROJ_PATH/running/cmge-sdk/cmge-sdk-manage/boot.log 2>&1 &
sleep 30
cat $PROJ_PATH/running/cmge-sdk/cmge-sdk-manage/boot.log
echo "------------------ end ---------------------"
nohup java -Xms512m -Xmx1024m -jar $PROJ_PATH/running/cmge-sdk/cmge-sdk-thirdparty/cmge-sdk-thirdparty.jar > $PROJ_PATH/running/cmge-sdk/cmge-sdk-thirdparty/boot.log 2>&1 &
sleep 30
cat $PROJ_PATH/running/cmge-sdk/cmge-sdk-thirdparty/boot.log
echo "------------------ end ---------------------"
nohup java -Xms512m -Xmx1024m -jar $PROJ_PATH/running/cmge-sdk/cmge-sdk-login/cmge-sdk-login.jar > $PROJ_PATH/running/cmge-sdk/cmge-sdk-login/boot.log 2>&1 &
sleep 60
cat $PROJ_PATH/running/cmge-sdk/cmge-sdk-login/boot.log
echo "------------------ end ---------------------"
nohup java -Xms512m -Xmx1024m -jar $PROJ_PATH/running/cmge-sdk/cmge-sdk-charge/cmge-sdk-charge.jar > $PROJ_PATH/running/cmge-sdk/cmge-sdk-charge/boot.log 2>&1 &
sleep 60
cat $PROJ_PATH/running/cmge-sdk/cmge-sdk-charge/boot.log
echo "------------------ end ---------------------"
完成脚本编写后,建议添加个第三方插件“Timestamper”,用于展示构建日志的时间。
完成插件的安装后,在项目中的构建环境环节,可以看到“Add timestamps to the Console Output”选项,我们对他进行勾选。
最终项目构建后,cmge-sdk-start.sh执行的效果如下:
4、构建邮件通知
安装邮箱拓展插件“Email Extension Plugin”。
进入Jenkins的“Manage Jenkins”菜单内的“Configure System”项。
该配置大坑,经常漏配置!!!
qq邮箱为例,获取smtp信息,然后再jenkins中联调。
联调通过后,最终可在项目中进行配置使用。
构建邮件的格式,我习惯这么处理:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>${ENV, var="JOB_NAME"}-第${BUILD_NUMBER}次构建日志</title>
</head>
<body leftmargin="8" marginwidth="0" topmargin="8" marginheight="4" offset="0">
<table width="95%" cellpadding="0" cellspacing="0" style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">
<tr>
(本邮件由系统自动发出,无需回复!)
<br />
各位好,以下是${PROJECT_NAME}项目构建信息
<br />
<td>
<font color="#CC0000">构建结果 - ${BUILD_STATUS}</font>
</td>
</tr>
<tr>
<td>
<br />
<b>
<font color="#0B610B">构建信息 - ${BUILD_STATUS}</font>
</b>
<hr size="2" width="100%" align="center" />
</td>
</tr>
<tr>
<td>
<ul>
<li>项目名称:${PROJECT_NAME}</li>
<li>构建编号:第${BUILD_NUMBER}次构建</li>
<li>触发原因:${CAUSE}</li>
<li>构建状态:${BUILD_STATUS}</li>
<li>构建日志:<a href="${BUILD_URL}console">${BUILD_URL}console</a>
</li>
<li>构建地址:<a href="${BUILD_URL}">${BUILD_URL}</a>
</li>
<li>工作目录:<a href="${PROJECT_URL}ws">${PROJECT_URL}ws</a>
</li>
<li>项目地址:<a href="${PROJECT_URL}">${PROJECT_URL}</a>
</li>
</ul>
<h4>
<font color="#0B610B">变更记录</font>
</h4>
<hr size="2" width="100%" />
变更明细:<a href="${PROJECT_URL}changes">${PROJECT_URL}changes</a>
<br />
</td>
</tr>
</table>
</body>
</html>
最终选择 Triggers 触发事件即可。
5、账号权限配置
考虑到多人使用 jenkins 后台进行构建的情况,我们需要对每个人进行权限配置,有的人可以配置项目;有的人只能构建和查看;有的人只能查看。
①、安装第三方插件 “Role-based Authorization Strategy”进行权限管理。
②、进入Jenkins的“Manage Jenkins”菜单内的“Configure Global Security”项,将Jenkins的授权策略修改为“Role-based Strategy”。
③、进入Jenkins的“Manage Jenkins”菜单内的“Manage and Assign Roles”项,配置角色和用户之前的关系。
至此,账号与角色之间的关系就配置好了。如果需要更精细到项目,也可以通过该插件实现,自行摸索吧!
评论区