Flask学习1:简介

Flask入门

web工作原理

1、C/S和B/S架构

​ C/S:客户端/服务器

​ B/S:浏览器/服务器

2、B/S架构工作原理

​ 客户端(浏览器) <=> WEB服务器(apache/nginx) <=> WSGI <=> Python(Flask)

Flask框架

1、简介

​ flask是一个非常小的Python Web框架,被称为微型框架,只提供了一个强健的核心,其他功能都是通过扩展来实现的,意味着可以根据项目的需求量身打造。

2、组成

  1. 测试、路由、WSGI系统
  2. 模板引擎(jinja2, 是flask核心开发组人员开发)

3、安装

pip install flask

4、完整程序

# 导入类库
from flask import Flask

# 创建实例
app = Flask(__name__)

# 视图函数
@app.route('/')
def index():
    return '<h1>Nice dandan</h1>'

# 启用实例
if __name__ == '__main__':
    app.run()

# 浏览器测试:http://127.0.0.1:5000/

5、启动参数

未分类

app.run(debug=True, threaded=True, port=8001, host=’0.0.0.0’)

6、请求与响应

变量或对象

未分类

请求钩子函数

未分类

7、视图函数

说明:

无参路由

# 无参路由

@app.route('/test2/')
def test2():
   return 'This is test2 page!'

带参路由

# 带参路由,参数写在<>中

@app.route('/welcome/<name>/')
def welcome(name):
   return 'Hello, %s~' % name

指定参数类型,如string(默认)、int、float、path(参数中的/不再作为分隔符)
@app.route('/user/int:uid')
  def show(uid):
      return '%d 号,Nice' % uid

测试path

 @app.route('/path/path:p')
 def path(p):
   return p

'''
说明:
   1.路由末尾的'/'建议加上,需要的时候,浏览器会自动加上,输入时加不加都可以
   2.若需要指定参数,将参数写在<>中,视图函数参数要与路由参数一致
   3.若需要知道参数类型,如int/float/path等,写在参数前,用‘:’与参数隔开
   4.不指定类型,参数默认是string,path其实也是字符串,只是'/'不再作为分隔符
'''  

8、请求(request)

python

请求

@app.route(‘/request/’) 
def req(): 
# 完整的url请求地址 
# return request.url
# 基础的url(除了参数以外的url,即不包括get参数)
# return request.base_url

# 主机地址和端口号
# return request.host_url

# 只有路由信息(只包含装饰器中的路由地址)
# return request.path

# 请求方式
# return request.method

# 客户端的ip地址
# return request.remote_addr

# 获取get参数
# return request.args['name']

# 获取请求头
return request.headers['User-Agent']

9、响应

# 响应
@app.route('/response/')
def response():
    # 默认状态码200
    # return 'Nice'

    # 在响应的后面指定状态码
    # return 'Page not found', 404

    # 先构造一个响应(也可以指定状态吗),然后返回
    resp = make_response('这是通过函数构造的响应', 404)
    return resp

10、重定向(redirect)

# 重定向
@app.route('/redirect/')
def new():
    # return '新的内容'
    # 重定向,需要指定一个路由地址
    # return redirect('/response/')

    # 根据视图函数,反向的构造出来路由地址,传递的参数是视图函数
    # return url_for('req')

    # 构造带参数的路由,直接写在后面即可
    # return url_for('welcome', name='Nian')
    return redirect(url_for('welcome', name='Nian'))

11、终止(abort)

# 抛出指定错误
@app.route('/abort/')
def err():
    # 使用abort函数,不是说控制权就归你了,
    # 他只是向系统抛出了指定的异常,
    # 异常的处理仍然会按照框架中写好的方式进行
    abort(404)
    return 'abort测试'

# 定制错误页面
@app.errorhandler(404)
def page_not_found(e):
    return 'Not found'

12、会话控制(cookie/session)

# 设置cookie
@app.route('/set_cookie/')
def set_cookie():
    resp = make_response('cookie已设置')

    # 设置cookie
    resp.set_cookie('name', '小啊念')
    return resp

# 获取cookie
@app.route('/get_cookie/')
def get_cookie():
    return request.cookies.get('name') or 'Stranges'


# 设置session
# 设置密钥,用于加密解密的字符串,不只是用于session
app.config['SECRET_KEY'] = '123456'

