使用Jenkins自动将maven webapp发布到远程演示服务器上

安装并配置Jenkins成功之后,接下来还需要将自动构建的war包发布到远程的演示服务器上,为了使操作更加灵活,可以使用SSH Shell的方式进行。为了有更好的体验,如果发布过程中出现错误自动发送邮件通知。

1. 配置邮件服务器及邮件模板
首先保证已经成功安装了Email Extension Plugin插件,然后依次点击左边的“Manage Jenkins” - “Configure System”,首先在Jenkins Location项目下面设置系统管理员的邮件地址,这里填写的邮箱地址必须跟下面设置的发件人邮箱一致,否则不能成功发送邮件。

接下来在 Extended E-mail Notification 项下面设置SMTP服务器和邮件模板,这里推荐使用QQ邮箱:

Default Recipients填写默认的接收人邮箱地址,多个用英文逗号(,)进行分割,邮件模板可以使用下面参考资料里面提供的模板。
Default Content Type内容:


构建通知:$PROJECT_NAME - Build # $BUILD_NUMBER - $BUILD_STATUS!

Default Subject内容:


(本邮件是程序自动下发的,请勿回复,请相关人员fix it,重新提交到git 构建)


项目名称:$PROJECT_NAME


构建编号:$BUILD_NUMBER


GIT版本号:${GIT_REVISION}


构建状态:$BUILD_STATUS


触发原因:${CAUSE}


构建日志地址:${BUILD_URL}console


构建地址:$BUILD_URL


变更集:${JELLY_SCRIPT,template="html"}


PS: 下面的 E-mail Notification 项是系统默认的邮件通知设置,如果安装了Email Extension Plugin插件可以不用设置了。

2. 配置SSH服务器
首先保证已经安装了Publish Over SSH插件,然后依次点击左边的“Manage Jenkins” - “Configure System”,在Publish over SSH项下面设置登录到远程服务器的配置信息,可以使用用户名/密码的方式,也可以使用证书的方式,这里建议使用后者。

为了安全性考虑,不建议使用root用户。可以使用下面的方法创建一个和root同等权限的账号:


useradd -o -u 0 -g 0 -M -d /root -s /bin/bash tom
passwd tom

使用非root用户(以tom为例)登录远程服务器,执行下面的命令生成密钥对


ssh-keygen -t rsa -C "tom@qq.com"

其中C参数用于设置注释,可以知道其用途。执行命令之后会分别提示文件存放的位置(默认为当前用户下的.ssh目录下)、文件名(默认为id_rsa和id_rsa.pub)、私钥的口令(passphrase,建议设置)。执行完成之后将公钥合并成authorized_keys文件:


cd /root/.ssh
cat id_rsa.pub > authorized_keys

这样在当前用户的home目录(root为/root,其他账号为/home/<user>)的.ssh目录下面就有了三个文件:id_rsa、id_rsa.pub和authorized_keys,如果是在root用户下执行的上述命令,必须确保三个文件一定要在/<user_home>/.ssh目录下,如果不存在需要手动创建,并且三个用户的权限owner应该为<user>。

接下来就可以在Publish over SSH项设置Passphrase和Key,分别是私钥的密码和id_rsa文件的内容,点击下面的Add按钮增加SSH Servers,如果不使用上面公共的密钥设置或者使用用户名密码可以将 Use password authenticatio, or use a different key 选项勾选。

设置完成之后可以点击下面的Test Configuration按钮,如果无误的话会出现Success的提示。
PS:如果对远程服务器进行了安全设置,需要将 /etc/ssh/sshd_config 文件中的 PermitRootLogin 项目设置为 without-password,这样root账号不能用密码直接远程登录,但可以使用密钥对进行登录。

3. 构建完成之后使用SSH发布到演示服务器上
详细创建Jenkins项目请见使用Jenkins实现自动构建Maven项目这篇文章,在项目的配置项中的Post Steps项中选中 Send files or execute commands over SSH:

