主旨

本文主要记录了下Jenkins升级插件过程中出现的场景,一次加班经历,事发时没有截图,有兴趣可以看看。

起因

需求

最近有个需求:在Jenkins流水线中完成下载Git上的文件简单修改并提交的功能

起初找到了相关的插件用法,即使用 SSH Agent Plugin 来完成这个功能

插件不生效

经测试无法完成效果,分别怀疑了以下几点:

  • 凭据配置有误
  • 写错了脚本
  • 当前未安装此插件
  • 当前插件版本过低
  • 当前插件由于某种原因未生效

排查不生效原因

经排查,发现的确没有生效,原因是之前运维同事做迁移时做的一系列骚操作搞的:

  • 用最新的Jenkins war包部署 + 老版本Jenkins家目录
  • 由于新版本需要使用新版本的插件才能生效,升级了所有插件
  • 升级完重启,启动不起来了……
  • 回退老版本war包,继续使用当前升级过插件的Jenkins家目录
  • 在插件管理处,按提示降级了部分插件

预感

等我看到 Manage Jenkins 那一片红的时候,就有预感这次要不简单,当时也没多想,去检查了下 SSH Agent Plugin 的版本

升级插件

发现提示Warn 需要升级此插件到某版本及以后,插件方能生效,没多想,升级就是了

没想此举为我昨晚的加班,打开了潘多拉魔盒…… 升级完重启,启动不起来了!

Jenkins挂机

启动报错如下:(昨晚没心情截图,直接搜的错误)

com.thoughtworks.xstream.mapper.CannotResolveClassException: com.michelin.cio.hudson.plugins.rolestrategy.RoleBasedAuthorizationStrategyat com.thoughtworks.xstream.mapper.DefaultMapper.realClass(DefaultMapper.java:79)atcom.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.DynamicProxyMapper.realClass(DynamicProxyMapper.java:55)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.PackageAliasingMapper.realClass(PackageAliasingMapper.java:88)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.ClassAliasingMapper.realClass(ClassAliasingMapper.java:79)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.ArrayMapper.realClass(ArrayMapper.java:74)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.SecurityMapper.realClass(SecurityMapper.java:71)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at hudson.util.XStream2$CompatibilityMapper.realClass(XStream2.java:379)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at org.jenkinsci.jruby.JRubyMapper.realClass(JRubyMapper.java:34)
at hudson.util.xstream.MapperDelegate.realClass(MapperDelegate.java:43)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.CachingMapper.realClass(CachingMapper.java:48)
at hudson.util.RobustReflectionConverter.determineType(RobustReflectionConverter.java:461)
at hudson.util.RobustReflectionConverter.doUnmarshal(RobustReflectionConverter.java:327)
Caused: jenkins.util.xstream.CriticalXStreamException: com.michelin.cio.hudson.plugins.rolestrategy.RoleBasedAuthorizationStrategy : com.michelin.cio.hudson.plugins.rolestrategy.RoleBasedAuthorizationStrategy
---- Debugging information ----
message : com.michelin.cio.hudson.plugins.rolestrategy.RoleBasedAuthorizationStrategy
cause-exception : com.thoughtworks.xstream.mapper.CannotResolveClassException
cause-message : com.michelin.cio.hudson.plugins.rolestrategy.RoleBasedAuthorizationStrategy
class : hudson.model.Hudson
required-type : hudson.model.Hudson
converter-type : hudson.util.RobustReflectionConverter
path : /hudson/authorizationStrategy
line number : 11
version : not available
-------------------------------
at hudson.util.RobustReflectionConverter.doUnmarshal(RobustReflectionConverter.java:356)
at hudson.util.RobustReflectionConverter.unmarshal(RobustReflectionConverter.java:270)
at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:72)
at com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:65)
at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:66)
at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:50)
at com.thoughtworks.xstream.core.TreeUnmarshaller.start(TreeUnmarshaller.java:134)
at com.thoughtworks.xstream.core.AbstractTreeMarshallingStrategy.unmarshal(AbstractTreeMarshallingStrategy.java:32)
at com.thoughtworks.xstream.XStream.unmarshal(XStream.java:1189)
at hudson.util.XStream2.unmarshal(XStream2.java:161)
at hudson.util.XStream2.unmarshal(XStream2.java:132)
at com.thoughtworks.xstream.XStream.unmarshal(XStream.java:1173)
at hudson.XmlFile.unmarshal(XmlFile.java:178)
Caused: java.io.IOException: Unable to read /var/lib/jenkins/config.xml
at hudson.XmlFile.unmarshal(XmlFile.java:181)
at hudson.XmlFile.unmarshal(XmlFile.java:161)
at jenkins.model.Jenkins.loadConfig(Jenkins.java:3005)
at jenkins.model.Jenkins.access$1300(Jenkins.java:304)
at jenkins.model.Jenkins$13.run(Jenkins.java:3104)
at org.jvnet.hudson.reactor.TaskGraphBuilder$TaskImpl.run(TaskGraphBuilder.java:169)
at org.jvnet.hudson.reactor.Reactor.runTask(Reactor.java:296)
at jenkins.model.Jenkins$5.runTask(Jenkins.java:1066)
at org.jvnet.hudson.reactor.Reactor$2.run(Reactor.java:214)
at org.jvnet.hudson.reactor.Reactor$Node.run(Reactor.java:117)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused: org.jvnet.hudson.reactor.ReactorException
at org.jvnet.hudson.reactor.Reactor.execute(Reactor.java:282)
at jenkins.InitReactorRunner.run(InitReactorRunner.java:48)
at jenkins.model.Jenkins.executeReactor(Jenkins.java:1100)
at jenkins.model.Jenkins.<init>(Jenkins.java:904)
at hudson.model.Hudson.<init>(Hudson.java:85)
at hudson.model.Hudson.<init>(Hudson.java:81)
at hudson.WebAppMain$3.run(WebAppMain.java:233)
Caused: hudson.util.HudsonFailedToLoad
at hudson.WebAppMain$3.run(WebAppMain.java:250)