# 设置session
@app.route('/set_session/')
def set_session():
    session['user'] = 'Likesea'
    return 'session已设置'

# 获取session
@app.route('/get_session/')
def get_session():
    return session.get('user', 'Strangers')

flask-script扩展

1、简介

​ 简单来说就是一个flask终端运行的解析器;因为在测试完项目后,最好不要改动任何代码,

否则可能会带来风险,所以借助扩展库实现启动,通过传递参数完成不同的启动。

2、安装

pip install flask-script

3、使用

# 导入类库
from flask_script import Manager

# 创建对象
manager = Manager(app)

# 启用实例
if __name__ == '__main__':
    manager.run()

# 启动:python manage.py runserver

4、启动参数

-? / --help :查看启动设置帮助
-h / --host :指定主机
-p / --port :指定端口
--threaded  :启动多线程
-d  :开启调试模式
-r  :代码修改后自动加载

# 实例:python manage.py runserver -d -r

蓝本(blueprint)

1、说明:

​ 当代码越来越复杂时,将所有的视图函数放在一个文件中很明显是不合适的,如果能够根据功能模块进行划分,存储在不同的文件中,蓝本就是为解决此问题而生的。

# 导入类库
from flask import Blueprint

# 创建蓝本对象
user = Blueprint('user', __name__)

# 添加路由(视图函数)
@user.route('/login/')
def login():
    return '登陆'


# 注册蓝本,未注册的蓝本处于休眠状态(无法使用)
from user import user

# 可以通过url_prefixl指定路由前缀
app.register_blueprint(user, url_prefix='/user')

扩展

1、MVC

​M:model, 模型,数据模型

V:view, 视图,负责数据展示

​C:controller, 控制器,负责业务逻辑的扩展

2、MTV

​M:model,模型,数据模型

​T:templates, 模板,负责数据展示

V:view function,视图函数,负责业务逻辑的处理

MySQL InnoDB MVCC实现

数据多版本(MVCC)是MySQL实现高性能的一个主要的一个主要方式,通过对普通的SELECT不加锁,直接利用MVCC读取指版本的值,避免了对数据重复加锁的过程,今天我们就用最简单的方式,来分析下MVCC具体的原理,先解释几个概念:

隐藏列

在分析MVCC原理之前,先看下InnoDB中数据行的结构:

未分类

在InnoDB中,每一行都有2个隐藏列DATA_TRX_ID和DATA_ROLL_PTR(如果没有定义主键,则还有个隐藏主键列):

  • DATA_TRX_ID表示最近修改该行数据的事务ID
  • DATA_ROLL_PTR则表示指向该行回滚段的指针,该行上所有旧的版本,在undo中都通过链表的形式组织,而该值,正式指向undo中该行的历史记录链表

整个MVCC的关键就是通过DATA_TRX_ID和DATA_ROLL_PTR这两个隐藏列来实现的。

事务链表

MySQL中的事务在开始到提交这段过程中,都会被保存到一个叫trx_sys的事务链表中,这是一个基本的链表结构:

未分类

事务链表中保存的都是还未提交的事务,事务一旦被提交,则会被从事务链表中摘除。

ReadView

有了前面隐藏列和事务链表的基础,接下去就可以构造MySQL实现MVCC的关键——ReadView。

ReadView说白了就是一个数据结构,在SQL开始的时候被创建。这个数据结构中包含了3个主要的成员:ReadView{low_trx_id, up_trx_id, trx_ids},在并发情况下,一个事务在启动时,trx_sys链表中存在部分还未提交的事务,那么哪些改变对当前事务是可见的,哪些又是不可见的,这个需要通过ReadView来进行判定,首先来看下ReadView中的3个成员各自代表的意思:

  • low_trx_id表示该SQL启动时,当前事务链表中最大的事务id编号,也就是最近创建的除自身以外最大事务编号;
  • up_trx_id表示该SQL启动时,当前事务链表中最小的事务id编号,也就是当前系统中创建最早但还未提交的事务;
  • trx_ids表示所有事务链表中事务的id集合。

上述3个成员组成了ReadView中的主要部分,简单图示如下:

未分类

