0%

Ansible的循环控制及条件任务

Ansible Playbook的循环控制、条件控制、处理程序以及错误处理机制。

阅读全文 »

Ansible PlayBook

如何使用Ansible Playbook来执行复杂任务。其中包括要如何检查Playbook的语法。

阅读全文 »

Ansible 基础概念

Ansible的基本环境、受控主机清单、Ansible的配置文件。

阅读全文 »

HTTP协议快速了解

先不要说GET和POST,HTTP协议是什么?

HTTP超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议。所有的www文件都必须遵守这个标准,HTTP的出现是为了发送和接受html文档。

我们目前通过浏览器访问的近乎所有的网页,都是通过HTTP协议接受和发送页面和请求的。在浏览网站时,你会发现地址栏的域名前,有http://https://这样的标记,这就说明你现在正在使用http协议来访问你所看到的这个页面。

那在这里再简单说一下HTTP和HTTPS区别。

由于我们的网络环境其实并不安全,我们通过HTTP协议获取的网页或者数据很容易被中间人监听或者篡改,有时候你可能会在百度这种页面上看到出现了与页面风格极其不符的弹窗广告,一种可能是你浏览器或者系统内的弹窗广告,还有一种可能就是你的页面被别人篡改过,广告被加入到了页面中。(这时候你可以问候你的ISP服务商)

为了防止我们的数据在互联网上裸奔,HTTPS面世了。他在HTTP协议的基础上引入了SSL/TLS加密技术,有了加密技术我们的数据哪怕被劫持了,但是攻击者没有我们密钥Key也是无法解密的。但是HTTPS绝对安全吗?这世上没有绝对的安全,如果为你颁发数字证书的机构把你的密钥泄露了,这不就是穿了层衣服的数据而已?想扒还是照样扒!但是多亏有法律,证书颁发机构应该不会去做这种事情。但是若通过其他方式知道了你的算法密钥也是一个道理。

回到HTTP,我们知道目前的HTTP 1.1版本有8种请求方式/方法:

请求方式 说明
GET 向特定的路径资源发出请求
POST 向指定的路径提交数据进行处理请求,一般用于表单的提交数据
HEAD 与get请求相似的响应,但是请求体不会被返回
OPTION 返回服务器针对特定资源所支持的HTTP请求方法
PUT 向指定资源位置上传其最新内容
DELETE 请求服务器删除请求的URL所标识的资源
TRACE 回显服务器收到的请求,主要用于测试或诊断
CONNECT HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器

在这里仅介绍两种常用的请求方法GET和POST。

GET和POST请求方法

GET请求方法

向特定的路径资源发出请求。常见发起GET请求方式:通过URL请求、src/href、Form表单等。

https://yeefire.com/getinfo?userName=yeefire&password=123

GET特点很明显,地址栏上出现?并且后面通过&连接一对对的键值对的话很有可能就是GET请求。

POST请求方法

向指定的资源提交要被处理的数据,多用于提交数据。多由Form表单发起POST请求。POST请求将参数放置在request-body请求体中。

GET和POST请求方法的区别

GET POST
GET在浏览器回退时是无所谓的 POST会再次提交请求
GET产生的URL地址可以被Bookmark POST不可以
GET请求会被浏览器主动cache POST不会,除非手动设置
GET请求只能进行url编码 POST支持多种编码方式
GET请求参数会被完整保留在浏览器历史记录里 POST中的参数不会被保留
GET请求在URL中传送的参数是有长度限制的 POST么有
对参数的数据类型,GET只接受ASCII字符 POST没有限制
GET因为参数直接暴露在URL上,所以不能用来传递敏感信息 POST相对来说更安全
GET参数通过URL传递 POST放在Request body中

HTTP状态码

HTTP状态码(HTTP Status Code)是用以表示网页服务器超文本传输协议响应状态的3位数字代码,所有状态码的第一个数字代表了响应的五种状态之一。

状态码 说明
1xx 指示信息–表示请求已接收,继续处理
2xx 成功–表示请求已被成功接收、理解、接受
3xx 重定向–要完成请求必须进行更进一步的操作
4xx 客户端错误–请求有语法错误或请求无法实现
5xx 服务器端错误–服务器未能实现合法的请求

路由和视图

什么是路由?可以理解成把访问的URL绑定到自定义的方法或函数上,这个函数叫做视图函数。当访问我们的URL链接时,就会按照写好的函数去执行动作。

