jenkins的不同项目类型之外部任务项目

今天介绍一下jenkins的不同项目类型之外部任务项目

这种外部任务项目靠这个 External Monitor Job 插件来实现的。
External Monitor Job Type1.7
下面是jenkins wiki上对这种类型项目的一共描述。

Jenkins is useful for monitoring the non-interactive execution of processes, such as cron jobs, procmail, inetd-launched processes. Often those tasks are completely unmonitored (which makes it hard for you to notice when things go wrong), or they send e-mails constantly regardless of the success or failure (which results into the same situation as you’ll quickly start ignoring them anyway.) Using Jenkins enables you to monitor a large number of such tasks with little overhead.
Jenkins用于监视非交互式执行的进程,例如cron、procmail、inetd-launched启动的进程。通常,这些任务是完全不受监控的
(这使得你很难注意到什么时候出了问题),例如他们不停地发送电子邮件,而不管成功与否(这会导致同样的情况,然后你会很快就会开始忽略这些邮件)。
使用Jenkins可以让你以很少的开销监控大量这样的任务。

说的简单一点 就是 监控进程的执行的。 其实就是在你执行的命令前面 加上jenkins指定个一个命令,
把你执行的命令包装起来,这样你执行的命令的,例如输出就会同步的显示到 配置好的这个 外部任务项目 中来。
下面我们根据实际例子来理解一下。

创建项目

创建一个外部项目,如下图所示

在这里插入图片描述
和自由风格的项目比较起来,这里的配置项少了太多了,这个外部项目只有一个名字就行了。

在这里插入图片描述

监视执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
对  Debian / Ubuntu  系统而言

sudo apt-get install jenkins-external-job-monitor 需要安装这个。

# obviously you should replace localhost with a FQDN if you want to run jobs from other machines.

export JENKINS_HOME=http://@localhost:8080/ # 很显然,你需要替换localhost 为你的 jenkins地址
java -jar jenkins-core-*.jar "external-build-job-name" command-to-run
java -jar jenkins-core-*.jar "external-build-test" ls -l

"external-build-job-name" 和 "external-build-test" 就是你在jenkins上新建的 外部任务 项目的名称。

这个 jenkins-core-*.jar 文件,一般会在 /usr/share/jenkins/external-job-monitor/ 下面找到



$ export JENKINS_HOME=http://user:pw@myserver.acme.org/path/to/jenkins/
$ java -jar /path/to/WEB-INF/lib/jenkins-core-*.jar "job name" <program arg1 arg2...>

1
2
3
4
5
6
7
8
9
10
对Windows系统而言

> set JENKINS_HOME=http://user:pw@myserver.acme.org/path/to/jenkins/
> java -jar \path\to\WEB-INF\lib\jenkins-core-*.jar "job name" cmd.exe /c <program arg1 arg2...>

在windows上的git-bash中执行。target/tmp 目录是我的其中一共插件编译运行时候的目录,这目录下面正好有需要的jar包文件。
export JENKINS_HOME="http://localhost:8080/jenkins"
java -jar target/tmp/webapp/WEB-INF/lib/jenkins-core-2.222.3.jar -h
Usage: <job-name> <command> <args..>

在这里插入图片描述

关闭jenkins的 CSRF

在执行的时候发现 报错了,

1
2
3
4
5
6
7
8
9
10
11
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>Error 403 No valid crumb was included in the request</title>
</head>
<body><h2>HTTP ERROR 403</h2>
<p>Problem accessing /jenkins/job/test_external/postBuildResult. Reason:
<pre> No valid crumb was included in the request</pre></p><hr><a href="http://eclipse.org/jetty">Powered by Jetty:// 9.4.5.v20170502</a><hr/>

</body>
</html>

下面我来解决这个问题,在jenkins2上,这个没有 取消的 按钮了。在网上搜了一堆都是 旧版本jenkins的解决办法。根据官网描述,Jenkins版本自2.204.6以来的重大变更有:删除禁用 CSRF 保护的功能。 从较旧版本的 Jenkins 升级的实例将启用 CSRF 保护和设置默认的发行者,如果之前被禁用。

虽然删除了禁用csrf保护功能,增加了安全性,但是在一些结合Gitlab、Spinnaker等等工具进行持续集成过程中就增加了一些认证环节,若没有进行相关配置,得到的一定是403的报错。因为集成服务都是在内网操作,为删繁就简,笔者便考虑关闭 CSRF 保护功能,于是乎,对此展开了摸索。

在这里插入图片描述

下面是新版本jenkins上的解决办法,临时解决的。因为取消这个,估计会导致安全风险。在master节点执行groovy脚本,如下。
在这里插入图片描述

关闭之后就是下面这样了。

在这里插入图片描述

好的,我继续之前的命令

在这里插入图片描述

可以发现有个一个 #1 号 构建了,点进去,直接进入到了 console output, 显示的内容就是我们 命令行数的 ls 命令的输出了。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