根据上图所示,所有数据行上DATA_TRX_ID小于up_trx_id的记录,说明修改该行的事务在当前事务开启之前都已经提交完成,所以对当前事务来说,都是可见的。而对于DATA_TRX_ID大于low_trx_id的记录,说明修改该行记录的事务在当前事务之后,所以对于当前事务来说是不可见的。

注意,ReadView是与SQL绑定的,而并不是事务,所以即使在同一个事务中,每次SQL启动时构造的ReadView的up_trx_id和low_trx_id也都是不一样的,至于DATA_TRX_ID大于low_trx_id本身出现也只有当多个SQL并发的时候,在一个SQL构造完ReadView之后,另外一个SQL修改了数据后又进行了提交,对于这种情况,数据其实是不可见的。

最后,至于位于(up_trx_id, low_trx_id)中间的事务是否可见,这个需要根据不同的事务隔离级别来确定。对于RC的事务隔离级别来说,对于事务执行过程中,已经提交的事务的数据,对当前事务是可见的,也就是说上述图中,当前事务运行过程中,trx1~4中任意一个事务提交,对当前事务来说都是可见的;而对于RR隔离级别来说,事务启动时,已经开始的事务链表中的事务的所有修改都是不可见的,所以在RR级别下,low_trx_id基本保持与up_trx_id相同的值即可。

最后用一张图来解释MySQL中的MVCC实现:

未分类

uwsgi的定时脚本任务

定时任务:

定时任务的脚本cron_job.py

未分类

意思就是每天9.20执行test module的init_daily_activities 方法

项目中的定时任务不管多少就加在这里,然后重启项目(django应用)

重启脚本就叫server.py吧

未分类

python Web开发之 WSGI & uwsgi & uWSGI

未分类

未分类

首先弄清下面几个概念:

WSGI

全称是Web Server Gateway Interface,WSGI不是服务器,python模块,框架,API或者任何软件,只是一种规范,描述web server如何与web application通信的规范。server和application的规范在PEP 3333中有具体描述。要实现WSGI协议,必须同时实现web server和web application,当前运行在WSGI协议之上的web框架有Bottle, Flask, Django。

WSGI是Web 服务器(uWSGI)与 Web 应用程序或应用框架(Django)之间的一种低级别的接口

wsgi server (比如uWSGI) 要和 wsgi application(比如django )交互,uwsgi需要将过来的请求转给django 处理,那么uWSGI 和 django的交互和调用就需要一个统一的规范,这个规范就是WSGI WSGI(Web Server Gateway Interface)

WSGI,全称 Web Server Gateway Interface,或者 Python Web Server Gateway Interface ,是为 Python 语言定义的 Web 服务器和 Web 应用程序或框架之间的一种简单而通用的接口。自从 WSGI 被开发出来以后,许多其它语言中也出现了类似接口。

WSGI 的官方定义是,the Python Web Server Gateway Interface。从名字就可以看出来,这东西是一个Gateway,也就是网关。网关的作用就是在协议之间进行转换。

WSGI 是作为 Web 服务器与 Web 应用程序或应用框架之间的一种低级别的接口,以提升可移植 Web 应用开发的共同点。WSGI 是基于现存的 CGI 标准而设计的。

uwsgi

与WSGI一样是一种通信协议,是uWSGI服务器的独占协议,用于定义传输信息的类型(type of information),每一个uwsgi packet前4byte为传输信息类型的描述,与WSGI协议是两种东西,据说该协议是fcgi协议的10倍快。

uWSGI

是一个web服务器,实现了WSGI协议、uwsgi协议、http协议等。

uWSGI是一个Web服务器,它实现了WSGI协议、uwsgi、http等协议。Nginx中HttpUwsgiModule的作用是与uWSGI服务器进行交换。

WSGI协议主要包括server和application两部分

  • WSGI server负责从客户端接收请求,将request转发给application,将application返回的response返回给客户端;

  • WSGI application接收由server转发的request,处理请求,并将处理结果返回给server。application中可以包括多个栈式的中间件(middlewares),这些中间件需要同时实现server与application,因此可以在WSGI服务器与WSGI应用之间起调节作用:对服务器来说,中间件扮演应用程序,对应用程序来说,中间件扮演服务器。