接下来就可以设置执行的任务内容了:

SSH Server里面选中上面创建的SSH Server,下面的Source files设置需要拷贝的war包或jar包路径和文件名,文件路径可以使用相对路径,根目录为项目的目录;Remove prefix可以把多余的路径前缀去掉,否则上传到服务器上的时候会自动创建对应的目录;Remote directory上传到服务器上的路径,可以不设置,默认为用户根目录;Exec command设置用于执行的脚本路径。新版本的Jenkins会有“Either Source files, Exec command or both must be supplied”的错误提示,要求同时设置上传文件和执行的命令,但是设置了还是会报这个错误提示,可以忽略,实际运行的时候不会出错。
需要注意的是,设置的SSH登录用户必须有操作远程服务器脚本的权限,既然shell脚本是自定义的,这样操作起来就非常灵活了。下面是用于发布到resin上的脚本内容:


DEPLOY_FILE='/root/demo-webapp.war'

# check deploy file exist
if [ ! -f "$DEPLOY_FILE" ]; then
echo "$DEPLOY_FILE not exist!"
exit 1
fi

# stop resin
java -jar /usr/resin/lib/resin.jar stop
# unzip
unzip $DEPLOY_FILE -d /root/demo-webapp/
# remove lib & classes
rm -rf /usr/wwwroot/demo/WEB-INF/lib/
rm -rf /usr/wwwroot/demo/WEB-INF/classes/
# copy to webroot
\cp -a /root/demo-webapp/. /usr/wwwroot/demo/
# TODO execute sql file

# remove war & files
rm -rf /root/demo-webapp/
rm -rf $DEPLOY_FILE
# start resin
java -jar /usr/resin/lib/resin.jar start

4. 设置邮件通知
点击Post-build Actions下面的 Add post-build action 按钮,选择 Editable Email Notification,出现对邮件通知的设置,上面的都使用默认的就可以,需要注意的是必须添加Triggers,否则不会发送邮件通知。点击下面的 Advanced Settings 按钮设置Trigger触发的条件。

Trigger可以设置很多出发条件,常用的主要有三类:Failure-Any(各种情况下的构建失败)、Success(构建成功)、Unstable (Test Failures)(测试失败)。Send To是指发送邮件给谁,默认发送给Developer,也就是对这次构建有过修改动作的人。关于邮件接收人,这里有必要说明一下Developers和Culprits两个角色:

Developers - 根据VCS(SVN或git等)中最后一次代码的提交人。邮件地址的规则是VCS提交人的用户名加上在Jenkins总设置中设置的默认邮箱后缀(Manage Jenkins - Configure System - Extended E-mail Notification - Default user E-mail suffix),比如SVN中组后一次提交人的用户名是 tom,默认邮箱后缀设置的是@qq.com,那么开发者的邮箱就是 tom@qq.com。
Culprits - 上面的Developers是最后一次代码的提交人,Culprits就是相关源码的所有提交人,邮箱地址的规则同上。

这样设置保存之后就可以根据设置的条件发送邮件通知了,非常方便。

参考资料:
「Jenkins+Git+Maven+Shell+Tomcat持续集成」经典教程
jenkins通过 ssh插件部署war包
Jenkins(Hudson)实现远程部署Web项目
解决非root用户用SSH不能无密码登陆本机问题。
Jenkins实践二:如何让你的构建失败通知所有人?——邮件,简聊,slack
Email-ext plugin Triggers

2 thoughts to “使用Jenkins自动将maven webapp发布到远程演示服务器上”

  1. @Jet Ma CI/CD的过程中大部分都是讲的如何处理源码、编译、打包、发布,相对应的数据库该如何处理呢?每次都生成数据库升级脚本吗? 如何做数据库的CI/CD呢? 比如MySQL和MS SQL Server. 希望能给点建议,谢谢!

  2. 你好,可以将需要更新的sql语句放在一个文件里面,然后更新的时候设置成自动执行就可以了

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注