静态路由

我们使用route装饰器来把URL绑定到视图函数上。

1
2
3
@app.route('/hello')
def index():
return '<h1>42Team</h1>'

静态路由-2020-04-26

当用户要访问/hello时,就会进入到index()方法,将由h1标签包裹的42Team文本返回。

动态路由

和静态路由相对,上一段代码中,只有用户在访问/hello的时候才会进入到index()方法中执行,而我们访问网页时能看到很多部分地址是可变的,这就是动态路由。

1
2
3
@app.route('/say_<name>')
def say_name(name):
return '<h1>My name is {}</h1>'.format(name)

动态路由-2020-04-26

路由 URL 中放在尖括号里的内容就是动态部分,任何能匹配静态部分的 URL 都会映射到这个路由上。调用视图函数时,Flask 会将动态部分作为参数传入函数。在这个视图函数中,name 参数用于生成个性化的欢迎消息。

你也可以指定不同的数据类型映射到不同的函数上。有string,int,float,path类型。path类型有点特殊,它可以包含/正斜线,默认类型为。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@app.route('/say_<string:chars>')
def say_string(chars):
return '<h1>String is {}</h1>'.format(chars)

@app.route('/say_<int:num>')
def say_num(num):
return '<h1>Int Num is {}</h1>'.format(num)

@app.route('/say_<float:long>')
def say_float(long):
return '<h1>Long Float Num is {}</h1>'.format(long)

@app.route('/say_<path:inputs>')
def say_path(inputs):
return '<h1>Path is {}</h1>'.format(inputs)

请求-响应循环

上一个章节写了一个简单的Flask程序,那么Flask的工作方式你是否好奇?下面会简单介绍一些Flask框架的设计理念。

应用和请求上下文

Flask收到来自浏览器客户端的请求后,需要让视图函数获取到一些对象,这样才能更好地处理请求。所以Flask用请求对象来封装浏览器发送的HTTP请求,Flask使用请求上下文来临时的把某些对象变为全局可访问的对象。有了请求上下文,就可以获取得到浏览器客户端发给服务器端的HTTP请求了,其中抱恨用户提交的表单、请求头等。

1
2
3
4
5
6
7

from flask import Flask,request

@app.route('/request')
def request_test():
user_agent = request.headers.get('User-Agent')
return 'Your Browser info : {}'.format(user_agent)

request.headers.get('User-Agent')可以获得客户端使用的浏览器的一些基本信息。

user-agent-2020-04-26

如果你想用request,需要从flask中导入request。你需要注意的是在这个视图函数中,我们把request当作一个全局变量来使用了。事实上,request不可能是全局变量,假设这时候有很多用户同时访问我们的服务。如果request是全局变量的话就会导致数据混乱,所以在多线程服务器中,每个线程同时处理着不同用户客户端发过来的数据,那么必然每个线程所使用的request也是不同的。Flask使用上下文让特定变量在一个线程在他的生面周期内可以访问,并且不会干扰其他线程。

线程是可单独管理的最小指令集,进程通常使用多个活动线程,有时候还会共享内存和文件句柄等其他资源。通常多线程Web服务器例如Flask会创建一个线程池,如果有客户访问服务器,那么会从线程池中抽出一个线程处理客户端发出的请求。

在Flask中有两种上下文:

  • 应用上下文
  • 请求上下文
变量名 类型 说明
request 请求上下文 请求对象。它封装了客户端发出的HTTP请求中的内容
session 请求上下文 用户会话,它的值是字典,解决HTTP协议无法维持回话的情况。
g 应用上下文 处理请求时用作临时存储的对象,每次请求都会重设这个变量
current_app 应用上下文 当前应用的应用实例

Flask在分派请求之前激活应用和请求上下文,该请求处理完成后会将其删除,也就是说在该用户线程运行结束后,会将一些上下文删除。当应用上下文被推送后,就可以在当前线程内使用current_app和g变量。同理当激活请求上下文后当前线程也可以使用request、session请求上下文。

如果不太理解这些概念也没有关系,后续我们会经常使用到。

请求分派

服务端接收到客户端发送的请求时,要找到处理该请求的对应的视图函数,Flask会在URL映射中查找请求的URL。URL映射是URL和视图函数之间的对应关系。Flask使用@app.route()装饰器来构建。

1
2
3
@app.route('/hello')
def index():
return '<h1>42Team</h1>'