WSGI协议其实是定义了一种server与application解耦的规范,即可以有多个实现WSGI server的服务器,也可以有多个实现WSGI application的框架,那么就可以选择任意的server和application组合实现自己的web应用。例如uWSGI和Gunicorn都是实现了WSGI server协议的服务器,Django,Flask是实现了WSGI application协议的web框架,可以根据项目实际情况搭配使用。

未分类

像Django,Flask框架都有自己实现的简单的WSGI server,一般用于服务器调试,生产环境下建议用其他WSGI server。

FastCgi协议, uwsgi协议, http协议有什么用?

nginx 和 uWSGI交互就必须使用同一个协议,而上面说了uwsgi支持fastcgi,uwsgi,http协议,这些都是nginx支持的协议,只要大家沟通好使用哪个协议,就可以正常运行了。

uwsgi是服务器和服务端应用程序的通信协议,规定了怎么把请求转发给应用程序和返回

# WSGI和uwsgi
https://www.jianshu.com/p/679dee0a4193
# uWSGI,WSGI和uwsgi
https://www.cnblogs.com/wspblog/p/8575101.html

jenkins使用git+gradle+webhook实现自动部署

1、下载jenkins

网址:http://mirrors.jenkins-ci.org/,可以按照操作系统来选择相应的安装方式。RC是候选发布版,我们选择LTS长期稳定版即可。

我采用的war包的部署方式,选择war-stable,找到最新的jenkins为2.121.2,进入目录下载,或者可以直接wget链接。

wget mirrors.jenkins-ci.org/war-stable/2.121.2/jenkins.war

war包的安装方式非常简单,直接扔进tomcat目录下,只要tomcat处于运行状态,就会自动解压。

2、配置jenkins

访问jenkins目录 http://你的域名或者ip:8080/jenkins,jenkins就会启动。

未分类

稍等片刻,等jenkins启动完毕后,为了验证身份,jenkins会要求你去本地目录下读取初始密码并填入。

未分类

然后就是jenkins的配置页面的首页,会让你选择安装插件的方式,这里我选则右边自定义插件的安装方式。

未分类

选择上方的无,然后选择git,gradle,由于这里未显示完整的插件列表,webhook需要在插件管理器中配置

未分类

未分类

点击安装,等待安装成功,创建管理员账户后,设置jenkins的访问路径,开始使用jenkins

未分类

进入插件管理器,点击左侧系统管理,选择管理插件

未分类

未分类

点击可选插件,由于我使用的仓库是coding,搜索coding webhook,直接安装,其他仓库同理,若没有集成好的插件,可以搜索webhook,使用Generic Webhook Trigger(webhook通用触发器)

未分类

3、新建任务

单击开始创建一个新任务,输入任务名称test,选择构建一个自由风格的软件项目

未分类

选择丢弃旧的构建,点击右下方高级,四个参数按照自己机器的磁盘空间来填写,因为jenkins每次构建结束后(无论成功还是失败)都会记录构建,长期会占用大量的空间

$JENKINS_HOME/jobs/[JOB_NAME]/builds 目录存储了该Jenkins job的全部构建记录(目录名为构建序号)

$JENKINS_HOME/jobs/[JOB_NAME]/builds/BUILD_NUMBER/artifacts 目录存储了该次构建的artifact

未分类

之后设置源码管理,设置仓库地址,选择用户凭据

未分类

设置webhook触发器,图中的都必须选中,webhook令牌可以不填

未分类

接着去仓库中配置webhook

未分类

若触发成功就会在$JENKINS_HOME的workspace目录下生成项目文件,包括项目文件夹test,和临时文件夹test@tmp

未分类

设置gradle自动打包,使用gradle wrapper,要求项目里必须有gradle wrapper的相关文件,否则要设置wrapper的路径。

未分类

若使用gradle,可以去系统管理的全局工具配置安装指定版本的gradle

未分类

若构建成功,就会在项目的build目录下生成war包,在我实际上线的项目中,由于用到了tomcat,还需要再增加构建步骤,将生成的war包拷贝到tomcat的webapps目录下

未分类

至此,项目自动部署配置完毕,只要我在本地修改完代码push到仓库中,服务器便会自动pull代码然后打成war包部署到tomcat下。

如何在Docker里正确集成Jenkins和Phabricator

