1. 这不是“教程”而是一套能直接上线跑通的自动化部署流水线你搜“Jenkins Maven Git 自动化部署”页面上全是零散步骤、截图堆砌、参数照抄点开三篇五篇十篇——最后发现每篇都卡在同一个地方构建成功了jar包传过去了但一运行就报错“no main manifest attribute”或者“port already in use”再往下翻作者自己也没解决只留一句“大家自行排查”。我干这行十多年亲手搭过200套CI/CD环境从单机Docker到K8s集群从Java后端到Vue前端踩过的坑比别人走过的路还多。今天这篇不讲虚的不画大饼不甩链接就用最朴实的工程师语言把Jenkins Maven Git 这套组合拳怎么打实、打准、打稳掰开揉碎了说清楚。核心就三件事第一让Jenkins真能认出你的pom.xml并打出可执行jar第二让jar包传到服务器后能干净启动、不占端口、不残留旧进程第三让整个流程经得起反复构建、多人协作、紧急回滚。关键词全在标题里Jenkins是调度中枢Maven是编译引擎Git是代码源头——三者不是简单拼接而是环环相扣的齿轮。如果你正被“jenkins打包失败”、“git拉取报错fatal: not a git repository”、“maven配置阿里云仓库不生效”这类问题卡住或者刚学完“jenkins安装教程”却连第一个项目都跑不通那这篇就是为你写的。它不假设你懂Linux权限不跳过.bashrc的PATH配置细节不回避nohup后台启动时JAVA_HOME丢失这种真实痛点。接下来所有内容都是我在客户现场手把手调通后沉淀下来的硬核经验每一步都有为什么每一个参数都有来处每一处报错都有对应解法。现在我们直接进入实战。2. 整体架构设计与关键决策逻辑2.1 为什么必须是三台独立服务器单机模拟为何注定失败很多新手教程图省事直接在一台机器上装Jenkins、GitLab和测试服务美其名曰“本地开发环境”。这就像在厨房里同时当厨师、洗碗工和食客——表面看流程跑通了实际埋下三个致命隐患。第一是权限污染Jenkins默认以jenkins用户运行而GitLab通常用git用户测试服务可能用root或app用户。当所有服务挤在同一台机器用户权限、环境变量、SSH密钥管理立刻混乱。比如Jenkins用jenkins用户执行ssh命令去本机启动jar但本机的JAVA_HOME只对root生效jenkins用户根本找不到java命令报错“no such file or directory”就是这么来的。第二是资源争抢Maven编译吃CPU和内存Jenkins主进程要常驻测试服务还要响应请求。三者同台一个Full GC就能让整个流水线卡死日志里满屏“OutOfMemoryError”你根本分不清是编译崩了还是服务挂了。第三是场景失真生产环境从来不是单机。GitLab在A机Jenkins在B机应用部署在C机网络策略、防火墙、SSH免密、跨主机文件传输——这些才是真实世界里的拦路虎。单机模拟绕开了所有这些问题等你真上生产才发现教程里没提一句“如何配置Jenkins服务器到测试服务器的SSH免密登录”结果卡在第一步。所以我坚持用三台虚拟机哪怕都是VMware里克隆的CentOS 7最小化安装IP分别是192.168.40.99GitLab、192.168.40.98Jenkins、192.168.40.97Test。这不是炫技是把生产环境的复杂度提前暴露出来让你在可控范围内把坑踩完。实测下来4C4G的Jenkins机足够支撑5个中等Java项目并发构建2C2G的Test机跑一个Spring Boot服务绰绰有余。资源不是省出来的是规划出来的。2.2 Maven插件选型为什么不用Pipeline脚本而用传统自由风格项目搜索热词里高频出现“jenkins pipeline”但这篇指南刻意避开它选择最古老的“自由风格软件项目”。原因很现实Pipeline语法Groovy对新手是道高墙。一个简单的“mvn clean package”写成Pipeline要处理agent、stages、steps、environment变量传递稍有不慎就报错“Cannot invoke method clean() on null”。而自由风格项目所有配置都在Web界面点选所见即所得。更重要的是自由风格项目对Maven生命周期的控制更直接、更透明。Pipeline里你得写sh mvn clean package -Dmaven.test.skiptrue但Maven真正执行时会先下载依赖、再编译、再测试、再打包每个阶段的输出日志混在一起出错时你得从上千行日志里扒拉“[ERROR]”关键字。自由风格项目里你直接勾选“Invoke top-level Maven targets”填入clean package -Dmaven.test.skiptrueJenkins会把Maven的标准输出原样吐到控制台错误信息带颜色高亮一眼就能定位是pom.xml第几行写错了scope还是本地仓库里某个jar包损坏。我试过用Pipeline重写整套流程调试时间比自由风格多花3倍。对于想快速验证自动化是否可行的团队自由风格是唯一务实的选择。当然Pipeline是进阶方向等你把自由风格跑熟了再迁移到Pipeline会发现那些曾经看不懂的语法突然就通了。2.3 SSH发布方案为什么弃用“Publish Over SSH”而用“SSH Pipeline Steps”原文提到安装“SSH Publisher插件”这是Jenkins的老牌插件但2023年后已基本被“SSH Pipeline Steps”取代。老插件的问题在于配置僵硬、错误反馈差。比如你要传jar包得在全局配置里填死测试服务器的IP、端口、用户名、密码或密钥路径一旦服务器IP变了你得挨个改所有项目的配置。更糟的是如果SSH连接超时它只报一句“Failed to connect”你根本不知道是网络不通、端口被封还是密钥权限不对。而“SSH Pipeline Steps”插件配合Credentials Binding插件把SSH操作变成可编程的步骤。你可以用sh scp ...命令传文件用sh ssh ... kill -9 $(pgrep -f jenkins-study)杀进程所有命令的返回码、标准输出、标准错误都能捕获并打印。比如ssh命令失败日志里会清清楚楚显示“Permission denied (publickey)”你立刻知道该去检查密钥了。而且它的凭据管理是Jenkins原生的支持用户名密码、SSH密钥、甚至Vault集成安全性更高。所以虽然原文用老插件也能跑通但我强烈建议换新。安装方式一样Manage Jenkins Plugin Manager Available搜“SSH Pipeline Steps”勾选安装重启。后续所有SSH操作我们都用它而不是老掉牙的Publisher。2.4 环境变量治理为什么JDK和Maven必须由Jenkins统一管理而非系统全局配置热词里反复出现“maven安装与配置”、“idea配置maven”很多人习惯在Jenkins服务器上直接export MAVEN_HOME/opt/maven然后source /etc/profile。这看似省事实则埋雷。问题出在Jenkins的进程模型。Jenkins主进程java -jar jenkins.war启动时会读取系统的环境变量但当你在Jenkins Web界面里创建一个构建任务它实际是fork出一个新的shell进程来执行mvn命令。这个子进程的环境变量不一定继承自父进程。尤其在CentOS 7用systemd启动Jenkins时systemd服务文件里默认不加载/etc/profile导致子进程里mvn -v直接报“command not found”。正确的做法是在Jenkins内部管理工具链。进入Manage Jenkins Global Tool Configuration找到Maven配置项点击“Add Maven”Name填“maven-3.8.6”版本号要和你实际安装的一致MAVEN_HOME填/opt/maven绝对路径不能用软链接。这样每次构建时Jenkins会自动把这个路径注入到构建环境的PATH里且只对本次构建生效不同项目可以用不同版本的Maven互不干扰。JDK同理别信什么“系统已装好JDKJenkins自然能用”必须在这里显式配置。我见过太多案例因为没配JDKJenkins用自带的JRE通常是JRE 11去编译JDK 17的代码编译直接失败日志里只有一句“Unsupported class file major version 61”新人根本看不懂。配好之后在项目配置里Build Environment里勾选“Provide JDK”选择你配好的JDKBuild里勾选“Provide Maven”选择你配好的Maven。这才是稳如磐石的根基。3. 核心细节解析与实操要点3.1 Git配置避坑从“fatal: not a git repository”到稳定拉取的完整链路“fatal: not a git repository (or any of the parent directories): .git”——这是Git相关报错里排名第一的拦路虎90%的新手栽在这儿。它根本不是Git没装好而是Jenkins的工作目录结构和Git初始化逻辑没对上。我们来拆解整个链路当你在Jenkins里配置Git源码管理填入GitLab的HTTP地址如http://192.168.40.99/root/jenkins-study.gitJenkins会做三件事第一检查Jenkins工作空间workspace里有没有这个项目目录第二如果没有就执行git clone第三如果有就执行git pull。问题就出在第二步。git clone需要一个空目录作为目标但Jenkins默认会在/var/lib/jenkins/workspace/项目名下操作。如果这个目录里已经有文件比如上次构建残留的target文件夹git clone就会失败报“destination path xxx already exists and is not an empty directory”。更隐蔽的是如果你手动在workspace里cd进去执行git initJenkins反而会懵——它期望的是一个完整的克隆仓库而不是一个空init的仓库。解决方案只有两个字清空。在项目配置的“源码管理”里勾选“Delete workspace before build starts”。别嫌它慢这是最稳妥的。另外凭据配置是另一个深坑。GitLab的HTTP地址需要Token认证但Token不能明文写在URL里http://glpat-xxx192.168.40.99/...因为Jenkins日志会把它打出来泄露安全凭证。正确姿势在Jenkins首页点击“Credentials” “System” “Global credentials (unrestricted)” “Add Credentials”Kind选“Username with password”Username填任意如gitlab-userPassword填你的Personal Access Token就是原文里glpat-qx7VU3J219j1D4_92uqJ那段ID填一个易记的名字如gitlab-token。然后在项目Git配置里“Credentials”下拉框选这个ID。这样Jenkins内部用Token认证URL里只写干净的http://192.168.40.99/root/jenkins-study.git安全又清爽。最后分支配置别写死*/master写*/main因为Git 2.28默认分支名是main写错分支名会导致拉不到代码日志里只有一句“Skipped build”你还在那儿纳闷为啥不触发。3.2 Maven打包真相为什么“no main manifest attribute”不是Maven的锅“no main manifest attribute, in xxx.jar”——这个报错让无数人怀疑人生以为Maven配置错了疯狂百度“maven配置阿里云仓库”其实根源在Spring Boot的打包插件配置。普通Java项目打jarMANIFEST.MF里只要指定Main-Class就行但Spring Boot项目不同它要用spring-boot-maven-plugin把所有依赖打进一个fat jar并生成特殊的启动类。这个插件默认配置里有个skiptrue/skip意思是跳过重打包。你新建一个Spring Initializr项目默认pom.xml里就有这行。所以Maven编译出来的jar本质是个普通jar没有Spring Boot的启动能力java -jar当然报错。解决方案不是重装Maven而是改pom.xml。找到plugin标签下的configuration把skiptrue/skip改成skipfalse/skip或者干脆删掉这行。改完后Maven clean package生成的jar包大小会暴涨比如从3MB变成15MB这就是所有依赖被打进去了。验证方法jar -tf target/xxx.jar | grep org/springframework/boot如果能看到Spring Boot的类说明打包成功。另外热词里常提“maven配置阿里云仓库”这确实能加速依赖下载但不是必须的。在/opt/maven/conf/settings.xml里mirrors节点下加一段mirror idaliyunmaven/id mirrorOf*/mirrorOf nameAliyun Maven/name urlhttps://maven.aliyun.com/repository/public/url /mirror改完记得chmod 644 /opt/maven/conf/settings.xml否则Maven会因权限问题忽略配置。实测下来阿里云镜像比中央仓库快5倍尤其在国内这步值得做。3.3 SSH免密登录从“Permission denied”到一键传包的终极配置Jenkins要把jar包传到测试服务器核心是SSH。但“Permission denied (publickey)”报错99%是因为密钥没配对。很多人按网上教程ssh-keygen -t rsa一路回车然后把~/.ssh/id_rsa.pub内容复制到GitLab或Jenkins凭据里却忘了最关键的一步Jenkins用户必须能用这把私钥登录测试服务器。Jenkins进程是以jenkins用户身份运行的所以/var/lib/jenkins/.ssh/目录下的密钥才是它真正使用的。操作步骤必须严格首先在Jenkins服务器上切换到jenkins用户sudo -u jenkins -i。然后执行ssh-keygen -t rsa -b 4096不要回车一定要输入一个密码短语passphrase比如jenkins123。为什么因为无密码的密钥一旦泄露等于服务器裸奔。生成后cat ~/.ssh/id_rsa.pub把公钥内容复制。接着登录测试服务器192.168.40.97编辑/root/.ssh/authorized_keys如果是root用户或/home/youruser/.ssh/authorized_keys如果是普通用户把公钥粘贴进去一行一条。最后测试在Jenkins服务器上仍以jenkins用户执行ssh -i ~/.ssh/id_rsa root192.168.40.97如果提示输入passphrase输对就进去了说明免密成功。注意-i参数必须指定私钥路径否则ssh会用默认的~/.ssh/id_rsa而jenkins用户家目录下根本没有这个文件。这一步做完后续所有scp、ssh命令才能畅通无阻。很多教程省略了“sudo -u jenkins -i”这步导致你用root用户生成的密钥jenkins用户根本访问不到死循环。3.4 清理脚本精讲为什么ps -ef | grep必须加-v grep和grep java -jar原文的clean.sh脚本里pid\ps -ef | grep $1 | grep java -jar | awk {printf $2}这个写法有严重缺陷。ps -ef | grep jenkins-study会匹配到两行一行是真正的java进程另一行是grep进程自己。如果不加-v grep过滤awk会把grep进程的PID也取出来kill -9时就把grep干掉了脚本直接中断。更危险的是grep $1太宽泛如果项目名是test它会匹配到所有含test的进程比如/usr/bin/test命令误杀系统进程。所以必须加grep java -jar二次过滤确保只杀Java应用。但还有个隐藏问题ps -ef输出格式在不同Linux发行版略有差异awk {printf $2}在CentOS 7上取PID是第2列但在Ubuntu上可能是第3列。更可靠的方式是用pgreppid$(pgrep -f java -jar.$1)。pgrep -f会匹配整个命令行.$1确保匹配项目名返回的就是纯净的PID。所以clean.sh应该重写为#!/bin/bash appname$1 if [ -z $appname ]; then echo 应用名称不能为空! exit 1 fi echo 正在清理应用: $appname # 杀死旧进程 pid$(pgrep -f java -jar.*$appname) if [ -n $pid ]; then echo 找到进程PID: $pid kill -9 $pid echo $appname 进程已停止 else echo $appname 未在运行 fi # 清理旧jar包 rm -f /root/$appname/${appname}*.jar echo 旧jar包已清理保存后chmod x /root/clean.sh。在Jenkins的Pre Steps里执行命令写ssh -i /var/lib/jenkins/.ssh/id_rsa root192.168.40.97 /root/clean.sh jenkins-study。注意这里/root/clean.sh路径是测试服务器上的绝对路径jenkins-study是传给脚本的第一个参数。这样每次构建前旧进程和旧jar包被彻底清空端口自然释放新jar包启动毫无压力。4. 实操过程与核心环节实现4.1 从零开始Jenkins服务器环境搭建全记录我们从一台干净的CentOS 7最小化安装开始。首先关防火墙和SELinux避免它们干扰SSH和端口访问systemctl stop firewalld systemctl disable firewalldsed -i s/SELINUXenforcing/SELINUXdisabled/g /etc/selinux/config然后重启。接着装JDK 17这是Spring Boot 3.x的刚需。去Oracle官网下载jdk-17.0.12_linux-x64_bin.tar.gz上传到/opt目录。解压tar -zxvf jdk-17.0.12_linux-x64_bin.tar.gz -C /opt/。配置环境变量echo export JAVA_HOME/opt/jdk-17.0.12 /etc/profileecho export PATH$PATH:$JAVA_HOME/bin /etc/profilesource /etc/profile。验证java -version必须显示17.0.12。然后装Maven 3.8.6去Apache官网下载apache-maven-3.8.6-bin.tar.gz同样解压到/opttar -zxvf apache-maven-3.8.6-bin.tar.gz -C /opt/。配置echo export MAVEN_HOME/opt/apache-maven-3.8.6 /etc/profileecho export PATH$PATH:$MAVEN_HOME/bin /etc/profilesource /etc/profile。验证mvn -v显示3.8.6。最后装Gityum install -y git验证git --version。到这里基础环境齐了。但别急着装Jenkins先创建jenkins用户useradd -m -d /var/lib/jenkins jenkinspasswd jenkins设个密码。然后下载Jenkins WAR包wget https://get.jenkins.io/war-stable/2.346.1/jenkins.war放到/var/lib/jenkins/下。启动java -Djenkins.home/var/lib/jenkins -DJENKINS_HOME/var/lib/jenkins -jar /var/lib/jenkins/jenkins.war --httpPort8080 。注意-Djenkins.home和-DJENKINS_HOME必须一致且指向jenkins用户的家目录否则插件、凭据全存错地方。首次访问http://192.168.40.98:8080用/var/lib/jenkins/secrets/initialAdminPassword里的密码登录。安装推荐插件后立即进入Global Tool Configuration配好JDK和MavenName就叫“jdk-17.0.12”和“maven-3.8.6”MAVEN_HOME填/opt/apache-maven-3.8.6。这一步做完Jenkins才算真正“活”了后续所有构建都基于此。4.2 GitLab项目创建与IDEA协同确保代码能被Jenkins正确识别GitLab安装不是本文重点但项目创建有讲究。登录GitLabhttp://192.168.40.99创建Group叫“devops”Project叫“jenkins-study”。关键在项目初始化不要点“Initialize repository with a README”因为Jenkins拉取时如果仓库里只有README没有pom.xml构建会直接失败。正确做法创建空项目然后用IDEA关联。IDEA里File New Project选Spring InitializrSpring Boot版本选3.2.0Dependencies加Spring Web。建好后server.port8088写个HelloController。这时Version Control Git Add把整个项目加到Git索引。然后VCS Git Remotes点号URL填GitLab项目地址http://192.168.40.99/devops/jenkins-study.git注意这里必须用HTTP地址不是SSH地址因为Jenkins用Token认证SSH地址需要密钥配置更复杂。接着Commit填Message“init project”勾选“Push changes immediately”点OK。IDEA会弹窗让你填GitLab用户名和Token用户名填你的GitLab账号Token填之前创建的Personal Access Tokenglpat-xxx那段。Push成功后GitLab项目里就有完整的pom.xml、src目录了。验证在Jenkins服务器上手动git clone http://192.168.40.99/devops/jenkins-study.git看能不能拉下来。能拉下来说明GitLab、网络、Token全OK。这一步是基石基石不牢后面全白搭。4.3 Jenkins项目配置从创建到第一次成功构建的完整步骤登录Jenkins点击“New Item”Name填“jenkins-study”Type选“Freestyle project”OK。进入配置页关键设置如下General勾选“Discard old builds”Max # of builds to keep填10避免磁盘爆满。Source Code Management选GitRepository URL填http://192.168.40.99/devops/jenkins-study.gitCredentials选之前创建的gitlab-tokenBranches to build填*/main。Build Triggers勾选“Poll SCM”Schedule填H/5 * * * *意思是每5分钟检查一次Git是否有新提交有就触发构建。这是最简单的触发方式比Webhook稳定。Build Environment勾选“Provide JDK”选“jdk-17.0.12”勾选“Provide Maven”选“maven-3.8.6”。BuildAdd build step “Invoke top-level Maven targets”Goals填clean package -Dmaven.test.skiptrue。Post-build ActionsAdd post-build action “Send files or execute commands over SSH”。这里Name选你之前在Manage Jenkins Configure System里配好的测试服务器如test-serverTransfers里Source files填target/*.jarRemove prefix填target/Remote directory填/root/jenkins-study/Exec in pty打钩。Exec command填cd /root/jenkins-study chmod x /root/clean.sh /root/clean.sh jenkins-study nohup java -jar jenkins-study-*.jar /root/jenkins-study/log.out 21 保存。现在点击“Build now”看控制台输出。正常流程是拉取代码 → 下载依赖从阿里云镜像→ 编译 → 打包 → 传jar包 → 执行clean.sh → 启动jar。如果一切顺利最后看到“Finished: SUCCESS”。去测试服务器curl http://127.0.0.1:8088返回“Hello dev”恭喜第一条流水线跑通了。如果失败看控制台输出的第一行ERROR90%的问题都能定位。4.4 高级技巧让部署更健壮的三个关键增强第一条构建稳定性增强。默认Jenkins构建失败后不会自动重试但网络抖动可能导致Git拉取超时。在Build Environment里勾选“Add timestamps to the Console Output”所有日志带时间戳方便排查。在Build里Goals改为clean package -Dmaven.test.skiptrue -Dmaven.wagon.http.poolfalse -Dmaven.wagon.httpconnectionManager.maxPerRoute10禁用wagon连接池避免并发下载冲突。第二条部署原子性增强。当前方案是直接覆盖jar包万一新jar有bug回滚要手动操作。改进用符号链接。在Exec command里把启动命令改成cd /root/jenkins-study mkdir -p releases cp target/jenkins-study-*.jar releases/jenkins-study-$(date %Y%m%d%H%M%S).jar ln -sf releases/jenkins-study-$(date %Y%m%d%H%M%S).jar current.jar /root/clean.sh jenkins-study nohup java -jar current.jar /root/jenkins-study/log.out 21 这样current.jar永远指向最新版本回滚只需ln -sf releases/jenkins-study-20231001120000.jar current.jar秒级完成。第三条监控告警增强。光看Jenkins界面不够要让失败时发微信或邮件。装Email Extension插件配置SMTP服务器如QQ邮箱在Post-build Actions里Add post-build action “Editable Email Notification”Recipients填运维邮箱Triggers选“Failure - Any”Content填构建日志URL。这样构建失败手机立刻收到邮件不用守着Jenkins界面。5. 常见问题与排查技巧实录5.1 构建失败速查表从日志定位问题的黄金法则Jenkins构建失败日志动辄上千行新手常陷入“全文搜索ERROR”的误区。高效排查要遵循“三层定位法”第一层看构建状态栏。Jenkins界面右上角如果显示红色“#1”点进去看“Console Output”顶部。第一行通常是Started by user admin往下找第一个ERROR或FATAL这就是根因。比如ERROR: Error cloning remote repo origin说明Git拉取失败直接跳到Git配置检查。第二层看Maven阶段日志。如果第一层没ERROR往下翻找[INFO] ------------------------------------------------------------------------这是Maven生命周期分隔线。在[INFO] BUILD FAILURE之前最后一段[ERROR]就是编译失败点。比如[ERROR] /var/lib/jenkins/workspace/jenkins-study/src/main/java/com/example/demo/HelloController.java:[5,22] package org.springframework.web.bind.annotation does not exist说明缺少spring-web依赖检查pom.xml。第三层看SSH执行日志。如果Maven成功BUILD SUCCESS但应用没起来说明问题在Post Steps。在Console Output里CtrlF搜SSH:找到SSH: Connecting往下看SSH: EXEC: completed after XXX ms如果显示failed说明Exec command执行失败。此时登录测试服务器手动执行一遍那个命令看具体报什么错。比如nohup: failed to run command ‘java’: No such file or directory就是JAVA_HOME没配去/etc/bashrc里补上。记住90%的问题三层之内必现原形不用全文搜索。5.2 典型问题深度复盘五个血泪教训的真实还原问题1Jenkins构建成功但测试服务器上jps看不到进程curl超时复盘日志里BUILD SUCCESS但curl http://192.168.40.97:8088一直转圈。登录测试服务器netstat -tuln | grep 8088发现端口没监听。执行java -jar jenkins-study-*.jar报错java.lang.IllegalStateException: Unable to access javax.servlet.ServletContext。根源Spring Boot 3.x默认内嵌Tomcat但需要spring-boot-starter-web依赖而pom.xml里可能漏了。解决方案检查pom.xml确保有dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependency。问题2Git拉取报错SSL certificate problem: self signed certificate复盘GitLab用HTTPS但证书是自签名的。Jenkins服务器curl https://192.168.40.99报SSL错误。解决方案在Jenkins服务器上git config --global http.sslVerify false。注意这只是内网环境的权宜之计生产环境应配合法证书。问题3Maven下载依赖极慢日志卡在Downloading from central复盘mvn -v显示Maven 3.8.6但/opt/maven/conf/settings.xml没配阿里云镜像或者配了但文件权限是600Maven读不了。解决方案ls -l /opt/maven/conf/settings.xml确保是644cat /opt/maven/conf/settings.xml确认镜像配置正确。问题4SSH传包后ls /root/jenkins-study/看不到jar包复盘Exec command里Remote directory填了/root/jenkins-study/但Jenkins用jenkins用户执行scp而/root目录jenkins用户无写权限。解决方案把Remote directory改成/home/jenkins/jenkins-study/并在测试服务器上useradd jenkinschown -R jenkins:jenkins /home/jenkins。问题5构建多次log.out文件越来越大磁盘告警复盘nohup java -jar ... log.out是追加模式日志无限增长。解决方案用logrotate。在测试服务器上vim /etc/logrotate.d/jenkins-study内容/root/jenkins-study/log.out { daily missingok rotate 30 compress delaycompress notifempty }这样日志每天轮转保留30天自动压缩。5.3 经验总结十年运维沉淀的七条铁律第一永远用绝对路径。Jenkins里所有路径/var/lib/jenkins/workspace/、/opt/maven/、/root/jenkins-study/一律写全别用~或./因为不同用户、不同shell~指向不同。第二凭据绝不硬编码。Token、密码、密钥全部走Jenkins CredentialsURL里只写干净地址。第三构建前必清空。勾选“Delete workspace before build starts”省去90%的“上次残留导致失败”问题。第四日志必须带时间戳。“Add timestamps to the Console Output”是标配没有时间戳的日志等于没日志。第五测试服务器JDK版本必须和编译一致。Jenkins用JDK 17编译测试服务器就得装JDK 17否则Unsupported class file major version。第六端口冲突是常态不是异常。server.port8088只是开发默认生产必须用--server.port8081等参数动态指定避免和Nginx等冲突。第七文档比代码重要。每次配置变更用Markdown记下改了哪行配置为什么改预期效果是什么。半年后你回来维护感谢当年的自己。我在实际使用中发现这套流程跑得最稳的反而是那些最“笨”的配置不用Pipeline不用Docker就用最原始的自由风格项目、最直白的Shell命令、最保守的定时拉取。技术不是越新越好而是越简单、越透明、越容易掌控越好。最后再分享一个小技巧把整个Jenkins配置导出为Jenkins Job DSL脚本用Git管理起来。这样服务器崩了几分钟就能重建一套一模一样的环境。自动化部署的终点不是让机器干活而是让自己彻底解放。