linux 扩容swap分区

linux 扩容swap分区

  1. 扩容swap分区

    1
    2
    3
    4
    扩容swap分区,有三种方式:
    方式一: 扩展正在使用的Swap分区的逻辑卷(lvm)
    方式二: 新建Swap分区(lvm)
    方式三: 新建swap file(dd)
  2. 方式三: 新建swap file(dd)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    //创建交换分区文件(60G)
    dd if=/dev/zero of=/swapfile bs=1024 count=62914560

    //格式化swapfile
    mkswap -f /swapfile

    //实现开机自动挂载交换文件
    echo '/swapfile swap swap defaults 0 0'|tee -a /etc/fstab

    //启用swapfile
    swapon /swapfile

    //查看swap
    free -m
    cat /proc/swaps

    //删除swap交换分区
    a.禁用swapfile
    swapoff /swapfile
    b.从/etc/fstab 中删除项目
    c.使用fdisk或yast工具删除分区。
  3. 扩展正在使用的Swap分区的逻辑卷(lvm)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    //关闭该卷的Swap分区
    swapoff -v /dev/VolGroup00/LogVol01

    //为该卷的容量增加1024M
    lvm lvresize /dev/VolGroup00/LogVol01 -L +1024M

    //格式化Swap分区
    mkswap /dev/VolGroup00/LogVol01

    //启用Swap分区
    swapon -va

    //验证结果
    free -m
  4. 方式二: 新建Swap分区(lvm)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    //新建一个1024M大小的逻辑卷
    lvm lvcreate VolGroup00 -n LogVol02 -L 1024M

    //格式化成Swap分区
    mkswap /dev/VolGroup00/LogVol02

    //将这个分区信息写进fstab文件(相当于分区表)
    echo '/dev/VolGroup00/LogVol02 swap swap defaults 0 0'|tee -a /etc/fstab

    //启动Swap分区
    swapon -va

    //验证结果
    free -m

HTTP协议

HTTP协议

  1. HTTP 简介
    1
    2
    3
    4
    HTTP协议是 Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web)服务器传输超文本到本地浏览器的传送协议.
    HTTP是一个基于TCP/IP通信协议来传递数据(HTML 文件,图片文件,查询结果等)
    HTTP是一个属于应用层的面向对象的协议,由于其简捷,快速的方式,适用于分布式超媒体信息系统.它于1990年提出,经过几年的使用与发展,得到不断地完善和扩展.目前在WWW中使用的是HTTP/1.0的第六版,HTTP/1.1的规范化工作正在进行之中,而且HTTP-NG(Next Generation of HTTP)的建议已经提出
    HTTP协议工作于客户端-服务端架构为上.浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求.Web服务器根据接收到的请求后,向客户端发送响应信息

HTTP请求响应

  1. HTTP 主要特点

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    1.简单快速
    客户向服务器请求服务时,只需传送请求方法和路径
    请求方法常用的有GET,HEAD,POST.每种方法规定了客户与服务器联系的类型不同.
    由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快

    2.灵活
    HTTP允许传输任意类型的数据对象.正在传输的类型由Content-Type加以标记

    3.无连接
    无连接的含义是限制每次连接只处理一个请求
    服务器处理完客户的请求,并收到客户的应答后,即断开连接.采用这种方式可以节省传输时间

    4.无状态
    HTTP协议是无状态协议.无状态是指协议对于事务处理没有记忆能力.
    缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大.
    另一方面,在服务器不需要先前信息时它的应答就较快

    5.支持B/S及C/S模式
  2. HTTP URL

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    HTTP使用统一资源标识符(Uniform Resource Identifiers,URI)来传输数据和建立连接.

    URL(Uniform Resource Locator,统一资源定位符)是一种特殊类型的URI,包含了用于查找某个资源的足够的信息
    URL,全称是,是互联网上用来标识某一处资源的地址.

    例如:
    普通URL的各部分组成:
    http://www.smallasa.com:8080/news/index.asp?boardID=5&ID=24618&page=1#name

    一个完整的URL包括以下几部分:
    1.协议部分
    该URL的协议部分为"http:",这代表网页使用的是HTTP协议
    在Internet中可以使用多种协议,如:HTTP,FTP等等.
    在"HTTP"后面的"//"为分隔符
    2.域名部分
    该URL的域名部分为"www.smallasa.com"
    一个URL中,也可以使用IP地址作为域名使用
    3.端口部分
    跟在域名后面的是端口,域名和端口之间使用":"作为分隔符
    端口不是一个URL必须的部分,如果省略端口部分,将采用默认端口
    4.虚拟目录部分
    从域名后的第一个"/"开始到最后一个"/"为止,是虚拟目录部分
    虚拟目录也不是一个URL必须的部分
    本例中的虚拟目录是"/news/"
    5.文件名部分
    从域名后的最后一个"/"开始到"?"为止,是文件名部分.
    如果没有"?",则是从域名后的最后一个"/"开始到"#"为止,是文件部分
    如果没有"?"和"#",则是从域名后的最后一个"/"开始到结束,都是文件名部分
    文件名部分也不是一个URL必须的部分,如果省略该部分,则使用默认的文件名
    本例中的文件名是"index.asp"
    6.锚部分
    从"#"开始到最后,都是锚部分
    锚部分也不是一个URL必须的部分
    本例中的锚部分是"name"
    7.参数部分
    从"?"开始到"#"为止之间的部分为参数部分,又称搜索部分,查询部分
    参数可以允许有多个参数,参数与参数之间用"&"作为分隔符
    本例中的参数部分为"boardID=5&ID=24618&page=1"
  3. URI 和 URL 的区别

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    * URI(uniform resource identifier),统一资源标识符,用来标识唯一的一个资源
    Web上可用的每种资源,如: HTML文档,图像,视频片段,程序等都是一个来URI来定位的
    URI一般由三部组成:
    * 访问资源的命名机制
    * 存放资源的主机名
    * 资源自身的名称,由路径表示,着重强调于资源

    * URL(uniform resource locator),统一资源定位器,它是一种具体的URI,即URL可以用来标识一个资源,而且还指明了如何locate这个资源
    URL是Internet上用来描述信息资源的字符串,主要用在各种WWW客户程序和服务器程序上,特别是著名的Mosaic
    采用URL可以用一种统一的格式来描述各种信息资源,包括文件,服务器的地址和目录等
    URL一般由三部组成:
    * 协议(或称为服务方式)
    * 存有该资源的主机IP地址(有时也包括端口号)
    * 主机资源的具体地址.如目录和文件名等

    * URN(uniform resource name),统一资源命名,是通过名字来标识资源,比如"mailto:java-net@java.sun.com"

    综上,
    URI是以一种抽象的,高层次概念定义统一资源标识,而URL和URN则是具体的资源标识的方式.
    URL和URN都是一种URI.
    笼统地说,每个URL都是URI,但不一定每个URI都是URL.这是因为URI还包括一个子类,即统一资源名称(URN),它命名资源,但不指定如何定位资源.
  4. HTTP之请求消息Request

    1
    2
    3
    4
    5
    客户端发送一个HTTP请求到服务器的请求消息包括以下格式:
    * 请求行(request line)
    * 请求头部(header)
    * 空行
    * 请求数据

