開始本篇章之前介紹一個寫筆記的方法:康奈爾筆記法(新學的,很實用)
在此之前老大讓它們弄一個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
-----------------------------------------------------------------------------------------------