|用Docker安装Jenkins非常简单,但要把一个运行在Docker里的Jenkins和Phabricator相集成,事情就变得不那么容易。

未分类

单独安装Jenkins并不复杂,用Docker安装Jenkins更加简单,甚至将Jenkins与Phabricator集成也不难,但要把一个运行在Docker里的Jenkins和Phabricator相集成,事情就变得不那么容易。

我把所有走过的坑全部隐藏,直接告诉你最正确的步骤。

这一步似乎很简单,但不要按照官方教程上所说的来,而按照以下命令执行:

docker run --name jenki
ns -p 8088:8080 -p 50000:50000 -v /var/jenkins_home:/var/jenkins_home -e PATH='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/src/arcanist/bin' jenkins/jenkins

-p 8088:8080是为了避免8080端口冲突(毕竟只要是个Java程序就想占用8080端口),-e设置里特意增加了/src/arcanist/bin是为下一步集成Phabricator里的Arcanist做准备,因为如果不在这里设置好这个环境变量的话,后面会带来很大麻烦。

因为官方提供的Docker里根本就没有Arcanist,所以我们必须进入Docker的容器,手工安装arc。

docker exec -it -u root jenkins bash

好在这个Docker并不复杂,只是一个Debian,所以我们以root用户进入,然后:

apt-get update
apt-get install php
apt-get install php-curl
apt-get install rsync
apt-get install vim
mkdir /src
cd /src
git clone git://github.com/facebook/libphutil.git
git clone git://github.com/facebook/arcanist.git

把你的ssh公钥私钥文件拷到/var/jenkins_home/.ssh里,因为后面不论是git还是rsync你都需要它们。然后再以jenkins用户身份进入Docker:

docker exec -it -u jenkins jenkins bash

然后:

arc set-config default http://your.phabricator.com/
cd /var/jenkins_home/.ssh
chmod 600 id_rsa
chmod 600 id_rsa.pub

至此,你已经把官方提供的Docker改得面目全非,才算正确地在Docker里安装好了arc和Jenkins。

接下来的步骤,你就可以参照官方教程一步一步执行,我就不再重复了。

如果你也遇到了类似的头疼问题,希望这篇文章能够对你有所启发。

使用Jenkins的任务自动跑脚本后发现,tomcat服务刚启动就被杀死

在Jenkins的使用中,遇到过的一个场景是:使用python自动执行tomcat bin目录下的startup.bat开启批处理,服务开启成功后就随着python脚本执行结束该服务就被杀死,开始以为是python脚本的问题,但是直接执行是没有问题的;之后一直查运行环境差异,发现也不是这个原因;到后来才怀疑到Jenkins任务结束时候自动关掉了所有的子进程。通过以下shell脚本片段解决了问题:

1.第一种方案: #临时改变BUILD_ID值,使得Jenkins不会找到并结束掉python脚本启动的后台进程
OLD_BUILD_ID=$BUILD_ID
echo $OLD_BUILD_ID
BUILD_ID=dontKillMe
./run.sh restart
#改回原来的BUILD_ID值
BUILD_ID=$OLD_BUILD_ID
echo $BUILD_ID

问题的根本在于是Jenkins使用processTreeKiller杀掉了所有子进程,而且这是Jenkins的默认行为。其实回头来看这个问题,就发现Jenkins的做法非常合理。当一次build异常结束,或被人终止时,必然需要结束所有这次build启动的子进程。下面的link提供了更多细节,以及解决方法。https://wiki.jenkins-ci.org/display/JENKINS/ProcessTreeKiller

2.第二种方案:

使用jenkins的批处理或者ant 启动tomcat失败。查了一下原因说是 jenkins在脚本执行结束后,就认为任务结束了,但是脚本启动的相关子程序仍然在运行。由于jenkins认为任务已经结束了,就结束了该构建相关的子进程。

解决办法:增加一个环境变量。

BUILD_ID=pleaseDontKillMe and it works like a charm。

可以添加在执行任务的节点设置中添加该变量。

解决详细步骤:

前置说明:我是通过slave节点来启动tomcat 的,所以再slave节点配置上述环境变量。

未分类

未分类

Android使用Jenkins自动化构建测试打包apk

