Jenkins Pipeline超时未终止任务问题排查与解决求助
Jenkins Pipeline超时后任务仍成功的问题排查与解决
问题原因
Jenkins的timeout步骤仅会中断Jenkins节点本地的进程,但你的脚本通过多层SSH嵌套(本地→server.com→localhost)执行Docker容器内的Python脚本,中断信号无法传递到最内层的运行进程:
- SSH默认不转发中断信号到远程会话,导致本地
run_script.sh收到中断后,远程的SSH进程和Docker容器不受影响 - 即使远程SSH进程收到信号,Docker容器作为独立进程空间,内部的Python脚本也不会自动终止,最终容器执行完成后返回成功状态,让Jenkins判定任务成功
实现超时后终止任务的方案
1. 让SSH转发中断信号
在SSH命令中添加-tt参数,强制分配伪终端,确保中断信号能从本地传递到远程会话:
修改run_script.sh:
#!/bin/bash set -e ssh -tt user@server.com " ssh -tt -p 30 xdy@localhost ' docker run --rm --name cont1 -e FTP_USER=$User -e FTP_PASSWD=$Pass -v /home/logs:/usr/myapp -w /usr/myapp server2.com:3000/mylog:1.1 python script.py' "
set -e确保脚本中任何命令失败时立即退出,让Jenkins捕获到失败状态。
2. 强制终止远程Docker容器
即使SSH转发了信号,容器内的Python进程可能不响应中断,需主动清理容器,可选两种方式:
方式一:Pipeline超时后触发清理
在Jenkinsfile的post阶段添加aborted钩子,超时中止时远程执行容器终止命令:
stage('My stage') { options { timeout(time: 5, unit: "MINUTES") } steps { script { sh './run_script.sh' } } post { aborted { sh ''' ssh -tt user@server.com " ssh -tt -p 30 xdy@localhost ' docker kill cont1 || true' " ''' } } }
docker kill cont1 || true确保容器不存在时命令不会报错。
方式二:脚本内捕获信号触发清理
在run_script.sh中添加信号捕获函数,收到中断时主动终止远程容器:
#!/bin/bash set -e # 定义中断信号处理函数 cleanup() { echo "收到中断信号,清理远程容器..." ssh -tt user@server.com " ssh -tt -p 30 xdy@localhost ' docker kill cont1 || true' " exit 1 } # 捕获SIGINT和SIGTERM信号 trap cleanup SIGINT SIGTERM # 执行原命令 ssh -tt user@server.com " ssh -tt -p 30 xdy@localhost ' docker run --rm --name cont1 -e FTP_USER=$User -e FTP_PASSWD=$Pass -v /home/logs:/usr/myapp -w /usr/myapp server2.com:3000/mylog:1.1 python script.py' "
脚本收到中断时会执行清理并以非0状态退出,让Jenkins判定任务失败。
捕获超时状态发送通知
Jenkins中任务超时属于aborted状态,可在post阶段针对该状态发送通知,以下是邮件通知示例:
stage('My stage') { options { timeout(time: 5, unit: "MINUTES") } steps { script { sh './run_script.sh' } } post { aborted { emailext( to: 'your-team@example.com', subject: "Jenkins任务 ${JOB_NAME} #${BUILD_NUMBER} 因超时中止", body: "任务链接: ${BUILD_URL}\n执行时长超过5分钟,已终止相关进程" ) } } }
如果使用其他通知工具(如企业微信、Slack),替换emailext为对应插件的执行步骤即可。
内容的提问来源于stack exchange,提问作者fr0zt
相关产品推荐
相关产品推荐