经过

按错误信息排解问题

发现问题不可怕,一顿 Google Bing 发现了 StackOverFlow 的相关问题解决办法

说是因为升级了 Role-based Authorization Strategy 插件会导致这个问题,What?? 我没升级它啊,这怎么回事!先看看外国老哥的解法:

简述解法:

  1. 备份下 Jenkins 家目录下的 config.xml
  2. 修改原 config.xml,注释掉 authorizationStrategy 块,修改 useSecurity 为 true
  3. 重启服务,访问成功再关闭服务
  4. 恢复 config.xml 备份 替换 config.xml
  5. 重启服务

按这一套操作后,的确服务能起来了

工程蒸发,引发的思考

接下来发现了另一个问题 ———— 所有工程都没了!!

先顾不上工程蒸发了的问题,手动创建了个测试流水线工程来测下 SSH Agent Plugin 是否生效,发现依旧无效

工程没了问题其实不大,因为用户还在权限还在构建工程的流水线脚本在 GitLab 上,大不了再配置一下就行了

我想了下,就算配置好工程后,使 SSH Agent Plugin 插件生效 还没完成啊,插件版本还是乱成了一锅粥,这不是定时炸弹么

简单了解了下,Jenkins 的插件升级后,降级的版本是有一个默认值的,但这个值不一定是当前 Jenkins 版本默认或可用的值,最好的办法是向上升级

思及此节,决定去升级下 Jenkins 及插件,另辟了一处实验场开搞

备份Jenkins家目录

Jenkins 家目录里最大的部分是 workspace 这个目录,就是每个构建工程运行时的家目录的父级,这个目录里的数据无需备份

将 Jenkins 家目录备走后,手动创建 workspace 目录,以防新工程无法构建

