Jenkins 常见问题与解决方案:我踩过的坑和填坑方法
一个让我崩溃的周末
去年某个周五晚上,公司唯一负责 CI 的同事离职了,Jenkins 就交到了我手上。周一早上,构建流水线全线报红:磁盘满了、好几个 job 卡在队列里不动、还有一个插件更新之后整个系统都进不去管理页面。那天我花了整整两天,把 Jenkins 常见的坑几乎踩了个遍。这篇教程就是我把那次“救火”经验整理出来的一份实战手册,希望你在遇到类似问题时不用像我那么狼狈。
问题一:磁盘空间不足导致构建莫名失败
这是 Jenkins 最经典的问题,也是最隐蔽的。表现形式通常是:构建日志写到一半突然中断、workspace 建不出来,或者 job 直接显示灰色(aborted)。
怎么发现
登录 Jenkins 后先看首页左下角的磁盘指示器。如果没有显示,就去 Manage Jenkins → System Log,搜 No space left on device。
我犯过的错
我第一反应是删构建产物,结果把还在使用的 archive 也给删了,导致下游 job 拉取产物失败。正确做法是:
# 先找出 Jenkins 目录里最占空间的东西
du -sh /var/lib/jenkins/* | sort -rh | head -20
结果一般就是 workspace/ 和 jobs/*/builds/ 排在最前面。
正确的清理方式
- 清理旧构建:千万别手动删目录!在每个 job 的配置里设置 "Discard old builds":
Days to keep builds: 30
Max # of builds to keep: 50
Artifacts to keep: 只保留最近 5 个
- 批量清理 workspace:装个 Disk Usage 插件,或者直接用脚本:
find /var/lib/jenkins/workspace -maxdepth 1 -type d -mtime +30 \
-exec rm -rf {} \;
- 从根源上解决:后来我把构建产物统一推到 Nexus/S3,Jenkins 里只留日志,磁盘问题基本绝迹了。
问题二:插件更新后系统打不开
那次我顺手点了 "Update all plugins",重启后 Manage Jenkins 页面直接白屏,日志里刷满了 ClassNotFoundException。
解决步骤
- 进入 Jenkins home 目录,其实插件的旧版本是有备份的:
cd /var/lib/jenkins
ls plugins/ | grep bak
# 可以看到 jenkins.bak 之类的备份文件
- 如果有备份,直接还原:
cp plugins/*.bak plugins/ 对应的 .jpi 文件
# 或者更暴力但有效的:
rm -rf plugins/*.jpi
cp -r plugins.bak/* plugins/
- 如果没有备份(当时我的惨状),就手动下载对应版本的
.hpi文件:
# 从 Jenkins 官方镜像下载指定版本
wget https://mirrors.jenkins.io/plugins/git/4.11.3/git.hpi \
-O /var/lib/jenkins/plugins/git.jpi
- 重启:
systemctl restart jenkins
血泪教训
永远不要点 "Update all"。我的做法是:每月固定一天,在低峰期手动挑 3-5 个需要更新的插件来更新,更新前先记下当前版本号。另外强烈建议用 JCasC(Configuration as Code)插件把配置存进 Git,这样就算炸了也能快速重建。
问题三:流水线卡在队列里不执行
周一早上看到十几个 job 在排队,但没有一个在跑。这种情况九成是 executor 出了问题。
排查清单
Manage Jenkins → Nodes:看 agent 是不是 offline。如果是内置节点(Built-in Node),检查一下 executor 数量是不是被设成了 0——这是个很常见的手滑操作。
看队列详情:点进排队中的 job,Jenkins 会告诉你它在等什么,比如:
Waiting for available executor on 'docker-agent'
There are no nodes with the label 'docker-agent'
- 最常见的幽灵卡死:某个 job 实际上已经挂了,但 executor 还显示 busy。处理方式:
# 找到僵尸进程
ps aux | grep -i jenkins
# 或者临时方案:重启对应的 agent
# 在 Nodes 页面点 "Disconnect" 再 "Bring online"
我的改进
我给关键流水线加上了超时,防止再次无限卡死:
pipeline {
agent { label 'docker-agent' }
options {
timeout(time: 30, unit: 'MINUTES')
timestamps()
}
// ...
}
问题四:Git 凭据失效 / 权限错误
构建报 Authentication failed for 'https://git.example.com/...',但凭据明明是配置过的。
排查过程
- Manage Jenkins → Credentials,确认凭据还在(有一次是升级之后凭据文件的权限变了)。
- 检查凭据文件的权限:
ls -l /var/lib/jenkins/credentials.xml
# 必须是 jenkins 用户可读
chown jenkins:jenkins /var/lib/jenkins/credentials.xml
- 最容易忽略的:job 里用的凭据 ID 和 Credentials 里的是否一致。我在流水线里写死了旧的 ID
git-cred-old,换成新的就通了:
withCredentials([usernamePassword(
credentialsId: 'git-cred-2024',
usernameVariable: 'GIT_USER',
passwordVariable: 'GIT_PASS')]) {
sh 'git clone https://${GIT_USER}:${GIT_PASS}@git.example.com/repo.git'
}
顺带一提:如果 Gitea/GitLab 更新了 Token 过期策略,所有凭据会在某一天集体失效——我后来给凭据设置了日历提醒,到期前主动续期。
问题五:构建慢如蜗牛
同一个 job,以前 5 分钟,后来要 25 分钟。用 Timestamper 一看,是某个 npm install 阶段占了 15 分钟。
优化手段(按收益排序)
- 找出瓶颈:用 Blue Ocean 或者每个 stage 的耗时统计,定位到具体步骤。
- 缓存依赖:
stage('install') {
steps {
sh 'npm ci --cache ~/.npm-cache'
}
}
- 并行化独立的 stage:
parallel(
'unit-test': { sh 'npm test' },
'lint': { sh 'npm run lint' }
)
- 增量构建:如果没必要每次都全量构建,可以在 Git 参数里启用浅克隆:
checkout scmGit(branches: [[name: '*/main']],
extensions: [cloneOptions(shallow: true, depth: 1)])
我把主流水线优化之后,从 25 分钟降到了 7 分钟,团队的开发体验立刻好了一大截。
实用小技巧汇总
- 日志排错第一站:
/var/log/jenkins/jenkins.log,90% 的答案都在里面 - 安全模式排障:出问题先停掉 nginx 之类的反向代理,直连 8080,排除网络层的干扰
- 备份:定期备份
jenkins_home里的jobs/、credentials.xml、config.xml,其他都可以重新下载 - ThinBackup 插件:配置自动备份,至少救过我一次
- 升级 Jenkins 本体前:先跑
java -jar jenkins.war --version确认 Java 版本兼容,Jenkins 2.357+ 强制要求 Java 11/17,这个坑我见过很多人掉进去
诚实的局限性
说实话,Jenkins 的问题远不止这些:多 master 的配置同步、Windows agent 的各种诡异行为、Pipeline 插件的 Groovy 沙箱限制,每一个都能单独写一篇文章。而且 Jenkins 的根本问题——用 XML/Groovy 描述一切、UI 老旧——靠这些技巧是解决不了的。如果你的团队规模在膨胀、流水线数量超过一两百个,认真考虑迁移到 GitLab CI 或 GitHub Actions 可能比继续填坑更划算。但如果 Jenkins 已经在稳定地服务你的团队,上面这些方法足以让它再多跑几年不出大事。
有问题欢迎交流,毕竟 Jenkins 的坑,我大概还有一半没踩完。