jenkins 作为一个自动化的集成工具,已经是必不可少的了。它里面提供各种插件,以及完备的基础流程设施,为大家的自动化集成之路提供了很多的方便。所以,我们有必要完整的实践一回。以切身体会到它的好处!

一、 操作步骤说明陈列

  1. 下载jenkins包,并安装;(两种方案,基于物理机和基于docker,视情况而定建议使用docker)

  2. 安装后,初始化jenkins,基本都是下一步下一步搞定,保持默认是比较稳妥的选择;

  3. 订立目标,需要完成什么的场景下的打包功能? git ?  subversion? 或者其他 ?

  4. 选择此场景需要的必要插件安装,并进行简单调试;

  5. 新建一个任务,尝试使用工具完成一次简单的打包操作;

  6. 完善一个任务,使其可以支持一些简单的参数定制,如分支的选择;

  7. 打包完成后,编写部署脚本,使其可以一键部署;

  8. 设置权限管理,使不同环境的包由不同级别的同学进行操作;

  9. 进行反复功能验证,及权限验证;

  10. 备注所有的操作流程,以便在进行下次重新安装时,能够随时搞定;

二、具体实践操作

  简单的安装和初始化,咱们就不多说了,网上一大堆的信息,随便找一个就能搞定,不找也能搞定,请参考官网: https://wiki.jenkins.io/display/JENKINS/Use+Jenkins

打包场景一: 如何打包 maven 管理的java项目 ?

  其实要打包这种项目比较简单,只要安装一个 maven integeration 的插件即可!如下:

  安装好后,新建一个 maven 任务即可!

  其实maven任务和其他任务不太一样的地方是,它会出现一个 pom.xml 的字样,其实就是自己去加载这个配置文件,然后自行调用 maven 进行打包。而如果想要更灵活,也是可以的,只需要使用 系统的命令进行自由构建即可!

  goal 里可写: clean install | package

  经过上面的操作后,你可能会发现,其实并不会打包成功,为什么呢?因为我们还没有安装 maven 的工具到系统上,或者说没有向 jenkins 解释 maven 在哪里,所以需要到全局工具配置一下!

  另外,如果你是需要打包 git 类的代码的话,一般只需要进行简单授权就可以了!

  到此,一个 简单的 maven java 项目打包就成功了!

但是,其实,打包到这个程度,其实对我们的环境部署一点更多的意义都没有,所以我们需要更深的定制化!咱们稍后再说!

先来说说,另一种项目的打包方式, h5 代码的打包。 更具体的讲,就是 基于 nodejs 的打包实现!

  首先,我们当然需要安装 node js 的插件了!

  同样,该插件安装好后,还要安装  nodejs 的软件!可以直接选择自动 安装 ! 注意要求的版本!

  安装好后,新建一个自由风格的任务!

  进入,把 node 的环境支持勾选上!然后定稿node 的打包命令!

  同样,git 相关的操作一样!

  至此,简单的 node 版本的代码打包功能也做好了。

  同样,只是进行打包,无法定制化的东西,对我们毫无意义,所以,我们需要更高级的定制 jenkins !

  例外:如果有依赖一些私有的包,那么,你可以选择安装私服,或者用如下方式解决:

# for local repository dependency...
ln -sf /var/lib/jenkins/pkg-bak/testmodule/ $WORKSPACE/node_modules/testmodule
npm install
npm run prod

三、 定制你的 jenkins 功能!

场景一: 我需要为一个git 仓库的多个分支打包?

  这个,简单, jenkins 中一添加定制化参数的功能,只需要添加一个文本参数就可以 了!

  在 git 分支一栏,写入 $branch 替换即可!

  如此,一个简单的支持 git 多分支打包的功能就做好了!

但是:每次都让我自己输入分支,好烦啊! 而且,我自己也不一定知道有什么样的分支,这可怎么办?

  借助 groovy 脚本,可以动态拉取 分支列表,进行显示了!

  简单来说就是,执行一些shell脚本 , 从 git 远端列举出分支,给到列表选项! groovy 脚本如下:

def git_url = "https://github.com/yougewe/elastic-job-lite"
def git_cmd = "/usr/local/git/bin/git ls-remote -h $git_url | grep -oP '(?<=refs/heads/).*' "
branch = ['bash', '-c', git_cmd].execute().text.readLines()

  好了,分支的选择,看起来我们已经解决得差不多了!

  但是,前端有个点,就是这分支的触发问题,其实我们可以更动态方式实现!

