更多精彩文章。前端
這麼多監控組件,總有一款適合你python
《程序員畫像,十年沉浮》github
最有用系列:web
《Linux生產環境上,最經常使用的一套「vim「技巧》npm
《Linux生產環境上,最經常使用的一套「Sed「技巧》bootstrap
若是一個上點規模的公司,技術團隊有什麼值得一作的系統,那麼發佈系統算一個。 jenkins
用的好好的,爲何要本身搞呢?總結下來,有下面幾點緣由:
一、 每一個公司的流程和技術棧都是不同的,生搬硬套,就像便祕同樣不暢。
二、 發佈系統技術開發成本不高,很容易搞。你要是以爲難搞,那必定是卡在複雜的公司人員環境和流程上。
三、 jenkins
這樣的工具要想作個加強功能,不比本身開發簡單。好比加個審批環節,作個表單嵌入什麼的。
一句話,本身搞個套餐不比改造現成的難。
開發一個發佈系統是很簡單的,雖然須要全棧的知識(前端、後臺、腳本)。有多簡單呢?咱們提供了兩我的力,只花了10個工做日就所有完成了。看完本文,你要是以爲不簡單,那就是咱們太牛掰了(囧),畢竟也是見識過七八個高開去作一樣事情的豪華陣容。
流程上是幫不了你什麼忙了,但在技術上,我將奉上我的以爲很不錯的一套實現。若是你的架構是基於SpringCloud
的,你會發現很貼心。發佈系統主要有如下功能:構建模塊、部署模塊、權限管理模塊、審計模塊
maven
,仍是
gradle
,再或者
cnpm
,
g++
等,都是經過傳入一堆參數到腳本中執行。在這裏推薦使用
python
腳本進行更多控制。
構建者能夠選擇任何一次提交進行構建。構建成功後,會自動給提交打tag(也能夠自定義tag)。同一個項目不容許同時打包。構建失敗,能夠從新進行構建,構建者會看到實時滾動的日誌。這裏有兩個技術點:
1) 如何獲取git的提交記錄並進行切換?
2) 如何顯示滾動日誌?
拿gitlab來講(由於用的最多)。加入gitlab的maven便可使用。
<dependency>
<groupId>org.gitlab</groupId>
<artifactId>java-gitlab-api</artifactId>
<version>4.1.0</version>
</dependency>
複製代碼
獲取最近提交記錄。
api.getAllCommits(projectId,page, branch)
複製代碼
打tag
api.addTag(projectId, tagName, hash, tagTitle, tagContent);
複製代碼
見本公衆號文章《滾動日誌的實現》
不少發佈系統讓人很不爽的一點,就是不支持單臺或者多臺發佈,不方便並且風險大。
部署頁面只顯示已經打包成功的記錄,按照提交時間倒序顯示。支持從新部署,不論是上次部署成功仍是失敗。部署界面以下:
點擊部署按鈕,便可顯示部署機器列表,能夠選擇一個或者多個進行部署。 部署記錄都會按照打包記錄進行分組,顯示在日誌列中。同一次部署,若是有一臺部署失敗,則默認部署總體部署失敗,能夠從部署日誌判斷當前的部署狀態。能夠看到系統實際上是沒有回滾的概念的,只有部署哪一個版本的概念。一個服務可能有上百臺機器,如何更優雅的顯示多版本共存的關係,有條件的團隊是不會放過這個改進的。
SpringCloud的部署過程
github上有不少開源的實現,隨便搬弄一套集成便可。咱們主要談一下權限理念。
權限設計有兩個要點。第一不能阻礙研發的開發效率,第二要嚴控線上的安全。因此線上和非線上環境是分開設計的。
1) 一個系統的用戶,要麼是超級管理員(就是神馬都能幹的那總);要麼是帶有線上權限標識的用戶;再就是普通用戶了。
2) 一個用戶,要麼是某個項目的成員,要麼不是
權限圖以下:
操做都會被記錄進操做歷史,而且發送郵件(或者其餘hook):
1) 修改項目,發送給項目成員全部人
2) 構建項目,發送給構建者構建結果
3) 部署項目,發送給項目成員全部人
全部的操做記錄,在項目中均可查。
發佈系統的web端,不過是套層皮囊。真正去執行的,仍是咱們的腳本。
使用python
腳本進行構建和發佈,是很是方便的。有些java
開發人員對腳本不是很熟,我這裏挑比較重要的點說明一下。
建議使用logging
模塊控制。效果見下圖。
import logging
def setup_logging():
root = logging.getLogger()
root.setLevel(logging.DEBUG)
ch = logging.StreamHandler(sys.stdout)
ch.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
root.addHandler(ch)
複製代碼
默認python執行異常是不輸出到stdout的,咱們須要強行轉換一下。
import sys
import traceback
try:
setup_logging()
#...
except Exception as e:
exc_type, exc_value, exc_traceback_obj = sys.exc_info()
traceback.print_exception(exc_type, exc_value, exc_traceback_obj, limit=2, file=sys.stdout)
複製代碼
發佈系統的機器應該都作了免密登陸。經過 ssh -t "su - sth"
能夠切換到任何一個用戶在遠端執行程序。 但實踐證實,經過python的subprocess
模塊執行存在諸多問題。因此咱們才用了paramiko
庫進行了遠程調用。
s = paramiko.SSHClient()
s.load_system_host_keys()
s.connect(srv, 22 )
(stdin, stdout, stderr) = s.exec_command(cmd)
last_line = ""
for line in stdout.readlines():
last_line = line
print( line)
s.close()
複製代碼
你們都應該知道kill -15
和kill -9
的區別。如下腳本讓程序等待10秒,而後使用kill -9
殺掉她。
注意:如下腳本有巨坑~,必定要傳參
n=0
while [[ $n -lt 10 ]]
do
let "n++"
ex=`ps aux|grep \/${flag}|grep -v grep | grep -v sc. | awk '{print $2}' `
echo $ex
if [[ $ex == "" ]]
then
echo "program not exist"
break
else
echo "send kill -15 to below:"
echo $ex
ps aux|grep \/${flag}|grep -v grep | grep -v sc. | awk '{print $2}' | xargs kill -15
sleep 1
fi
if [[ $n -eq 10 ]]
then
# after 10s , try to send kill -9
ps aux|grep \/${flag}|grep -v grep | grep -v sc. | awk '{print $2}' | xargs kill -9
fi
done
##start jar
echo "start jar"
nohup -jar $jar >/dev/null 2>&1 &
echo "restart ${flag} !!!"
sleep 2
ex=`ps aux|grep \/${flag}|grep -v grep | grep -v sc. | awk '{print $2}' `
if [[ $ex == "" ]]
then
echo "Fail"
else
echo "new PID is "
echo $ex
echo "OK"
fi
exit
複製代碼
vue
幹這個大材小用了。咱們選擇了後臺都熟悉的bootstrap
,配上一個比較古老好看的AdminLTE
框架。
但這麼多頁面寫起來也是很是浪費時間的,因此咱們也集成了ejs
模版引擎。
1) 要信得過本身團隊,信得過本身。若是公司環境複雜。少開會去討論,少扯皮。先閉關鎖國再改革開放。先閉門造車,作出個東東來,再讓各位大爺們品頭論足,進行修改。畢竟也花不了多長時間,原型驅動再好不過了,你又不是一次性作個百分項目。
2) 設計時必定要考慮項目類型的多樣性和分佈式。別等着需求來了,量來了,把你連根拔起。
3) 自動化雖然好,也要準備好應急的手動化方式。若是CTO親自給你來電了,這並不見得是一件好事。