HTTP请求消息结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
请求行以一个方法符号开头,以空格分开,后面跟着请求的URI和协议的版本

GET请求例子:
GET /562f25980001b1b106000338.jpg HTTP/1.1
Host img.mukewang.com
User-Agent Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36
Accept image/webp,image/*,*/*;q=0.8
Referer http://www.imooc.com/
Accept-Encoding gzip, deflate, sdch
Accept-Language zh-CN,zh;q=0.8

第一部分: 请求行,用来说明请求类型,要访问的资源以及所使用的HTTP版本
* GET说明请求类型为GET
* "/562f25980001b1b106000338.jpg"为要访问的资源
* 该行的最后一部分说明使用的是HTTP1.1版本
第二部分: 请求头部,紧接着请求行之后的部分,用来说明服务器要使用的附加信息
* HOST将指出请求的目的地
* User-Agent,服务器端和客户端脚本都能访问它,它是浏览器类型检测逻辑的重要基础.该信息由你的浏览器来定义,并且在每个请求中自动发送等等
第三部分: 空行
请求头部后面的空行是必须的
即使第四部分的请求数据为空,也必须有空行
第四部分: 请求数据也叫主体,可以添加任意的其他数据


POST请求例子:
POST / HTTP1.1
Host:www.wrox.com
User-Agent:Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)
Content-Type:application/x-www-form-urlencoded
Content-Length:40
Connection: Keep-Alive

name=Professional%20Ajax&publisher=Wiley

第一部分: 请求行,第一行明了是post请求,以及http1.1版本
第二部分: 请求头部
第三部分: 空行
第四部分: 请求数据

  1. HTTP之响应消息Response
    1
    2
    3
    4
    5
    6
    一般情况下,服务器接收并处理客户端发过来的请求后会返回一个HTTP的响应消息
    HTTP响应也由四个部分组成:
    * 状态行
    * 消息报头
    * 空行
    * 响应正文

HTTP响应消息结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
响应请求例子:
HTTP/1.1 200 OK
Date: Fri, 22 May 2009 06:07:21 GMT
Content-Type: text/html; charset=UTF-8

<html>
<head></head>
<body>
<!--body goes here-->
</body>
</html>