场景二: 我需要支持多个仓库进行切换打包,当然这里的仓库将必然影响到上面分支列表的选择!

  可以使用 Active Choice 这个插件,可以让我们在需要的时候触发一次分支的选择,比如支持 分支快速过滤!达到数据联动的效果;

  然后,也可以使分支依赖于动态的仓库进行变更分支列表等等!总之, Active Choice 插件真是很方便发挥!

  最终的效果就是,我们可以选择,多仓库,动态列表多分支,进行打包!

总之,通过这个联动支持,以及简单groovy知识,你可以有很大的发挥空间;

场景三: 我需要将打好的包部署到指定服务器上?

这是个关键的问题,就是我们打包来的包,应该处理的问题!

这里有两个核心问题: 1. 我如何找到打包后的东西? 2. 如何将找到的东西部署到线上?

  如果不能很好的处理这些包,我们将很无奈!所以  shell 就出场了!

  jenkins 支持在打包后进行一些自定义的操作! 比如 上传包到另外的服务器,或者部署到另外的地方等等!总之,就是任你发挥!

一般地说,查找打包后的东西,要依赖于你的代码实现,所以具体问题具体分析;当然了,你可以通过mvn等命令直接订制打包的各种配置,从而活动查找的麻烦;

另外,对于部署到服务器,至少有两个解决方案:1. 直接通过scp等服务器拷贝技术,将包放到目标服务器即可; 2. 将包打包成可执行的安装包,上传yum源服务器,在使用端直接拉取镜像即可;

  比如如下的脚本 ,我们可以将它部署到我们指定服务器的 docker 容器中!

  参考脚本如下:

echo "hello, build over ??? would you scp or deploy apps ??? work dir: $WORKSPACE , repository: $spec_repository;"
# specify dev environment or product environment
deploy_env_server="root@172.10.11.16"
deploy_path_prefix="/opt/docker/webapps/test"
docker_app_startup_script="/etc/init.d/startup restart";
case "$spec_repository" in
richCash)
docker_container_name="test_container";
docker_app_startup_script="/etc/init.d/startup restart";
deploy_path_prefix="/opt/docker/webapps/";
deploy_sub_path="$deploy_environment"
case "$deploy_environment" in
"test-p8081")
docker_container_name="test_p8081_container"
;;
docker_container_name="test_p8083_container"
;;
*)
# default container
;;
esac
deploy_path_prefix="/opt/docker/webapps/$deploy_sub_path";
;;
test2-01)
deploy_path_prefix="/opt/docker/webapps/test2-01";
docker_container_name="test2_01_container";
docker_app_startup_script="/etc/init.d/startup restart";
;;
*)
echo "not find special configures in $spec_repository, do the default thing";
;;
esac
# deploy script
deploy_script_path="ssh $deploy_env_server \"docker exec $docker_container_name bash -c '$docker_app_startup_script'\""; pom_file="$WORKSPACE/pom.xml";
pom_file_tmp="$pom_file\.tmp";
cd $WORKSPACE;
cat $pom_file | awk '{if($0 ~ /<parent>/){parent_begin++; print "no dump parent"} else if(parent_begin > 0){ if($0 ~ /<\/parent>/){parent_begin = 0; print "match the parent end.";} else {print "hit parent dump"; }} else { print $0;}}' > $pom_file_tmp
package_artifactId=`grep "<artifactId>" $pom_file_tmp | head -n | sed -e 's/\(\s*<artifactId>\|<\/artifactId>\s*\)//g'`;
package_version=`grep "<version>" $pom_file_tmp | head -n | sed -e 's/\(\s*<version>\|<\/version>\s*\)//g'`;
package_full_name="$package_artifactId-$package_version.jar" # 定义为jar包写死
package_full_path="$WORKSPACE/target/$package_full_name";
echo "packaged file is: $package_full_name";
scp $package_full_path $deploy_env_server:"$deploy_path_prefix/$package_full_name";
# restart the server...
eval $deploy_script_path;

  如上,是对 jar 包的部署方式,我们再来看下 h5 包的部署方式:

