基于python实现jenkins自动发布代码平台

基于python实现jenkins自动发布代码平台
2015-04-29 15:51:27
原创作品,允许转载,转载时请务必以超链接形式标明文章  原始出处 、作者信息和本声明。否则将追究法律责任。 http://linuxpython.blog.51cto.com/10015972/1640358

前言:

jenkins自动发布代码平台是我2014年6月搭建的,截止目前已经有50多个项目的dev、beta、 生产环境都接入了jenkins,公司开发team中大部分是用GIT管理代码,也有一部分是用svn管理代码。我的实现原理是,通过jenkins构建新版本代码,然后用python脚本发布到生产环境。用户在jenkins界面上点击构建,即完成在线更新发布代码并邮件通知相关人员发布成功。

一、Jenkins安装部署

1,部署java环境。(这里用的是jdk7和tomcat7)

1
2
3
4
5
6
7
8
9
10
11
12
13
mkdir -p /data/webserver
cd /data/webserver
wget 
rpm -ivh jdk-7u55-linux-x64.rpm
wget 
tar zxvf apache-tomcat-7.0.53.tar.gz
cat > /etc/profile.d/development.sh <<EOF
export JAVA_HOME=/usr/java/jdk1.7.0_55
export JRE_HOME=$JAVA_HOME/jre
export CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH
export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH
EOF
source /etc/profile.d/development.sh

2,部署jenkins项目

从官网下载jenkins程序包,上传到服务器的程序目录,删除tomcat/webapps目录下的所有文件,然后修改tomcat配置文件指定程序目录即可

1
2
< Host  name = "localhost"   appBase = "/data/www/jenkins"
             unpackWARs = "true"  autoDeploy = "true" >

启动tomcat:   ./startup.sh

浏览器访问:http://172.20.0.1:8080/jenkins

二、Jenkins项目构建

1,安装maven插件,由于部分开发team使用了maven管理,这里需要安装maven插件,安装的是3.2.2版本;

2,私服配置,如下

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
vim /root/.m2/settings.xml
<? xml  version = "1.0"  encoding = "UTF-8"  standalone = "no" ?>
< settings  xmlns = "http://maven.apache.org/SETTINGS/1.0.0"  xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation = "http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd" >
     <!--将此文件放在目录(~/.m2)下做为maven的设置文件-->
     < servers >
         < server >
             < id >snapshots</ id >
             < username >deployment</ username >
             < password >deployment</ password >
         </ server >
         < server >
             < id >releases</ id >
             < username >deployment</ username >
             < password >deployment</ password >
         </ server >
     </ servers >
     < mirrors >
         < mirror >
             < id >nexus</ id >
             < mirrorOf >*</ mirrorOf >
             < name >internal nexus repository</ name >
             < url >http://172.20.135.19:8080/nexus/content/groups/public/</ url >
         </ mirror >
     </ mirrors >
     < profiles >
         < profile >
             < id >nexus</ id >
             < repositories >
                 < repository >
                     < id >central</ id >
                     < url >http://nisabi</ url >
                     < releases >
                         < enabled >true</ enabled >
                     </ releases >
                     < snapshots >
                         < enabled >true</ enabled >
                     </ snapshots >
                 </ repository >
             </ repositories >
             < pluginRepositories >
                 < pluginRepository >
                     < id >central</ id >
                     < url >http://nisabi</ url >
                     < releases >
                         < enabled >true</ enabled >
                     </ releases >
                     < snapshots >
                         < enabled >true</ enabled >
                     </ snapshots >
                 </ pluginRepository >
             </ pluginRepositories >
         </ profile >
     </ profiles >
     < activeProfiles >
         < activeProfile >nexus</ activeProfile >
     </ activeProfiles >
</ settings >

3,在jenkins操作界面---系统管理---插件管理中,安装git、go插件,svn已经默认安装,由于开发项目有用到go语言,这里需要安装go插件;

4,在jenkins操作界面新建一个项目,可以选择自由风格软件项目或maven项目,在配置中填写源码管理地址、授权帐号、Branches to build(分支名)、pom.xml(根据具体项目来写)、add-post-build-step-----execute shell;

5,在execute shell框中填写服务器脚本地址,保存即可