Jenkins这东西搭建起来真是一点也不省心啊,看着别人的教程摸着石头过河,配置的东西有点多啊,稍有不慎,就构建不成功啦!即使步骤跟别人一样也会报各种乱七八糟的错误啊哈哈~~这东西只能佛系搭建~~在经历几十次的随缘构建之后,终于构建成功啦~~好感人!眼泪掉下来。。。。。。在此做下记录,造福广大群众!阿弥陀佛~~废话少说,且看如下操作:

下载Jenkins并安装

官网下载地址:https://jenkins.io/download

未分类

我们下载如图所示Window版本,下载下来是个.zip的压缩包,我们解压一下得到如下图所示文件:

未分类

双击即可开始安装,一直Next,即可安装完成。

环境变量配置

  • Java环境配置
  • Android SDK环境配置

右键此电脑-属性-高级系统设置-环境变量

在系统变量中添加 :

变量名 JAVA_HOME

变量值 E:Javajdk8 (路径根据自己实际的java安装目录选择)

变量名 ANDROID_HOME

变量值 E:AndroidSDK (路径根据自己实际的java安装目录选择)

未分类

然后在系统的Path变量中添加 :%Java_Home%bin

未分类

以上是Java环境的基本配置,作为一名Android开发攻城狮应该都知道基本操作。接下来就是重头戏啦!!!

Jenkins配置

安装完jenkins一般会自动在浏览器中打开,没有的话在浏览器输入 localhost:8080 或者 127.0.0.1:8080 页面出来后会提示选择安装插件,第一个是默认推荐的插件,第二个是自己选择要安装的插件

未分类

我们直接选默认的就好,点击第一个坐等jenkins自动安装插件

未分类

插件安装后需要创建你的账号

未分类

创建完就可以登录Jenkins控制台啦!

未分类

点击左侧 系统管理-系统设置

未分类

来到如下设置页面:

未分类

点开主目录右边的高级设置,修改一下工作空间根目录(路径任意,自己知道就行),若不改,aapt编译时会报错,因为windows版本默认的根目录在C盘底下路径过长

未分类

往下拉配置全局属性,勾选环境变量,添加如下键值对

未分类

为什么说GRADLE_USER_HOME字段要固定写呢,因为要和Gradle的配置字段一致,否则编译会报错,如果这里不进行配置Gradle会使用默认的目录,会因为默认目录路径太长导致编译报错,是不是很坑!!!

未分类

配置完点击左下角保存按钮保存配置。

回到主页面点击左侧 新建任务

未分类

输入一个任务名称,选择构建一个自由风格的软件项目,点击确定

未分类

这样在 我的视图 里就能看到创建的任务啦,点击任务,进入任务详细页面

未分类

点击配置,进行构建前的详细配置,先配置普通项General,勾选Github prooject,设置远程仓库地址,以Github为例:

未分类

然后设置 源码管理 勾选Git,添加Github项目地址,你的Github账号密码

未分类

然后设置 构建触发器 (非必需设置)设置了只是多了一种构建方式,可以勾选 触发远程构建 ,然后设置一个身份验证令牌,即可通过浏览器访问链接触发构建

未分类

如红色方框所示,有两种拼接链接的方式触发构建,你可以在浏览器中输入 localhost:8080/me/my-views/view/all/job/Test/build?token=123456 或者 /buildWithParameters?token=123456 来触发构建。

也可以勾选Poll SCM,设置每隔一段时间自动构建,我设置了每小时构建一次,如下图所示

未分类

语法参考如下:

未分类

接下来设置 构建 点击增加构建步骤,选择Invoke Gradle script

未分类

勾选Invoke Gradle,选择gradle

未分类

Tasks 填写 clean build 命令

未分类

最后设置 构建后操作 点击增加构建后操作步骤,选择Archive the artifacts

未分类

填入正则表达式路径,匹配用于存档的apk

未分类

