Jenkins执行远程Shell命令时如何捕获错误文本并推送至Telegram
Jenkinsfile 中 executeOnServer 函数错误信息优化方案
问题根源在于原实现只捕获了退出码异常,没有收集远程命令执行的真实错误输出(比如Docker守护进程的报错内容),导致Telegram推送的消息缺少关键详情。以下是修改后的实现:
修改后的函数代码
private def executeOnServer(String serverCredentialId, String command) { def stdout = "" def stderr = "" try { // 使用sshCommand直接捕获标准输出和错误输出(推荐方式) def cmdResult = sshCommand( credentialsId: serverCredentialId, command: command, returnStdout: true, returnStderr: true, timeout: 120 // 超时时间,单位秒 ) stdout = cmdResult.stdout.trim() stderr = cmdResult.stderr.trim() // 检查命令退出码,非0则主动抛出异常 if (cmdResult.exitStatus != 0) { throw new Exception("命令执行退出码: ${cmdResult.exitStatus}") } } catch (Exception e) { // 整合完整错误信息 def errorMsg = """⚠️ 远程命令执行失败 --- 服务器凭据ID: ${serverCredentialId} 执行命令: `${command}` --- 异常原因: ${e.getMessage()} --- 错误输出详情: ${stderr ?: stdout ?: '无输出内容'}""" // 推送至Telegram telegramSend(message: errorMsg) // 重新抛出异常,保持流水线错误状态 throw e } }
关键优化点
- 改用sshCommand步骤:相比
sshPublisher,sshCommand可以直接获取命令的标准输出(stdout)和错误输出(stderr),无需从构建日志中模糊截取,能精准拿到真实错误内容。 - 主动检查退出码:即使命令执行过程中没抛出异常,只要退出码非0就主动触发异常,确保所有执行失败场景都能被捕获。
- 整合完整错误上下文:把服务器信息、执行的命令、异常原因、真实错误输出全部整合到推送消息中,方便快速定位问题。
- 保留流水线错误状态:重新抛出异常,避免掩盖错误,让Jenkins流水线能正确标记失败状态。
备选方案(若坚持用sshPublisher)
如果因为环境限制必须使用sshPublisher,可以通过截取构建日志的方式获取错误内容:
private def executeOnServer(String serverCredentialId, String command) { try { sshPublisher(publishers: [sshPublisherDesc( configName: serverCredentialId, transfers: [sshTransfer(execCommand: command, execTimeout: 120000)] )]) } catch (Exception e) { // 截取构建日志最后50行作为错误详情(可根据需求调整行数) def logContent = currentBuild.rawBuild.getLog(50).join('\n') def errorMsg = """⚠️ 远程命令执行失败 服务器凭据ID: ${serverCredentialId} 执行命令: `${command}` 异常信息: ${e.getMessage()} 日志详情: ${logContent}""" telegramSend(message: errorMsg) throw e } }
这种方式的缺点是日志可能包含其他无关内容,不如sshCommand精准。
内容的提问来源于stack exchange,提问作者RaiMX
相关产品推荐
相关产品推荐

