Jenkins Solutions
Final Target to this solutionsSCM: Git/SVN/GitHubStatic Anlyst: SonarBuild: Jenkins/MavenUnit Test: JunitDeployment: Jenkins/KVM(Howto Rollback)Accept Test: Cu
SCM:
Static Anlyst:
Build:
Unit Test:
Deployment:
Accept Test:
Scenario1
------------------------
Step1:
jekins+maven+svn/gitHub+junit ->Windows
Step2:
Implementation based on rhel
Step3:
plugins
Step4:
Implementation based on ubuntu
以下参考均为网络文章,出处如下,蓝色字体为亲历亲为
http://blog.csdn.net/onlyqi
==========================================================
Jekins
----------------------------------------------------------------------------------------------------
Jenkins是一个CI工具。它可以持续编译,运行你的代码;运行UT或集成测试;将运行结果发送至邮件,或展示成报告。。。
这样做的最终目的是:
让项目保持健康的状态。如果任何checkin break了build,每个人都会在最短的时间内通知到,然后问题被fix。接下来的开发将建立在一个健康正确的基础上,而不是任由问题累积,最后失控。
最后,你的项目随时可以被deliver给用户,因为,你的项目每一天都在健康,茁壮的生长。这就是CI的意义所在。
Jenkin和cruisecontrol
Jenkins和cruisecontrol都是CI工具,二者在CI中发挥的作用完全一致。
而Jenkins作为新一代的CI工具,渐渐开始取代cruisecontrol。二者都是java程序,但:
1,Jenkins提供更为友好的用户界面,而cruisecontrol在界面方面糟糕的几乎等于没有。
2,Jenkins内置的功能提供了极大的便利,不论是新建一个build,还是日常使用,你需要做的大部分时候仅仅是在用户界面上点击而已。
在cruisecontrol新建build是通过创建config.xml来完成的。它仅仅提供非常有限的功能,很多时候你会发现,需要自己完成很多工作。
3,Jenkins作为一个欣欣向荣的开源项目,有大批的plugin。当你发现需要一个Jenkins本身并不提供的功能是,搜索一下plugin,总会有收获。非常多的流行工具如JBehave,cobertura都提供jenkins插件。
而针对cruisecontrol的plugin却很少。
4,Jenkins友好的用户界面让学习成本很少,你可以在最短的时间内开始你的工作。
事实上,Jenkins是我见过的最好的开源项目之一,它简洁实用的用户界面设计,完善的文档,丰富的插件。当你开始使用它,你就会爱上它。
当你需要一个build工具时,Jenkins几乎是当下的不二选择。
Jenkins和Hudson
Jenkins起源于Hudson。Hudson在商业软件的路上继续前行,而Jenkins则作为开源软件,从hudson分支出来。
因此现在的jenkins和hudson非常类似,但是随着二者各自的发展,已经有了一些不同。
要想更多的了解Jenkins,当然最好是访问它的官方网站。也可以参考我的下一篇文章:
Jenkins(二)
至少和官网比起来,它是中文的~
官网:https://wiki.jenkins-ci.org/display/JENKINS/Meet+Jenkins
我的这篇文章仅仅是简单的根据上文,介绍Jenkins提供了哪些功能。具体大家还是要自己学习啦~
官网首页就提供了windows版本的Jenkins安装包。我们可以下载一个用于学习。安装后自动打开http://localhost:8080,你就能看见Jenkins的界面了。
其他也需要安装的是:
1,Jenkins是java程序,因此需要安装JDK。
2,同时运行job需要提供repository,也就是存放Jenkins定期poll源代码的地方。我们可以去github免费注册一个。
3,如果想在Jenkins中使用ant,maven等,则还需要单独安装。但不是必须的。
启动Jenkins
Jenkins天生支持unix-like system。
- 直接运行
好吧,Jenkins是一个java程序,所以要运行它,只需要:
$ java -jar jenkins.war
我们也可以使用nohup命令,让Jenkins在后台运行。
之后打开URL http://myServer:8080 就可以方便的操作Jenkins了
官网给了一个sh的例子,用于启动Jenkins。可以参考一下。
- 在Servlet container中运行
Alternatively, if you have a servlet container that supports Servlet 2.4/JSP 2.0, such as Glassfish v2, Tomcat 5 (or any later versions), then you can run them as services, and deployjenkins.war as you would any other war file.
For example,
you could simply place the jenkins.war file in Tomcat’s webapps directory.
http://localhost:8080/jenkins
同时Jenkins提供一些默认不会启动的特殊的功能,参考下面的link来enable它们。
https://wiki.jenkins-ci.org/display/JENKINS/Features+controlled+by+system+properties
Jenkins的目录结构
和CruiseControler一样,Jenkins需要一个目录来存储相关文件:JENKINS_HOME。默认为 ~/.jenkins。即为user的home目录下的一个隐藏目录。我们也可以更改JENKINS_HOME,指向我们希望的地方。
(注意因为是隐藏目录,所以需要使用ls -al 才能看到)
JENKINS_HOME
如果有权限管理,则在HOME目录下还会有users目录。
从目录结构来看,和CruiseController非常相似。其中config.xml是Jenkins重要的配置文件。我们都知道Jenkins用于monitor多个build,而jobs这个目录无疑就是存储每个build相关信息的地方。
总的来说,Jenkins目录结构非常直白,简洁。
备份和恢复
备份和恢复非常简单,就是简单的copy Jenkins的目录就好了:
All the settings, build logs, artifact archives are stored under the JENKINS_HOME directory. Simply archive this directory to make a back up. Similarly, restoring the data is just replacing the contents of the JENKINS_HOME directory from a back up.
移动/拷贝/重命名 job
由于每个jobs都有自己单独的目录,我们可以很容易的:
修改后执行下面的命令刷新:
http://[jenkins-server]/[command]
在这里[command]可以是:exit 退出,restart 重启, reload 重载。
创建一个Project
因为Jenkins可以用于运行各种CI,测试,批处理任务等等,所以在Jenkins中将这些任务统称为“free-style software project”.
Jenkins也提供了其他类型的jobs,例如:
1,如果项目是Maven,Jenkins还提供了一种仅用于Maven Project的job。但其实free-style software projec仍然可以用于创建Maven项目,只不过这种更适合Maven项目,结合的更好而已。
2,也可以创建一个"Monitor an external job“用于监控外部进程。
3,或者一个Matrix project,也就是multi-configuration project。
我不确定是否仅有这4种job,也许使用插件可以创建更多类型的job,大家自己看资料吧。
下面是如何创建一个最常见的“free-style software project"的过程:
Go to Jenkins top page, select "New Job", then choose "Build a free-style software project". This job type consists of the following elements:
- optional SCM, such as CVS or Subversion where your source code resides. 指定源代码在哪。
Note: In software engineering, software configuration management (SCM) is the task of tracking and controlling changes in the software.
- optional triggers to control when Jenkins will perform builds. 指定Jenkins何时触发一次build。
- some sort of build script that performs the build (ant, maven, shell script, batch file, etc.) where the real work happens 触发build时,使用的脚本文件,例如ant。在这个脚本文件中,我们可以从svn下载最新代码,删除上次build的临时文件,创建必要目录,编译源 代码,运行,打包等一系列工作。
- optional steps to collect information out of the build, such as archiving the artifacts and/or recording javadoc and test results. 收集log信息。
- optional steps to notify other people/systems with the build result, such as sending e-mails, IMs, updating issue tracker, etc. 通知相关人员build的结果。
例如我们使用的build script就是ant,在Jenkins中运行ant。在脚本文件中,可以直接使用Jenkins提供的一些变量。
同时,每个job可以有多个step。例如:将运行程序定义为step1,运行单元测试定义为step2,生成coverage报告定义为step3。
同时还可以定义post-build action。例如:生成javadoc,或清理程序运行的临时文件目录等。
自动运行Build
触发一个build有三种方式:
- Builds in Jenkins can be triggered periodically (on a schedule, specified in configuration) 这里定义schedule的语法是unix常见的cron语法。
- Or when source changes in the project have been detected
可以设置Jenkins定时检查SVN是否发生了变化,也可以手动检查:http://YOURHOST /jenkins/job/PROJECTNAME/pollong。也可以设置Jenkins为post-commit,这个方式尤其适用于那些检查是 否代码改变会花费很长时间的情况。
- Or they can be automatically triggered by requesting the URL:
http://YOURHOST/jenkins/job/PROJECTNAME/build
Distributed builds
Jenkins supports the "master/slave" mode, where the workload of building projects are delegated to multiple "slave" nodes, allowing single Jenkins installation to host a large number of projects, or provide different environments needed for builds/tests.
在现实中需要使用distributed builds情况很多,例如:一个web application的build,需要分别验证firefox和IE的行为,那么就需要到windows机器上运行IE。
或因为性能问题,将build分布到多个slave节点去。
到Jenkins的管理界面,就可以方便的添加节点。配置节点时,需要提供节点所在的机器,登陆用户名密码,使用的目录等。
但是slave并不需要再安装Jenkins。jenkins会自动启用slave agent,将build需要tools考到远程机器上。
需要注意的是:the build results and artifacts will always end up on the master server. 因此不需要跑到各个节点去查看build产生的文件,log等。
其实在slave节点,会创建一个本地的workspace,并在运行时使用这个workspace。因为毕竟build运行在slave节点上,所以这个节点肯定要有运行build需要的所有因素。
总之添加节点并远程运行build真是太方便了~
添加节点后,在master Jenkins home目录下会出现关于该节点的配置文件。
Jenkins将自动决定在哪个节点上运行build,根据下列策略:
Some slaves are faster, while others are slow. Some slaves are closer (network wise) to a master, others are far away. So doing a good build distribution is a challenge. Currently, Jenkins employs the following strategy:
- If a project is configured to stick to one computer, that's always honored.
- Jenkins tries to build a project on the same computer that it was previously built.
- Jenkins tries to move long builds to slaves, because the amount of network interaction between a master and a slave tends to be logarithmic to the duration of a build (IOW, even if project A takes twice as long to build as project B, it won't require double network transfer.) So this strategy reduces the network overhead.
Jenkins通过运行slave agents来完成分布式build。最常见的情况是:slave agent运行在各个slave 节点。master通过SSH远程启动/停止slave agent,进而控制各个节点的行为。
一共有下列4种方式启动slave agent:
•The master starts the slave agents via ssh
• Starting the slave agent manually using Java Web Start
• Installing the slave agent as a Window service
• Starting the slave agent directly from the command line on the slave machine from the command line
需要注意的是这4种方式适用于不同的情况,例如slave节点在防火墙后,导致master无法通过SSH启停slave agent。此时只能用后三种方式,但是往往有一些弊端,比如master无法自动停止/重启 slave agent.
一旦添加node成功,你就可以在job中指定这个job在哪个node运行:
Restrict where this project can be run (如果不指定则由Jenkins自行决定,即可以在slave节点运行,也可以在master节点运行,甚至在一次build中就可以自行来回切换)。
配置Jenkins,让它收集更多的log
https://wiki.jenkins-ci.org/display/JENKINS/Logging
我想这对于初学Jenkins的人,用来判断问题所在太有用了。
在流行持续集成的今天,我们在各个环境:alpha,beta和production 都部署了唯一的Jenkins服务器。
Jenkins服务器统一负责该环境内所有组件的持续集成。也就是说,一个Jenkins服务器会有很多个build。所以有时会用到上面提到的”Monitor an external job“。
但不是Distributed Builds。
同时由于Jenkins会进入每个环境,包括production,因此会使用auto deployment的方式,自动完成Jenkins在各个环境的部署。
用户管理
毫无疑问Jenkins中需要有用户管理的功能,因为除开发人员外,有多种角色的人需要查看build的结果。
在Jenkins中的系统管理中,可以设置“任何用户可以做任何事” 或 “登录用户可以做任何事”。
因此前一个选项意味着,任何浏览JenkinsURL的用户都可以修改Jenkins。或只有登录用户才能做修改。
所以我把Jenkins中的用户划分为两类:可登录用户和不可登录用户。
1,只要是修改过repository,即对build产生过影响的用户,都会被Jenkins记录在本地的database中。这类用户我们可以在Jenkins界面->查看用户中浏览。
但这类用户不是正式的Jenkins用户,也不能登录Jenkins。这类用户的权限由上面说的系统管理中的配置决定。通常只有查看build的权限,没有修改权限。
2,只有在Jenkins中明确注册的用户,才能够登录Jenkins,并且有权限控制。同时注册过的用户,在 JENKINS_HOME目录下的users目录下,都有一个单独的目录来存储相关信息。我不太清楚是否能够通过copy/paste将用户部署到其他地 方去,回头测试一下。
既然要满足各种人对jenkins使用的各种需求,因此权限管理远没有这么简单。具体大家还得自己去看啊~
Jenkins Script Console
Jenkins提供了一个script console
也可以通过URL直接访问:http://myserver:8080/hudson/script
可惜只能用Groovy 反证我不懂。在使用Jenkins的过程中,当然也会遇到一些问题。在这里我把我遇到的,比较奇怪的问题列出来,供大家参考。
环境变量
我在一个slave node上运行job时发现,被启动的程序显示找不到环境变量。
原来,当Jenkins在slave上启动一次build时,不会应用当前用户的profile。因此我们得自己解决这个问题。
解决方式有很多:
1,在创建slave node时,可以指定要传递的环境变量。这种方法不好的地方就是,相当于hard code,当实际的环境变量改变时,也需要手工修改slave node的配置。
2,想办法自己应用:运行shell前运行:. /usr/usr_account/.profile (注意第一个点后面有空格),这个是最好的方法,因为所有的环境变量都会生效,而不是仅仅某一个。
或者在调用的ant中,或ksh script中指定某个具体的环境变量。
进程被kill
需求是这样的:在Jenkins中一个job运行完毕时,可以配置它触发下一个job运行。这种情况很常见,例如一个 job中启动一个程序并运行了UT,当运行完毕时,我们可能会希望一个集成测试的job被触发。这里隐含的意思就是,我们希望程序能一直运行,直到所有的 测试结束,最后再显式的停止这个程序。
然而在实施的过程中,我遇到了一个大问题:在第一个job运行结束后,程序就被杀掉了。第二个job没有运行测试的时间。
来看看这个人遇到的类似的问题:
I am trying to run a shell script to stop/start the JBoss instance, but when the Hudson job completes, the JBoss instance shutdowns.
由于现实中事情的复杂性(在Jenkins中调用了ant,ant调用了ksh,ksh最终启动了程序),我绕了很大一圈才怀疑到Jenkins上。在这之前,我尝试在ant中使用,在调用ksh时使用nohup,但是问题依旧。
而问题的根本在于是Jenkins使用processTreeKiller杀掉了所有子进程,而且这是Jenkins的 默认行为。其实回头来看这个问题,就发现Jenkins的做法非常合理。当一次build异常结束,或被人终止时,必然需要结束所有这次build启动的 子进程。下面的link提供了更多细节,以及解决方法。
https://wiki.jenkins-ci.org/display/JENKINS/ProcessTreeKiller
Jenkins home目录下的tools目录没有被同步到slave node
在Jenkins的home目录下,有两个自动生成的目录: tools and usercontent。
当我在使用slave node时,我注意到在每个slave node的上,Jenkins自动建了一个tools目录。因此我想当然的以为,tools目录是用来存放用户自己需要的第三方工具的。
例如,我在project中需要使用ant 1.8.2。而tools中则存放了ant 1.8.2,同时在建立slave node时,Jenkins自动将ant1.8.2拷贝到了slave node的tools下。
然而在之后的使用中,我发现在master node的tools中放置其他的第三方工具后,slave node的tools中并没有增加。因此slave node上的project并不能使用对应的第三方工具。
事实真相是,我应该使用usercontent目录,而不是直接使用tools目录。
当用户需要某个第三方工具时,正确的做法是将安装包放到usercontent目录。然后在Jenkins system management中要求安装这个工具。
userContent目录的说明:
You can use this directory to place your own custom content onto your Jenkins server. You can access files in this directory at http://myserver/hudson/userContent (if you are running
Jenkins on an application server) or http://myserver/userContent (if you are running in standalone mode).
之后Jenkins会自动将该工具安装到tools目录下,同时也会同步到slave node的tools下。像我这样直接扔在master node的tools下,是不会自动同步的。
还有一种解决方案:
Jenkins 并没有机制自动将master node上的tools目录下的内容同步到slave node上。这意味着如果在slave node上运行project需要某些特殊工具(或jar包),只能事先在slave node所在的box上安装好(或准备好)。
但是在某些极端条件下,slave node并没有准备好这些工具。
例如,我们使用Jenkins来自动deployment最新的release到production,而安装release意味着很多附加功能,例如环境检查,安装程序,自动启停程序,启动cluster等复杂操作。
我们使用Ant script来完成这些操作。但Ant在production环境没有安装。
因此我希望将ant相关的jar放到master jenkins根目录的tools目录,然后将tools同步到slave node的tools目录下,之后在slave node上运行Ant就可以使用这些jar包了。
但是目前我们只能通过使用一个工具rsync来将tools下的内容同步到slave node:
On master, I have a little shell script that uses rsync to synchronize master's/var/jenkins to slaves (except/var/jenkins/workspace) I use this to replicate tools on all slaves.
如何取得slave node上的jenkins home
我在脚本里,或Ant中使用环境变量JENKINS_HOME的时候发现一个问题: 尽管限制了job在slave node上运行,但是这个变量的值还是master node的 JENKINS_HOME。而不是在slave node的配置中配置的“Remote FS root”
一个解决方案是,在创建slave node时,在配置页面下方的node properties中添加一个环境变量:SLAVE_HOME=上面配置的“Remote FS root”目录。这样就可以在slave node上使用这个变量了。
比如在ant中,加入:
来获取所有的环境变量。
之后用就可以了。
在所有的projects中传递参数
一个需求:有3个projects,run.program, run.ut, run.integration.test
它们使用在一个project完成后自动trigger另外一个的方式,形成了一个chain。同时第一个project是parameterized- project,即build时需要提供输入参数。其中一个输入参数是,boolean ifRunUT,是否运行UT。
现在,如果在第一个project中选择不运行UT,则skip后面的那个project,之后继续运行第三个project,也就是集成测试。
解决方法是安装这个plugin:https://wiki.jenkins-ci.org/display/JENKINS/Parameterized+Trigger+Plugin
同时将后面的run.ut改为parameterized-project,同时有唯一的一个输入参数ifRunUT。
上面的plugin可以将第一个project的输入参数传递到它触发的下一个project。这样当后面的run.ut发现ifRunUT=false时,就自动返回successful,之后该project继续触发之后的run.integration.test。
听上去有点无聊,但是试想一下,如果有两个关于ut的project:run.ut.1 run.ut.2。上面的方法就可以一次配置,skip掉两个projects,而不需要配置多次。
更重要的是,这种做法使得整个chain的配置都集中在一个地方,而不是分散在各个project中。每次build都需要去多个projects配置参数是很让人崩溃的。
------------------------------------------------------
jenkins邮件配置
--------------------------------------------
[原创] Jenkins 邮件配置 (使用 Jenkins Email Extension Plugin)
本文主要对 jenkins 的邮件通知进行介绍,
- jenkins 内置的邮件功能
- 使用插件扩展的邮件功能
1. 先介绍下 基本的Jenkins 邮件服务器 配置
1)system config 页面 (以公用的163邮件服务器为例):
可以勾选 “通过发送测试邮件配置”
This is test email #1 sent from Jenkins |
2)下面接着对构建的job 添加邮件发送的步骤,
2. 使用插件 “Email Extersion Plugin”进行扩展
ps:
http://www.cnblogs.com/GGHHLL/p/jenkins.html
------------------------------------------------
Linux 环境下搭建 Jenkins(Hudson)平台
安装jenkins:安装 jenkins 有两种方式:
安装方式一:
- sudo
java -jar jenkins.war –httpPort=18080 –ajp13Port=18009
命令启动这个脚本,这样jenkins就能正常提供服务了。
安装方式二:安装 RPM包
为了能够使用jenkins库,首先需要导入jenkins库的 key:
- sudo
wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat/jenkins.repo sudo rpm –import http://pkg.jenkins-ci.org/redhat/jenkins-ci.org.key
开启服务(关闭,重启):
- sudo
service jenkins start|stop|restart
运行job时遇到的问题:
遇到的问题: 不能使用MVN命令;
排查过程:
①Jenkins 默认创建进程,启动任务的用户名是 jenkins,使用root权限查看passwd,可以看到这个用户默认情况下 ssh 为false,也就是说这个用户默认情况下是不能使用ssh进行登录的,除非修改 passwd中相应字段为 bash,然后sourse;
jenkins:x:500:500:mengqc:/home/jenkins:/bin/fasle
passwd文件的格式:
②默认情况下 Jenkins 的安装目录是 /var/lib/jenkins/ ,项目根目录是 /var/lib/jenkins/jobs/workspace
从目录上看,就知道这个是需要 root 权限才能执行一些命令,但是我们通过界面 执行一些命令使用的是admin用户,纵使我们在 根目录下 能适应mvn命令,但是问题也不能解决。
还有一个简单的测试Maven 是否加入到了环境变量中的方法,在执行mvn命令时,填写maven安装的绝对路径,如果能够执行,说明不是权限的问题,而是环境变量的问题。
①安装 ssh slave 插件;
②启动slave 服务;
③jenkins-系统管理-节点管理:重新设置 slave机器的 Remote FS root 为 /home/admin/xxx
(主要是添加了workspace的目录) $ITEM_ROOTDIR
④把master的节点数设为0,这样默认情况下就会使用 slave节点。
问题:
如果修改 工作目录(Remote FS root),可能会遇到:
- “main”java.lang.NoclassDefFoundError:hudson/maven/agent/Main
解决方法:使用我们的脚本 对slave进行 重启操作。
解决方案二:
mvn和一些基本的命令是可以运行了,但是运行shell脚本时还是没有权限,因为 新建的这个跳转连接user=root ,group=root,并且对这个链接 使用chown/chgrp 都是没有效果的,执行一些操作命令是还是没有权限;
①安装jenkins
Java代码
- sudo
wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat/jenkins.repo - sudo
rpm --import http://pkg.jenkins-ci.org/redhat/jenkins-ci.org.key - sudo
yum install jenkins - rpm
-ql jenkins
②. 配置jenkins
Java代码
// edit JENKINS_PORT, JENKINS_USER
sudo vi /etc/sysconfig/jenkins
③. 修改jenkins权限(如果修改JENKINS_USER情况下)
Java代码
- ####
- sudo
chown -R admin /usr/lib/jenkins - sudo
chgrp -R admin /usr/lib/jenkins - ####
- sudo
chown -R admin /var/log/jenkins - sudo
chgrp -R admin /var/log/jenkins - sudo
chown -R admin /var/lib/jenkins - sudo
chgrp -R admin /var/lib/jenkins - sudo
chown -R admin /var/cache/jenkins - sudo
chgrp -R admin /var/cache/jenkins (这个如果不改,会出现404)
④. 启动jenkins
Java代码
sudo /sbin/service jenkins start
或者
http://www.51testing.com/html/87/300987-815659.html
Linux安装Jenkins手册
一、前期准备工作
因为我是在Windows系统上连接Linux服务器以及需要把在Windows系统下载的安装包上传到Linux系统,所以需要用到两个工具---putty和FileZilla。
Putty是一个免费的、Windows 32平台下的telnet、rlogin和ssh客户端,但是功能丝毫不逊色于商业的telnet类工具。 用它来远程管理Linux十分好用。
FileZilla是一种快速、可信赖的FTP客户端以及服务器端开放源代码程式,具有多种特色、直觉的接口。
这两款工具都是免安装的,使用非常方便。
二、卸载和安装LINUX上的JDK
2.1卸载linux上自带的jdk
用root用户登陆到系统,打开一个终端输入
# rpm -qa|grep gcj
显示内容其中包含下面两行信息
# java-1.4.2-gcj-compat-1.4.2.0-27jpp
# java-1.4.2-gcj-compat-devel-l.4.2.0-27jpp
卸载
# rpm -e java-1.4.2-gcj-compat-devel-l.4.2.0-27jpp
# rpm -e java-1.4.2-gcj-compat-l.4.2.0-27jpp
卸载其他自己安装的JDK就直接用rpm -e
2.2安装JDK
去http://www.oracle.com/technetwork/java/javase/downloads/jdk-6u32-downloads-1594644.html拿1.6.0举例,下载一个Linux Platform的JDK,建议下载RPM格式的(我下载的是
2.2
注:我的jdk安装包放在home目录下
[root@testdep home]# chmod 755 jdk-6u32-linux-i586-rpm.bin
[root@testdep home]# ./ jdk-6u32-linux-i586-rpm.bin
准备中… ######################################## [100%]
Unpacking JAR files...
Java(TM) SE Development Kit 6 successfully installed.
Product Registration is FREE and includes many benefits:
* Notification of new versions, patches, and updates
* Special offers on Oracle products, services and training
* Access to early releases and documentation
Product and system data will be collected. If your configuration
supports a browser, the JDK Product Registration form. will
be presented. If you do not register, none of this information
will be saved. You may also register your JDK later by
opening the register.html file (located in the JDK installation
directory) in a browser.
For more information on what data Registration collects and
how it is managed and used, see:
http://java.sun.com/javase/registration/JDKRegistrationPrivacy.html
Press Enter to continue.....
Done.
2.3安装jdk主程序包
程序会自动生成一个jdk-6u32-linux-i586.rpm文件,这是主程序包,下面来安装;
[root@testdep home]#rpm –ivh jdk-6u32-linux-i586.rpm
2.4设置环境变量
[root@ testdep home]# export JAVA_HOME=/usr/java/jdk1.6.0_32
[root@ testdep home]# export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
[root@ testdep home]# export PATH=$PATH:$JAVA_HOME/bin
当然这样设置环境变量是可以生效的,但是只对当前shell生效。如果从另外一个shell登陆,将不能使用刚才设置的变量。所以最好的方法还是修改.bashrc文件。
我用下面这个
cd ~
[root@testdep ~]#vi .bashrc
export JAVA_HOME=/usr/java/jdk1.6.0_32(这里的jdk的版本号可以通过cd /usr/java查看)
export JAVA_HOME
export PATH=$PATH:$JAVA_HOME/bin
export PATH
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export CLASSPATH
注:保存成功后需要通过. .bashrc使此脚本生效。
当然也可以通过更改/etc/profile来实现,不过不推荐这么做,因为这样的设置将对所有用户的shell都生效,对系统安全会产生影响。下面来验证一下变量设置是否生效(在验证前先logout一下,再重新登陆);
[root@testdep home]# echo $JAVA_HOME
/usr/java/jdk1.6.0_32/
[root@testdep home]# echo $CLASSPATH
/usr/java/jdk1.6.0_32/lib/dt.jar:/usr/java/jdk1.6.0_32/lib/tools.jar
[root@testdep home]# echo $PATH
/usr/java/jdk1.6.0_32/bin/:/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/root/bin
[root@testdep home]# JAVA-version
JAVA version "jdk1.6.0_32"
JAVA(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_06-b03)
JAVA HotSpot(TM) Client VM (build 1.4.2_06-b03, mixed mode)
2.5测试环境变量是否安装成功
环境设置OK,看看JDK是否能正常工作,我们来写一个测试文件test.java
[root@LinuxServer rpm]#vi test.java
class test
{
}
保存退出,下面来编译、执行;
[root@testdep home]# javac test.java
[root@testdep home]# java test
Hello World!
OK,工作正常。
2.6
比如要给用户longware以运行java命令的权限,
[root@LinuxServer root]# vi /home/longware/.bashrc
export JAVA_HOME=/usr/java/jdk1.6.0_32
export JAVA_HOME
export PATH=$PATH:$JAVA_HOME/bin
export PATH
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export CLASSPATH
2.7
三、在Linux下配置Tomcat服务器
Tomcat是稳固的独立的Web服务器与Servlet Container,不过,其Web服务器的功能则不如许多更健全的Web服务器完整,如Apache Web服务器(举例来说,Tomcat没有大量的选择性模块)。不过,Tomcat是自由的开源软件,而且有许多高手致力于其发展。
3.1安装jdk
在安装Tomcat之前需要安装j2sdk(Java 2 Software Development Kit),也就是JDK。
请参考第一部分卸载和安装LINUX上的JDK。
3.2下载tomcat
在http://tomcat.apache.org/download-60.cgi
3.3解压tomcat安装包
解压缩刚才的tomcat安装包(apache-tomcat-6.0.35.tar.gz)。
注:我把tomcat安装包暂时通过FileZilla上传到了home目录下。
[root@testdep home]#tar –zxvf apache-tomcat-6.0.35.tar.gz
3.4为压缩包指定目录
把解压缩的文件放在一个新建的目录下
[root@testdep home]#cp -R apache-tomcat-6.0.35 /usr/local/tomcat ;
//拷贝apache-tomcat-6.0.35到/usr/local/下并重命名为tomcat
3.5设置tomcat的路径
[root@testdep home]cd ~
[root@testdep home]vi .bashrc
//在第一步卸载和安装Linux JDK设置jdk的路径后面加上tomcat的路径
//vi编辑器的使用方法请大家百度一下
注:修改过.bashrc文件后需要通过一下命令使.bashrc生效。
[root@testdep home]. .bashrc
安装完后,重新启动tomcat以使JAVA_HOME和TOMCAT_HOME的设置生效.
3.6启动tomcat
运行命令:
[root@testdep home]#/usr/local/tomcat/bin/startup.sh;
//正常情况下可以见到如下的信息:
Using CATALINA_HOME: /usr/local/tomcat
Using CATALINA_TEMDIR: /usr/local/tomcat/temp
Using JAVA_HOME: /usr/java/jdk1.6.0_35
3.7关闭tomcat
运行命令:
[root@testdep home]#/usr/local/tomcat/bin/shutdown.sh;
四、在Tomcat里边配置Jenkins
4.1
4.2
[root@testdep home]cd /usr/local/tomcat/webapps
可看出刚刚上传的jenkins war包。
4.3
4.4
五、Jankins的相关配置
5.1
意思是tomcat容器没有使用UTF-8编码,所以不能使用中文作为任务名称,可以在tomcat中进行配置。
[root@testdep home]# cd /usr/local/tomcat/conf
[root@testdep home]#vi server.xml
……
connectionTimeout="20000"
redirectPort="8443"URIEncoding="UTF-8"/>
……
注:增加了utf-8的编码格式URIEncoding="UTF-8"
5.2默认情况下,JENKINS_HOME会在当前用户的家目录下建立,名称为.jenkins,
在linux下:~/.jenkins
----------------------------------------------持续集成Jenkins API常见用法
您的评价: | | |
【背景】:部门在搞持续集成,使用jenkins作为核心调度,要再其基础上进行二次封装,所以需要研究下jenkins的api。笔者主要负责搭建平台,在研究用法也花费了些时间,本文主要做个简要的记录,希望能为各位朋友节省时间。
【环境】:(默认读者已经具备了基本的持续集成经验和jenkins用法)
1. Jenkins1.455
2. 系统Suse
3. Tomcat
4. Java
【API介绍】
【API实践】
1.创建
curl -X POST http://www.xxx.xxx/jenkins/createItem?name=JavaStd
2.禁用
curl -X POST http://www.xxx.xxx/jenkins/job/JavaStd/disable
3.启用
curl -X POST http://www.xxx.xxx/jenkins/job/JavaStd/enable --user peterguo:peterguo
4.删除
curl -X POST http://www.xxx.xxx/jenkins/job/JavaStd/doDelete --user peterguo:peterguo
5.获取项目描述
curl -X GET http://www.xxx.xxx/jenkins/job/JavaStd/description --user peterguo:peterguo
6.获取配置文件
curl -X GET http://www.xxx.xxx/jenkins/job/JavaStd/config.xml --user peterguo:peterguo
7.触发SCM检查
curl -X GET http://www.xxx.xxx/jenkins/job/JavaStd/polling --user peterguo:peterguo
8.普通触发
curl -X GET http://www.xxx.xxx/jenkins/job/JavaStd/build --user peterguo:peterguo
9.带参数触发
curl -X GET "http://www.xxx.xxx/jenkins/job/helloworld-freestyle/buildWithParameters?bAllTest=&Choices=2&strParam=abc" --user peterguo:peterguo
10.带参数和补丁触发
curl -X POST "http://www.xxx.xxx/jenkins/job/helloworld-freestyle/buildWithParameters?bAllTest=&Choices=2&strParam=abc" --user peterguo:peterguo -F "action=upload" -F "patch.diff=@OtherTest.java.patch"
注:带补丁触发需要先安装补丁插件,并设置项目的补丁参数
【Python调用】
importpycurl url = "http://10.129.145.112:8081/jenkins/job/helloworld-freestyle/config.xml" crl = pycurl.Curl() crl.setopt(pycurl.VERBOSE,1) crl.setopt(pycurl.FOLLOWLOCATION, 1) crl.setopt(pycurl.MAXREDIRS, 5) crl.setopt(pycurl.USERPWD, "peterguo:peterguo") crl.setopt(pycurl.CONNECTTIMEOUT, 60) crl.setopt(pycurl.TIMEOUT, 300) crl.setopt(pycurl.HTTPPROXYTUNNEL,1) crl.fp = StringIO.StringIO() crl.setopt(pycurl.URL, url) crl.setopt(crl.WRITEFUNCTION, crl.fp.write) crl.perform() ret = crl.fp.getvalue()
来自:http://my.oschina.net/sanpeterguo/blog/197931
----------------------------------------
config.xml of Jenkins
Jenkins 有两类config.xml:
在Jenkins home之下的config.xml是Jenkins server的配置文件。
另外在每个job或project自己的目录下,还有一个config.xml。它包含了是这个job的配置信息。
The Jenkins home directory contains all the details of your Jenkins server configuration, details that you configure in the Manage Jenkins screen.
A user appearing in this list cannot necessarily log on to Jenkins.
SCM user
(People who make changes to code in a source code repository that Jenkins is monitoring)
It is a good idea for developers to use their SCM username here: in
this case, Jenkins will be able to work out what users contributed to the SCM changes
that triggered a particular build.
Post-build Actions 对应了 config.xml中的
builder 就对应build
Source Code Management
portfolio controller builder-maven , publishers:ant merge.results
portfolio package:builder-ant
每个job下面都有一个workspace,里面有hudson_migration需要的所有ant脚本。
同时 workspace/trunk下 对于一个项目有两个文件:
portfolio
portfolio_pom.xml
https://sami.cdt.int.thomsonreuters.com/svn/searchandnavigation_searchandnavigation/Development/CP1.5/trunk/SourceCode/Controller/portfolio
with the final step (deployment into production) being a manual one dictated by
the business rather than the development team.
Maven
----------------------------------------------------------------------------------------------------
当我们在IDE中开发时,经常需要使用maven。现在流行的java的IDE有eclipse,intellij等等。对于maven而言,我们可以将IDE分为两类:
1,Eclipse等和maven结合的不够紧密的IDE。
Eclipse和Maven结合的并不算好,如果在eclipse中想使用maven,需要安装插件:m2e
安装该插件之后,你才能在eclipse中看到关于maven的菜单,并且可以创建maven项目,执行maven goal等。
为了在命令行中使用maven,我们往往会在本地再单独安装一个maven。这样就会有一个问题:eclipse中运行maven goal时,即可以选择使用embedded maven,也可以选择单独安装的maven。如下:
为了在命令行中使用maven的效果和在eclipse中执行maven goal的效果一致,建议在eclipse中选择单独安装的maven而不是内嵌的maven。
2,Intellij,Netbeans等较为紧密的IDE。
在intellij这类IDE中,不需要单独安装maven插件了。我们还是需要自己安装maven,同时也可以配置所使用的maven(默认是按环境变量M2_HOME):
- 在导入一个maven项目时,往往需要下载很多本地repository中没有的dependency。如果出现连不上互联网的repository时,我们可以:
1,打开maven settings.xml,配置代理。或让maven去指定的repository下载。注意maven有默认的settings.xml在maven home的conf目录下。
user settings.xml默认是没有的,但是可以创建且其将覆盖默认的settings.xml
在IDE中安装了maven插件之后,就可以直接运行maven package来打包了。
如果没有在IDE中安装插件而是单独安装了maven程序,则可以在命令行中直接执行mvn package来打包。
二者没有本质区别,本文以在IDE中直接为例。
要将项目打包,有两种选择:生成一个jar包;或一个包含jar包,配置文件,脚本文件等等的一个zip文件(assembly)。
如果没有在pom中显示的指定,则会使用默认的插件(通过查看effective pom可以看到)并按默认方式打包。
我们常用maven-jar-plugin来生成jar包。如果希望生成assembly,则除了maven-jar-plugin外,再使用插件maven-assembly-plugin来生成zip包。
- <</span>plugin>
-
<</span>artifactId>maven-jar-plugin</</span>artifactId> -
<</span>version>2.3.1</</span>version> -
<</span>executions> -
<</span>execution> -
<</span>id>default-jar</</span>id> -
<</span>phase>package</</span>phase> -
<</span>goals> -
<</span>goal>jar</</span>goal> -
</</span>goals> -
<</span>configuration> -
<</span>archive> -
<</span>manifest> -
<</span>addClasspath>true</</span>addClasspath> -
<</span>mainClass>com.thomsonreuters.PALFullExtractor.ExtractorMain</</span>mainClass> -
</</span>manifest> -
</</span>archive> -
</</span>configuration> -
</</span>execution> -
</</span>executions> -
</</span>plugin>
- <</span>plugin>
-
<</span>artifactId>maven-assembly-plugin</</span>artifactId> -
<</span>version>2.2</</span>version> -
<</span>executions> -
<</span>execution> -
<</span>id>make-assembly</</span>id> -
<</span>phase>package</</span>phase> -
<</span>goals> -
<</span>goal>single</</span>goal> -
</</span>goals> -
<</span>configuration> -
<</span>archive> -
<</span>manifest> -
<</span>mainClass>com.thomsonreuters.PALFullExtractor.ExtractorMain</</span>mainClass> -
</</span>manifest> -
</</span>archive> -
<</span>descriptorRefs> -
<</span>descriptorRef>jar-with-dependencies</</span>descriptorRef> -
</</span>descriptorRefs> -
<</span>descriptors> -
<</span>descriptor>D:projectnamesrcmainassemb ly/assembly.xml</</span>descriptor> -
</</span>descriptors> -
</</span>configuration> -
</</span>execution> -
</</span>executions> -
</</span>plugin>
注意其中2点:
1,descriptorRef -- jar-with-dependencies 就是将程序依赖的所有第三方类库都打入jar包,这样就不需要在运行时指定class-path了。
2,descriptor -- 指定assembly文件所在的位置。我们还需要创建一个assembly.xml来详细说明package的目录结构和内容。
assembly.xml文件的示例:
- <</span>assembly>
-
<</span>id>package</</span>id> -
<</span>formats> -
<</span>format>zip</</span>format> -
</</span>formats> -
<</span>includeBaseDirectory>false</</span>includeBaseDirectory> -
<</span>fileSets> -
<</span>fileSet> -
<</span>directory>src/main/resources/config</</span>directory> -
<</span>outputDirectory>config</</span>outputDirectory> -
-
<</span>includes> -
<</span>include>*.xsd</</span>include> -
<</span>include>*.dtd</</span>include> -
<</span>include>*.xml</</span>include> -
<</span>include>*.properties</</span>include> -
<</span>include>*.key</</span>include> -
</</span>includes> -
<</span>lineEnding>lf</</span>lineEnding> -
</</span>fileSet> -
<</span>fileSet> -
<</span>directory>src/main/resources/script</</span>directory> -
<</span>outputDirectory></</span>outputDirectory> -
-
-
-
<</span>includes> -
<</span>include>*.ksh</</span>include> -
<</span>include>*.cmd</</span>include> -
</</span>includes> -
<</span>lineEnding>lf</</span>lineEnding> -
</</span>fileSet> -
</</span>fileSets> -
<</span>dependencySets> -
<</span>dependencySet> -
<</span>outputDirectory>lib</</span>outputDirectory> -
</</span>dependencySet> -
</</span>dependencySets> - </</span>assembly>
这样打好的package名叫例如:project-1_0.zip中解压后就会得到脚本文件以及另外两个目录config(包含配置文件),和lib目录(包含所有依赖的第三方类库和projectName.jar)
我们还可以在assembly按需要构建更复杂的package结构。
从maven-jar-plugin和maven-assembly-plugin的pom文件可以看到它们都指定了:package
这会导致运行mvn package命令时运行这两个插件。
直接搜索这两个插件的名字可以找到maven官网中队插件更详细的介绍。
Maven中的几个重要概念(三):POM
http://maven.apache.org/guides/introduction/introduction-to-the-pom.html本文基本上是翻译+一点点理解。
- 什么是POM
POM(Project Object Model) 是Maven的基础。它是一个XML文件,包含了Maven用来build项目所需要的项目配置的信息。
(译者:在使用ant进行build时,我们需要通过script告诉ant每一步要做什么,同时提供每一步需要的信息。
例如,首先要编译,编译的源代码在哪里,目标代码放哪里等等。
在Maven中我们不需要告诉Maven应该做些什么,仅需要在pom中提供一些必要的信息即可。对于那些在pom中没有提到的信息,Maven就会使用默认值。
例如Maven默认源代码在src/main/java中。因此Maven在最大程度上简化了项目build的过程。)
它包含了可用于大部分项目的默认值。例如,build directory默认使用定义;source directory,默认使用了src/main/java;test source directory默认使用了src/main/test等等。
在Maven1中(Maven的早期版本)POM的名字是project.xml,而在Maven 2中改为pom.xml。
(译者:通常认为Maven从1到2发生了根本性的改变,因此尽管可能你使用的Maven是3.x的版本,仍然会发现很多以m2命名的目录。)
同时,以前在maven.xml中包含的goal,plugin等信息现在也被放到了pom.xml中。当执行一个task或goal时,Maven搜索当前目录下的pom文件,从其中取出需要的配置信息并执行goal。
(译者:plugin和goal的概念非常重要,请参考我的另外一篇介绍Maven中的lifecycle的文章。)
- Super POM
(译者:文中分别写出了Maven2.0.x和2.1.x的super POM的具体内容。这里请参考原文)
- 最简单的pom.xml
一个最简单的POM文件需要包括的内容如下:
(译者:也就是说,如果想建立一个简单的Maven项目,提供一个如此简单的POM就够了。Maven会自动完成剩下的事情)
- project root
- modelVersion - should be set to 4.0.0
- groupId - the id of the project's group.
- artifactId - the id of the artifact (project)
- version - the version of the artifact under the specified group
一个POM必须配置项目的groupId, artifactId, 和version。这三个值构成了项目的fully qualified artifact name。那就是::。对于上面的例子,fully qualified artifact name就是“com.mycompany.app:my-app:1”
同时,正如在第一节提到的,如果一些配置信息没有被提供,Maven将会使用默认值。这些默认值之一是packaging type。如果POM中没有配置它,将会使用默认值jar。
此外,如同你在最简单的POM中看到的,这个POM并没有配置所使用的repositories。
(译者:repository是Maven中的另外一个重要概念,不清楚的同学请参考我的另外一篇关于Maven中repository的文章。)
如果你使用这个POM来build你的项目,它将从Super POM继承repository的配置。因此,当Maven发现需要下载POM中的dependency时,它会到Super POM中配置的默认repository,http://repo1.maven.org/maven2去下载。
- Project Inheritance 项目继承
(译者:project inheritance 和下面要提到的project aggregation 是理解项目间POM父子关系的关键,必须理解。)
另外一些可包含在POM中的信息是:
- dependencies
- developers and contributors
- plugin lists (including reports)
- plugin executions with matching ids
- plugin configuration
- resources
其实Super POM就是项目继承的的一个例子。然而你同样可以通过在POM中加入,来引入其他的父POM。
示例一:
在前面的例子中我们已经引入了“com.mycompany.app:my-app:1”这个项目,现在我们再引入另一个项目“com.mycompany.app:my-module:1”并以此为例,讲述如何让my-app成为my-module的父项目。
同时让它们的目录结构如下:
.
my-module/pom.xml 指的是my-module这个项目的POM,而pom.xml指my-app的POM。
现在,我们把my-module的POM修改成下面:
注意现在我们加了一个配置,parent。这个配置允许我们设置哪个项目(artifact)是当前项目的父项目。我们 需要设置父POM的fully qualified artifact name。配置好之后,my-module的POM就可以从my-app的POM中继承一些配置信息了。
另外,如果我们希望my-module的groupId和/或version与父项目保持一致,我们甚至可以删除my-module的POM中的groupId和/或version。
示例二:
然而上例是有局限性的。只有当父项目已经安装到local repository中,或者必须是特殊的文件结构(父项目的pom.xml在子项目的pom.xml的父一级目录里)时,上例才工作。
(译者:我工作的就是类似的父子项目。子项目依赖于父项目。每次修改了父项目的代码后,必须运行:
mvn install //将父项目编译并加入到repository中
之后才能顺利的运行子项目。)
如果父项目没有安装到local repository中,同时目录结构如下(父子项目在平行的目录结构中)就会有问题:
.
为了解决这个目录结构(也可以是其他目录结构)导致的问题,我们必须在parent section中使用。
如同的字面意思(相对路径),它是module的pom.xml到父pom.xml的相对路径。
- Project Aggregation 项目集成
project aggregation 和project inheritance类似。但与project inheritance在my-module中设置父POM不同的是,project aggregation是在父POM中设置my-module。
通过这种方式,父项目在知道它的子模块。同时,如果在父项目上执行Maven命令,父项目和所有的子模块都会执行该命令。
(译者:这就是为什么在Maven的POM中既有父子关系,又有子父关系。)
要使用project aggregation, 必须:
1, 将父POM的改为“pom”。
2, 在父POM中设置子模块的路径。
示例三:
再次使用之前的pom示例和目录结构,如下:
com.mycompany.app:my-app:1's POM
com.mycompany.app:my-module:1's POM
目录结构:
.
如果我们想把my-module加到my-app中,可以简单的讲my-app的pom.xml改为如下:
的值是从com.mycompany.app:my-app:1的pom到com.mycompany.app:my-module:1的pom的相对路径(在例子中使用module的artifactId,即my-module作为目录名,所以设置的不是module名,而是目录的名字)。
现在,对于my-app运行的任何一个Maven命令(或者说phase或goal),同时也会在my-module上运行。
示例四:
但是如果我们将目录改为:
.
父pom应该怎么设置呢?
答案是,使用和实例三同样的方法,将路径加到中。
- Project Inheritance和Project aggregation的使用
如果你有好几个Maven项目,同时它们有着类似的配置信息,你可以重构你的这些项目,通过将这些相同的配置抽取出来,放到一个父项目中去。
这样,你需要做的所有事情就是让你的Maven项目继承父项目,然后这些共同的配置就会生效了。
同时,如果你有一组项目,它们需要在一起build和process,你可以创建一个父项目,同时将这些子项目配置成父项目的modules。通过这种方式,你只需要build父项目而子项目就都会build了。
(译者:例如我工作的项目,多个项目,比如项目A,B,C共享同样的核心代码。采取的方式就是将核心代码抽取出来做成一个父项目称为core,将)这些项目配置为父项目的modules。
可以通过build core项目,就build了所有的modules。
但有时也需要变通一下:当运行比如A项目的daily build时,我们并不需要build所有的项目。这时的做法就是,对于core项目,实际有4个pom文件:
pom.xml, A_pom.xml, B_pom.xml, C_pom.xml。当运行A的daily build时,实际在build环境中使用的是A_pom.xml。同时该pom文件中,core的子模块只有A一个。
另外需要注意的一点是:如何build的问题
例如我前面提到的我工作的项目,如果修改了core中的代码,并想重新build项目A时,有三种方法。
1,在core项目上运行mvn build。这样core, A, B, C4个项目都会被build。
2,如果只想build项目A,就用A_pom.xml覆盖core的pom文件,然后运行mvn build。则会build项目core和A。
3,或者,对core项目运行mvn install(该命令会编译,build并将build出来的jar包安装到repository中去), 之后再在A项目运行mvn build)
但是,当然了,你也可以同时使用项目集成和项目继承。意思是,你可以在子项目的pom中配置parent,同时在父项目中配置modules。你只需要明确下面3个规则:
1, 在每一个子项目pom中都要配置parent。
2,将父项目pom的packaging改为“pom”。
3,在父pom中配置子modules。
(译者:到此项目间的关系已经讲完了,让我们来总结一下:
当我们拿到了几个相关项目时,一定要先搞清楚这些项目间的父子关系。我们不仅要考察每一个项目的pom文件,弄清楚他们之间的集成和继承关系,也需要留意项目的目录结构,以防止有些设置并没有生效。
只有弄清楚了项目的关系,我们才能正确的使用Maven的功能)
(译者:原文中还有一个示例五,是关于将上面3点都融合在一起的pom文件,我觉得没有必要再累述了。)
(另外需要说明的一点,如果打开本地的repository,你会发现每个artifact(通常是jar包)也有自己的pom文件。其实原因很简单:Maven也要管理这些artifact。比如类库A,同时也依赖于类库B,C。
因此repository中的artifact也需要pom文件来说明它们之间的关系)
- 项目的插入值和变量
Maven鼓励的一种做法是,不要自我重复。然而,有时候还是需要在几个不同的地方使用相同值。为了保证仅在唯一的地方定义值,Maven允许你在pom中使用你自己定义的变量。
例如,为了在pom几个不同的地方使用相同的值,project.version,你可以这样做:
${project.version}
同时,在pom文件中定义:
需要注意的是,这些变量是在继承机制生效后赋值的。这意味着,如果一个父项目pom包含变量,这些变量会被子项目继承并可以在子项目中直接使用。
这里有三种可使用的变量:
Project Model Variables
所有在pom中的独立的element都可以作为一个变量。例如${project.groupId},${project.version},${project.build.sourceDirectory} 等等。参考POM reference来得到所有的properties。
所有这些变量使用时都应加上前缀"project."。你也可能看到一些以“pom.”为前缀的情况,但是已经不赞成这么做了。
Special Variables
basedir | The directory that the current project resides in. |
project.baseUri | The directory that the current project resides in, represented as an URI.Since Maven 2.1.0 |
maven.build.timestamp | The timestamp that denotes the start of the build. Since Maven 2.1.0-M1 |
对于build timestamp的格式问题,可以通过指定,如下:
日期格式需要遵守的规则可以参考 SimpleDateFormat(java的)的API文档。如果没有设置这个值,则使用上例中的默认值。
最后一种就是前面提到的,不累述。
原文到此结束,但我还想加一点关于POM中的dependency的内容。
dependency描述了当前项目对其他项目的依赖关系。如下例,表示当前项目依赖于log4j artifact(并非父子关系)。
同样我们使用的很多第三方工具,如JUnit等等,都需要使用dependency加入到项目的POM中(当然也可以使用项目继承的方法,从父项目继承)。
在eclipse中使用Maven插件时,可以使用图形化界面添加dependency。过程是:
1,点击添加dependency。
2,输入名字,如JUnit。此时Maven插件会到使用的remote repository中搜索相应的类库。
3,搜索到以后,点击希望添加的artifact,确定。此时POM文件已经被修改了,加入了新增的dependency。
4,点击保存。这时Maven就会开始从remote repository下载artifact。
如果没有按照Maven插件,另外一种方法就是直接修改pom.xml,加入dependency部分。保存后Maven即开始下载artifact。
不过这里有一个问题,直接修改pom.xml时,往往不知道要添加的类库的完整名称, 即::,进而也不知道该怎么填 写等内容。
这里有一个方法,下面的网站是browse repository的:
https://repository.sonatype.org/index.html#nexus-search;quick~junit
使用方法类似:搜索后,找到想要的类库,然后就能看到对应的
完毕~~~
关于POM,可以参考http://maven.apache.org/pom.html 得到更详细的解释。
看完了Maven中的几个重要概念一,二和三,相信对Maven已经有比较全面的了解了。
这个时候开始看Maven的完全参考手册就会非常轻松了。----------------------------
首先是Maven的官网guide,包含了相当多的内容。有时间的时候应该全部浏览一遍。
http://maven.apache.org/guides/index.html
参考原文:
http://maven.apache.org/guides/introduction/introduction-to-repositories.html
在Maven出现之前,如果我们希望在自己的程序中使用第三方类库,需要怎么做呢?
首先,得到这个类库的jar包。可以从官网上下载,也可以从别的地方copy过来。
然后把这个包import到IDE中的JRE System Library中,就可以开始使用了。
不算复杂,但使用Maven更简单。你只需要告诉Maven,我需要用某个类库,就OK了。
Maven将自动去获取你需要的这个类库,从哪?repository。
A repository in Maven is used to hold build artifacts and dependencies of varying types.
repository只有两种:local and remote。所以当你告诉Maven要使用某类库时(即当一个项目声明要使用一个dependency),Maven做的事情就是:从它在网络上的远程repository 找到这个类库,下载到你本地的repository(默认在c盘 ....m2repository)中。
如果Maven发现你本地的repository已经有这个类库,那就什么都不做。
因此,remote repository包含了相当丰富的流行的类库/框架/工具。如果你需要使用某个很偏门儿的类库,那么,通常还是只能用老方法,自己去下载先。
下载后可以在命令行中运行mvn install,将类库安装到自己本地的repository中去。
远程repository有两种,一种是由公共组织提供的:
a third party to provide their artifacts for downloading (for example, repo1.maven.org anduk.maven.org house Maven's central repository).
我们通常都会使用这些repository。这些repository有两个问题:
1,网络问题。例如你所在的环境没有网络。或者公司对互联网访问有限制,导致你无法访问到。
2,由于Maven已经相当流行,有时这些repository服务器会因为负载过高而出现问题。
默认情况下,会去默认的repository 下载artifact。
http://repo1.maven.org/maven2/ (从前提供了browse的功能,但是现在被禁止了)
如果不想使用这个默认的repository,可以在settings.xml中使用mirrors来指定别的。但是在POM中可以指定使用的repository所以这个设置可能被覆盖。
(关于settings.xml,可以参考 http://maven.apache.org/settings.html#Servers。个人认为要必要把这个也好好看看。)
另一种可以是公司自己搭建的,用于公司内部人员共享的repository。这样通常就不会有网络和负载的问题了。
文章最后讲述了如何搭建internal repository。有兴趣的同学自行参考。
需要说明的一点是:
Such an internal repository can be downloaded from using HTTP or the file system (using afile://URL), and uploaded to using SCP, FTP, or a file copy.
Note that as far as Maven is concerned, there is nothing special about this repository: it is anotherremote repository that contains artifacts to download to a user's local cache, and is a publish destination for artifact releases.
因此repository没有什么特别,它可以是任何一个文件系统,上传和下载可以使用多种协议。但需要使用repository manager来搭建一个repository server。
http://maven.apache.org/repository-management.html
讲述了3种repository manager工具,及其作用。
最后再提一下关于settings.xml。有两种settings.xml:
- The Maven install: $M2_HOME/conf/settings.xml
- A user's install: ${user.home}/.m2/settings.xml
第一个settings.xml,也称为global settings。第二种,也称为user settings。这里有一点及其重要的!不论是global settings还是user settings,settings.xml都不会被自动创建。
例如,你现在想把local repository放到一个你自己指定的地方,而不是默认的地方,就可以创建一个user settings,同时在其中指定你需要的位置。
原文:http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html
当我们在使用Maven做一些工作,如打包,编译,运行测试等等任务时,我们已经使用到了Maven中的几个重要概念:
lifecycle, phase and goal。
例如,如果我们使用ant打包,我们需要清晰的在脚本中告诉ant:
源代码在哪,打包的目标文件类型如jar,目标文件夹在哪。首先要编译,然后运行测试,最后打包。
而Maven为了在最大程度上简化我们的工作,因而定义了lifecycle, phase and goal。我们仅仅需要简单的运行:
mvn package(package是一个phase), 包就自动打好了。
而实际上,mvn package这个命令会运行以下6个步骤(左边这列是步骤名,同时也是phase的名字,右边是对应的goal):
process-resources | resources:resources |
compile | compiler:compile |
process-test-resources | resources:testResources |
test-compile | compiler:testCompile |
test | surefire:test |
package | jar:jar |
因此使用Maven打包时,用到的信息和步骤一点都不比用ant少,只不过使用到的信息,定义在了POM文件中(本文并不涉及);而步骤定义在了lifecycle, phase and goal中。
也就是说,Maven定义了一系列的best practice。
在这里,对与打包这个任务,我们仅需要使用Maven中已经定义好的这些best practice,就能简单的完成日常工作了。
下面我们首先介绍这些best practice,也就是定义好的lifecycle, phase, goal。
之后介绍如果我们不想使用best practice,比如,我们想在打包时,在上面的test-complie(这个步骤仅编译测试代码,但不会运行测试用例)之后,运行测试。同时,还希 望能使用一个第三方工具检查测试用例的代码覆盖率,并形成一个报表。也就是说,我们希望在打包结束时,同时得到一个测试代码覆盖率的报告,应该怎么做。
现在开始~
- There are three built-in build lifecycles: default, clean and site.
有三种内置的build lifecycle:The default lifecycle handles your project deployment, the clean lifecyclehandles project cleaning, while thesite lifecycle handles the creation of your project's site documentation.
- Each of these build lifecycles is defined by a different list of build phases, wherein a build phase represents a stage in the lifecycle.
For example, the default lifecycle has the following build phases (这里并不包含所有的phase,只是举例):
1,validate - validate the project is correct and all necessary information is available
2,compile - compile the source code of the project
3,test - test the compiled source code using a suitable unit testing framework. These tests should not require the code be packaged or deployed
4,package - take the compiled code and package it in its distributable format, such as a JAR.
5,integration-test - process and deploy the package if necessary into an environment where integration tests can be run
6,verify - run any checks to verify the package is valid and meets quality criteria
7,install - install the package into the local repository, for use as a dependency in other projects locally
8,deploy - done in an integration or release environment, copies the final package to the remote repository for sharing with other developers and projects.
执行一个phase将会执行这个lifecycle前面的所有phase。
下面这个例子执行了clean lifecycle和default lifecycle到install为止的所有phase。
mvn clean install
However, even though a build phase is responsible for a specific step in the build lifecycle, the manner in which it carries out those responsibilities may vary.
And this is done by declaring the goals bound to those build phases.
A goal represents a specific task (finer than a build phase) which contributes to the building and managing of a project.
也就是说,执行phase实际执行的是goal。如果一个phase没有绑定goal,那这个phase就不会被执行。
一些phase默认已经绑定了一些goal。对于default lifecycle来说, 这些被绑定的goal并不完全相同,而是和packaging value相关。所谓的packaging value就是
jar//这个很好理解,对于不同的包类型,打包的过程不尽相同,因此需要执行的goal也不同。
一个goal是独立的,它可以被绑定到多个phase中去,也可以一个phase都没有。如果一个goal没有被绑定到任何一个lifecycle,它仍然可以直接被调用,而不是被lifecycle调用。
因此可以这样理解phase与goal的关系:
phase其实就是goal的容器。实际被执行的都是goal。phase被执行时,实际执行的都是被绑定到该phase的goal。
goal与goal之间是独立的。因此单独执行一个goal不会导致其他goal被执行。
下面的例子
mvn clean dependency:copy-dependencies package
clean是phase。
dependency:copy-dependencies是plugin-in dependency 的goal copy-dependencies。
package也是一个phase。
maven会顺序执行这3个对象中包含的所有goal。
Plugin
另外一种将goal绑定到phase的方法就是在project中使用plugin。即在POM中配置。
Plugins are artifacts that provide goals to Maven. Furthermore, a plugin may have one or more goals wherein each goal represents a capability of that plugin.
这里我们先思考一个问题,goal的本质是什么?
例如我们上面提到的需要,希望在打包时得到一个测试代码覆盖率的报告。
实现的方法就是:
1,将计算代码覆盖率的工具,例如cobertura,安装到Maven的repository中。此时cobertura就是一个plugin。
最简单的方法就是将cobertura加到项目的dependency中就行了。Maven会自动去网上的公共repository中下载项目依赖的的dependency到本地的repository中。
2,修改POM文件(可参考下面的pom的例子),将这个plugin,连同要执行的goal,加到package这个phase中去。
由于现在Maven已经非常流行,所以这些工具的官网上都会提供在Maven中使用该工具时,应使用什么命令。
参考cobertura网站,我们可以知道对于这个工具,对应的命令是:
mvn cobertura:cobertura (即phase和goal的名字都是cobertura)
3,此时再运行mvn package,就会运行cobertura这个plugin的goal,也就是cobertura。
之后我们就会在默认的位置找到生成的报表。
因此,goal其实是由存在于Maven的repository中的plugin提供的一个个小的功能程序。
它是Maven的lifecycle以及phase的基本组成元素。同时,我们也可以通过将各种各样的goal加入到Maven的phase中,从而根据自己的实际需求,灵活实现各种定制功能。
下面是一个更general的例子,该POM中展示了,如何将display-maven-plugin中的goal time绑定到process-test-resources这个phase中。
...
通过前面的例子我们明白,完全可以自行开发一个java程序,作为goal绑定到phase中后执行。
但Maven对嵌入到它之中的plugin有一些标准,在开发程序时需要遵循。
下面链接中列出了主要的Maven plugin。
http://maven.apache.org/plugins/index.html
同时关于plugin还可以参考下面链接中的plugin文档,得到更详细的解释。
-----------------------------------
基本上运行maven有两种形式:
1,Maven
比如:Maven Build--Build是一个phase。
2,Maven plug-in:goal
比如:Maven assembly:assembly 指运行assembly plug-in 中的assemly goal。
在运行Maven项目时经常可以看到大量的类似信息:
[INFO] >>> maven-assembly-plugin:2.2:assembly (default-cli) @
//这里的插件全称是maven-assembly-plugin
//嗯,回头还得再扫一眼maven。(default-cli) @
[WARNING] The POM for opensymphony:quartz-all:jar:1.6.3 is missing, no dependency information available
[INFO]
[INFO] --- maven-resources-plugin:2.4.3:resources (default-resources) @ name---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 12 resources --后面紧跟这个插件的运行结果。
[INFO]
[INFO] --- maven-compiler-plugin:2.3.2:compile (default-compile) @ name---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:2.4.3:testResources (default-testResources) @ name---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:2.3.2:testCompile (default-testCompile) @ name ---
[INFO] Nothing to compile - all classes are up to date
maven install
maven test
maven build 等等
这些相当于运行phase的快捷方式。如果需要修改phase,在每个phase中指定不同的goal,就可以右键点击:
project->run as ->maven build。。。
此时,在goal中写入希望运行的phase名字,如install。其他的选择则是用来修改它的一些行为,如skip tests就可以了。
maven相当于一个独立的项目。对pom。xml进行了修改,都需要重新build这个项目。
Junit
----------------------------------------------------------------------------------------------------
Git/GitHub
----------------------------------------------------------------------------------------------------
SVN
----------------------------------------------------------------------------------------------------
java打包
------------------------------------------------------------------
jar包
http://docs.oracle.com/javase/tutorial/deployment/jar/basicsindex.html
The Java™ Archive (JAR) file format enables you to bundle multiple files into a single archive file. Typically a JAR file contains the class files and auxiliary resources associated with applets and applications.
jar使用的是zip压缩技术,我们也可以选择不压缩。
- 基本命令
基本的打jar包的命令很简单:
jar cf test.jar input-file(s)
cf的意思是打一个jar文件。其他参数请自己查询。
test.jar是指定的jar文件的名字。
input-file(s)是 指定哪些文件应该被包括到jar中去。通常是代码编译后产生的class文件。另外如果代码中引用了其他类库,也就是jar包。我们可以一并和源代码打到 一个jar包里,这样运行时,一个jar包就够了。如果选择仅将源代码打进jar包,则在程序运行时,还必须将需要的类库放到合适的地方并加入 classpath中。
- manifest 文件
执行完上面的命令后,就生成了一个jar包。如果我们解压这个jar包,可以看到这样一个文件:
META-INF/MANIFEST.MF,内容是:
Manifest-Version: 1.0
Created-By: 1.7.0 (Oracle Corporation)
这是自动生成的manifest文件。
此时如果运行:
java -jar test.jar
将会返回:
Failed to load Main-Class manifest attribute from test.jar
程序无法运行,因为java不知道程序的入口在哪。
- Main-Class header in manifest file
通过在manifest file中指定Main-Class属性,就可以告诉程序入口了。有两种方法:
1,手工修改mafifest file。
We first create a text file named Manifest.txt
with the following contents:
然后运行:
jar cfm MyJar.jar Manifest.txt MyPackage/*.class
m的意思是使用一个已有的manifest文件。此时java -jar MyJar.jar就可以工作了。
2,使用参数e
jar cfe app.jar MyApp MyApp.class
参数e将manifest文件中的Main-class设置为:MyApp 。这样就不用手工修改文件了。
另外说一下引用第三方类库的问题。前面说了,可以将java代码依赖的第三方类库一并打包进一个jar文件,也可以只将java代码放进jar文件,在程序运行时再另外指定classpath。
对于第二种方式,manifest文件中,还有一个属性,class-path。使用这个属性,我们就可以直接指定classpath了,而不是在每次运行的时候麻烦的单独指定。
注意,这种方式有以下限制:
The Class-Path header points to classes or JAR files on the local network, not JAR files within the JAR file or classes accessible over internet protocols. To load classes in JAR files within a JAR file into the class path, you must write custom code to load those classes. For example, if MyJar.jar contains another JAR file calledMyUtils.jar, you cannot use theClass-Path header inMyJar.jar's manifest to load classes inMyUtils.jar into the class path.
例如,MyApp.jar在运行时需要一个MyUils.jar。首先造一个manifest文件,加入以下内容:
class-path: directory-name/MyUils.jar
和前面一样,运行jar cfm,使用已有的manifest文件生成jar文件,该jar文件仅包含MyApp的class文件:
jar cfm MyJar.jar Manifest.txt MyPackage/*.class
然后MyApp.jar就可以直接运行,而不必指定classpath了:
java -jar MyApp.jar
我们还可以在manifest文件中指定package的版本:
http://docs.oracle.com/javase/tutorial/deployment/jar/packageman.html
对于第一种方式,即在运行时指定classpath:
java -cp ${CLASSPATH} main-class
需要注意的是 ${CLASSPATH}
For a .jar or .zip file that contains .class files, the class path ends with the name of the .zip or .jar file
因此只能是这样的:
CLASSPATH="$codeHome/lib/commons-collections-3.2.1.jar:$codeHome/lib/commons-io-2.0.jar:$codeHome/lib/saxon-xpath-8.7.jar"
CLASSPATH=.;D:JAVALIB;C:DOCJavaT
最后,由于现在maven在
更多推荐
所有评论(0)