三、Python发布脚本

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#!/usr/bin/python
#coding=utf-8
'''
Created on 2014-6-19
@author: huangyishan
'''
import re,sys,os,time,datetime
import pexpect
import hashlib
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
prompt = '[$#>]'
ssh_newkey='Are you sure you want to continue connecting'
rsync_prompt='total size.*'
ip_list=["0.0.0,1","0.0.0.2"]
user="omadmin"
password="password"
local_path="/root/.jenkins/jobs/passport/workspace/wasabi-web-front/target/ROOT.war"
target_path="/data/program/front/ROOT.war"
log_path="/data/tmplog/passport/master/fabu_"
command="md5sum %s" %(target_path)
server_script_exec="sh /data/sh/program_update.sh"
cur_time = time.strftime('%Y_%m_%d_%H_%M')
log_file_name = log_path + cur_time + ".log"
recipientas_list=["huangyishan@admin.com"]
 
itheme= '帐号中心生产环境版本更新发布'
email_server_IP='x.x.x.x'
mail_user="product_release@xxx.com"
mail_pass="password"
def send_email_succeed(recipientas_list,addresser,itheme,email_server_IP,log_file_name,server_ip,local_file_md5,target_file_md5):
     msg = MIMEMultipart()
     msg['Subject'] = itheme
     msg['From'] = addresser
     msg['To'] = ";".join(recipientas_list)
     html_succeed = """\
         < html >
         < head ></ head >
         < META  http-equiv = Content -Type  content = "text/html; charset=utf-8" >
         < body >
         < p >Hi,各位伙伴< br >
         &nbsp;&nbsp;&nbsp;&nbsp;< font  color = "green"  size = 5  ><====服务器IP %s ====> passport.coocaa.com 帐号中心生产环境版本更新发布成功.</ font >< br >< br >< br >
         &nbsp;&nbsp;&nbsp;&nbsp;< font  size = 5  >如发现版本有问题,请及时联系黄怡善,电话:</ font >< font  color = "green"  size = 5  > 137XXXX6716</ font >< br >< br >< br >
         &nbsp;&nbsp;&nbsp;&nbsp;< font  size = 5  >本地版本文件MD5: </ font >< font  color = "green"  size = 5  >%s</ font >< br >
         &nbsp;&nbsp;&nbsp;&nbsp;< font  size = 5  >服务器版本文件MD5: </ font >< font  color = "green"  size = 5  >%s</ font ></ font >< br >
         </ p >
         </ body >
         </ html >"""%(server_ip, local_file_md5, target_file_md5)
     part1 = MIMEText(html_succeed, 'html',_charset="utf-8")
     
     #fp = open(log_file_name, 'rb')
     #part2 = MIMEText(fp.read(), 'plain',_charset="utf-8")
     #fp.close()
     msg.attach(part1)
     #msg.attach(part2)
     try:
         s = smtplib.SMTP()
         s.connect(email_server_IP)
         s.login(mail_user,mail_pass)
         s.sendmail(addresser, recipientas_list, msg.as_string())
         s.quit()
     except Exception, e:
         print str(e)
         return False
def send_email_fail(recipientas_list,addresser,itheme,email_server_IP,log_file_name,server_ip,local_file_md5,target_file_md5):
     msg = MIMEMultipart()
     msg['Subject'] = itheme
     msg['From'] = addresser
     msg['To'] = ";".join(recipientas_list)
     html_succeed = """\
         < html >
         < head ></ head >
         < META  http-equiv = Content -Type  content = "text/html; charset=utf-8" >
          < body >
         < p >Hi,各位伙伴< br >
         &nbsp;&nbsp;&nbsp;&nbsp;< font  color = "red"  size = 5  ><====服务器IP %s ====> 帐号中心生产环境版本更新发布失败,</ font >< font  size = 5  >附件有详细发布日志,请查看.</ font >< br >< br >< br >
         &nbsp;&nbsp;&nbsp;&nbsp;< font  color = "red"  size = 5  >请及时联系黄怡善,电话:</ font >< font  color = "green"  size = 5  > 137XXXX6716</ font >< br >< br >< br >
         &nbsp;&nbsp;&nbsp;&nbsp;< font  color = "red"  size = 5  >本地版本文件MD5: </ font >< font  color = "green"  size = 5  >%s</ font >< br >
         &nbsp;&nbsp;&nbsp;&nbsp;< font  color = "red"  size = 5  >服务器版本文件MD5: </ font >< font  color = "green"  size = 5  >%s</ font >< br >
         </ p >
         </ body >
         </ html >
         """%(server_ip, local_file_md5, target_file_md5)
     part1 = MIMEText(html_succeed, 'html',_charset="utf-8")
     #fp = open(log_file_name, 'rb')
     #part2 = MIMEText(fp.read(), 'plain',_charset="utf-8")
     #fp.close()
     msg.attach(part1)
     #msg.attach(part2)
     try:
         s = smtplib.SMTP()
         s.connect(email_server_IP)
         s.login(mail_user,mail_pass)
         s.sendmail(addresser, recipientas_list, msg.as_string())
         s.quit()
     except Exception, e:
         print str(e)
         return False