第一部分: 状态行,由HTTP协议版本号,状态码,状态消息三部分组成
* "HTTP/1.1"表明HTTP版本为1.1版本
* 200 表示状态码
* "ok" 表示状态消息
第二部分: 消息报头,用来说明客户端要使用的一些附加信息
* Date 生成响应的日期和时间
* Content-Type 指定了MIME类型的HTML(text/html),编码类型是UTF-8
第三部分: 空行,消息报头后面的空行是必须的
第四部分: 响应正文,服务器返回给客户端的文本信息

  1. HTTP之状态码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    状态代码有三位数字组成,第一个数字定义了响应的类别,共分五种类别:
    1xx: 指示信息,表示请求已接收,继续处理
    2xx: 成功,表示请求已被成功接收,理解,接受
    3xx: 重定向,要完成请求必须进行更进一步的操作
    4xx: 客户端错误,请求有语法错误或请求无法实现
    5xx: 服务器端错误,服务器未能实现合法的请求

    常见状态码:
    200 OK //客户端请求成功
    400 Bad Request //客户端请求有语法错误,不能被服务器所理解
    401 Unauthorized //请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用
    403 Forbidden //服务器收到请求,但是拒绝提供服务
    404 Not Found //请求资源不存在,输入了错误的URL
    500 Internal Server Error //服务器发生不可预期的错误
    503 Server Unavailable //服务器当前不能处理客户端的请求,一段时间后可能恢复正常
  2. HTTP请求方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    根据HTTP标准,HTTP请求可以使用多种请求方法:
    HTTP1.0定义了三种请求方法: GET,POST,HEAD
    HTTP1.1新增了五种请求方法: OPTIONS,PUT,DELETE,TRACE,CONNECT

    GET 请求指定的页面信息,并返回实体主体
    HEAD 类似于GET请求,只不过返回的响应中没有具体的内容,用于获取报头
    POST 向指定资源提交数据进行处理请求,数据被包含在请求体中.POST请求可能会导致新的资源的建立或对已有资源的修改
    PUT 从客户端向服务器传送的数据取代指定的文档的内容
    DELETE 请求服务器删除指定的页面
    CONNECT HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器
    OPTIONS 允许客户端查看服务器的性能
    TRACE 回显服务器收到的请求,主要用于测试或诊断
  3. HTTP工作原理

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    HTTP协议定义WEB客户端如何从WEB服务器请求WEB页面,以及服务器如何把Web页面传送给客户端

    HTTP协议采用了"请求/响应"模型:
    客户端向服务器发送一个请求报文,请求报文包含请求的方法,URL,协议版本,请求头部和请求数据
    服务器以一个状态行作为响应,响应的内容包括协议的版本,成功或者错误代码,服务器信息,响应头部和响应数据


    HTTP请求/响应的步骤:
    1.客户端连接到WEB服务器
    一个HTTP客户端(通常是浏览器)与WEB服务器的HTTP端口(默认为80)建立一个TCP套接字连接
    例如,http://www.baidu.com
    2.发送HTTP请求
    通过TCP套接字,客户端向WEB服务器发送一个文本的请求报文
    一个请求报文由请求行,请求头部,空行和请求数据4部分组成
    3.服务器接受请求并返回HTTP响应
    WEB服务器解析请求,定位请求资源.服务器将资源复本写到TCP套接字,由客户端读取.
    一个响应由状态行,响应头部,空行和响应数据4部分组成
    4.释放连接TCP连接
    若connection模式为close,则服务器主动关闭TCP连接,客户端被动关闭连接,释放TCP连接
    若connection模式为keepalive,则该连接会保持一段时间,在该时间内可以继续接收请求
    5.客户端浏览器解析HTML内容
    客户端浏览器首先解析状态行,查看表明请求是否成功的状态代码.
    然后解析每一个响应头,响应头告知以下为若干字节的HTML文档和文档的字符集
    最后客户端浏览器读取响应数据HTML,根据HTML的语法对其进行格式化,并在浏览器窗口中显示


    例如: 在浏览器地址栏键入URL,按下回车之后会经历如下流程
    1. 浏览器向DNS服务器请求解析该URL中的域名所对应的IP地址
    2. 解析出IP地址后,根据该IP地址和端口(默认80)与服务器建立TCP连接
    3. 浏览器发出读取文件的HTTP请求,该请求报文作为TCP三次握手的第三个报文的数据发送给服务器
    4. 服务器对浏览器请求作出响应,并把对应的html文本发送给浏览器
    5. 释放TCP连接
    6. 浏览器解析html文本并显示内容
  4. GET和POST请求的区别

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    GET请求:
    GET /books/?sex=man&name=Professional HTTP/1.1
    Host: www.wrox.com
    User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)
    Gecko/20050225 Firefox/1.0.1
    Connection: Keep-Alive
    最后一行是空行

    POST请求:
    POST / HTTP/1.1
    Host: www.wrox.com
    User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)
    Gecko/20050225 Firefox/1.0.1
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 40
    Connection: Keep-Alive

    name=Professional%20Ajax&publisher=Wiley

    1.GET和POST提交差异
    * GET提交
    请求的数据会附在URL之后(就是把数据放置在HTTP协议头中),以"?"分割URL和传输数据,多个参数用&连接
    例如:
    "login.action?name=hyddd&password=idontknow&verify=%E4%BD%A0%E5%A5%BD"
    如果数据是英文字母/数字,原样发送
    如果数据是空格,转换为+
    如果数据是中文/其他字符,则直接把字符串用BASE64加密,得出"%E4%BD%A0%E5%A5%BD",其中"%XX"中的XX为该符号以16进制表示的ASCII
    * POST提交
    把提交的数据放置在是HTTP包的包体中
    示例中:
    "name=Professional%20Ajax&publisher=Wiley"
    因此,GET提交的数据会在地址栏中显示出来,而POST提交,地址栏不会改变

    2.传输数据的大小
    首先声明: HTTP协议没有对传输的数据大小进行限制,HTTP协议规范也没有对URL长度进行限制

    在实际开发中存在的限制主要有:
    * GET
    特定浏览器和服务器对URL长度有限制
    因此对于GET提交时,传输数据就会受到URL长度的限制
    例如:IE对URL长度的限制是2083字节(2K+35)
    * POST
    由于不是通过URL传值,理论上数据不受限
    但实际各个WEB服务器会规定对post提交数据大小进行限制,Apache,Nginx,IIS6都有各自的配置

    3.安全性
    POST的安全性要比GET的安全性高
    比如: 通过GET提交数据,用户名和密码将明文出现在URL上.因为登录页面有可能被浏览器缓存,其他人查看浏览器的历史纪录就可以拿到你的账号和密码.除此之外,使用GET提交数据还可能会造成"Cross-site request forgery"攻击

    4.HTTP GET,POST,SOAP协议都是在HTTP上运行的
    * GET,请求参数是作为一个key/value对的序列附加到URL上的
    查询字符串的长度受到WEB浏览器和WEB服务器的限制,不适合传输大型数据集,同时它很不安全
    * POST,请求参数是在HTTP标题的一个不同部分(entity body)传输的,这一部分用来传输表单信息,因此必须将"Content-type"设置为"application/x-www-form-urlencoded"
    POST设计用来支持WEB窗体上的用户字段,其参数也是作为key/value对传输.但是,它不支持复杂数据类型.因为POST没有定义传输数据结构的语义和规则
    * SOAP,是HTTP POST的一个专用版本,遵循一种特殊的xml消息格式,"Content-type"设置为"text/xml",任何数据都可以xml化

    HTTP协议定义了很多与服务器交互的方法,最基本的有4种: GET,POST,PUT,DELETE.
    一个URL地址用于描述一个网络上的资源,而HTTP中的GET,POST,PUT,DELETE就对应着对这个资源的查,改,增,删4个操作
    我们最常见的就是GET和POST了.GET一般用于获取/查询资源信息,而POST一般用于更新资源信息

    GET和POST的区别:
    * GET提交的数据会放在URL之后,以"?"分割URL和传输数据.参数之间以&相连,而POST方法是把提交的数据放在HTTP包的Body中
    * GET提交的数据大小有限制(因为浏览器对URL的长度有限制),而POST方法提交的数据没有限制
    * GET方式需要使用Request.QueryString来取得变量的值,而POST方式通过Request.Form来获取变量的值
    * GET方式提交数据,会带来安全问题,而POST不会

git errror

git error

  1. git pull error
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    [root@dev yaya]# git pull
    There is no tracking information for the current branch.
    Please specify which branch you want to merge with.
    See git-pull(1) for details

    git pull <remote> <branch>

    If you wish to set tracking information for this branch you can do so with:

    git branch --set-upstream-to=origin/<branch> release


    解决方法:
    [root@dev yaya]# git branch
    dev
    master
    * release

    [root@dev yaya]# git branch -a
    dev
    master
    * release
    remotes/origin/HEAD -> origin/master
    remotes/origin/dev
    remotes/origin/master
    remotes/origin/release

    [root@dev yaya]# git branch --set-upstream-to=origin/release
    Branch release set up to track remote branch release from origin.

    [root@dev yaya]# git pull
    Already up-to-date.

python error info

