Jenkins Slave执行远程Git操作时抛出InterruptedException问题排查
问题
我想创建一个Jenkins任务,用来在指定的多个代码仓库中合并自定义选择的两个分支。以下是我的流水线代码:
pipeline { agent any parameters { text(name: 'REPOSITORIES', description: 'List of repository URLs (one per line)', defaultValue: 'https://git.xxx.com') string(name: 'SOURCE_BRANCH', description: 'Source branch to merge', defaultValue: 'Branch_sourceBranch') string(name: 'TARGET_BRANCH', description: 'Target branch to merge into', defaultValue: 'Branch_targetBranch') } stages { stage('Merge Branches') { steps { script { def repositories = params.REPOSITORIES.tokenize('\n') for (repository in repositories) { checkout([$class: 'GitSCM', branches: [[name: "*/${SOURCE_BRANCH}"]], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: 'GITHUB_TOKEN_123', url: repository]]]) sh "git reset --hard" // just for test sh "git checkout ${TARGET_BRANCH}" // sh "git fetch" - also fails sh "git merge origin/${SOURCE_BRANCH}" sh "git push origin" } } } } }
运行时,所有通过sh执行的远程Git操作(如git pull、git fetch、git push)都会报错,本地操作(如git checkout、git reset)能正常执行。执行到sh git push origin时的错误日志如下:
14:33:52 Running on jenkins-slave-prg-xldzf in /var/lib/jenkins/workspace/XXX/Merge_project 14:33:52 [Pipeline] { 14:33:52 [Pipeline] stage 14:33:52 [Pipeline] { (Merge Branches) 14:33:52 [Pipeline] script 14:33:52 [Pipeline] { 14:33:52 [Pipeline] checkout 14:33:53 The recommended git tool is: NONE 14:33:59 using credential GITHUB_TOKEN_123 14:33:59 Cloning the remote Git repository 14:34:02 Cloning repository https://git.xxx.com 14:34:02 > git init /var/lib/jenkins/workspace/XXX/Merge_project # timeout=10 14:34:02 Fetching upstream changes from https://git.xxx.com 14:34:02 > git --version # timeout=10 14:34:02 > git --version # 'git version 2.39.3' 14:34:02 using GIT_ASKPASS to set credentials 14:34:02 > git fetch --tags --force --progress -- https://git.xxx.com +refs/heads/*:refs/remotes/origin/* # timeout=10 14:34:05 > git config remote.origin.url https://git.xxx.com # timeout=10 14:34:05 > git config --add remote.origin.fetch +refs/heads/*:refs/remotes/origin/* # timeout=10 14:34:06 Avoid second fetch 14:34:06 Checking out Revision 590162cae7effe128609425879eb595ca64aa948 (refs/remotes/origin/Branch_sourceBranch) 14:34:06 > git rev-parse refs/remotes/origin/Branch_sourceBranch^{commit} # timeout=10 14:34:06 > git config core.sparsecheckout # timeout=10 14:34:06 > git checkout -f 590162cae7effe128609425879eb595ca64aa948 # timeout=10 14:34:07 Commit message: "testCommit change 1" 14:34:07 > git rev-list --no-walk 590162cae7effe128609425879eb595ca64aa948 # timeout=10 14:34:07 [Pipeline] sh 14:34:08 + git reset --hard 14:34:08 HEAD is now at 590162ca testCommit change 1 14:34:08 [Pipeline] sh 14:34:08 + git checkout Branch_targetBranch 14:34:08 Previous HEAD position was 590162ca testCommit change 1 14:34:08 Switched to a new branch 'Branch_targetBranch' 14:34:08 branch 'Branch_targetBranch' set up to track 'origin/Branch_targetBranch'. 14:34:08 [Pipeline] sh 14:34:08 + git merge origin/Branch_sourceBranch 14:34:08 Updating 91102452..590162ca 14:34:08 Fast-forward 14:34:08 testFile/test.xsd | 1 + 14:34:08 README.md | 3 ++- 14:34:08 2 files changed, 3 insertions(+), 1 deletion(-) 14:34:08 [Pipeline] sh 14:34:29 Cannot contact jenkins-slave-prg-xldzf: java.lang.InterruptedException
服务器负载不高,推测问题和远程Git操作相关,请问需要配置什么才能避免这个InterruptedException?
解决方案
解决这个问题,你可以从以下几个方面调整配置和流水线代码:
1. 延长Git操作超时时间
Jenkins默认Git操作超时为10分钟,远程操作可能因网络或仓库规模需要更长时间。你可以:
- 在
checkout步骤中添加克隆超时配置:
checkout([$class: 'GitSCM', branches: [[name: "*/${SOURCE_BRANCH}"]], doGenerateSubmoduleConfigurations: false, extensions: [[$class: 'CloneOption', timeout: 30]], // 设置为30分钟 submoduleCfg: [], userRemoteConfigs: [[credentialsId: 'GITHUB_TOKEN_123', url: repository]]])
- 给
sh步骤的远程Git命令单独设置超时:
sh timeout: 30, unit: 'MINUTES', script: 'git push origin'
2. 确保Git远程操作使用有效凭证
checkout步骤的凭证不会自动传递给后续sh执行的Git命令,需要显式处理:
- 使用
withCredentials步骤传递凭证,直接在push命令中使用:
withCredentials([string(credentialsId: 'GITHUB_TOKEN_123', variable: 'GIT_TOKEN')]) { sh "git push https://${GIT_TOKEN}@git.xxx.com ${TARGET_BRANCH}" }
- 或者配置Git凭证助手临时存储凭证:
sh "git config credential.helper 'store --file=.git/credentials'" sh "echo 'https://${GIT_TOKEN}@git.xxx.com' > .git/credentials"
3. 为每个仓库创建独立工作目录
多个仓库共用同一工作空间可能导致Git配置冲突,建议为每个仓库单独创建子目录:
def repoDir = repository.tokenize('/')[-1].replace('.git', '') dir(repoDir) { checkout([$class: 'GitSCM', branches: [[name: "*/${SOURCE_BRANCH}"]], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: 'GITHUB_TOKEN_123', url: repository]]]) sh "git reset --hard" sh "git checkout ${TARGET_BRANCH}" sh "git merge origin/${SOURCE_BRANCH}" sh "git push origin" }
4. 调整Jenkins主从节点通信超时
如果是主节点和代理节点之间的通信中断,需要修改Jenkins全局配置:
- 进入Jenkins管理界面 → 系统管理 → 系统设置
- 在“代理设置”中,增大“代理连接超时”和“代理读取超时”的值(比如设为300秒)
5. 简化Git操作流程
当前流水线先拉取源分支再切换目标分支,可直接拉取目标分支后合并,减少不必要的步骤:
checkout([$class: 'GitSCM', branches: [[name: "*/${TARGET_BRANCH}"]], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: 'GITHUB_TOKEN_123', url: repository]]]) sh "git merge origin/${SOURCE_BRANCH}" sh "git push origin"
内容的提问来源于stack exchange,提问作者SSV
相关产品推荐
相关产品推荐

