远程触发构建后检查 Jenkins 作业状态
Check Jenkins job status after triggering a build remotely
我有一个脚本可以使用令牌远程触发 Jenkins 上的作业。这是我的脚本:
JENKINS_URL='http://jenkins.myserver.com/jenkins'
JOB_NAME='job/utilities/job/my_job'
JOB_TOKEN='my_token'
curl "${JENKINS_URL}/${JOB_NAME}/buildWithParameters?token=${JOB_TOKEN}"
在我 运行 之后,我得到以下响应:
* Hostname was NOT found in DNS cache
* Trying 10.5.187.225...
* Connected to jenkins.myserver.com (10.5.187.225) port 80 (#0)
> GET /jenkins/job/utilities/job/my_job/buildWithParameters?token=my_token HTTP/1.1
> User-Agent: curl/7.37.1
> Host: jenkins.myserver.com
> Accept: */*
>
< HTTP/1.1 201 Created
* Server nginx/1.6.2 is not blacklisted
< Server: nginx/1.6.2
< Date: Tue, 03 Feb 2015 23:40:47 GMT
< Content-Length: 0
< Location: http://jenkins.myserver.com/jenkins/queue/item/91/
< Connection: keep-alive
< Cache-Control: private
< Expires: Wed, 31 Dec 1969 16:00:00 PST
<
* Connection #0 to host jenkins.myserver.com left intact
我注意到 return 是 header 中的 queue url:http://jenkins.myserver.com/jenkins/queue/item/91。但是我不知道我应该如何使用这个 return url.
1) 我想知道是否有人知道如何查看我刚刚创建的作业的状态?
2) 由于上面的响应没有 return 作业 #,我不能真正使用这个 api 调用:
curl http://jenkins.myserver.com/jenkins/job/utilities/job/my_job/8/api/json
检查状态。那么我从上面的响应中得到locationurl后,哪里可以得到job name和job number呢?
谢谢
当您触发一个作业时,该作业将被放入队列中。实际构建仅在开始 运行 时创建,此时构建获得构建编号。如果您的所有执行者都很忙,有时可能需要很长时间才能创建并启动构建 运行。
触发作业时获取内部版本号的唯一方法是使用 Jenkins CLI 的 "build" 命令。如果您使用 -w 选项,该命令将不会 return 直到构建开始,然后它会打印 "Started build #N"
你其实不需要javacli.jar,一个ssh客户端就够了。参见 https://wiki.jenkins-ci.org/display/JENKINS/Jenkins+SSH
除此之外没有已知的解决方案。您也许能够搜索构建并找到一个在您触发作业时触发的构建,但这需要大量工作。
我遇到了类似的问题,只能通过休息 api 获取状态。
这是我的解决方案(这是一个弱且不稳定的解决方案!):
#Ex. http://jenkins.com/job/test
JOB_URL="${JENKINS_URL}/job/${JOB_NAME}"
#here you can ask for next build job number
function getNextBuildNr(){
curl --silent ${JOB_URL}/api/json | grep -Po '"nextBuildNumber":\K\d+'
}
# this will request the Status of job
function getBuildState(){
buildNr=
curl --silent ${JOB_URL}/${buildNr}/api/json | grep -Po '"result":\s*"\K\w+'
}
#this will wait for your Job state, by polling Jenkins every second
function waitForJob() {
buildNr=
state=""
while [ "${state}" == "" ]
do
sleep 1
state=$(getBuildState ${buildNr})
echo -n '.'
done
echo -e "\n"
}
#now you can run and build
BUILD_NR=$(getNextBuildNr)
# input here your code/function to trigger the job
waitForJob ${BUILD_NR}
BUILD_STATE=$(getBuildState ${BUILD_NR})
echo "$BUILD_STATE"
我使用 Jenkins 服务器的轮询解决了这个问题。当远程启动作业时,return header 拥有作业 queue URL。使用这个可以进行更多 API 次调用以获取状态。
步骤:
- 开始作业
- 解析return'Location'header
- 轮询 queue 寻找工作开始
- 工作 queue 条目将在其 json 或 xml 中有一个 'executable' 条目,一旦它开始
- 轮询作业状态等待结果
我使用 python 和 Requests 模块来做到这一点
#!/usr/bin/python
import requests
import re
import sys
import json
import time
# secs for polling Jenkins API
#
QUEUE_POLL_INTERVAL = 2
JOB_POLL_INTERVAL = 20
OVERALL_TIMEOUT = 3600 # 1 hour
# job specifics: should be passed in
auth_token = 'buildmaster:173223588624f980c3AAA68d4d8efe0c'
jenkins_uri = '192.168.115.187:8080'
job_name = 'rf_systest'
build_token = 'rf_systest_auth_token'
# start the build
#
start_build_url = 'http://{}@{}/job/{}/build?token={}'.format(
auth_token, jenkins_uri, job_name, build_token)
r = requests.post(start_build_url)
# from return headers get job queue location
#
m = re.match(r"http.+(queue.+)\/", r.headers['Location'])
if not m:
# To Do: handle error
print "Job starte request did not have queue location"
sys.exit(1)
# poll the queue looking for job to start
#
queue_id = m.group(1)
job_info_url = 'http://{}@{}/{}/api/json'.format(auth_token, jenkins_uri, queue_id)
elasped_time = 0
print '{} Job {} added to queue: {}'.format(time.ctime(), job_name, job_info_url)
while True:
l = requests.get(job_info_url)
jqe = l.json()
task = jqe['task']['name']
try:
job_id = jqe['executable']['number']
break
except:
#print "no job ID yet for build: {}".format(task)
time.sleep(QUEUE_POLL_INTERVAL)
elasped_time += QUEUE_POLL_INTERVAL
if (elasped_time % (QUEUE_POLL_INTERVAL * 10)) == 0:
print "{}: Job {} not started yet from {}".format(time.ctime(), job_name, queue_id)
# poll job status waiting for a result
#
job_url = 'http://{}@{}/job/{}/{}/api/json'.format(auth_token, jenkins_uri, job_name, job_id)
start_epoch = int(time.time())
while True:
print "{}: Job started URL: {}".format(time.ctime(), job_url)
j = requests.get(job_url)
jje = j.json()
result = jje['result']
if result == 'SUCCESS':
# Do success steps
print "{}: Job: {} Status: {}".format(time.ctime(), job_name, result)
break
elif result == 'FAILURE':
# Do failure steps
print "{}: Job: {} Status: {}".format(time.ctime(), job_name, result)
break
elif result == 'ABORTED':
# Do aborted steps
print "{}: Job: {} Status: {}".format(time.ctime(), job_name, result)
break
else:
print "{}: Job: {} Status: {}. Polling again in {} secs".format(
time.ctime(), job_name, result, JOB_POLL_INTERVAL)
cur_epoch = int(time.time())
if (cur_epoch - start_epoch) > OVERALL_TIMEOUT:
print "{}: No status before timeout of {} secs".format(OVERALL_TIMEOUT)
sys.exit(1)
time.sleep(JOB_POLL_INTERVAL)
输出:
Tue Jan 30 16:24:08 2018: Job rf_systest added to queue: http://buildmaster:173223588624f980c344668d4d8efe0c@192.168.115.187:8080/queue/item/164/api/json
Tue Jan 30 16:24:39 2018: Job rf_systest not started yet from queue/item/164
Tue Jan 30 16:25:00 2018: Job started URL: http://buildmaster:173223588624f980c344668d4d8efe0c@192.168.115.187:8080/job/rf_systest/79/api/json
Tue Jan 30 16:25:01 2018: Job: rf_systest Status: None. Polling again in 20 secs
Tue Jan 30 16:25:21 2018: Job started URL: http://buildmaster:173223588624f980c344668d4d8efe0c@192.168.115.187:8080/job/rf_systest/79/api/json
Tue Jan 30 16:25:21 2018: Job: rf_systest Status: None. Polling again in 20 secs
Tue Jan 30 16:25:41 2018: Job started URL: http://buildmaster:173223588624f980c344668d4d8efe0c@192.168.115.187:8080/job/rf_systest/79/api/json
Tue Jan 30 16:25:41 2018: Job: rf_systest Status: None. Polling again in 20 secs
Tue Jan 30 16:26:01 2018: Job started URL: http://buildmaster:173223588624f980c344668d4d8efe0c@192.168.115.187:8080/job/rf_systest/79/api/json
Tue Jan 30 16:26:01 2018: Job: rf_systest Status: None. Polling again in 20 secs
Tue Jan 30 16:26:21 2018: Job started URL: http://buildmaster:173223588624f980c344668d4d8efe0c@192.168.115.187:8080/job/rf_systest/79/api/json
Tue Jan 30 16:26:21 2018: Job: rf_systest Status: SUCCESS
JSON 来自 Jenkins queue 一旦它的工作开始:
{
"_class": "hudson.model.Queue$LeftItem",
"actions": [
{
"_class": "hudson.model.CauseAction",
"causes": [
{
"_class": "hudson.model.Cause$RemoteCause",
"addr": "10.20.30.60",
"note": null,
"shortDescription": "Started by remote host 10.20.30.60"
}
]
}
],
"blocked": false,
"buildable": false,
"cancelled": false,
"executable": {
"_class": "org.jenkinsci.plugins.workflow.job.WorkflowRun",
"number": 45,
"url": "http://192.168.115.187:8080/job/rf_systest/45/"
},
"id": 95,
"inQueueSince": 1517342648136,
"params": "",
"stuck": false,
"task": {
"_class": "org.jenkinsci.plugins.workflow.job.WorkflowJob",
"color": "blue_anime",
"name": "rf_systest",
"url": "http://192.168.115.187:8080/job/rf_systest/"
},
"url": "queue/item/95/",
"why": null
}
您可以为此使用 Jenkins API。 Python 脚本示例:
import json
import requests
import time
job_name = "testjob" . #Give your job name here
def jenkins_job_status(job_name):
try:
url = "https://your_jenkins_endpoint/job/%s/lastBuild/api/json" %job_name #Replace 'your_jenkins_endpoint' with your Jenkins URL
while True:
data = requests.get(url).json()
if data['building']:
time.sleep(60)
else:
if data['result'] == "SUCCESS":
print "Job is success"
return True
else:
print "Job status failed"
return False
except Exception as e:
print str(e)
return False
if __name__ == "__main__":
if jenkins_job_status(job_name):
print "Put your autmation here for 'job is success' condition"
else:
print "Put your autmation here for 'job is failed' condition"
完全 groovy 启用的解决方案如下所示:
import groovy.json.JsonSlurper
while(true){
sh """
curl -X POST -u "admin:xxx" "https://another-jenkins.com/job/jobName/build"
"""
def response = sh(script: """ curl -X GET -u "admin:xxx" "https://another-jenkins.com/job/jobName/lastBuild/api/json" """, returnStdout: true)
def jsonSlurper = new JsonSlurper()
def obj = jsonSlurper.parseText(response)
if (!obj.building){
if(obj.result=="FAILURE"){
println("remote jenkins failing")
//throw new Exception("QA JENKINS returns failure.")
}
break;
}
sleep(3000)
}
对于那些需要从另一个 Jenkins 触发远程 Jenkins 作业的人来说,这里有一个非常好的解决方案,可以触发远程作业并检查其状态:https://github.com/jenkinsci/parameterized-remote-trigger-plugin/blob/master/README_PipelineConfiguration.md
就这么简单:
def handle = triggerRemoteJob job: 'https://myjenkins:8080/job/JobWithoutParams', auth: TokenAuth(apiToken: '<theApiToken>', userName: '<userName>'), parameters: 'param1=abc\nparam2=xyz'
我有一个脚本可以使用令牌远程触发 Jenkins 上的作业。这是我的脚本:
JENKINS_URL='http://jenkins.myserver.com/jenkins'
JOB_NAME='job/utilities/job/my_job'
JOB_TOKEN='my_token'
curl "${JENKINS_URL}/${JOB_NAME}/buildWithParameters?token=${JOB_TOKEN}"
在我 运行 之后,我得到以下响应:
* Hostname was NOT found in DNS cache
* Trying 10.5.187.225...
* Connected to jenkins.myserver.com (10.5.187.225) port 80 (#0)
> GET /jenkins/job/utilities/job/my_job/buildWithParameters?token=my_token HTTP/1.1
> User-Agent: curl/7.37.1
> Host: jenkins.myserver.com
> Accept: */*
>
< HTTP/1.1 201 Created
* Server nginx/1.6.2 is not blacklisted
< Server: nginx/1.6.2
< Date: Tue, 03 Feb 2015 23:40:47 GMT
< Content-Length: 0
< Location: http://jenkins.myserver.com/jenkins/queue/item/91/
< Connection: keep-alive
< Cache-Control: private
< Expires: Wed, 31 Dec 1969 16:00:00 PST
<
* Connection #0 to host jenkins.myserver.com left intact
我注意到 return 是 header 中的 queue url:http://jenkins.myserver.com/jenkins/queue/item/91。但是我不知道我应该如何使用这个 return url.
1) 我想知道是否有人知道如何查看我刚刚创建的作业的状态?
2) 由于上面的响应没有 return 作业 #,我不能真正使用这个 api 调用:
curl http://jenkins.myserver.com/jenkins/job/utilities/job/my_job/8/api/json
检查状态。那么我从上面的响应中得到locationurl后,哪里可以得到job name和job number呢?
谢谢
当您触发一个作业时,该作业将被放入队列中。实际构建仅在开始 运行 时创建,此时构建获得构建编号。如果您的所有执行者都很忙,有时可能需要很长时间才能创建并启动构建 运行。
触发作业时获取内部版本号的唯一方法是使用 Jenkins CLI 的 "build" 命令。如果您使用 -w 选项,该命令将不会 return 直到构建开始,然后它会打印 "Started build #N"
你其实不需要javacli.jar,一个ssh客户端就够了。参见 https://wiki.jenkins-ci.org/display/JENKINS/Jenkins+SSH
除此之外没有已知的解决方案。您也许能够搜索构建并找到一个在您触发作业时触发的构建,但这需要大量工作。
我遇到了类似的问题,只能通过休息 api 获取状态。
这是我的解决方案(这是一个弱且不稳定的解决方案!):
#Ex. http://jenkins.com/job/test
JOB_URL="${JENKINS_URL}/job/${JOB_NAME}"
#here you can ask for next build job number
function getNextBuildNr(){
curl --silent ${JOB_URL}/api/json | grep -Po '"nextBuildNumber":\K\d+'
}
# this will request the Status of job
function getBuildState(){
buildNr=
curl --silent ${JOB_URL}/${buildNr}/api/json | grep -Po '"result":\s*"\K\w+'
}
#this will wait for your Job state, by polling Jenkins every second
function waitForJob() {
buildNr=
state=""
while [ "${state}" == "" ]
do
sleep 1
state=$(getBuildState ${buildNr})
echo -n '.'
done
echo -e "\n"
}
#now you can run and build
BUILD_NR=$(getNextBuildNr)
# input here your code/function to trigger the job
waitForJob ${BUILD_NR}
BUILD_STATE=$(getBuildState ${BUILD_NR})
echo "$BUILD_STATE"
我使用 Jenkins 服务器的轮询解决了这个问题。当远程启动作业时,return header 拥有作业 queue URL。使用这个可以进行更多 API 次调用以获取状态。
步骤:
- 开始作业
- 解析return'Location'header
- 轮询 queue 寻找工作开始
- 工作 queue 条目将在其 json 或 xml 中有一个 'executable' 条目,一旦它开始
- 轮询作业状态等待结果
我使用 python 和 Requests 模块来做到这一点
#!/usr/bin/python
import requests
import re
import sys
import json
import time
# secs for polling Jenkins API
#
QUEUE_POLL_INTERVAL = 2
JOB_POLL_INTERVAL = 20
OVERALL_TIMEOUT = 3600 # 1 hour
# job specifics: should be passed in
auth_token = 'buildmaster:173223588624f980c3AAA68d4d8efe0c'
jenkins_uri = '192.168.115.187:8080'
job_name = 'rf_systest'
build_token = 'rf_systest_auth_token'
# start the build
#
start_build_url = 'http://{}@{}/job/{}/build?token={}'.format(
auth_token, jenkins_uri, job_name, build_token)
r = requests.post(start_build_url)
# from return headers get job queue location
#
m = re.match(r"http.+(queue.+)\/", r.headers['Location'])
if not m:
# To Do: handle error
print "Job starte request did not have queue location"
sys.exit(1)
# poll the queue looking for job to start
#
queue_id = m.group(1)
job_info_url = 'http://{}@{}/{}/api/json'.format(auth_token, jenkins_uri, queue_id)
elasped_time = 0
print '{} Job {} added to queue: {}'.format(time.ctime(), job_name, job_info_url)
while True:
l = requests.get(job_info_url)
jqe = l.json()
task = jqe['task']['name']
try:
job_id = jqe['executable']['number']
break
except:
#print "no job ID yet for build: {}".format(task)
time.sleep(QUEUE_POLL_INTERVAL)
elasped_time += QUEUE_POLL_INTERVAL
if (elasped_time % (QUEUE_POLL_INTERVAL * 10)) == 0:
print "{}: Job {} not started yet from {}".format(time.ctime(), job_name, queue_id)
# poll job status waiting for a result
#
job_url = 'http://{}@{}/job/{}/{}/api/json'.format(auth_token, jenkins_uri, job_name, job_id)
start_epoch = int(time.time())
while True:
print "{}: Job started URL: {}".format(time.ctime(), job_url)
j = requests.get(job_url)
jje = j.json()
result = jje['result']
if result == 'SUCCESS':
# Do success steps
print "{}: Job: {} Status: {}".format(time.ctime(), job_name, result)
break
elif result == 'FAILURE':
# Do failure steps
print "{}: Job: {} Status: {}".format(time.ctime(), job_name, result)
break
elif result == 'ABORTED':
# Do aborted steps
print "{}: Job: {} Status: {}".format(time.ctime(), job_name, result)
break
else:
print "{}: Job: {} Status: {}. Polling again in {} secs".format(
time.ctime(), job_name, result, JOB_POLL_INTERVAL)
cur_epoch = int(time.time())
if (cur_epoch - start_epoch) > OVERALL_TIMEOUT:
print "{}: No status before timeout of {} secs".format(OVERALL_TIMEOUT)
sys.exit(1)
time.sleep(JOB_POLL_INTERVAL)
输出:
Tue Jan 30 16:24:08 2018: Job rf_systest added to queue: http://buildmaster:173223588624f980c344668d4d8efe0c@192.168.115.187:8080/queue/item/164/api/json
Tue Jan 30 16:24:39 2018: Job rf_systest not started yet from queue/item/164
Tue Jan 30 16:25:00 2018: Job started URL: http://buildmaster:173223588624f980c344668d4d8efe0c@192.168.115.187:8080/job/rf_systest/79/api/json
Tue Jan 30 16:25:01 2018: Job: rf_systest Status: None. Polling again in 20 secs
Tue Jan 30 16:25:21 2018: Job started URL: http://buildmaster:173223588624f980c344668d4d8efe0c@192.168.115.187:8080/job/rf_systest/79/api/json
Tue Jan 30 16:25:21 2018: Job: rf_systest Status: None. Polling again in 20 secs
Tue Jan 30 16:25:41 2018: Job started URL: http://buildmaster:173223588624f980c344668d4d8efe0c@192.168.115.187:8080/job/rf_systest/79/api/json
Tue Jan 30 16:25:41 2018: Job: rf_systest Status: None. Polling again in 20 secs
Tue Jan 30 16:26:01 2018: Job started URL: http://buildmaster:173223588624f980c344668d4d8efe0c@192.168.115.187:8080/job/rf_systest/79/api/json
Tue Jan 30 16:26:01 2018: Job: rf_systest Status: None. Polling again in 20 secs
Tue Jan 30 16:26:21 2018: Job started URL: http://buildmaster:173223588624f980c344668d4d8efe0c@192.168.115.187:8080/job/rf_systest/79/api/json
Tue Jan 30 16:26:21 2018: Job: rf_systest Status: SUCCESS
JSON 来自 Jenkins queue 一旦它的工作开始:
{
"_class": "hudson.model.Queue$LeftItem",
"actions": [
{
"_class": "hudson.model.CauseAction",
"causes": [
{
"_class": "hudson.model.Cause$RemoteCause",
"addr": "10.20.30.60",
"note": null,
"shortDescription": "Started by remote host 10.20.30.60"
}
]
}
],
"blocked": false,
"buildable": false,
"cancelled": false,
"executable": {
"_class": "org.jenkinsci.plugins.workflow.job.WorkflowRun",
"number": 45,
"url": "http://192.168.115.187:8080/job/rf_systest/45/"
},
"id": 95,
"inQueueSince": 1517342648136,
"params": "",
"stuck": false,
"task": {
"_class": "org.jenkinsci.plugins.workflow.job.WorkflowJob",
"color": "blue_anime",
"name": "rf_systest",
"url": "http://192.168.115.187:8080/job/rf_systest/"
},
"url": "queue/item/95/",
"why": null
}
您可以为此使用 Jenkins API。 Python 脚本示例:
import json
import requests
import time
job_name = "testjob" . #Give your job name here
def jenkins_job_status(job_name):
try:
url = "https://your_jenkins_endpoint/job/%s/lastBuild/api/json" %job_name #Replace 'your_jenkins_endpoint' with your Jenkins URL
while True:
data = requests.get(url).json()
if data['building']:
time.sleep(60)
else:
if data['result'] == "SUCCESS":
print "Job is success"
return True
else:
print "Job status failed"
return False
except Exception as e:
print str(e)
return False
if __name__ == "__main__":
if jenkins_job_status(job_name):
print "Put your autmation here for 'job is success' condition"
else:
print "Put your autmation here for 'job is failed' condition"
完全 groovy 启用的解决方案如下所示:
import groovy.json.JsonSlurper
while(true){
sh """
curl -X POST -u "admin:xxx" "https://another-jenkins.com/job/jobName/build"
"""
def response = sh(script: """ curl -X GET -u "admin:xxx" "https://another-jenkins.com/job/jobName/lastBuild/api/json" """, returnStdout: true)
def jsonSlurper = new JsonSlurper()
def obj = jsonSlurper.parseText(response)
if (!obj.building){
if(obj.result=="FAILURE"){
println("remote jenkins failing")
//throw new Exception("QA JENKINS returns failure.")
}
break;
}
sleep(3000)
}
对于那些需要从另一个 Jenkins 触发远程 Jenkins 作业的人来说,这里有一个非常好的解决方案,可以触发远程作业并检查其状态:https://github.com/jenkinsci/parameterized-remote-trigger-plugin/blob/master/README_PipelineConfiguration.md
就这么简单:
def handle = triggerRemoteJob job: 'https://myjenkins:8080/job/JobWithoutParams', auth: TokenAuth(apiToken: '<theApiToken>', userName: '<userName>'), parameters: 'param1=abc\nparam2=xyz'