python 错误信息

  1. python SNIMissingWarning 错误信息
    1
    2
    3
    4
    5
    6
    7
    8
    错误信息:
    [root@rabbitmq zabbix]# pip search redis
    /usr/lib/python2.7/site-packages/pip/_vendor/requests/packages/urllib3/util/ssl_.py:318: SNIMissingWarning: An HTTPS request has been made, but the SNI (Subject Name Indication) extension to TLS is not available on this platform. This may cause the server to present an incorrect TLS certificate, which can cause validation failures. You can upgrade to a newer version of Python to solve this. For more information, see https://urllib3.readthedocs.io/en/latest/security.html#snimissingwarning.
    SNIMissingWarning
    /usr/lib/python2.7/site-packages/pip/_vendor/requests/packages/urllib3/util/ssl_.py:122: InsecurePlatformWarning: A true SSLContext object is not available. This prevents urllib3 from configuring SSL appropriately and may cause certain SSL connections to fail. You can upgrade to a newer version of Python to solve this. For more information, see https://urllib3.readthedocs.io/en/latest/security.html#insecureplatformwarning.

    解决方法:
    pip install pyOpenSSL ndg-httpsclient pyasn1

git workflow

git 工作流程

  1. 设置用户信息

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    [root@dev ~]# git config --global user.name "smallasa"
    [root@dev ~]# git config --global user.email "smallasa@sina.com"
    [root@dev ~]# git config --global push.default simple
    [root@dev ~]# git config --global http.postBuffer 24288000

    [root@dev ~]# git config --list
    user.email=smallasa@sina.com
    user.name=smallasa
    push.default=simple
    http.postbuffer=24288000
  2. 克隆版本库

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    [root@dev ~]# git clone http://github.com/smallasa/yaya.git
    Cloning into 'yaya'...
    Username for 'http://github.com': smallasa
    Password for 'http://smallasa@github.com':
    remote: Counting objects: 3, done.
    remote: Total 3 (delta 0), reused 0 (delta 0)
    Unpacking objects: 100% (3/3), done.

    或者:
    [root@dev ~]# git clone http://{USER}:{PASSWD}@github.com/smallasa/yaya.git
  3. 查看当前分支

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    [root@dev ~]# cd yaya/
    //查看本地分支
    [root@dev yaya]# git branch
    * master
    //查看远程分支
    [root@dev yaya]# git branch -a
    * master
    remotes/origin/HEAD -> origin/master
    remotes/origin/master

    补充: 删除分支
    [root@dev yaya]# git push origin --delete dev
    [root@dev yaya]# git push origin :release
  4. 创建分支

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    方法一:
    [root@dev yaya]# git branch release
    [root@dev yaya]# git branch
    * master
    release
    [root@dev yaya]# git checkout release
    Switched to branch 'release'
    [root@dev yaya]# git branch
    master
    * release

    方法二:
    [root@dev yaya]# git checkout -b dev
    Switched to a new branch 'dev'

    [root@dev yaya]# git branch
    * dev
    master
    release
  5. 将分支推送到远端仓库上

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    [root@dev yaya]# git branch -a
    dev
    * master
    release
    remotes/origin/HEAD -> origin/master
    remotes/origin/master

    [root@dev yaya]# git push origin release
    Username for 'http://github.com': smallasa
    Password for 'http://smallasa@github.com':
    Total 0 (delta 0), reused 0 (delta 0)
    To http://github.com/smallasa/yaya.git
    * [new branch] release -> release

    [root@dev yaya]# git branch -a
    dev
    * master
    release
    remotes/origin/HEAD -> origin/master
    remotes/origin/master
    remotes/origin/release
  6. 在release分支提交一个新文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    [root@dev yaya]# git checkout release
    [root@dev yaya]# echo '第一次发布版本' |tee -a a.txt
    [root@dev yaya]# git add a.txt
    [root@dev yaya]# git commit -m "add a.txt"

    [root@dev yaya]# git log -1
    commit 88d1fce9a2ce84f8fc3dce9223b81b2858d564f8
    Author: smallasa <smallasa@sina.com>
    Date: Mon Sep 11 09:02:52 2017 +0800

    第一次发布版本
  7. 对提交的内容打标签

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    [root@dev yaya]# git tag -a v1.0 -m "v1.0版本发布"
    [root@dev yaya]# git tag
    v1.0
    [root@dev yaya]# git show v1.0
    tag v1.0
    Tagger: smallasa <smallasa@sina.com>
    Date: Mon Sep 11 09:03:55 2017 +0800
    v1.0版本发布
    commit 88d1fce9a2ce84f8fc3dce9223b81b2858d564f8
    Author: smallasa <smallasa@sina.com>
    Date: Mon Sep 11 09:02:52 2017 +0800
    第一次发布版本
    diff --git a/a.txt b/a.txt
    new file mode 100644
    index 0000000..a12bebd
    --- /dev/null
    +++ b/a.txt
    @@ -0,0 +1 @@
    +第一次发布版本

    [root@dev yaya]# git push origin v1.0
    Counting objects: 5, done.
    Delta compression using up to 2 threads.
    Compressing objects: 100% (3/3), done.
    Writing objects: 100% (4/4), 470 bytes | 0 bytes/s, done.
    Total 4 (delta 0), reused 0 (delta 0)
    To http://smallasa:smallasa123@github.com/smallasa/yaya.git
    * [new tag] v1.0 -> v1.0

    补充:
    [root@dev yaya]# git push origin v1.0 //推送单个tag到远程分支
    [root@dev yaya]# git push --tags //推送所有tag到远程分支

    [root@dev yaya]# git push origin --delete tag v1.0 //删除远程分支上指定tag
    或者:
    [root@dev yaya]# git tag -d Remote_Systems_Operation
    [root@dev yaya]# git push origin :refs/tags/Remote_Systems_Operation


    [root@dev yaya]# echo '第二次发布版本'|tee -a a.txt
    [root@dev yaya]# git add a.txt
    [root@dev yaya]# git commit -m "第二次发布版本"

    [root@dev yaya]# echo '第三次发布版本'|tee -a a.txt
    [root@dev yaya]# git add a.txt
    [root@dev yaya]# git commit -m "第三次发布版本"

    [root@dev yaya]# git log
    commit cf76593438f987e61bf6dc7cd390c33edbf30804
    Author: smallasa <smallasa@sina.com>
    Date: Mon Sep 11 09:11:16 2017 +0800

    第三次发布版本

    commit 3a2b63f0786a6d16bc4bc50af132186b2d4e3fb2
    Author: smallasa <smallasa@sina.com>
    Date: Mon Sep 11 09:10:47 2017 +0800

    第二次发布版本

    commit 88d1fce9a2ce84f8fc3dce9223b81b2858d564f8
    Author: smallasa <smallasa@sina.com>
    Date: Mon Sep 11 09:02:52 2017 +0800

    第一次发布版本

    commit 7e6aa66ceec96fed7ba4b4a5e9d7d302974a987d
    Author: smallasa <smallasa@sina.com>
    Date: Wed Aug 30 12:03:04 2017 +0800

    Initial commit
  8. 回退到指定tag

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    [root@dev yaya]# git tag
    v1.0
    [root@dev yaya]# git show v1.0
    tag v1.0
    Tagger: smallasa <smallasa@sina.com>
    Date: Mon Sep 11 09:03:55 2017 +0800

    v1.0版本发布

    commit 88d1fce9a2ce84f8fc3dce9223b81b2858d564f8
    Author: smallasa <smallasa@sina.com>
    Date: Mon Sep 11 09:02:52 2017 +0800

    第一次发布版本

    diff --git a/a.txt b/a.txt
    new file mode 100644
    index 0000000..a12bebd
    --- /dev/null
    +++ b/a.txt
    @@ -0,0 +1 @@
    +第一次发布版本

    [root@dev yaya]# cat a.txt
    第一次发布版本
    第二次发布版本
    第三次发布版本

    [root@dev yaya]# git reset --hard 88d1fce9a2ce84f8fc3dce9223b81b2858d564f8
    HEAD is now at 88d1fce 第一次发布版本

    [root@dev yaya]# cat a.txt
    第一次发布版本

    注意:
    1.回退标签后,要基于回退当前目录创建一个新的分支:
    [root@dev yaya]# git checkout -b bugfix
    [root@dev yaya]# git branch
    * bugfix
    master
    release

    2.切换回原分支(此时还是回退tag位置):
    //切换回原分支,并查看当前提交日志
    [root@dev yaya]# git checkout release
    Switched to branch 'release'
    [root@dev yaya]# git log
    commit 88d1fce9a2ce84f8fc3dce9223b81b2858d564f8
    Author: smallasa <smallasa@sina.com>
    Date: Mon Sep 11 09:02:52 2017 +0800

    第一次发布版本

    commit 7e6aa66ceec96fed7ba4b4a5e9d7d302974a987d
    Author: smallasa <smallasa@sina.com>
    Date: Wed Aug 30 12:03:04 2017 +0800

    Initial commit

    //回退到第三次提交位置
    [root@dev yaya]# git reflog
    88d1fce HEAD@{0}: checkout: moving from bugfix to release
    88d1fce HEAD@{1}: checkout: moving from release to bugfix
    88d1fce HEAD@{2}: reset: moving to 88d1fce9a2ce84f8fc3dce9223b81b2858d564f8
    cf76593 HEAD@{3}: commit: 第三次发布版本
    3a2b63f HEAD@{4}: commit: 第二次发布版本
    88d1fce HEAD@{5}: commit: 第一次发布版本
    7e6aa66 HEAD@{6}: checkout: moving from master to release
    7e6aa66 HEAD@{7}: clone: from http://github.com/smallasa/yaya.git

    [root@dev yaya]# git reset --hard cf76593
    HEAD is now at cf76593 第三次发布版本

    [root@dev yaya]# cat a.txt
    第一次发布版本
    第二次发布版本
    第三次发布版本
  9. 修复bug,并合并

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    //切换到bugfix分支,修改bug
    [root@dev yaya]# git checkout bugfix
    [root@dev yaya]# echo '修复Bug' |tee -a a.txt
    [root@dev yaya]# git add a.txt
    [root@dev yaya]# git commit -m "修复Bug"
    [root@dev yaya]# git tag v2.0
    [root@dev yaya]# git tag
    v1.0
    v2.0

    //合并到release分支:
    [root@dev yaya]# git checkout release

    [root@dev yaya]# cat a.txt
    第一次发布版本
    第二次发布版本
    第三次发布版本

    [root@dev yaya]# git merge bugfix
    Auto-merging a.txt
    CONFLICT (content): Merge conflict in a.txt
    Automatic merge failed; fix conflicts and then commit the result.

    [root@dev yaya]# cat a.txt
    第一次发布版本
    <<<<<<< HEAD
    第二次发布版本
    第三次发布版本
    =======
    修复Bug
    >>>>>>> bugfix

    [root@dev yaya]# vim a.txt
    第一次发布版本
    修复Bug
    第二次发布版本
    第三次发布版本

    [root@dev yaya]# git add a.txt
    [root@dev yaya]# git commit -m "修复bug"
    [release 1adfe0e] 修复bug

    [root@dev yaya]# git push origin --tags