echo "hello, build over ??? work dir: $WORKSPACE , repository: $spec_repository; branch: $branch ;"
# specify dev environment or product environment
deploy_env_server="root@172.11.1.12"
docker_container_name="web_container";
deploy_path_prefix="/opt/docker/webapps/";
deploy_sub_path="$deploy_environment"
deploy_path_prefix="$deploy_path_prefix""$deploy_sub_path"
deploy_package_bak_path="/opt/docker/webapps/bak/"
docker_app_startup_script="ls "
case "$deploy_environment" in
"web-p81")
docker_container_name="web_81_container"
;;
*)
# default container
;;
esac
datetime=`date '+%Y%m%d%H%M'`;
package_full_name="$spec_repository-$branch-$datetime.tar.gz"
package_full_origin_path_prefix="/var/lib/jenkins/tmppackages/h5"
package_full_origin_path="$package_full_origin_path_prefix/$package_full_name";
deploy_package_bak_path="$deploy_package_bak_path""$package_full_name"
# deploy script
deploy_script_path="ssh $deploy_env_server \"rm -rf $deploy_path_prefix/*; if [ ! -d $deploy_path_prefix ]; then mkdir -p $deploy_path_prefix; fi; tar -xzf $deploy_package_bak_path -C $deploy_path_prefix\""; package_dist_origin_path="$WORKSPACE/dist";
cd $package_dist_origin_path;
tar -czf $package_full_origin_path -C $package_dist_origin_path .;
echo "packaged file is: $package_full_origin_path";
scp $package_full_origin_path $deploy_env_server:"$deploy_package_bak_path";
# restart the server...
eval $deploy_script_path;

  如上,h5 的打包方式,区别在于需要手动打包一为 gz 包,然后到目标机器进行解压缩即是安装!

  
  如上,就可以进行一键部署测试环境了!
  剩下的,就是自己自由发挥了!
  同理于 h5 的部署方式!

四、重难点提示

其实,准确来说,上面的操作都比较常规,因为都是最终的结果步骤展示!但是其实这其中有很多的坑,期望提示对你有帮助!

1. 使用groovy 进行分支获取时, 需要对 git 命令进行免密授权操作,否则将永远拉不到分支;

2. 使用scp, scp 这些命令调用远程,需要免密登录,否则授权失败;

3. 使用 ssh xx@1.2.2.4 "ls ." 运行远程命令如同本地命令;

4. 真正的部署脚本可以远程服务器上,也可以写在部署机器上;

5. 出于安全考虑,默认情况下运行jenkins的用户都不是root,所以一般不要以为在terminal操作正常的命令,在jenkins上也能正常;

五、jenkins带来的切实好处

为什么一定要用jenkins?难道就因为其名声大燥吗?其实是是因为它真的能带来这些好处:

1. 部署速度指数级提升,以前按照个人的操作速度,要10分钟左右的操作且要记忆多种复杂关联命令,现在可能只要2分钟一键搞定,爽不爽?

2. 部署信息有迹可查,如果按照之前的部署,谁部署出了问题,完全不知道,但是jenkins上有操作记录,更易发现问题;

3. 解决了系统兼容性问题引发的不适,之前各自部署来源不一致,可能导致各种难查问题,而用jenkins则保证完全一致;

4. 拒绝不可靠错误代码的上线,借助于jenkins的单元测试功能,可以发现在一些简单代码的问题,避免之前的误操作上线;

5. 因为收口部署方式,对于后续新的部署方案,有了更加有利的支持,比如想加入sonar代码扫描,只需修改下部署部署脚本即可;

附:

  Q: jenkins 使用插件进行部署,调用运行shell脚本不成功?
    nohup 运行 java 程序,被关掉后无法重启。可能原因是 该进程尚未被挂到当前会话,就被kill或者退出。解决办法是加上适当延迟。

# 该进程可能启动缓慢
nohup java -jar a.jar & #sleep 延迟可以处理异步问题
sleep
echo " start over, new pid: $! !!!"

  Q: 有哪些方便的插件推荐?
  Publish On SSH & SSH Slaves, 方便进行远程部署。
  Rebuilder, 方便进行相同参数的部署重新执行, rebuild 即可,避免反复选择参数信息。
  Active Choice, 下拉框,可以触发脚本执行,方便进行动态响应,而不是全静态的参数。
  Timestamper, 可以获取时间参数,以便进行日志类记录;
  user build vars plugin, 获取各种系统变量;
  Workspace Cleanup Plugin, 空间清理插件,避免jenkins占用太多空间;

一句话总结:有时知道问题比解决问题更重要!