for server_ip in ip_list:
     log_file = open(log_file_name, "a")
     child=pexpect.spawn("/usr/bin/rsync -e 'ssh -p 22222' -avzcP %s %s@%s:%s" %(local_path, user, server_ip, target_path))
     child.logfile=log_file
     
     index = child.expect([ssh_newkey, 'password: ', pexpect.EOF, pexpect.TIMEOUT])
     if index == 0:
         child.sendline('yes')
         child.expect ('password: ')
         child.sendline(password)
         child.expect(rsync_prompt,timeout=None)
     elif index == 1:
         child.sendline(password)
         child.expect(rsync_prompt,timeout=None)
     elif index == 2:
         print "%s rsync: %s EOF ERROR %s" %('#'*10, server_ip, '#'*10)
     elif index == 3:
         print "%s rsync: %s TIMEOUT ERROR %s" %('#'*10, server_ip, '#'*10)
         
     log_file.close()
     child.close()
     
     time.sleep(5)
     
     log_file = open(log_file_name, "a")
     child=pexpect.spawn("/usr/bin/ssh -p 22222 %s@%s" %(user, server_ip))
     child.logfile=log_file
     
     index = child.expect([ssh_newkey, 'password: ', pexpect.EOF, pexpect.TIMEOUT])
     if index == 0:
         child.sendline('yes')
         child.expect ('password: ')
         child.sendline(password)
         child.expect (prompt)
         child.sendline(command)
         child.expect (prompt)
         child.sendline('exit')
     elif index == 1:
         child.sendline(password)
         child.expect (prompt)
         child.sendline(command)
         child.expect (prompt)
         child.sendline('exit')
     elif index == 2:
         print "%s ssh: %s EOF ERROR %s" %('#'*10, server_ip, '#'*10)
     elif index == 3:
         print "%s ssh: %s TIMEOUT ERROR %s" %('#'*10, server_ip, '#'*10)
         
     log_file.close()
     child.close()
     
     os.system("md5sum %s | awk '{print $1}' > /data/tmplog/passport/master/upload_file_local.log" %(local_path))
     os.system("grep %s %s | awk '{print $1}' | egrep -v 'md5sum|omadmin' | tail -n 1  > /data/tmplog/passport/master/upload_file_remote.log" %(target_path, log_file_name))
         
     for localmd5 in open("/data/tmplog/passport/master/upload_file_local.log"):
         local_file_md5 = localmd5
     
     for remotemd5 in open("/data/tmplog/passport/master/upload_file_remote.log"):
         target_file_md5 = remotemd5
         
     if target_file_md5 == local_file_md5:
         log_file = open(log_file_name, "a")
         child=pexpect.spawn("/usr/bin/ssh -p 22222 %s@%s" %(user, server_ip))
         child.logfile=log_file
         
         index = child.expect(['password: ', pexpect.EOF, pexpect.TIMEOUT])
         if index == 0:
             child.sendline(password)
             child.expect (prompt)
             child.sendline(server_script_exec)
             child.expect (prompt)
             child.sendline('exit')
         elif index == 1: 
             print "%s script exec: %s EOF ERROR %s" %('#'*10, server_ip, '#'*10)
         elif index == 2:
             print "%s script exec: %s TIMEOUT ERROR %s" %('#'*10, server_ip, '#'*10)
         send_email_succeed(recipientas_list,addresser,itheme,email_server_IP,log_file_name,server_ip,local_file_md5,target_file_md5)
     else:
         send_email_fail(recipientas_list,addresser,itheme,email_server_IP,log_file_name,server_ip,local_file_md5,target_file_md5)

此脚本的功能说明如下:

1,将构建好的代码包,用rsync同步到生产环境服务器中转目录program;

2,通过ssh登录生产环境服务器,调用program_update.sh脚本,将中转目录program下的代码更新到站点程序目录,更新完之后如果站点访问有BUG,那么可以将program下的前一个版本代码进行回滚;

3,构建的代码包和上传到生产环境的代码包通过md5校验一致性;

4,项目构建发布成功后,发邮件给项目相关人员;

5,执行此脚本的日志输出到文件,可以进行查看问题;


关于jenkins平台的项目构建操作很简单,希望我的文章可以给大家有所帮助,如有问题可以咨询我,也希望大家给予建议!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值