zabbix action tiggers

zabbix action tiggers

  1. 常用变量值
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    默认接收人:故障{TRIGGER.STATUS},服务器:{HOSTNAME1}发生: {TRIGGER.NAME}故障!

    默认信息:
    告警主机:{HOSTNAME1}
    告警时间:{EVENT.DATE} {EVENT.TIME}
    告警等级:{TRIGGER.SEVERITY}
    告警信息: {TRIGGER.NAME}
    告警项目:{TRIGGER.KEY1}
    问题详情:{ITEM.NAME}:{ITEM.VALUE}
    当前状态:{TRIGGER.STATUS}:{ITEM.VALUE1}
    事件ID:{EVENT.ID}

    恢复信息:打钩
    恢复主旨:恢复{TRIGGER.STATUS}, 服务器:{HOSTNAME1}: {TRIGGER.NAME}已恢复!

    恢复信息:
    告警主机:{HOSTNAME1}
    告警时间:{EVENT.DATE} {EVENT.TIME}
    告警等级:{TRIGGER.SEVERITY}
    告警信息:{TRIGGER.NAME}
    告警项目:{TRIGGER.KEY1}
    问题详情:{ITEM.NAME}:{ITEM.VALUE}
    当前状态:{TRIGGER.STATUS}:{ITEM.VALUE1}
    事件ID:{EVENT.ID}

python 爬虫

