ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Windows Jenkins 安装与 CI/CD 流水线实战

Windows Jenkins 安装与 CI/CD 流水线实战 Jenkins 在 Windows 上安装教程网上一搜一大把但真正能一次跑通的没几个。大部分内容抄来抄去卡在“初始密码在哪”“插件装不上”“服务起不来”这几步就直接断档了。我自己在 Windows Server 和 Windows 10/11 上前后装过七八次 Jenkins从最早的 Java 8 时代一路跟到现在的 JDK 17踩过的坑基本能凑成一本小册子。这篇就把 Windows 环境下 Jenkins 从零到跑通一条自动化流水线的完整过程摊开讲包括安装方式怎么选、JENKINS_HOME 为什么要挪、国内源怎么换、GitLab 怎么接、部署包怎么落地、钉钉怎么通知以及最常见的十几个报错怎么排。不管你是刚接触 CI/CD 的新手还是想把手上的 Jenkins 从 C 盘挪出来、从单机折腾到内网可用的老手都能在这篇里找到能直接抄的部分。1. 先想清楚Windows 上跑 Jenkins 合不合适装法怎么挑很多人一上来就问“装哪个版本”其实更该先问的是“我这台机器适不适合长期跑 Jenkins”。这一步想明白了后面选安装方式、规划目录、分配账号都是顺理成章的事。1.1 三种安装方式的真实取舍Windows 上装 Jenkins 主流就三条路官方 MSI 安装包、下载 war 包自己跑、以及用容器跑。这三条路没有绝对优劣只有场景匹配度我按实际使用体验拆一下。安装方式上手难度服务自启升级维护适合场景MSI 安装包最低自带装完即成服务重跑安装包即可长期使用的测试/构建机war 包手动运行中等需要自己包一层换个 war 文件重启临时验证、想完全掌控参数容器方式偏高依赖容器运行时换镜像版本已有容器体系、需要快速重建MSI 包最大的价值在于它帮你把“注册成 Windows 服务”这件事做完了。装完之后 Jenkins 会随系统启动机器重启不用人工干预这对一台长期挂在机房里做构建的机器来说是刚需。它的代价是默认配置藏得比较深改 JENKINS_HOME、改 JVM 参数都得去动安装目录下的配置文件。war 包方式的好处是透明。你用一行java -jar启动它端口、内存、编码、工作目录全都在命令行里写得清清楚楚出问题一眼能看明白。但它默认是前台进程cmd 窗口一关就没了想让它常驻还得自己用服务包装工具比如 WinSW、NSSM 这类包一层或者干脆丢进“任务计划程序”里。我个人的习惯是先拿 war 包跑一遍确认环境没问题确定要长期用了再换 MSI 装成服务。容器方式在 Windows 上要看你用的是哪种容器。如果本机装的是 Docker Desktop那跑 Jenkins 确实省事但前提是机器本身要开虚拟化支持而且容器里的 Jenkins 要访问宿主机文件、要调用 Windows 上的构建工具时会多一层路径映射的麻烦事。除非你团队本来就在用容器否则我不建议为了装 Jenkins 专门去折腾容器环境。提示如果你只是想在本地验证一个流水线脚本能不能跑通直接用 war 包最省事验证完删目录就干净了不会在系统里留服务和注册表项。1.2 装之前必须确认的机器条件Jenkins 本身不挑机器但它背后跑的东西很挑。真实情况是Jenkins 主进程占用不大真正吃资源的是它同时并发跑的构建任务。一台机器上如果同时跑 Maven 打包、npm 构建、前端打包内存瞬间就上去了。我给的建议配置是这样的CPU 四核起步内存 8GB 是底线16GB 比较舒服。磁盘方面Jenkins 主目录加上构建产生的临时文件、归档产物增长速度快得惊人。我自己那台测试机上一个中等规模项目跑了大半年JENKINS_HOME 从几百兆涨到十几个 G大头全是历史构建的工作区和归档产物。所以磁盘至少留出 50GB 的余量。系统版本上Windows Server 2016/2019/2022 和 Windows 10/11 专业版都能装。家庭版虽然也能跑起来但在服务账号、计划任务、本地安全策略这些地方会有限制遇到权限相关的问题会多绕几圈不太建议。还有一条容易被忽略的是这台机器是否要承担“构建机”的角色。如果只是当调度器只负责触发和接收 Webhook真正的构建在别的机器上跑那配置可以压得很低如果要在这台机器上编译、打包、甚至直接部署那就按上面说的标准来配。1.3 目录规划为什么我强烈建议把 JENKINS_HOME 挪出 C 盘这是整篇文章里我最想强调的一点。默认情况下JENKINS_HOME 会落在系统盘上MSI 安装通常是安装目录下war 包方式则是用户目录下的.jenkins。这个目录里装着你的所有任务配置、构建历史、插件、凭据是整个 Jenkins 的大脑。问题在于它会长得非常大而且增长速度不可控。C 盘空间被吃满是很多人遇到的第一个“莫名其妙 Jenkins 就挂了”的原因。第二个原因是备份和迁移——你要备份 Jenkins本质上就是备份 JENKINS_HOME如果它散落在C:\Program Files里面权限复杂、路径带空格备份脚本写起来很难受。我现在的做法是统一放到D:\jenkins\home只做两件事把这个路径设成 JENKINS_HOME 环境变量然后确保运行 Jenkins 的那个账号对这个目录有完全控制权限。目录结构大概长这样D:\jenkins\ ├── home\ # JENKINS_HOME所有配置和数据 │ ├── jobs\ # 各个任务 │ ├── plugins\ # 已安装插件 │ ├── secrets\ # 初始密码等敏感文件 │ ├── users\ # 用户配置 │ └── config.xml ├── backup\ # 定期备份 └── tools\ # 可选的本地工具链注意挪 JENKINS_HOME 这件事一定要在“第一次启动 Jenkins 之前”做。如果已经跑起来、建了一堆任务再挪需要停服务、复制整个目录、改配置、确认权限任何一步出错都可能让任务配置丢失。新手就一次到位。2. Windows 安装实操从 JDK 到服务自启环境规划好了接下来就是动手。这一节我按 MSI 和 war 两条路都讲一遍你按自己的场景选一条跟着做就行。2.1 JDK 安装与环境变量配置Jenkins 是 Java 写的没 JDK 它连启动都启动不了。版本这件事坑了不少人网上很多老教程还在教 JDK 8但现在的新版本 Jenkins 早就跑不动 JDK 8 了当前主流的长期支持版本基本都要求 Java 17 或更高部分版本还支持 Java 11。所以别犹豫直接上 JDK 17兼容性和后续插件生态都更省心。下载渠道我一般选开源发行版比如 Eclipse Temurin 的 JDK 17安装过程干净、没有多余捆绑。安装时有个小细节不要把 JDK 装到带空格或中文的路径下C:\Program Files\Java这种带空格的路径虽然大多数情况能跑但在某些构建脚本里会因为引号处理不当导致奇怪的报错。我习惯装到D:\dev\jdk17。装完之后配两个环境变量JAVA_HOME值填 JDK 的根目录不带\bin例如D:\dev\jdk17Path追加%JAVA_HOME%\bin配置入口在“此电脑 → 右键属性 → 高级系统设置 → 环境变量”改的是系统变量那一栏。改完一定要新开一个 cmd 窗口老窗口不会重新读取环境变量执行java -version echo %JAVA_HOME%看到版本号输出且 JAVA_HOME 指向你刚配的路径这一步就算过了。这里多解释一句为什么必须用 JAVA_HOME 而不是直接把 java.exe 加进 PathJenkins 以及它调用的一堆构建工具Maven、Gradle、Ant都会主动读 JAVA_HOME 来定位 JDK只配 Path 是不够的会报“找不到 Java 运行时”这类错误。2.2 MSI 安装包方式一路下一步里藏着什么去 Jenkins 官网下载页拿 Windows 的.msi安装包双击运行。安装向导里只有几个页面但每一页都值得停一下。第一个是安装路径的选择。默认会在C:\Program Files\Jenkins如果你的系统盘紧张这里就可以改到 D 盘。第二个是服务登录账号向导会问你用本地系统账号还是指定账号运行服务。默认的本地系统账号权限非常大能访问整台机器上的几乎所有资源方便但有安全顾虑指定一个专用账号更规范但要记得给这个账号配好对 JENKINS_HOME 和构建目录的读写权限否则后面会报各种“拒绝访问”。第三个是端口默认 8080如果这台机器上已经有别的服务占了 8080这里就要改比如改成 8081。装完之后安装程序会自动把 Jenkins 注册成 Windows 服务并尝试启动。你可以打开服务管理器确认一下应该能看到一个叫 Jenkins 的服务。如果状态是“正在运行”打开浏览器访问http://localhost:8080就能看到界面了。但先别急着往下走。如果你想按前面说的把 JENKINS_HOME 挪到 D 盘这时候应该先停服务然后去安装目录找到jenkins.xml这个文件它是服务的配置文件用记事本打开改两处service idjenkins/id nameJenkins/name env nameJENKINS_HOME valueD:\jenkins\home/ executable%BASE%\jre\bin\java.exe/executable arguments-Xrs -Xmx2048m -Dfile.encodingUTF-8 -Dhudson.lifecyclehudson.lifecycle.WindowsServiceLifecycle -jar %BASE%\jenkins.war --httpPort8080/arguments logmoderotate/logmode onfailure actionrestart delay60 sec/ /service这里面的-Xmx2048m是给 Jenkins 进程分配的堆内存上限根据你机器内存调8GB 内存的机器给 2048MB 比较合适16GB 可以给到 4096MB。-Dfile.encodingUTF-8这个参数是为了解决中文乱码后面讲问题排查时会再提到。改完保存手动创建D:\jenkins\home目录确认服务账号有完全控制权限再启动服务。注意jenkins.xml 里改 JENKINS_HOME只对通过这个服务启动的 Jenkins 生效。如果你同时又手动开 cmd 跑了个 war那个进程读的是环境变量或者默认路径两个实例会打架。改配置之前先确认所有 Jenkins 进程都停了。2.3 war 包方式更可控的“绿色版”玩法如果你想完全掌控启动参数war 包方式更合适。下载jenkins.war放到一个你规划好的目录比如D:\jenkins\jenkins.war。先把 JENKINS_HOME 设成系统环境变量然后新开 cmd 窗口执行set JENKINS_HOMED:\jenkins\home cd /d D:\jenkins java -Xmx2048m -Dfile.encodingUTF-8 -Duser.timezoneAsia/Shanghai -jar jenkins.war --httpPort8080第一次启动你会看到一大段日志滚出来最后停在“Jenkins is fully up and running”就说明起来了。这个窗口不能关关掉进程就结束了。想让它常驻有两个思路一是用服务包装工具把它包成 Windows 服务二是在“任务计划程序”里建一个“计算机启动时触发”的任务命令行填上面的启动命令并勾选“不管用户是否登录都要运行”。war 包方式还有个好处是升级特别简单停掉服务用新的 war 文件覆盖旧的再启动就行。而 MSI 方式升级需要重新跑一遍安装程序虽然也不复杂但中间会多几个确认页面。另外 war 包方式可以很方便地同时跑多个实例只需要用不同的端口和不同的 JENKINS_HOMEjava -jar jenkins.war --httpPort8081这一点在你想做“试验环境”和“正式环境”隔离时很有用改坏了直接删目录重来不污染正式环境。2.4 首次解锁与插件安装换国内源的正确姿势不管哪种方式启动第一次访问http://localhost:8080都会要求你输入初始管理员密码。这个密码存在这个文件里JENKINS_HOME\secrets\initialAdminPassword直接用记事本打开把里面那串字符复制粘贴进去就行。如果你找不到这个文件八成是 JENKINS_HOME 路径跟你以为的不一样——这是新手最常见的困惑。确认路径最快的办法是看 Jenkins 启动日志的第一行它会打印出JENKINS_HOME的实际位置或者登录后在“系统管理 → 系统信息”里也能看到。解锁之后的下一步是插件安装页面通常会给你两个选项安装推荐插件或者自己选。我的建议是新手直接选推荐插件它会把 Git、Pipeline、凭据管理、邮件通知这些基础插件一次装好省得后面一个个补。但这里大概率会卡住——默认的更新站点在国内访问很慢进度条走到一半就不动了或者直接报错说连不上。这时候要么耐心等有时候十几分钟也能过要么就直接换国内镜像源。换源的位置在“系统管理 → 插件管理 → Advanced高级”把 Update Site 那一栏的地址换成国内镜像的地址比如清华或华为云提供的 Jenkins 镜像站点保存后回到“可选插件”页面点一下“立即获取”列表会重新加载。如果连“插件管理”页面都进不去因为推荐插件安装卡住了还有一个办法是直接改配置文件。停掉 Jenkins编辑JENKINS_HOME\hudson.model.UpdateCenter.xml?xml version1.1 encodingUTF-8? sites site iddefault/id urlhttps://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json/url /site /sites把 url 换成镜像站点地址保存后重启 Jenkins。这样下次打开插件管理走的就是国内线路了。注意换源之后如果页面提示“该实例似乎已离线”不要慌这通常只是更新站点探测失败不影响 Jenkins 本体运行也不影响已经装好的插件。真正影响的是“能不能在线发现新插件”。如果你的环境确实无法访问外部源那就走离线安装路线后面第 3.5 节会细说。2.5 服务账号与开机自启的确认MSI 方式装完之后服务是自动配置好开机自启的。你可以打开服务管理器找到 Jenkins 服务右键属性确认“启动类型”是“自动”。如果之前因为调试把它改成了手动记得改回来。用 war 包 任务计划程序的方式也要确认任务的触发条件是“计算机启动时”而不是“用户登录时”。这个区别很关键如果设成登录时触发服务器重启后没人登录Jenkins 就不会起来别人访问会直接连接失败。服务账号这件事值得单独说一句。如果你用的是本地系统账号Jenkins 进程就有很大的权限构建脚本里能做的事非常多方便但风险也大。如果换成专用账号需要额外确认几件事这个账号对 JENKINS_HOME 有完全控制权、对工作区目录有读写权限、如果构建脚本要访问网络共享还得单独授权。权限没配齐最典型的症状就是构建时报“Access is denied”而手动在 cmd 里跑同样的命令一点问题都没有——因为手动跑用的是你自己的账号。3. 装完别急着建任务核心配置与插件清单Jenkins 能打开界面只是第一步真正让它干活还得做几项基础配置。这一节讲的东西配好了后面建任务会顺很多。3.1 全局工具配置JDK、Git、Maven、Node 怎么指入口在“系统管理 → 全局工具配置”。这一页的意义是把工具路径集中管理任务里就不用每次写绝对路径了。JDK 这一项把“自动安装”的勾去掉然后填个名字比如 jdk17JAVA_HOME 填你实际的路径。为什么要取消自动安装因为自动安装会去下载 JDK在受限网络环境下大概率失败而且版本不可控。自己指定本地路径最省事。Git 这一项填git.exe的完整路径通常是C:\Program Files\Git\cmd\git.exe。注意是cmd目录下的那个不是bin目录。填完之后下面的“Git 安装”会自动识别出版本号如果识别不出来就说明路径填错了。这一步没配好后面拉代码会直接报“git not found”。Maven、Gradle、NodeJS 同理都是取消自动安装、填本地路径。NodeJS 需要额外装一下 NodeJS 插件才会有这一项。前端项目特别容易踩的坑是Jenkins 服务用的环境变量跟你登录用户的环境变量不是一套所以就算你在 cmd 里npm -v能出版本号Jenkins 里跑同样的命令还是可能报找不到。这种时候老老实实在全局工具配置里指绝对路径或者干脆在构建脚本里写全路径。3.2 凭据管理三种类型各自的用武之地凭据管理的入口在“系统管理 → 凭据 → 系统 → 全局凭据”。这里存的东西是加密的比你在脚本里硬编码密码安全得多。常用的就三类Username with password最常用。拉 GitLab 上的私有仓库、登录需要认证的接口都靠它。SSH Username with private key部署到 Linux 服务器时用。把私钥内容贴进去Jenkins 就能免密登录目标机器。Secret text一个单纯的字符串。钉钉机器人的加签密钥、各种 API Token 都是这一类。有一点必须提醒凭据一旦创建界面上就再也看不到明文了只能替换不能查看。所以创建的时候一定要确认粘贴正确尤其是私钥多了个换行或者少了最后一行都会导致认证失败而报错信息往往很不直观。在流水线里引用凭据的标准写法是withCredentials块或者credentials()函数比如withCredentials([usernamePassword(credentialsId: gitlab-user, usernameVariable: GIT_USER, passwordVariable: GIT_PASS)]) { bat git clone http://%GIT_USER%:%GIT_PASS%git.example.com/group/repo.git }注意上面这个写法里账号密码会出现在命令中日志里通常会被 Jenkins 自动打码但为了彻底避免泄漏更规范的做法是用checkout步骤配合凭据 ID让 Jenkins 自己去处理认证细节。3.3 Git/GitLab 集成Connection 配置与 Webhook 触发让 Jenkins 能自动感知代码提交是自动化的起点。整体思路是Jenkins 上配一个 GitLab 连接GitLab 那边配一个 Webhook代码一推就通知 Jenkins 建任务。Jenkins 侧的配置分两步。第一步装 GitLab 插件在插件管理里搜 GitLab 安装并重启。第二步去“系统管理 → 系统配置”往下找到 GitLab 区域填三个东西Connection name 随便起个名字GitLab host URL 填你 GitLab 的地址Credentials 填一个有 API 权限的 Token在 GitLab 里用个人访问令牌生成勾上 api 权限。填完点“Test Connection”能返回成功就说明通了。这里有个高频坑测试连接失败报的却是含糊的网络错误。九成的情况是 Jenkins 系统配置最上面那个 “Jenkins URL” 填的是http://localhost:8080而 GitLab 服务器根本访问不到这个地址。解决办法是把 Jenkins URL 改成 GitLab 能访问到的真实地址比如http://192.168.1.100:8080/。GitLab 侧就是配置 Webhook进项目 → Settings → WebhooksURL 填http://jenkins地址:8080/project/任务名Trigger 勾上 Push events保存后点一下 Test 看看能不能收到 200 响应。同时别忘了在 Jenkins 任务里勾上“Build when a change is pushed to GitLab”这个触发器。如果两边网络确实不通还有个退而求其次的办法用轮询 SCM在任务的构建触发器里勾“Poll SCM”填H/5 * * * *意思是每 5 分钟去问一次代码有没有变化。缺点是慢优点是只要有出方向的网络就行不需要 GitLab 主动访问 Jenkins。3.4 参数化构建与构建触发器让任务灵活起来同一个任务你可能既想构建 main 分支又想构建 release 分支既想部署到测试环境又想部署到生产环境。这些需求都靠“参数化构建”解决。在任务配置里勾上“This project is parameterized”然后加参数。常用的两种是Choice Parameter选项参数给几个固定选项比如环境选 test 或 prod。好处是防止手输错。String Parameter字符串参数自由输入比如分支名、版本号、Commit ID。参数在脚本里通过环境变量访问Windows 下就是%参数名%Linux 下是$参数名。这点在写 bat 脚本时特别容易搞混写成了$BRANCH结果拿到空值脚本就按空分支去拉代码报一堆莫名其妙的错。至于触发器常用的有这么几种触发器触发条件适用场景Build after other projects上游任务成功后多模块串联构建Build periodically按 cron 定时每日构建、夜间回归Poll SCM定时检查代码变化无法配 Webhook 时的替代方案GitLab Webhook收到 GitLab 推送实时触发最推荐手动触发人工点按钮生产发布必须有人确认生产环境的部署任务我强烈建议不要挂任何自动触发器只允许人工点按钮并且加一个“是否确认发布”的参数作为二次确认。自动触发部署到生产早晚会出事。3.5 插件安装与离线安装内网环境怎么做能联网的环境插件安装就是在“插件管理 → 可选插件”里搜、勾、装。唯一要注意的是有些插件会带一堆依赖装完之后必须重启 Jenkins 才生效重启前它会在页面上提示你。内网环境就麻烦一些。典型场景是Jenkins 机器完全不能访问外网但你需要装某个插件。Z做法是找一台能上网的机器进入 Jenkins 插件的下载页面搜索插件名下载对应的.hpi文件注意要下载适合你 Jenkins 版本的版本号。然后回到内网 Jenkins在“插件管理 → Advanced → Upload Plugin”里上传这个文件上传完会自动安装依赖并提示重启。这个流程有个坑插件的依赖不会自动下载。如果待装插件依赖另外三个插件你只上传一个.hpi会提示依赖缺失。解决办法是把依赖也一起下下来按依赖顺序逐个上传。经验法则是先在能联网的环境里装一遍把插件目录JENKINS_HOME\plugins整个复制到内网机器上再重启 Jenkins这样最省事。不过要保证两边 Jenkins 版本接近版本差异太大可能加载不起来。4. 实战一条能用的 Windows 自动化部署流水线前面都是准备工作这一节直接上一条完整的流水线从拉代码到部署到通知全串起来。4.1 自由风格还是 Pipeline我的选型建议Jenkins 建任务时第一个要选的就是任务类型。最常见的是“构建一个自由风格的软件项目”和“流水线Pipeline”。自由风格任务的好处是图形化配置每一步都能在界面上找到对应的地方对新手友好。但它有个硬伤配置存在 Jenkins 的 XML 里不好做版本管理也没法代码评审。任务一多谁改了什么、什么时候改的基本查不清。Pipeline 的配置写在 Jenkinsfile 里可以跟着代码一起提交到 Git 仓库改动有 diff、有记录、能回滚。我现在的做法是临时验证用自由风格正式项目一律 Pipeline而且尽量用声明式Declarative语法它比脚本式Scripted更结构化报错信息也更友好。4.2 一份可以直接抄的 Jenkinsfile下面这份是偏通用的模板Java 项目直接能用其他语言改改构建命令就行。pipeline { agent any options { timestamps() // 控制台加时间戳 timeout(time: 30, unit: MINUTES) // 整体超时保护 buildDiscarder(logRotator(numToKeepStr: 20, artifactNumToKeepStr: 5)) disableConcurrentBuilds() // 禁止并发避免部署撞车 } parameters { choice(name: ENV, choices: [test, prod], description: 部署目标环境) string(name: BRANCH, defaultValue: main, description: 构建分支) } environment { APP_NAME demo-web DEPLOY_DIR D:\\deploy\\${APP_NAME} } stages { stage(拉取代码) { steps { echo 开始拉取分支${params.BRANCH} git branch: ${params.BRANCH}, credentialsId: gitlab-user, url: http://git.example.com/group/demo-web.git } } stage(编译打包) { steps { bat mvn -B clean package -DskipTests } } stage(归档产物) { steps { archiveArtifacts artifacts: target/*.jar, fingerprint: true } } stage(停止服务) { steps { bat sc query ${APP_NAME} nul 21 sc stop ${APP_NAME} || echo 服务未安装跳过 } } stage(拷贝部署包) { steps { bat if not exist ${DEPLOY_DIR} mkdir ${DEPLOY_DIR} robocopy target ${DEPLOY_DIR} *.jar /R:2 /W:2 /NFL /NDL /NJH /NJS if %ERRORLEVEL% GEQ 8 exit /b 1 } } stage(启动服务) { steps { bat sc start ${APP_NAME} } } } post { success { echo 构建成功${env.BUILD_URL} } failure { echo 构建失败请查看日志${env.BUILD_URL}console } always { junit allowEmptyResults: true, testResults: target/surefire-reports/*.xml } } }几个关键点解释一下。disableConcurrentBuilds()在部署类任务里几乎是必须的否则两次构建同时往同一个目录里拷贝文件结果是灾难性的。robocopy的退出码有讲究0 到 7 都算成功8 以上才是真失败所以在脚本里判断的是GEQ 8而不是常见的NEQ 0。这个细节坑过很多人脚本明明拷贝成功了却报错退出。timeout也是保命的。我有一次遇到构建卡在一个网络请求上整整挂了一晚上把执行器全占满了后面所有任务都在排队。加了超时之后最坏情况就是这一个任务失败不会把整个 Jenkins 拖死。4.3 部署包怎么落地几种目标环境的做法上面例子中部署是“本机部署”也就是 Jenkins 和运行服务的机器是同一台直接停服务、拷文件、起服务。这在测试环境很常见。如果目标是另一台 Windows 机器可选的做法就有几种了共享目录 robocopy把目标机器的某个目录映射成共享Jenkins 直接往共享里拷。优点是简单缺点是共享权限配置麻烦而且拷过去的文件要靠目标机器上的脚本去重启服务。远程命令执行使用 Windows 自带的远程管理能力在目标机器上执行脚本完成停服务、替换文件、起服务。需要提前在两边配好信任关系。走制品库 目标机拉取Jenkins 把包上传到内部的制品仓库目标机器上的部署脚本从制品库拉取。这种方式最适合多台机器同时部署也方便回滚。如果目标是 Linux 服务器那就用 SSH 那一套。Jenkins 上装好对应的发布插件配好 SSH 凭据构建完成后直接把包传过去再执行一段远程脚本。这里要特别注意路径和权限传过去之后文件的属主可能是登录用户而服务是用另一个账号跑的替换文件后如果服务起不来第一件事就是查属主和读写权限。4.4 钉钉自定义消息通知构建结果发到钉钉群是团队里反馈最快的方式。做法是装钉钉相关的 Jenkins 插件然后在钉钉群里添加一个自定义机器人拿到 Webhook 地址和加签密钥。配置分两处。一处在“系统管理 → 系统配置”里填机器人的 Webhook 地址和加签密钥保存后点测试群里能收到消息就说明通了。另一处在任务里自由风格任务加一个构建后步骤Pipeline 任务在post段里加一行调用。消息内容建议自定义成表格或者 Markdown 格式把关键信息塞进去比如### 构建通知 - 项目${JOB_NAME} - 环境${ENV} - 分支${BRANCH} - 状态构建成功 - 编号${BUILD_NUMBER} - 耗时长${BUILD_DURATION} - 详情[点击查看](${BUILD_URL}console)这里用到的${JOB_NAME}、${BUILD_NUMBER}、${BUILD_URL}都是 Jenkins 自动注入的环境变量直接用就行。下表列几个我在流水线里用得最多的变量名含义典型用途JOB_NAME任务名称通知里标识项目BUILD_NUMBER构建序号拼接版本号BUILD_URL本次构建的页面地址通知里放详情链接WORKSPACE当前构建的工作目录脚本里定位文件GIT_COMMIT本次构建的提交哈希记录发布版本GIT_BRANCH本次构建的分支通知里标识分支NODE_NAME执行该构建的节点名排查是哪台机器跑的EXECUTOR_NUMBER执行器编号临时文件隔离命名有个小细节值得注意钉钉机器人默认对消息频率有限制如果流水线特别活跃、构建特别频繁可能会触发限流导致通知发不出去。解决办法是加个判断只对失败和成功忽略中间状态发通知或者把通知收敛到日汇总。4.5 回滚怎么做才不慌回滚方案一定要在第一次上线前就准备好而不是出事之后再临时想。我的做法基于一个很简单的前提每次构建的产物都归档了并且有构建号可以对应。具体操作是建一个独立的手动触发的回滚任务参数只有一个——要回滚到的构建号。任务逻辑是从对应构建号里取出归档的部署包停服务替换文件起服务。整个过程和正常部署唯一的区别就是包从哪来。Jenkins 里配合buildDiscarder保留最近 20 次构建意味着你随时能回滚到最近 20 个版本中的任意一个。如果想保留更久可以把归档产物单独存到一台文件服务器上不占 JENKINS_HOME 的空间。提示回滚任务本身也要能自动化不要写成“人工登服务器手动覆盖文件”。真出事的时候人在慌乱中手动操作最容易点错目录。5. 踩坑记录Windows 环境下最常见的问题这部分是我这些年真正被折腾过的点按类型整理成速查表遇到问题直接对号入座。5.1 安装与启动类问题速查现象大概率原因处理办法访问 8080 打不开页面服务没起来或端口冲突服务管理器看服务状态用 netstat 查端口占用启动日志停在某一行不动JENKINS_HOME 权限不足给服务账号配完全控制权限提示 Java 版本不支持JDK 版本太低换 JDK 17找不到 initialAdminPasswordJENKINS_HOME 路径判断错了看启动日志第一行的实际路径服务开机不自动起启动类型被改成手动服务属性里改回自动换目录后任务全没了换了 JENKINS_HOME 但没迁移数据停服务后完整复制原目录这几个里最值得展开的是端口冲突。8080 是个很热门的端口很多中间件默认都用它。判断方法很简单在 cmd 里执行netstat -ano | findstr :8080会列出占用该端口的进程 ID再到任务管理器里对一下是哪个程序。改 Jenkins 端口的话MSI 方式改 jenkins.xml 里的--httpPortwar 方式改启动命令里的--httpPort。还有一个比较隐蔽的Jenkins 明明在跑但页面报“该实例似乎已离线”。这种情况一般是 Jenkins 尝试访问外部更新站点失败导致的本机运行完全正常。如果你只是用它跑本地任务可以直接忽略如果要去掉这个提示把更新站点换成能访问的地址就行。5.2 插件与网络类问题插件装不上是内网和新装环境最集中的问题区。常见表现和处理方式进度条卡住不动更新站点访问慢。换国内镜像源或者耐心等有时候十几分钟能过。提示证书错误目标站点证书链不完整。确认系统时间是否正确或者改用镜像站点。依赖缺失手动上传.hpi时只传了主插件。把依赖一起传或直接复制整个 plugins 目录。装完插件 Jenkins 起不来插件版本和 Jenkins 本体不兼容。停服务删掉 plugins 目录下对应插件的文件夹和.jpi文件重启即可回到装之前的状态。插件装好了但功能菜单不出现没重启 Jenkins或者任务类型不支持该功能。注意删插件目录前一定先停服务。服务运行中删插件文件会导致 Jenkins 启动时报插件元数据损坏处理起来更麻烦。5.3 构建与脚本类问题这一类问题的特点是手动跑脚本一切正常Jenkins 里跑就报错。原因基本都是环境差异。典型的有下面几个。中文乱码。控制台里中文变成问号或者方块。根因是编码不一致Jenkins 进程用一套编码cmd 用另一套脚本文件本身又是第三套。三层对齐才能解决。我的标准做法是在 Jenkins 启动参数里加-Dfile.encodingUTF-8在 bat 脚本开头加chcp 65001并且确保脚本文件本身以 UTF-8 保存不带 BOM。三处都改了基本就不会乱码了。脚本执行到一半闪退。这是 Windows 下特别常见的问题。bat 脚本如果没有显式处理退出码中间某条命令失败后Jenkins 会认为整个构建成功后面的步骤却全都没执行。标准写法是在脚本末尾统一处理echo off chcp 65001 nul call :doBuild if %ERRORLEVEL% NEQ 0 exit /b %ERRORLEVEL% echo 全部完成 exit /b 0 :doBuild mvn -B clean package -DskipTests if %ERRORLEVEL% NEQ 0 exit /b 1 exit /b 0这样任何一步失败都能被 Jenkins 正确捕获把构建标红。路径里有空格。C:\Program Files这种路径如果脚本里没加引号命令会被拆成两段报“找不到文件”。所有涉及路径的地方统一加双引号养成习惯。找不到命令。手动能在 cmd 里跑通的命令Jenkins 里报“不是内部或外部命令”。原因是 Jenkins 服务用的系统环境变量跟你当前用户的环境变量不是一套。解决办法是在全局工具配置里指定完整路径或者在脚本开头set PATH%PATH%;D:\dev\tools\bin手动补上。改完之后要注意改了系统环境变量Jenkins 服务必须重启才会读取到新值。Git 拉代码报认证失败。凭据配错了或者用 HTTP 方式拉代码但 GitLab 那边禁用了这种方式。检查顺序是先确认凭据 ID 写对了再确认这个凭据在 GitLab 上有仓库的读权限最后确认 URL 协议和端口都对。5.4 运行维护类问题Jenkins 跑起来不难难的是让它持续跑一年不出事。这几个点我都是有血的教训。磁盘被吃满。JENKINS_HOME 里的工作区和归档产物是主要增长源。每个任务都要配“丢弃旧的构建”保留次数和天数按需设置。另外可以在“系统配置”里限制工作区保留策略。如果机器上有大量小文件磁盘清理工具也要定期跑。我的经验是如果一台构建机每月增长超过 20GB就该考虑加磁盘或者把产物外移了。构建日志过大。一个跑了半小时的构建产出几十兆日志不稀奇日志堆多了同样占空间。除了限制保留数量还可以装日志相关的插件只保留最近几天的完整日志或者把日志重定向到文件并定期清理。备份 JENKINS_HOME。最靠谱的备份方式是停服务把整个 JENKINS_HOME 目录复制一份起服务。不停服务也能复制但可能拿到不一致的配置文件恢复时偶发问题。如果在意服务不可用时间可以只备份关键部分config.xml、jobs目录、users目录、credentials.xml、plugins目录。plugins体积大如果配置文件里能看出插件版本也可以选择不备份、恢复时重装。升级要谨慎。Jenkins 版本升级之前先看插件兼容性列表。我的标准流程是备份 JENKINS_HOME在测试环境用同样的配置升一遍跑通几个核心任务再动正式环境。升级 war 包的方式最简单MSI 方式需要重跑安装包。升级之后如果某个插件报版本不兼容可以先禁用这个插件让 Jenkins 起来再找兼容版本。时间同步。这个容易被忽略。Jenkins 的构建历史、GitLab 的提交时间、钉钉的消息时间如果对不上排查问题时会非常混乱。Windows 机器上把时间同步服务配好是件很小但很有价值的事。最后再说一个软性的经验Jenkins 的权限别一次性放开给所有人。至少把“系统管理”相关的权限收紧构建任务的配置权限按项目组划分。我见过配置权限全开的 Jenkins一年多之后没人说得清某个任务里的部署脚本是谁写的、为什么要那么写维护成本高得离谱。我个人在实际操作中的体会是Windows 上跑 Jenkins 最容易翻车的从来不是 Jenkins 本身而是环境差异——服务账号和登录用户的差异、服务进程和 cmd 窗口的环境变量差异、编码差异、路径差异。凡是遇到“手动能跑、Jenkins 不能跑”的情况别急着改脚本先去对比这两个执行环境的差别十有八九问题就在那里。另外能提前做的准备就不要拖到出事之后再补JENKINS_HOME 一次挪到位、归档产物一次开好、回滚任务一次建好这三件事花不了一小时但能省下后面无数个加班的夜晚。
返回列表