/helloURL映射到index()视图函数中。如果你有点忘记了视图函数和路由这些概念你可以回去看看《路由和视图》。完整的路由和视图操作叫做请求分派。

request请求对象

Flask通过请求上下文request来对外开放请求对象。请求对象很有用,它包含了客户端浏览器发送的HTTP全部请求信息。下表中列出所有请求对象常用属性和方法。

属性或方法 返回类型 说明
form 字典 存储请求提交的所有表单字段
args 字典 存储通过URL查询字符串传递的所有参数
values 字典 formargs的合集
cookies 字典 存储请求的所有cookie
headers 字典 存储请求的所有HTTP请求头
files 字典 存储请求上传的所有文件
method 字符串 返回当前HTTP请求方法
is_secure 布尔 是否使用可靠的HTTPS加密连接
endpoint 字符串 返回处理当前请求的视图函数的函数名
scheme 字符串 URL 方案(http 或 https)
host 字符串 请求定义的主机名,如果客户端其定义了端口号,还包括端口号
remote_addr 字符串 客户端的发送HTTP请求的IP地址
path 字符串 URL的路径部分
url 字符串 客户端请求的完成URL
get_data() 返回请求主体缓冲的数据

请求钩子

使用请求钩子可以在处理视图函数前进行额外的操作,可以用于建立数据库连接或者验证用户身份。当然也可以请求结束后执行的额外的操作,比如关闭数据库连接等。

请求钩子 说明
before_request 在每次请求前执行
before_first_request 仅第一次请求时执行
after_request 如果没有未处理的异常,会在请求结束后执行
teardown_request 即使有未处理的异常,也会在请求结束后执行

在钩子函数和视图函数之间共享数据一般使用上下文全局变量g。例如before_request 处理程序可以从数据库中加载已登录用户,并将其保存到 g.user 中。随后调用视图函数时,便可以通过 g.user 获取用户。

响应

Flask在调用视图函数后,会将其返回值作为相应内容。多数情况下,响应就是返回一个HTML页面或者JSON数据。

HTTP协议中不仅仅要有请求响应的字符串,还有一个部分叫做状态码,这个在HTTP协议快速了解章节中提到过。Flask默认正常情况下的状态码是200,表明请求已经被正确的处理。

如果视图函数需要返回一个指定的状态码,那么在字符串后方,加入加入第二个参数。将返回码作为第二个参数返回到页面上。

当然你也可以添加第三个参数,在这里返回你自定义的响应首部,也就是响应头。

1
2
3
@app.route('/return_code')
def return_code():
return 'Where Is Status Code ?', 233 , {'Are you ok ':'Yeah!'}

如果不想每次都在return后面接上这些参数组成的远足你也可以使用Flask视图函数提供的make_response()函数,将上述的三个参数传入进这个函数,等效于我们直接在return后面写。

1
2
3
4
5
6
7
8
from flask import make_response

@app.route('/')
def index():
response = make_response('Where Is Status Code ?', 233 , {'Are you ok ':'Yeah!'})
response.set_cookie('', '42')
return responseanswer

响应头-2020-04-26

常见的响应对象如下表格。

属性或方法 说明
status_code HTTP数字状态码
headers 包含随响应发送的所有首部
content_length 响应主体的长度
set_data() 使用字符串或字节值设定响应
set_cookie() 为响应添加一个cookie
delete_cookie() 删除一个cookie

重定向

有一个特殊的响应叫重定向,这种响应没有页面,但是会告诉浏览器一个新的URL,用来加载新页面。重定向的HTTP状态码通常是302。

可以通过redirect()函数来返回重定向响应。

1
2
3
4
5
from flask import redirect

@app.route('/redirect')
def do_redirect():
return redirect('/hello')

你也可以自己定义重定向,不过既然已经有提供好的函数就不要使用自定义重定向的方式了。

1
2
response.status_code=302
response.headers['Location']='/hello'

返回错误

还有一种特殊的响应由 abort() 函数生成,用于处理错误。下面这里例子中,如果user路径后方参数不是root,那么会返回HTTP500状态码(服务器内部错误)。

1
2
3
4
5
6
7
from flask import abort

@app.route('/user/<user>')
def get_user(user):
if user != 'root':
abort(500)
return '<h1>Hello, {}</h1>'.format(user)