python 爬虫

  1. 爬虫是什么

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    爬虫概念: 在互联网上获取资源的程序

    爬虫种类:
    * 网络爬虫
    是一个自动提取网页的程序,它为搜索引擎从万维网上下载网页,是搜索引擎重要组成
    * 传统爬虫
    从一个或若干初始网页URL开始,获取初始网页上的URL,在抓取网页过程中,不断从当前页面上抽取新的URL放入队列,直到满足系统一定停止条件

    爬虫工作原理:
    * 爬虫根据一定的网页分析算法过滤与主题无关的链接,保留有用的链接并将其放入等待抓取的URL队列
    * 它将根据一定的搜索策略从队列中选择下一步要抓取的网页URL,并重复上述过程,直到满足一定条件时停止
    * 所有被爬虫抓取的网页将会被系统存储,进行一定的分析下,过滤,并建立索引,以便之后查询和检索

    爬虫策略:
    * 广度优先
    在抓取过程中,在完成当前层次的搜索后,才进行下一层的搜索
    * 最佳优先
    它只访问经过网页分析算法预测为"有用"的网页
    * 深度优先
    可能会导致"trapped"问题
  2. URL和Cookie

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    URL: 统一资源定位符,互联网上资源均有其唯一地址

    URL 构成:
    * 模式/协议/服务方式
    * 文件所在主机IP地址及端口号
    * 主机上资源位置

    浏览器如何显示网页:
    * 用户在浏览网页过程中,比如: http://image.baidu.com/ ,通常会看到显示出一系列图片及百度搜索框,这个过程其实就是用户输入网页后,经过DNS服务器,找到服务器主机,向服务器发出一个请求,服务器经过解析之后,发送给用户的浏览器HTML,JS,CSS等文件,浏览器进行解析,用户便可以看到浏览器显示的图片
    * 因此,用户看到的网页实质上是由HTML代码构成的,爬虫爬来的便是这些内容,通过分析和过滤这些HTML代码,实现对图片,文件等资源的获取

    DOM:
    * DOM将HTML文件表达为树结构
    * 定义了访问和操作HTML文档的标准

    Cookie:
    * Cookie是由服务器端产生的,发送给User-Agent(一般是浏览器),浏览器会将Cookie的key/value保存到某个目录下的文本文件内,下次访问同一网站时就发送该Cookie给服务器
    *
  3. urllib2库

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    例1:
    import urllib2
    response = urllib2.urlopen('http://www.baidu.com')
    print(response.read())

    说明:
    urlopen(url,data,timeout)
    * 第一个参数,url
    * 第二个参数,是访问url时要传送的数据
    * 第三个参数,是设置超时时间

    read方法,可以返回获取到的网页内容


    例2:
    import urllib2
    request = urlib2.Request('http://www.baidu.com')
    response = urllib2.urlopen(request)
    print(response.read())

    * urlopen参数可以传入一个request请求(request对象实例)
    说明:
    Reuest(url,data,headers)
    * 第一个参数,url
    * 第二个参数,是访问url时要传送的数据
    * 第三个参数,是headers

    http定义了与服务器交互的不同方式:
    * GET[获取/查询]
    GET方式直接以链接形式访问,链接中包含了所有参数
    * POST[更新]
    POST把提交的数据放置在试HTTP包的包体中

    Headers设置:
    * User-Agent
    部分服务器或proxy会通过该值来判断是否是浏览器发出的请求
    用于模拟浏览器
    * Content-Type
    使用REST接口时,服务器会检查该值,用来确定HTTP body中的内容该怎么解析
    * application/xml
    在XML RPC,如RESTful/SOAP调用时使用
    * application/json
    在JSON RPC调用时使用
    * application/x-www-form-urlencoded
    浏览器提交web表单时使用
  4. urllib 和 urllib2区别

    1
    2
    3
    * urllib2 可以接受一个Request类的实例来设置URL请求的headers,urllib仅可以接受URL
    * urllib提供urlencode方法来GET查询字符串产生,而urllib2没有
    urllib中的urlencode函数,可以把key-value这样的键值对转换成我们想要的格式,返回是a=1&b=2这样的字符串
  5. request库

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    例1:
    import request
    url = 'http://www.baidu.com'
    response = request.get(url)
    print(response.status_code)
    print(response['content-type'])
    print(response.content)

    * request发送请求
    r = request.get('https://github.com/timeline.json')
    r = request.post('https://github.com/post')
    * 为URL传递参数
    value = {'k1':'v1','k2':'v2'}
    r = request.get('http://github.com/get',params=value)
    print(r.url)
    * 响应内容
    r = request.get('https://github.com/timeline.json')
    print(r.text)
    * 响应状态码
    r = request.get('http://github.com/get')
    print(r.status_code)
    * 响应头
    r = request.get('http://github.com/get')
    print(r.headers)
    * Cookie
    r = request.get('http://github.com/get')
    print(r.Cookies)
    * 超时
    request.get('http://...',timeout=0.001)

    * 错误与异常
    request异常一般都继承request.exception.RequestException
    遇到网络问题,request会抛出一个ConnectionError异常
    遇到请求超时,request抛出一个timeout异常
    遇到无效http响应时,request抛出httpError异常
    遇到请求超过设定最大重定向次数,抛出TooManyRediects异常
  6. 网页内容抓取方法

    1
    2
    3
    * 正则表达式
    * Lxml
    强大的HTML与XML的python库

python 进阶

循环设计:

  1. 循环对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    >>> f = open('test.txt')
    >>> f.next()
    '123\n'
    >>> f.next()
    '456\n'
    >>> f.next()
    '789\n'
    >>> f.next()
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    StopIteration
  2. 迭代器:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    >>> a = [1,2,3]
    >>> b = iter(a)
    >>> b.next()
    1
    >>> b.next()
    2
    >>> b.next()
    3
    >>> b.next()
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    StopIteration
  3. 生成器:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    >>> def gen():
    ... a = 10
    ... yield a
    ... a = a*10
    ... yield a
    ... yield 1000
    ...
    >>> for i in gen():
    ... print i
    ...
    10
    100
    1000
  4. 生成器表达式:

    1
    2
    3
    >>> L = [ x**2 for x in range(3)]
    >>> L
    [0, 1, 4]
  5. 表推导

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    >>> G = ( x**2 for x in range(3) )
    >>> G
    <generator object <genexpr> at 0x7feb3b6fd2d0>
    >>> G.next()
    0
    >>> G.next()
    1
    >>> G.next()
    4
    >>> G.next()
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    StopIteration

动态类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
1.动态类型
* 引用
* 引用与对象分离

2. 传值(值传递)
>>> a = 1
>>> def change_i(a):
... a = a+1
... pass
... return a
...
>>> print(change_i(a))
2
>>> print(a)
1

3. 传址(指针传递)
>>> b = [1,2,3]
>>> def change_l(b):
... b[0] = b[0] + 1
... return b
...
>>> print(change_l(b))
[2, 2, 3]
>>> print(b)
[2, 2, 3]