下载新war包,部署Tomcat

在中科大的静像站下载了2.222.3的war包 https://mirrors.ustc.edu.cn/jenkins/war-stable/2.222.3/

部署到Tomcat的ROOT目录下

修改Tomcat conf/server.xml,修改 Tomcat 编码为UTF-8

修改 conf/context.xml,修改静态资源缓存最大值,需添加一行 <Resources cachingAllowed="true" cacheMaxSize="100000" />

启动Tomcat

访问测试Jenkins服务,查看插件错误警告

访问服务后,发现服务还可以登录,进来看到工程都还在!点开 Manage Jenkins 处,发现仍是大面积报红,检查发现是 Pipeline 依赖的组件不正确,按错误提示去 pluginManager updates处找到被依赖的插件,按提示升级,升级完重启(大部分插件需要重启以激活)

重启后,Pipeline相关的错误不在了,再去看其他的,直到所有的都解决了,插件也都正常了

除了之前插件上的报红,还有几处安全提示,我们的Jenkins不连外网,就一并关掉了

最后 Manage Jenkins 就变成了这样

备份,恢复服务

备份原服务家目录,将新版本部署到原 Tomcat,还原新版本家目录,重启服务

在恢复过程中,有提示某些数据 Unreadable,这些可以通过点击提示,管理这些旧数据,我这边因为主要的东西都在,就选了清除不可读数据了

后续工程修复,测试插件

所有失而复得的工程,其实只记录了内部的一些参数,但 SCM 如Git,这些流水线脚本信息都没记录,可能是因为 Git 插件升级所致

苦逼的一个一个加回来,好在工程不多,也就10来个,等所有工程修复好后,我测试了下之前失效的插件,插件可用了 :happy:

结尾

写这段文字主要记录一下这件挺坑的事,警示自己或大家,不要在没备份的情况下,去做一些不可逆的操作,比如升级 Jenkins,备份的作用同样适用于其他场景