注意abort()的参数必须是异常的状态码。服务器会根据错误码自动生成错误描述。而且一旦使用了abort()那么控制权就不会是调用它的函数了,它会直接抛出相应的异常。


42Team Flask框架

前排提示

《42Team-Flask框架》系列教程仅限大连东软信息学院网络中心所属的42Team社团内部使用,该系列文档属于内部资料,仅用于所有42Team社团成员学习使用。

最近一次的更新日期:2020年4月24日

本次更新内容:请求与响应

阅读全文 »

Flask介绍

什么是Web框架?

随着Web项目发展的越来越快,传统Web项目开发也就变得越来越复杂,需要花上大量的开发时间,所以为了简化传统Web开发流程,Web框架横空出世。你可以理解为Web框架把一些基础、经常需要的代码进行了第二次的封装,我们不再需要大量的重复代码去实现功能了。仅用Web框架提供给我们的方法去实现功能就好。或者说我们不用再关心底层是如何实现的,省下的时间来关注如何给用户返回一份满意的数据即可。每个Web框架都有一些核心的思想,例如Flask框架就是为了让Web框架更精简、更高效而与大家见面的。

Flask框架特点

小、精、能干。俗称小钢炮!

FLask原生并不支持数据库访问、Web表单验证和用户验证等高级功能,这些功能需要通过拓展的形式去实现,然后再进行集成。我们作为开发者,可以任意挑选符合项目需求的拓展,这样可以让我们按需使用各类模块到我们开发的系统中,更精简、高效。

Flask框架本身只包含路由分发,请求和响应的封装和插件系统,在加上作者自己的Werkzeug(处理WSGI)、jinja2(模板引擎)和Flask-SQLAlchemy扩展(Model层),这几个同一个作者的项目构成一个完整的MVC框架。

Flask是什么?不是什么?

下面引用一段官方文档中的话。

Flask 永远不会包含数据库层,也不会有表单库或是这个方面的其它东西。 Flask 本身只是 Werkezug 和 Jinja2 的之间的桥梁,前者实现一个合适的 WSGI 应用,后者处理模板。 当然, Flask 也绑定了一些通用的标准库包,比如 logging 。 除此之外其它所有一切都交给扩展来实现。

为什么呢?因为人们有不同的偏好和需求, Flask 不可能把所有的需求都囊括在核心里。大多数 web 应用会需要一个模板引擎。然而不是每个应用都需要一个 SQL 数据库的。

Flask 的理念是为所有应用建立一个良好的基础,其余的一切都取决于你自己或者扩展。

FLask框架应用场景

理论上所有的场景都可以覆盖得到,从上面的介绍你也知道了,Flask是一个轻量级的Web框架,那么面对的应用场景最好也是轻量级的。如果想使用Flask框架构建一个大型Web应用当然也是没有问题的,但到那时候你应该需要考虑一下要不要换成Django框架了,面对大型Web项目Python阵营中的Django或许更适合。

那么Flask应用场景最好是:轻量级的环境、前后端分离架构或者是仅作为一个API服务等等。

目前面向校内师生的项目,算是一个小型项目,所以我们学习使用Flask来开启Web的大门是个不错的选择。


返回目录

使用Pycharm来构建一个全新的Flask项目

在学习了Python基础时,已经使用过了Pycharm,Pycharm的使用我不在赘述。在这里我会以截图和视频的方式为将Flask的第一步带领大家一起完成。

打开Pycharm

打开Pycharm界面-2020-04-17

如果你打开后直接进入了原有项目的编码页面,没关系。找到File菜单,选择New Project...之后跟着下一步去操作就好。

如果界面和我的一样,那么你选择Create New Project来创建一个新的项目。

新建项目

新建项目-2020-04-17

进到新建项目的界面,要注意几个点:

  • 左侧首先要选择的Flask
  • 选择Flask后你需要选一个项目存放位置(Location),没有特殊需求那就使用默认的Location
  • 展开Project Interpreter,确保使用了New enviroment using Virtualenv虚拟环境来构建我们的Flask项目

之后点击CREATE按钮来创建项目。

Pycharm创建项目中……

开始创建虚拟环境和Flask项目-2020-04-17

创建完成

创建完项目之后你会看到这样的界面,并且在代码编辑区域没有任何报错,并且在底部的Terminal终端区域可以看到每行命令有(venv)的标示。证明此时此刻你的虚拟环境和Flask框架已经安装并成功的创建了项目。

创建完成-2020-04-17

