如何调度Jenkins Pipeline单次构建及延迟执行远程脚本检查任务
解决方案
1. 实现Jenkins Pipeline在特定日期时间运行一次
有两种常用方式实现一次性定时调度:
方式一:通过流水线配置页面设置一次性定时任务
在流水线的配置页面找到Build periodically选项,填写对应时间的cron表达式即可。例如要在2024年10月15日14:30运行一次,cron表达式为:
30 14 15 10 *
注意:Jenkins的cron表达式格式为
分 时 日 月 周,需确认Jenkins服务器的时区设置是否与预期一致。
方式二:在Pipeline脚本中添加一次性触发器
直接在流水线代码里通过triggers块定义一次性cron触发器,示例如下:
pipeline { agent any triggers { cron('30 14 15 10 *') // 2024-10-15 14:30 执行一次 } stages { stage('Execute Task') { steps { echo 'Running one-time scheduled task' } } } }
如果需要动态指定运行时间(比如从构建参数传入),可以通过字符串拼接生成cron表达式,注意格式必须严格符合分 时 日 月 周的规则。
2. 远程VM执行脚本+延迟轮询检查状态
针对远程VM无法访问Jenkins的场景,采用Jenkins主动SSH轮询的方案,分两个流水线实现:一个启动远程脚本,另一个负责定时检查状态并触发后续流程。
流水线1:启动远程后台脚本
该流水线通过SSH连接远程VM,将脚本后台运行并记录PID,随后触发检查流水线:
pipeline { agent any stages { stage('Start Remote Script') { steps { script { // 配置远程VM的SSH连接信息 def remoteConfig = [ name: 'Remote-Prod-VM', host: '192.168.1.100', user: 'ubuntu', identityFile: '/var/lib/jenkins/.ssh/id_rsa', allowAnyHosts: true ] // 后台运行脚本并记录PID sshCommand remote: remoteConfig, command: ''' # 创建临时目录存放PID和日志,避免权限冲突 mkdir -p /tmp/jenkins-task nohup /opt/scripts/your-script.sh > /tmp/jenkins-task/output.log 2>&1 & echo $! > /tmp/jenkins-task/script.pid ''' } } } stage('Trigger Check Pipeline') { steps { build job: 'Remote-Script-Status-Check', parameters: [ string(name: 'REMOTE_HOST', value: '192.168.1.100'), string(name: 'PID_FILE', value: '/tmp/jenkins-task/script.pid'), string(name: 'LOG_FILE', value: '/tmp/jenkins-task/output.log') ] } } } }
流水线2:延迟轮询检查状态
该流水线通过SSH检查远程进程状态,若未完成则延迟10分钟重新触发自身;若完成则拉取日志并触发后续流水线:
pipeline { agent any parameters { string(name: 'REMOTE_HOST', description: '远程VM的IP/主机名') string(name: 'PID_FILE', description: '远程VM上的PID文件路径') string(name: 'LOG_FILE', description: '远程VM上的日志文件路径') } options { timeout(time: 24, unit: 'HOURS') // 设置最大轮询时长,避免无限循环 } stages { stage('Check Script Status') { steps { script { def remoteConfig = [ name: 'Remote-Prod-VM', host: params.REMOTE_HOST, user: 'ubuntu', identityFile: '/var/lib/jenkins/.ssh/id_rsa', allowAnyHosts: true ] // 检查进程是否存活:返回0表示存活,非0表示已结束 def exitCode = sshCommand remote: remoteConfig, command: "ps -p \$(cat ${params.PID_FILE}) > /dev/null 2>&1; echo \$?" exitCode = exitCode.trim() if (exitCode == '0') { echo "远程脚本仍在运行,10分钟后再次检查" // 延迟10分钟(600秒)重新触发当前流水线 build job: env.JOB_NAME, parameters: [ string(name: 'REMOTE_HOST', value: params.REMOTE_HOST), string(name: 'PID_FILE', value: params.PID_FILE), string(name: 'LOG_FILE', value: params.LOG_FILE) ], wait: false, quietPeriod: 600 } else { echo "远程脚本执行完成,拉取输出日志" // 从远程VM拉取日志文件 sshGet remote: remoteConfig, from: params.LOG_FILE, into: 'script-output.log', override: true // 触发后续流水线,传递日志文件 build job: 'Post-Processing-Pipeline', parameters: [file(name: 'SCRIPT_LOG', value: 'script-output.log')] } } } } } }
关键注意事项
- 确保Jenkins服务器能通过SSH无密码访问远程VM(配置密钥对);
quietPeriod参数控制延迟触发的秒数,10分钟对应600秒;- 添加
timeout选项避免无限轮询,可根据实际需求调整超时时长; - 远程脚本的PID和日志文件建议存放在专属临时目录,避免与其他进程冲突。
内容的提问来源于stack exchange,提问作者Furkan Aksit
相关产品推荐
相关产品推荐