害你加班的bug就是我写的,记一次升级Jenkins插件引发的加班的更多相关文章

  1. 实现一个最简单的VIM文本编辑器(可能有bug,随便写了一个)

    简单的写了一个文本编辑器,功能很简单,但足以把文件IO相关的操作熟悉了,可能功能或者分配的大小还不够完善.请参考参考: #include <stdio.h> #include <co ...

  2. Jmeter实现登录、创建BUG、解决bug的手写脚本

    一.登录 1.          打开jmeter.添加线程组,命名为test,如下图: 2.          添加HTTp默认请求 1)服务器名称或IP:这里只能填写域名或IP地址 2)端口号:配 ...

  3. Cordova webapp实战开发:(5)如何写一个Andorid下自动更新的插件?

    在 <Cordova webapp实战开发:(4)Android环境搭建>中我们搭建好了开发环境,也给大家布置了调用插件的预习作业,做得如何了呢?今天我们来学一下如何自己从头建立一个And ...

  4. 自写图片遮罩层放大功能jquery插件源代码,photobox.js 1.0版,不兼容IE6

    阿嚏~~~ 话说本屌丝没啥开发插件的经验,可是天公不作美,公司须要让我自己开发个图片放大的插件 但公司老大的话,宛如吾皇之圣旨,微臣必当肝脑涂地,莫敢不从啊~~~ 于是乎,作为一个超级小白,本人仅仅能 ...

  5. 优雅的使用sublime写lua~ sublime lua相关必装插件推荐~~

    缘起 lua脚本语言虽好,代码写得飞快,可是写错了调试起来却很困难,lua使用者经常容易犯得一个错误是--写错变量名了,if end 嵌套太多没匹配~,多打了一个逗号, 假设定义了一个变量 local ...

  6. 华丽的使用sublime写lua~ sublime lua相关必装插件推荐~~

    缘起 lua脚本语言虽好,代码写得飞快,可是写错了调试起来却很困难,lua使用者经常容易犯得一个错误是--写错变量名了,if end 嵌套太多没匹配~,多打了一个逗号, --假设定义了一个变量 loc ...

  7. 怎么用js写一个类似于百度输入框的搜索插件

    PS:这次做的这个小插件只是在前端实现,并没有经过数据库.需要用到的的框架:1.bootstrap.css的样式 2.Vue.js 最终效果如下: JS部分: $(window).click(func ...

  8. 一句DELETE引发的加班(Mysql 恢复Delete删除的数据)

    本机用的Navicat连mysql测试DB又连了正式DB,因为本地与正式要频繁操作所以都打开了很多查询,本来要DELETE删除测试DB的数据,没看清在正式环境执行了.共删除了325条数据,然后在网上找 ...

  9. IDEA Plugin,写一个看股票指数和K线的插件

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 没招了,不写点刺激的,你总是不好好看! 以前,我不懂.写的技术就是技术内容,写的场景 ...

随机推荐

  1. 通用权限管理系统组件 (GPM - General Permissions Manager)

    有的公司开发人员只那么几个,一个人支撑整个公司所有的IT系统实在有点累,不想自己写权限系统了,自己琢磨不也是要花时间和精力,要为此付出多少时间和汗水阿,细细的皱纹不知要多多少呢,重复建设不是白白浪费生 ...

  2. 码云git本地仓库链接远程仓库

    原文链接: 点我 git提交时,仓库是空的,本地有源码   应该打开cmd   归到项目路径 然后输入git push -u origin master -f 是把本地的项目强制推送到空的仓库 git ...

  3. C++获取当前系统时间并格式化输出

    C++中与系统时间相关的函数定义在头文件中. 一.time(time_t * )函数 函数定义如下: time_t time (time_t* timer); 获取系统当前日历时间 UTC 1970- ...

  4. CF1324F Maximum White Subtree——换根dp

    换根dp,一般用来解决在无根树上,需要以每个节点为根跑一边dfs的dp问题 我们做两遍dfs 先钦定任意一个点为根 第一遍,算出\(f_i\)表示\(i\)的子树产生的答案,这里,子树指的是以我们钦定 ...

  5. P4168 蒲公英

    神仙分块,把减写成加调了半小时.. 不过这题也启示我们其实有的分块题要把多个块的信息拿到一起维护 以前做的都是每个块的信息单独维护 写的分块题还不太多,同时维护一个块的左右边界好像有点冗余,不过这样代 ...

  6. requests抓取数据示例

    1:获取豆瓣电影名称及评分 # 抓取豆瓣电影名称及评分 url="https://movie.douban.com/j/search_subjects" start=input(& ...

  7. 首次使用AWS服务器EC2

    AWS有一年的免费套餐,这个便宜我得占. 申请的时候需要填写银行卡,AWS暂不支持储蓄卡,只好绑信用卡了. 创建EC2实例之后,下一个要解决的问题就是远程root访问. 1. 修改安全组设置 2. s ...

  8. Eugene and an array(边界麻烦的模拟)

    一道看似小学生的题,搞了我几个小时...... 首先思路就有两种: \(Ⅰ.找和为0的bad子串,再用n*(n+1)/2-bad子串得到答案\) \(Ⅱ.找和不为0的good子串\) 如果你选择找ba ...

  9. 牛客小白月赛16 小石的妹子 二分 or 线段树

    牛客小白月赛16 这个题目我AC之后看了一下别人的题解,基本上都是线段树,不过二分也可以. 这个题目很自然就肯定要对其中一个进行排序,排完序之后再处理另外一边,另一边记得离散化. 怎么处理呢,你仔细想 ...

  10. Spring官网阅读(十五)Spring中的格式化(Formatter)

    文章目录 Formatter 接口定义 继承树 注解驱动的格式化 AnnotationFormatterFactory FormatterRegistry 接口定义 UML类图 FormattingC ...