初始项目目录结构

项目初始目录结构-2020-04-17

在项目初始结构你会看到这些目录结构:

  • static Web静态文件的存储目录(图片资源、JS、CSS等)
  • templates 页面模版文件存储目录
  • venv 虚拟环境的工作目录(不需要人为干预)

以及单独的一个app.py文件

开启调试模式

右上角的运行环境有一个下拉框,选择配置环境选项。

更改运行环境信息-2020-04-17

在弹出的配置环境窗口中勾选上勾选调试模式,调试模式可以让在开发过程中遇到错误的情况下将错误信息和详细的数据返回到页面上,方便开发时排除错误。

但是切记!不要在生产环境中使用调试模式,否则会泄漏源代码中信息,如果被别有用心之人利用并且发起攻击则后果很严重。

勾选调试模式-2020-04-17


返回目录

How to install RHEL8(Centos) on Dell R710/R610 server

When I install RHEL8.x I cound’t discover my RAID Controller’s devices on Install Storage set-up optional.When I try to google find the resolutions I know a large number of storage controller device’s drivers has been removed from RHEL8,which means the Dell R710/R610 installed H700 RAID controller card won’t be supported RHEL 8.X natively.

Nevertheless you can still install RHEL8 on these machines with use of driver update disk(DUD).

Setup DUD

Using this link below ,you are specifically looking for the megaraid_sas drivers.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
dmesg | grep raid
[ 3.702959] megaraid_sas: loading out-of-tree module taints kernel.
[ 3.703082] megaraid_sas: module verification failed: signature and/or required key missing - tainting kernel
[ 3.705684] megaraid_sas 0000:03:00.0: FW now in Ready state
[ 3.705687] megaraid_sas 0000:03:00.0: 63 bit DMA mask and 32 bit consistent mask
[ 3.705915] megaraid_sas 0000:03:00.0: firmware supports msix : (0)
[ 3.705918] megaraid_sas 0000:03:00.0: current msix/online cpus : (1/16)
[ 3.705919] megaraid_sas 0000:03:00.0: RDPQ mode : (disabled)
[ 3.750024] megaraid_sas 0000:03:00.0: controller type : MR(512MB)
[ 3.750027] megaraid_sas 0000:03:00.0: Online Controller Reset(OCR) : Enabled
[ 3.750029] megaraid_sas 0000:03:00.0: Secure JBOD support : No
[ 3.750030] megaraid_sas 0000:03:00.0: NVMe passthru support : No
[ 3.750032] megaraid_sas 0000:03:00.0: FW provided TM TaskAbort/Reset timeout : 0 secs/0 secs
[ 3.750036] megaraid_sas 0000:03:00.0: megasas_init_mfi: fw_support_ieee=67108864
[ 3.750069] megaraid_sas 0000:03:00.0: INIT adapter done
[ 3.750071] megaraid_sas 0000:03:00.0: Jbod map is not supported megasas_setup_jbod_map 5389
[ 3.795034] megaraid_sas 0000:03:00.0: pci id : (0x1000)/(0x0079)/(0x1028)/(0x1f17)
[ 3.795039] megaraid_sas 0000:03:00.0: unevenspan support : no
[ 3.795041] megaraid_sas 0000:03:00.0: firmware crash dump : no
[ 3.795042] megaraid_sas 0000:03:00.0: jbod sync map : no

If you specific DUD drivers that you need for RHEL8 is below address to download.

https://elrepo.org/linux/dud/el8/x86_64/dd-megaraid_sas-07.707.51.00-1.el8_1.elrepo.iso

When you downloaded the DUD ISO driver.Using the dd to burn it in another USB or DVD media devices.

dd if=dd-megaraid_sas-07.707.51.00-1.el8_1.elrepo.iso of=/dev/sdc

Installation System

The install process is as follows:

  • Download RHEL8.x media file and burn to usb or dev devices media.
  • Download DUD drivers in iso format and burn to usb drive.
  • Boot with both RHEL8 and DUD mounted before booting Install RHEL.
  • Installer should detect the DUD iso and install the proper drivers.

During booting RHEL8 Installer and When you see a countdown on the screen.At this time interrupt the installer with the TAB key and append the following to your boot options last.

inst.dd=/dev/sdb

On my system, the DUD was /dev/sdb and the RHEL8 install media was /dev/sda.

Soon after you can view the RAID Devices find it out.

Install it usually.