1
2
3
4
5
6
7
8
9
10
你的web服务器会自动解压jenkins.war文件,你可以在WEB-INF/lib 目录下面找到如下jar包文件。
jenkins-core-*.jar
remoting-*.jar
ant-1.7.0.jar
commons-io-1.4jar
commons-lang-2.4.jar
jna-posix-*.jar
xstream-*.jar

这个 java -jar /path/to/jenkins-core-*.jar 会发现它依赖 的其他jar包文件的。

注意: 旧的jenkins版本 (1.324之前的) 还需要这个 winstone.jar 文件. 这个文件可以在顶层目录中找到,然后需要手动添加到classpath中, 可以使用java命令中的-classpath or -cp 选项。

The JENKINS_HOME variable is used to locate the server Jenkins is running, so this must be set.
这个 JENKINS_HOME 的环境变量是定位你的jenkins的,必须设置成你的jenkins的url地址,
如果需要账号密码, 你的url地址中可以带上 username:password@ 这个。

注意: 通过 username:password 认证登录是在 Jenkins 1.324 添加进去的
在这之前的版本你需要配置anonymous 匿名构建的权限,或者通过 curl命令发送post请求 XML 给 jenkins 来实现。

你可以复制 jenkins-core-*.jar 和其他 jar 文件 到 另外的机器上, 然后另外的机器上也就是可以执行了。这里说的是 其他机器可以采用复制 jar 文件的方式来安装。

在执行这个命令的 时候 标准输出和标准错误 会被记录,然后发送给 jenkin 上的 外部任务项目 上。
命令的返回 非0 值 会被设置为项目构建失败。

监视 cron

1
2
3
4

JENKINS_HOME=http://myserver.acme.org/path/to/jenkins/
0 * * * * export JENKINS_HOME=$JENKINS_HOME; java -jar jenkins-core-*.jar "backup" backup.sh 2>&1 > /dev/null

注意,你也可以把这里的 backup.sh 脚本的运行 放到 jenkins 上的 自由风格的项目中执行。

Submit a run programatically

通过将XML发送到HTTP提交执行及其结果。这意味着您可以从任何地方提交执行记录,只要遵循相同的XML格式。例如通过curl命令,通过python,java等等等 发送http请求。

xml内容格式如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<run>
<log encoding="hexBinary">...hex binary encoded console output...</log>
<result>... integer indicating the error code. 0 is success and everything else is failure</result>
<duration>... milliseconds it took to execute this run ...</duration>
<displayName>... The name to be displayed rather than the build number ...</displayName>
<description>... Description of the build ...</description>
</run>

<duration> 是可选的
从版本1.429开始, <displayName>. <description>也是可以选的,这3个没有顺序要求,但是必须要在<log > <result>后面. <log encoding="hexBinary">. 里面是 十六进制编码的二进制数据,你可以放任何字符,xml中不允许的字符也是可以放的,因为都转义了。

然后这个xml内容需要发送到 类似的 地址上: http://myhost/jenkins/job/_jobName_/postBuildResult.

下面给个简单例子:
$ curl -X POST -d '<run><log encoding="hexBinary">4142430A</log><result>0</result><duration>2000</duration></run>' \
http://user:pass@myhost/jenkins/job/_jobName_/postBuildResult

# 4142430A 是 ABC

Submit a run per CLI

最简单的方式通过 CLI、ssh 来提交 run 执行。把gzip压缩的log日志文件通过管道 pipe 传给命令。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
$ cat result.log.gz | ssh jenkins set-external-build-result --display 7d552c4ba_Linux_tb21 --job buildbot --result 1 -b --duration 42 --log -


这个例子很模糊,这里的 jenkins set-external-build-result 指的是什么呢?


https://github.com/mamh-java/external-monitor-job-plugin/blob/master/src/main/java/hudson/cli/SetExternalBuildResultCommand.java
@Extension
public class SetExternalBuildResultCommand extends CLICommand {

@Override
public String getShortDescription() {
return "Set external monitor job result.";
}

@Option(name="--job", aliases={"-j"}, metaVar="JOB", usage="Name of the external monitor job", required=true)
public transient TopLevelItem job;

@Option(name="--display", aliases={"-n"}, metaVar="DISPLAY", usage="Display name of the build", required=false)
public transient String displayName;

@Option(name="--result", aliases={"-r"}, metaVar="RESULT", usage="0: success, 1: fail", required=false)
public transient int result = 0;

@Option(name="--duration", aliases={"-d"}, metaVar="DURATION", usage="Number of milli-seconds it took to run this build", required=false)
public transient long duration = 0;

@Option(name="--log", aliases={"-l"}, metaVar="-|LOG", usage="Log to be set. '-' to read from stdin (gzipped).", required=true)
public String log;

@Option(name="--dump-build-number", aliases={"-b"}, usage="Log the produced build number to the standard output", required=false)
public boolean dumpBuildNumber;