常见函数OOP

1
2
3
4
5
6
hasattr(o,f)
getattr(o,f)
setattr(o,f,new_f)
delattr(o,f)
isinstance(o,f)
issubclass(c,par)

数据库

1
2
3
4
5
6
7
8
9
1. 连接数据库
2. 创建数据库
3. 创建表
4. 插入数据
5. 查询数据
6. 更新数据
7. 删除数据
8. 提交数据
9. 关闭数据库

python library memory_profiler

python library memory_profiler

  1. 模块说明

    1
    memory_profiler是监控python进程工具,它可以分析出每一行代码所增减的内存状况
  2. 安装

    1
    [root@dev test]# pip install memory_profiler psutil
  3. 示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    [root@dev test]# cat del.py
    import time

    @profile
    def my_func():
    a = [1] * (10 ** 6)
    b = [2] * (2 * 10 ** 7)
    time.sleep(10)
    del b
    del a
    print "+++++++++"

    if __name__ == '__main__':
    my_func()


    [root@dev test]# python -m memory_profiler del.py
    +++++++++
    Filename: del.py

    Line # Mem usage Increment Line Contents
    ================================================
    3 11.285 MiB 0.000 MiB @profile
    4 def my_func():
    5 18.930 MiB 7.645 MiB a = [1] * (10 ** 6)
    6 171.520 MiB 152.590 MiB b = [2] * (2 * 10 ** 7)
    7 171.531 MiB 0.012 MiB time.sleep(10)
    8 18.941 MiB -152.590 MiB del b
    9 11.309 MiB -7.633 MiB del a
    10 11.312 MiB 0.004 MiB print "+++++++++"
  4. 对象不删除,直接赋值,内存是否会继续增长

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    方式一:
    [root@dev test]# cat aaa.py
    @profile
    def my_func():
    a = 'a' * 1024 * 1024 * 1024;
    a = 'a' * 1024 * 1024
    a = 'a' * 1024
    del a
    print "+++++++++"

    if __name__ == '__main__':
    my_func()

    [root@dev test]# python -m memory_profiler aaa.py
    +++++++++
    Filename: aaa.py

    Line # Mem usage Increment Line Contents
    ================================================
    1 11.281 MiB 0.000 MiB @profile
    2 def my_func():
    3 1035.297 MiB 1024.016 MiB a = 'a' * 1024 * 1024 * 1024;
    4 12.285 MiB -1023.012 MiB a = 'a' * 1024 * 1024
    5 12.285 MiB 0.000 MiB a = 'a' * 1024
    6 12.285 MiB 0.000 MiB del a
    7 12.289 MiB 0.004 MiB print "+++++++++"


    方式二:
    [root@dev test]# cat bbb.py
    @profile
    def my_func():
    a = 'a' * 1024 * 1024 * 1024;
    del a
    a = 'a' * 1024 * 1024
    del a
    a = 'a' * 1024
    del a
    print "+++++++++"

    if __name__ == '__main__':
    my_func()
    [root@dev test]# python -m memory_profiler bbb.py
    +++++++++
    Filename: bbb.py

    Line # Mem usage Increment Line Contents
    ================================================
    1 11.277 MiB 0.000 MiB @profile
    2 def my_func():
    3 1035.293 MiB 1024.016 MiB a = 'a' * 1024 * 1024 * 1024;
    4 11.289 MiB -1024.004 MiB del a
    5 12.285 MiB 0.996 MiB a = 'a' * 1024 * 1024
    6 12.285 MiB 0.000 MiB del a
    7 12.285 MiB 0.000 MiB a = 'a' * 1024
    8 12.285 MiB 0.000 MiB del a
    9 12.289 MiB 0.004 MiB print "+++++++++"

    综上,是否del对象没有影响,新赋的值会替代旧的值
  5. 对象赋值是否会增加同样的内存

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    方式一:
    [root@dev test]# cat ccc.py
    @profile
    def my_func():
    a = 'a' * 1024 * 1024 * 1024;
    b = a
    del a
    print "+++++++++"

    if __name__ == '__main__':
    my_func()

    [root@dev test]# python -m memory_profiler ccc.py
    +++++++++
    Filename: ccc.py

    Line # Mem usage Increment Line Contents
    ================================================
    1 11.285 MiB 0.000 MiB @profile
    2 def my_func():
    3 1035.301 MiB 1024.016 MiB a = 'a' * 1024 * 1024 * 1024;
    4 1035.301 MiB 0.000 MiB b = a
    5 1035.301 MiB 0.000 MiB del a
    6 1035.305 MiB 0.004 MiB print "+++++++++"

    方式二:
    [root@dev test]# python -m memory_profiler ddd.py
    +++++++++
    Filename: ddd.py

    Line # Mem usage Increment Line Contents
    ================================================
    1 11.281 MiB 0.000 MiB @profile
    2 def my_func():
    3 1035.297 MiB 1024.016 MiB a = 'a' * 1024 * 1024 * 1024;
    4 1035.297 MiB 0.000 MiB b = a
    5 1035.297 MiB 0.000 MiB del a
    6 11.293 MiB -1024.004 MiB del b
    7 11.297 MiB 0.004 MiB print "+++++++++"

    综上,把a赋值给b,内存没有增加.但是只删除其中一个对象的时候,内存不会减

python 内存管理