app/build/outputs/release/*.apk的意思是匹配app/build/outputs/release路径下所有拓展名为.apk的安装包,看这路径是不是很熟悉,其实就是项目路径下apk的输出路径

未分类

存档后Jenkins-release-v1.0.0.apk就会显示在Jenkins项目最后一次成功的构建结果

未分类

到此配置基本完成,是时候构建一波了,回到任务主页,点击立即构建

未分类

左下角会出现构建进度,蓝色圆点表示成功,红色圆点表示失败,点击构建序号,下拉选择控制台输出可以查看构建日志

未分类

未分类

至此,构建就大功告成啦!

在本地的JenkinsWork工作空间目录下可以看到从Github上拉取的项目源码

未分类

构建成功打包的apk在此目录下

未分类

接下来我们可以设置让构建打包好的apk自动发布到fir,详细教程请移步至http://blog.fir.im/jenkins文章写得很详细,我就不多说了。发布到fir后,平常测试人员找你要测试包,你可以对他说:“自己去fir下载。”一脸帅气.jpg

好了,今天就分享到这,祝大家Jenkins构建之路愉快!

使用jenkins+svn自动部署java/vue项目

之前发布代码需要每次本地打包–>发到服务器–>重启tomcat等一系列操作,服务器多了会很繁琐,使用jenkins可以自动部署和统一管理,解放人力,挤出很多喝茶时间。

1、下载jenkins.war
官网地址 http://jenkins-ci.org/
下载最新版本
http://mirrors.jenkins-ci.org…

2、把下载的war包放到到服务器tomcat的webapps目录下,启动tomcat
3、启动成功后log会打印一个UUID密码,复制,登陆时用
4、输入tomact地址,进入jenkins首页,会提示自动安装需要的插件(如果不能在线安装,需要去自己下载之后上传
插件下载地址 http://updates.jenkins-ci.org…

5、创建项目
  
首页点击新建item

未分类

创建一个自由风格项目,自定义一个名称projectName,确认

未分类

6、配置svn,点击add 添加自己的svn账户

未分类

7、配置触发器(指定时间自动部署)

不需要自动触发的同学可略过此步骤,之后手动点击立即构建按钮即可
05 10 * * * 为cron表达式,表示每天上午10:05

未分类

8、设置execute shell(部署时执行的脚本)

这里用java项目举例

BUILD_ID=DONTKILLME
# ProjectName是刚才**第5步**中填入的名称,jenkins默认工作空间为/root/.jenkins/workspace
cd /root/.jenkins/workspace/projectName/
# 将代码打包
mvn package
# 将打包后的代码移到服务器的tomcat目录下,这里我自己写了一个deploy.sh去处理copy-解压-备份-重启tomcat等一系列操作
cd /root/.jenkins/workspace/projectName/target
mv projectName.war /home/shibo && deploy.sh

以上shell脚本只是举例,具体可根据自己需求更改,比如vue的话就将mvn package改为npm run build……

到这就可以保存了,然后测试一下是否可以正常使用。首页点击制定项目下三角,点击立即构建即可。

未分类

下面是我在搭建的时候遇到的一些问题,仅供参考:
1、第一次登录后下线,第二次不能用user账户登陆
解决方法:去/root/.jenkins/secrets下找到initialAdminPassword ,复制密码,用admin登陆
2、maven分布式子项目没有web.xml,导致mvn打包报错
解决方法:在pom.xml中添加

<properties>
    <failOnMissingWebXml>false</failOnMissingWebXml>
</properties>

3、execute shell中执行deploy.sh脚本时,有用到shutdown.sh和startup.sh两个命令,
发现tomcat关闭后,startup不能自动启动
原因是execute会自动kill掉tomcat
解决方法:在execute shell第一行添加BUILD_ID=DONTKILLME
4、execute shell时,有时有一些不是很重要的脚本命令出错,我们需要忽略他们,继续执行,
需要点开 高级–>设置Exit code to set build unstable = 1

Jenkins不同job之间依赖关系的两种配置方式

项目之间总有依赖,比如A Job执行完执行B Job,如下图所示,如何建立依赖呢?

未分类

配置上游

我们通常喜欢配置上游依赖,在B中配置

未分类

配置如下信息。选择在其他项目构建完成后进行构建:
Project to watch:依赖的项目名称
Trigger only if build is stable:只有在A项目构建文档后进行构建,过滤条件。

这样我们执行A项目构建,紧接着B项目也会构建。

未分类

配置下游

现在把上面的B job的配置删除了,我们在A中配置它的下游。

未分类

上面的配置下游项目变为了B,其他都一样。然后我们执行A构建,B也会在A构建完成后,进行构建。

未分类

Done!