jenkins 自动化部署实战的更多相关文章

  1. Linux下的Jenkins+Tomcat+Maven+Gitlab+Shell环境的搭建使用(jenkins自动化部署)

    jenkins自动化部署 目标:jenkins上点构建(也可以自动检查代码变化自动构建)>>>项目部署完成. 一.安装jenkins 1.下载jenkins 这里我选择的是war包安 ...

  2. Linux下的Jenkins+Tomcat+Maven+Git+Shell环境的搭建使用(jenkins自动化部署)【转】

    jenkins自动化部署 目标:jenkins上点构建(也可以自动检查代码变化自动构建)>>>项目部署完成. 一.安装jenkins 1.下载jenkins 这里我选择的是war包安 ...

  3. Jenkins自动化部署代码

    通过jenkins自动化部署项目代码可以大幅度节省打包上传部署的时间,提高开发测试的工作效率 ========== 完美的分割线 =========== 1.Jenkins是什么 1)Jenkins是 ...

  4. Linux下的Jenkins+Tomcat+Maven+Git+Shell环境的搭建使用(jenkins自动化部署)

    jenkins自动化部署 目标:jenkins上点构建(也可以自动检查代码变化自动构建)>>>项目部署完成. 一.安装jenkins 1.下载jenkins 这里我选择的是war包安 ...

  5. AspNetCore容器化(Docker)部署(四) —— Jenkins自动化部署

    一.前言 (Jenkins.Docker.Git/Svn组建一套简单的自动化发布流程) 文章中用到的相关服务器角色 角色 环境 功能 开发机 Win10.Docker(Linux OS) 编码.调试 ...

  6. jenkins自动化部署项目1--下载安装启动(windows)

    年初以来断断续续研究jenkins自动化部署项目,前些天终于搞定了,接下来一点点把做的时候遇到的坑以及自己的心得写下来,方便以后复用. 我的jenkins服务是是部署在windows上的 一.下载安装 ...

  7. Jenkins自动化部署入门详细教程

    大纲 1.背景 在实际开发中,我们经常要一边开发一边测试,当然这里说的测试并不是程序员对自己代码的单元测试,而是同组程序员将代码提交后,由测试人员测试: 或者前后端分离后,经常会修改接口,然后重新部署 ...

  8. Windows环境下实现Jenkins自动化部署

    详见:https://blog.csdn.net/Try_harder_every_day/article/details/79170065 Jenkins自动化部署: 几条具体的思路:1.开发人员将 ...

  9. Jenkins 自动化部署上线

    转载于互联网 jenkins自动化部署项目,通过jenkins 部署来节省运维时间,不需要手动cp上线及版本发布 Jenkins 自动化部署上线 Jenkins Jenkins 自动化部署上线一.Je ...

随机推荐

  1. jmeter添加断言

    先创建一个线程组,再创建一个http请求. 为了方便观察,我们添加两个监听器,察看结果树和断言结果. 添加断言:响应断言,响应断言也是比较常用的一个断言 设置响应断言:正常情况下响应代码是200.选择 ...

  2. 你不知道的JavaScript--Item19 执行上下文(execution context)

    在这篇文章里,我将深入研究JavaScript中最基本的部分--执行上下文(execution context).读完本文后,你应该清楚了解释器做了什么,为什么函数和变量能在声明前使用以及他们的值是如 ...

  3. Android 自定义 ViewPager 打造千变万化的图片切换效果

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38026503 记得第一次见到ViewPager这个控件,瞬间爱不释手,做东西的主 ...

  4. Connection reset by peer的常见原因

    1,如果一端的Socket被关闭(或主动关闭,或因为异常退出而 引起的关闭),另一端仍发送数据,发送的第一个数据包引发该异常(Connect reset by peer). Socket默认连接60秒 ...

  5. [python]多线程模块thread与threading

    Python通过两个标准库(thread, threading)提供了对多线程的支持 thread模块 import time import thread def runner(arg): for i ...

  6. TestNG监听器实现用例运行失败自动截图、重运行功能

    注: 以下内容引自 http://blog.csdn.net/sunnyyou2011/article/details/45894089 (此非原出处,亦为转载,但博主未注明原出处) 使用Testng ...

  7. 如何解决开机出现Missing operating system的故障

    刚刚一哥们火急火燎的来找我,说他的笔记本开机出现一行字,进不了系统,好可怕,里面存了好多资料呢,让我给他看看,看能不能整好.看的出来,把他吓坏了.我开玩笑问他是不是遇到勒索的了,显示的那句话是不是&q ...

  8. bzoj 1426 收集邮票

    f[i]:当前已拥有i种邮票,还需要买的邮票数的期望值. g[i]:当前已拥有i种邮票,还需要的钱的期望值. 每张邮票初始都是1元钱,每买一张邮票,还没购买的邮票每张都涨价1元.  f[i]=1+(n ...

  9. awk的递归

    想来惭愧,之前写的一篇文章<用awk写递归>里多少是传递里错误的信息.虽然那篇文章目的上是为了给出一种思路,但实际上awk是可以支持函数局部变量的. awk对于局部变量的支持比起大多数过程 ...

  10. 关于DatePicker在模态窗体下失效的问题

    最近用bootstrap做了一个租赁相关的管理系统,由于前端知识薄弱,也是编查资料边做.关于一些控件的用法,也是从网上查资料.下面,来说一下在写前端页面时遇到的几个坑. 这个系统中,日期控件用的是Da ...