更多精彩文章。前端
这么多监控组件,总有一款适合你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亲自给你来电了,这并不见得是一件好事。