Jenkins流水线脚本编译错误:catch语法异常排查求助
问题描述
尝试使用以下Jenkinsfile部署Django构建时,任务立即返回编译错误,环境配置如下:
- 云实例1(归属用户
preProd)部署App&WebServer - 云实例2(归属用户
jenkins)部署Jenkins服务器,且jenkins用户公钥已添加至实例1,免密登录正常 - Jenkins Web界面管理员为
testUser,使用含GitHub密钥的流水线任务 - 目标是在实例1部署Django构建
提供的Jenkinsfile:
#!groovy node { try { stage 'Checkout' sshagent(credentials : ['1000']) { sh 'ssh -o StrictHostKeyChecking=no preProd@xxx.xxx.xxx.xx uptime' sh 'ssh -v preProd@xxx.xxx.xxx.xx' } sh 'cd preprod-testP' sh 'pwd' sh 'ls' sh 'git init' sh 'git status' sh 'git pull https://xxxxxxxxxxxx:ghp_qwfaqwefdaf21asffasfas1e@github.com/testP/preprod-testP.git' sh 'git branch' stage 'Build' sh 'virtualenv env -p python3' sh '. env/bin/activate' sh '/home/preProd/preprod-testP/env/bin/pip freeze' sh '/home/preProd/preprod-testP/env/bin/pip install -r requirements.txt' stage 'Test' sh '/home/preProd/preprod-testP/env/bin/python manage.py makemigrations' sh '/home/preProd/preprod-testP/env/bin/python manage.py migrate' stage 'Deploy' sh 'JENKINS_NODE_COOKIE=dontKillMe nohup /home/preProd/preprod-testP/env/bin/python manage.py runserver 0.0.0.0:8000 &' sh 'echo "deployment is successfully completed."' sh 'sudo service gunicorn restart' sh 'sudo service nginx restart' } catch (err) { sh 'echo "Build failed :face_with_head_bandage: \n`${env.JOB_NAME}#${env.BUILD_NUMBER}` <${env.BUILD_URL}|Open in Jenkins>"' throw err } }
收到的错误信息:
Started by user testUser Obtained Jenkinsfile from git https://github.com/testP/preprod-testP.git org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed: WorkflowScript: 35: unexpected token: catch @ line 35, column 5. catch (err) { ^ 1 error at org.codehaus.groovy.control.ErrorCollector.failIfErrors(ErrorCollector.java:309) ...(省略堆栈跟踪) Finished: FAILURE
错误排查与修复方案
1. 核心语法错误:Groovy解析失败
错误提示unexpected token: catch,根源是Jenkinsfile的Groovy语法不规范,导致解析器无法识别try块的边界,同时存在其他语法问题:
(1) Stage语法规范
Jenkins Pipeline的stage需要用括号包裹名称,正确写法为stage('Checkout'),而非stage 'Checkout'(旧语法兼容性差,严格Groovy语法要求带括号)。
(2) 多行sh命令的换行问题
Deploy阶段的sh命令被拆分为两行,Groovy会将其视为独立语句,触发语法错误。需合并为一行,或用Groovy多行字符串("""/'''包裹)。
(3) 修正后的完整Jenkinsfile
#!groovy node { try { stage('Checkout') { sshagent(credentials : ['1000']) { sh 'ssh -o StrictHostKeyChecking=no preProd@xxx.xxx.xxx.xx uptime' sh 'ssh -v preProd@xxx.xxx.xxx.xx' } // 每个sh是独立shell进程,cd不影响后续命令,需用绝对路径或合并命令 sh 'cd /home/preProd/preprod-testP && pwd && ls && git init && git status' sh 'cd /home/preProd/preprod-testP && git pull https://xxxxxxxxxxxx:ghp_qwfaqwefdaf21asffasfas1e@github.com/testP/preprod-testP.git' sh 'cd /home/preProd/preprod-testP && git branch' } stage('Build') { sh 'cd /home/preProd/preprod-testP && virtualenv env -p python3' // 虚拟环境激活需与后续命令在同一shell进程,合并执行 sh 'cd /home/preProd/preprod-testP && . env/bin/activate && pip freeze && pip install -r requirements.txt' } stage('Test') { sh '/home/preProd/preprod-testP/env/bin/python manage.py makemigrations' sh '/home/preProd/preprod-testP/env/bin/python manage.py migrate' } stage('Deploy') { // 合并多行runserver命令 sh 'JENKINS_NODE_COOKIE=dontKillMe nohup /home/preProd/preprod-testP/env/bin/python manage.py runserver 0.0.0.0:8000 &' sh 'echo "deployment is successfully completed."' sh 'sudo service gunicorn restart' sh 'sudo service nginx restart' } } catch (err) { // 用多行字符串修复echo命令换行问题 sh '''echo "Build failed :face_with_head_bandage: `${env.JOB_NAME}#${env.BUILD_NUMBER}` <${env.BUILD_URL}|Open in Jenkins>"''' throw err } }
2. 额外逻辑问题修正
- 独立sh进程的cd无效:每个
sh命令都是单独的shell会话,cd preprod-testP仅对当前sh进程生效,后续pwd/ls仍在Jenkins工作目录执行,需用绝对路径或用&&合并多个命令到同一个sh中。 - 虚拟环境激活生效问题:
. env/bin/activate必须和后续的pip/python命令在同一个shell进程执行,否则激活状态不会传递,需合并为一个sh命令。
3. 验证步骤
- 替换为修正后的Jenkinsfile
- 重新触发流水线,确认编译错误消失
- 若仍有问题,查看Jenkins控制台的具体shell执行日志,排查路径、权限问题(例如
sudo是否配置免密)
内容的提问来源于stack exchange,提问作者Santana
相关产品推荐
相关产品推荐

