开始本篇章之前介绍一个写笔记的方法:康奈尔笔记法(新学的,很实用)
在此之前老大让它们弄一个web端更新的界面系统,本来我也打算用django+bootstrap+python实现,但是此时python和bootstrap还没有特别熟悉,目前技术不达标。不过期间碰到了jenkins,一个现成的实现持续交付部署的开源项目(但他的作用可不止如此),赞叹开源界的庞大。
----------------------------------------------------------------------------------------------
一:简介
官网:https://jenkins.io/
用于:监控外部调用的执行工作
用于:持续的软件版本/项目的发布(功能很多需要探索)
Jenkins 是一个开源软件项目,基于 java 开发的 持续集成 工具,旨在提供一个开放易用的软件平台;
二:流程架构
1、研发集成后上传 svn/git
2、创建项目 center --- 将svn上的对应版本 上传到分发服务器
3、创建项目 check --- 检查查看目前使用的版本是哪个,避免下面更新把现有的更新
4、创建项目 online --- 更改 onlinever 文件中的版本号,供客户端python检索更新
5、python.py --- 编写脚本,写到cron,实现检测md5、修改软链、删除老的版本
Jenkins 在日常使用中的架构如下,连接 svn/git,下载到分发服务器上(中控/vps中心),然后客户端 poll 分发服务器内容。
三:安装 jenkins
1、安装启动
目前版本为2.7.4,下面实验环境在 centos7 上,具体安装环境步骤,官网有明确说明
方式一:
wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo
rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key
yum install jenkins
systemctl start jenkins
方式二:
wget https://pkg.jenkins.io/redhat-stable/jenkins-2.7.4-1.1.noarch.rpm
rpm -ivh jenkins-2.7.4-1.1.noarch.rpm
systemctl start jenkins
方式三:
wget http://mirrors.jenkins.io/war-stable/latest/jenkins.war
java -jar jenkins.war(war文件路径) --port=8080(端口)
或者安装 tomcat 并放到 webapps 下启动(会自动解压)
2、web端访问
web访问ip:8080 > 将该路径下的密码粘贴到这 > 自定义或者默认安装插件 > 填写资料(用户名密码用于后期登陆)
项目目录(即家目录)默认在 /var/lib/jenkins
三:持续化集成发布 wordpress
线上环境我们应用的话,我们要有自己的 svn 或者 git 等版本管理服务,因为我们实验就暂时借用 wordpress 的svn;wordpress 是一个有 GUN 协议的开源项目,php 写的非常主流的博客系统,很美观并支持中文。
svn :http://core.svn.wordpress.org/tags/
1、新建项目 wordpress_center_last
目的:作为分发服务器
指定svn,拉取指定的版本(最新)
将下载的版本打包为 tar.gz,利于传输
记录此版本压缩包的 md5 值,用于比对
记录此版本号到文件 lastver,用于客户端检索自动更新
准备:
mkdir -p /data/web/wordpress/download
chown -R /data/web/wordpress/
/var/lib/jenkins/workspace/wordpress_center_last/wordpress-3.1 //poll过来的路径
接下来就是点点点 .........
2、检查项目 wordpress_check
目的:检查客户端在线的版本
检查现在客户端对应的版本,如果都已经是最新的版本,就不用更新了,节约资源
并且可以根据需求查看目前对应的版本
可以用的工具有很多 python的fabric、ansible、shell 等都可以
方式一:fabric
vim /data/web/wordpress/fabfile.py
#!/usr/bin/env python from fabric.api import * env.user=‘test‘ #新建用户,也可以用root用户,但要在客户端上传公钥 env.password=‘123‘ env.hosts = [‘localhost‘,‘192.168.1.104‘,‘192.168.1.107‘,] #设置客户端的ip def host_type(): run(‘uname -s;echo $USER‘) def check_ver(): run("""ONLINE_VER=`curl -s http://center_ip:8080/deploy/onlinever`; ONLINE_WP=/var/www/releases/wordpress-$ONLINE_VER; test -d $ONLINE_WP && echo "$ONLINE_WP is exists" || echo "$ONLINE_WP is not exists" """) |
方式二:ansible(推荐:集合了fabric、saltstack等众多自动化工具的优点)
vim /etc/ansible/host //编写ip列表模块,比如 test
3、创建项目 wordpress_online
目的:更新版本
新建文本 onlinever,记录版本号,供客户端python脚本检索其内容进行更新
首先随便执行一个版本,初始化一下(顺便测试)
四:编写客户端更新脚本 (python为例)
#!/usr/bin/env python #coding=utf-8 import urllib,urllib2 import os,sys import hashlib,tarfile import shutil #定义分发服务器上用的到变量,最好配个dns服务器,供内部使用 URL_LASTVER = "http://192.168.1.107/wordpress/lastver" URL_ONLINEVER = "http://192.168.1.107/wordpress/onlinever" URL_PKG = " #定义本地路径变量 LOCAL_DOWNLOAD = "/data/web/wordpress/local/download/" #客户端系下载的tar包 LOCAL_DEPLOY = "/data/web/wordpress/local/deploy/" #客户端解压使用版本目录 DOC_WWW = "/data/web/wordpress/local/www" #软链 至 worpress 版本 TOBE_KEEP = 2 #要保留的版本数量 WHITE_LST = [] #禁止删除版本的白名单 #定义用到的文件名字 APP_NAME = "wordpress" LASTVER = urllib2.urlopen(URL_LASTVER).read().strip() #读取最新版本号 URL_LAST_PKG = URL_PKG + "%s-%s.tar.gz" % (APP_NAME,LASTVER) #服务端tar包 LOCAL_LAST_PKG = os.path.join(LOCAL_DOWNLOAD + "%s-%s.tar.gz" % (APP_NAME,LASTVER)) #客户端tar包 ONLINEVER = urllib2.urlopen(URL_ONLINEVER).read().strip() #读取在线版本号 LOCAL_ONLINE_PKG = os.path.join(LOCAL_DEPLOY + "%s-%s" % (APP_NAME,ONLINEVER)) #在线使用的版本 #初始化本地目录 def init(): if not os.path.exists(LOCAL_DOWNLOAD): os.makedirs(LOCAL_DOWNLOAD) if not os.path.exists(LOCAL_DEPLOY): os.makedirs(LOCAL_DEPLOY) #检查最新的版本并下载 def checkMd5file(f): #由md5判断下载是否正确 URL_LAST_PKG_MD5 = f + ".md5file" URL_MD5 = urllib2.urlopen(URL_LAST_PKG_MD5).read().strip() with open(LOCAL_LAST_PKG) as fd: m = hashlib.md5(fd.read()).hexdigest() if m == URL_MD5: return True return False def downLoad(f): # req = urllib2.urlopen(f) # data = req.read() # with open(LOCAL_LAST_PKG,‘wb‘) as fd: # fd.write(data) # 一次性读完,有点占内存 req = urllib2.urlopen(f) n = 1 while True: data = req.read(4096) #以4096为单位下载,节省内存 if not data: break if n == 1: with open(LOCAL_LAST_PKG,‘wb‘) as fd: fd.write(data) n += 1 elif n > 1: with open(LOCAL_LAST_PKG,‘a‘) as fd: fd.write(data) n += 1 if checkMd5file(URL_LAST_PKG): return True return False def checkLastVersion(): WHITE_LST.append(LASTVER) #加入白名单,禁止删除 if not os.path.exists(LOCAL_LAST_PKG): downLoad(URL_LAST_PKG) extract_dir = os.path.join(LOCAL_DEPLOY + "%s-%s" % (APP_NAME,LASTVER)) if not os.path.exists(extract_dir): #解压本地download下的包 tar = tarfile.open(LOCAL_LAST_PKG) tar.extractall(LOCAL_DEPLOY) #tarFile(LOCAL_LAST,LOCAL_DEPLOY) #解压下载的tar包 #def tarFile(fn,d): # tar = tarfile.open(fn) # tar.extracall(‘d‘) #检查在线的版本,替换软链 def checkOnlineVersion(): WHITE_LST.append(ONLINEVER) #加入白名单,禁止删除 if os.path.exists(LOCAL_ONLINE_PKG): if not os.path.exists(DOC_WWW): #此路径是指源目录 os.symlink(LOCAL_ONLINE_PKG,DOC_WWW) else: target = os.readlink(DOC_WWW) if target != LOCAL_ONLINE_PKG: os.unlink(DOC_WWW) os.symlink(LOCAL_ONLINE_PKG,DOC_WWW) #对版本号进行排序,删除多余不用的版本 def versionSort(l): from distutils.version import LooseVersion vs = [LooseVersion(i) for i in l] vs.sort() return [o.vstring for o in vs] def clear(): DOWNLOAD_LST = [i.split(‘-‘)[1][:-7] for i in os.listdir(LOCAL_DOWNLOAD)] #取download下的版本号 DEPLOY_LST = [i.split(‘-‘)[1] for i in os.listdir(LOCAL_DEPLOY)] tobe_del_download = versionSort(DOWNLOAD_LST)[:-TOBE_KEEP] tobe_del_deploy = versionSort(DEPLOY_LST)[:-TOBE_KEEP] for d in tobe_del_download: fn = os.path.join(LOCAL_DOWNLOAD + "%s-%s.tar.gz" % (APP_NAME,d)) if d not in WHITE_LST: #不删除使用的和最新的版本 os.remove(fn) for d in tobe_del_deploy: fn = os.path.join(LOCAL_DEPLOY + "%s-%s" % (APP_NAME,d)) if d not in WHITE_LST: #不删除使用的和最新的版本 #os.remove(fn) #这只能删除空目录 shutil.rmtree(fn) #执行时加个文件锁,避免重复执行 def lockFile(f): if os.path.exists(f): print "%s is runing......" % __file__ sys.exit() with open(f,‘w‘) as fd: fd.write(str(os.getpid())) def unlockFile(f): #解锁文件 if os.path.exists(f): os.remove(f) #主程序 if __name__==‘__main__‘: lockFile(‘/tmp/.deploy.lock‘) init() checkLastVersion() print "checkLastVersion" checkOnlineVersion() print "checkOnlineVersion" clear() print "clear" #time.sleep(10) unlockFile(‘/tmp/.deploy.lock‘)
crontab -e #按时执行,可用ansible管理
*/5 * * * * python /data/web/wordpress/update.py
-----------------------------------------------------------------------------------------------