python 内存管理

  1. 内存管理

    1
    2
    3
    4
    5
    6
    7
    8
    9
    * 内存状况
    * 引用计数(使用sys包中的getrefcount(param)查看)
    * 对象引用对象
    * 垃圾回收
    * 阈值
    gc.set_threshold()
    gc.get_threshold()
    * 分代回收策略
    * 孤立"引用环"问题
  2. 内存状态

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    在python中,执行"x = 1"后,我们需要了解其过程: 系统先找一块内存,将数字1存储进去,然后将"x"指向当前的这块内存
    如下:
    >>> x = 1
    >>> print(x)
    1
    >>> id(x)
    37577064

    示例1:
    >>> x = 4 # 说明 x 指向了内存地址 37576992,内存地址中存储值为 4
    >>> id(x)
    37576992
    >>> y = 5 # 说明 y 指向了内存地址 37576968,内存地址中存储值为 5
    >>> id(y)
    37576968

    示例2:
    >>> x = y # 说明 x 指向了 y 所指向的内存地址
    >>> id(x)
    37576968
    >>> id(y)
    37576968

    示例3:
    >>> x = 4 # 说明 x 指向了内存地址 37576992,内存地址中存储值为 4
    >>> id(x)
    37576992
    >>> x = 5 # 说明 x 指向了内存地址 37576968,内存地址中存储值为 5
    >>> id(x)
    37576968
    在python中,一开始初始化存储在内存的东西是不可以更改的(x),我们所能更改的只是它的引用

    示例4:
    >>> x = 'hello'
    >>> y = 'hello'
    >>> id(x)
    139654005921952
    >>> id(y)
    139654005921952

    >>> x = "hello world"
    >>> y = "hello world"
    >>> id(x)
    140026311813376
    >>> id(y)
    140026311813280

    综上:
    如果是短字符, x 和 y 指向的是同一个内存引用对象地址,内存地址存储值唯一
    如果是长字符, x 和 y 指向的是不同的内存引用对象地址,即使内存地址存储值一样
  3. 内存引用计数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    引用计数记录指向对象引用的个数:当引用对象时,引用计数加1;当移除对象引用时,引用计数减1;当引用计数变为0,则被释放.引用计数无法释放"引用环"的对象

    引用计数增加:
    * 对象被创建时
    * 别名被创建
    * 被作为参数传递给函数
    * 成为容器对象的一个元素

    引用计数减少:
    * 一个本地引用离开了其作用范围,比如函数结束
    * 对象别名被销毁(del)
    * 对象别名被赋值给其他的对象
    * 对象被从一个容器对象中移除
    * 容器对象本身被销毁

    引用计数获取:
    >>> from sys import getrefcount
    >>> x = 'hello'
    >>> print(getrefcount(x))
    2
    >>> y = x
    >>> print(getrefcount(y))
    3
    >>> z = y
    >>> print(getrefcount(z))
    4
    >>> z = 'world'
    >>> print(getrefcount(z))
    2
    >>> print(getrefcount(y))
    3

    对象引用对象:
    [root@dev test]# cat obj1.py
    #!/usr/bin/env python
    class from_obj(object):
    def __init__(self,to_obj):
    self.to_obj = to_obj
    b = [1,2,3]
    a = from_obj(b)
    print(id(a.to_obj))
    print(id(b))

    [root@dev test]# python obj1.py
    139851871660944
    139851871660944
  4. 垃圾回收

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    垃圾回收机制用来回收循环应用的对象
    垃圾回收机制会根据内存的分配和释放情况的而被调用:比如分配内存的次数减去释放内存的次数大于某一个阈值的时候
    注意: 当内存溢出时,不会自动调用gc,gc更看重的是垃圾对象的个数,而不是大小.

    垃圾回收阈值:
    >>> import gc
    >>> print(gc.get_threshold())
    (700, 10, 10)
    >>> gc.set_threshold(600,10,10)
    >>> print(gc.get_threshold())
    (600, 10, 10)

    调用gc的策略有两种: 一种是固定时间间隔进行调用;另一种是基于事件的调用

    gc垃圾回收方法:
    可以发现,只有容器对象才会出现引用循环,比如:列表,字典,类,元组

    首先,为了追踪容器对象,需要每个容器对象维护两个额外的指针,用来将容器对象组成一个链表,指针分别指向前后两个容器对象,方便插入和删除操作;其次,每个容器对象还得添加gc_refs字段
    一次gc垃圾回收步骤:
    1.使得gc_refs等于容器对象的引用计数
    2.遍历每个容器对象(a),找到它(a)所引用的其它容器对象(b),将那个容器对象(b)的gc_refs减去1
    3.将所有gc_refs大于0的容器对象(a)取出来,组成新的队列,因为这些容器对象被容器对象队列的外部所引用
    4.任何被新队列里面的容器对象,所引用的容器对象(旧队列中)也要加入到新队列里面
    5.释放旧队列里面的剩下的容器对象

    gc分代机制:
    gc采用分代(generations)的方法来管理对象,总共分为三代:generation 0,1,2
    * 新产生的对象放到第0代里面
    * 如果该对象在第0代的一次gc垃圾回收中活了下来,那么它就被放到第1代里面
    * 如果第1代里面的对象在第1代的一次gc垃圾回收中活了下来,它就被放到第2代里面

    gc.set_threshold(threshold0,threshold1,threshold2)
    设置gc每一代垃圾回收所触发的阈值:
    从上一次第0代gc后,如果分配对象的个数减去释放对象的个数大于threshold0,那么就会对第0代中的对象进行gc垃圾回收检查.
    从上一次第1代gc后,如过第0代被gc垃圾回收的次数大于threshold1,那么就会对第1代中的对象进行gc垃圾回收检查
    从上一次第2代gc后,如过第1代被gc垃圾回收的次数大于threshold2,那么就会对第2代中的对象进行gc垃圾回收检查
    如果threshold0设置为0,表示关闭分代机制


    gc常用函数:
    * gc.set_debug(flags)
    设置gc的debug日志,一般设置为gc.DEBUG_LEAK

    * gc.collect([generation])
    显式进行垃圾回收,可以输入参数:0代表只检查第一代的对象;1代表检查一,二代的对象;2代表检查一,二,三代的对象.如果不传参数,执行一个full collection,也就是等于传2

    * gc.set_threshold(threshold0[, threshold1[, threshold2])
    设置自动执行垃圾回收的频率
    例如: (700,10,10)
    当计数器从(699,3,0)增加到(700,3,0),gc模块就会执行gc.collect(0),即检查一代对象的垃圾,并重置计数器为(0,4,0)
    当计数器从(699,9,0)增加到(700,9,0),gc模块就会执行gc.collect(1),即检查一,二代对象的垃圾,并重置计数器为(0,0,1)
    当计数器从(699,9,9)增加到(700,9,9),gc模块就会执行gc.collect(2),即检查一、二、三代对象的垃圾,并重置计数器为(0,0,0)

    * gc.get_count()
    获取当前自动执行垃圾回收的计数器,返回一个长度为3的列表
    例如:(488,3,0)
    488是指距离上一次一代垃圾检查,Python分配内存的数目减去释放内存的数目(注意:是内存分配,而不是引用计数的增加)
    3是指距离上一次二代垃圾检查,一代垃圾检查的次数
    0是指距离上一次三代垃圾检查,二代垃圾检查的次数