分类目录归档:开发

nginx spdy patch for 1.14.0 1.13.12

spdy 协议由于安卓碎片化的存在 暂时还是需要保留一段时间的兼容性

准备升级到nginx1.14的时候发现 work process 会自动 退出, 同时系统日志有 nginx segfault的信息

修改配置,抓取coredump信息,需要做以下内容
nginx 增加

worker_rlimit_core 5000M;
working_directory /path/to/cores/;
$> ulimit -c unlimited
$> mkdir /opt/coredump/ && chown nobody.nobody /opt/coredump/ # 先建目录,还要确认nginx用户可以写此目录
$> echo “/opt/coredump/core-%e-%p-%h-%t” > /proc/sys/kernel/core_pattern

拿到coredump文件后使用gdb分析

gdb /path/to/nginx /path/to/cores/nginx.core
backtrace full

发现问题指向了
src/http/ngx_http_spdy.c:ngx_http_spdy_state_read_data 的
buf->last = ngx_cpymem(buf->last, pos, size);

简单调试发现buf->last是个0, ngx_cpymem会因为内存越界导致coredump

而分析代码 + gdb 断点调试 看到初始化r->request_body->buf的部分: ngx_http_spdy_init_request_body(r) 并未执行

打印r->request_body 内容发现这块被初始化了,对比nginx1.12.2和1.10.3版本发现旧版本则是未做初始化

翻了下调用的部分:ngx_http_request_body: ngx_http_read_client_request_body 可以看到在nginx 1.13.12版本开始会对r->request_body 做了初始化操作,这部分直接导致了SPDY 补丁 的不兼容

所以答案就很简单了,修改下判断条件即可

新补丁放在了:https://github.com/favortel/nginx_patch/blob/master/nginx-1.14.0_spdy_h2.patch
参考文档:
https://toontong.github.io/blog/nginx-gdb-coredump-segfault.html
https://www.nginx.com/resources/wiki/start/topics/tutorials/debugging/
http://lxr.nginx.org/source/src/http/ngx_http_request_body.c
http://lxr.nginx.org/source/src/http/ngx_http_request_body.c?v=nginx-1.12.2

gcc 与 ld 的lib顺序

事情是这样子的,有个编译出来的.so文件,死活在找一个诡异版本的libcrypto.so,而我检查过环境变量和编译参数还有ldconfig,并未包含这些东西
绕了一个大圈子,查找编译文件并未包含这些路径,最后在简化测试的时候发现了问题所在
#ld -shared -o test.so -lcrypto
极为简单的一个测试,发现在故障机器上编译出来的.so还是包含了错误的libcrypto.so
strace下发现了问题,这是因为ld有个依赖顺序:
“/usr/x86_64-redhat-linux/lib64/”,”/usr/local/lib64/”, “/lib64/”,/usr/lib64/, /usr/x86_64-redhat-linux/lib/ , /lib/ , /usr/lib/

而刚巧,这机器在/usr/local/lib64/被不知名土人放了个错误版本的libcrypto.so

另外,补充下,如果用了-L参数指定路径,那么这个路径则是最优先的

而LD_LIBRARY_PATH 则是执行时查找的动态链接库位置,跟ldconfig功能一样,不影响编译,因此以上例子查找ldconfig是不必要的

而最重要的是解决问题的思路,分割问题==>缩小范围==>定位问题!

python 替换\n

一般来说,python可以通过strip() 或者replace(‘\n’,”)的方式来替换掉\n 字符

不过改动某个功能代码的时候异常的发现两种替换方式都失败了,debug定位了下,发现数据是通过readlines()的方式读取进来的
而readlines 会自动的把字符中的\r\n 更改为 \\r\\n,从而导致替换失败

嗯,如果是readlines的数据,只能用replace(‘\\n’,”)了
当然,不要用readlines比较好

半吊子的程序员之: python 抓不到的execpt

最近写了个try except的时候,发现每次都出现except,但是注释掉try except代码却不出错
try:
code line 1
code line 2

except:
excpet code …

查了下文档,可以用sys.exc_info()[0]把excpet信息打印出来
我的这个例子中刚好是在函数块中直接sys.exit(X),导致了exceptions.SystemExit
于是改了下代码,在main函数中处理了下,才sys.exit(X),错误自然也就没了

恩恩,我是半吊子的程序猿

python mysql乱码问题

最近临时有个需求需要用python 爬点中文数据,结果悲催的发现乱码了

查了下资料,这里做下总结:

1. 首先python的代码需要是UTF-8的

# -*- coding: utf-8 -*-

2.确认mysql的数据库和表编码是UTF8的

show create database …

show create table…

如果不是,alter table或者database设置下编码(请注意alter database编码造成的影响)

3.pytho mysql连接时确认使用UTF8

MySQLdb.connect (…,charset=’utf8′)

4.暂时来说,应该是正常的了,如果还不行,请尝试如下操作:

修改/etc/my.cnf

[client]default-character-set = utf8

[mysqld]default-character-set = utf8

在python代码中增加:

reload(sys)

sys.setdefaultencoding(‘utf-8’)

正则表达式说明


  传统上,POSIX 定义了两种正则表达式语法, 即:基本正则表达式(BRE)和扩展正则表
  达式(ERE)。

  其中, BRE 定义的语法符号包括:

  .       - 匹配任意一个字符。
  []      - 字符集匹配,匹配方括号中定义的字符集之一。
  [^]     - 字符集否定匹配,匹配没有在方括号中定义的字符。
  ^       - 匹配开始位置。
  $       - 匹配结束位置。
  \(\)    - 定义子表达式。
  \n      - 子表达式向前引用,n 为 1-9 之间的数字。 由于此功能已超出正则语义,需
            要在字符串中回溯,因此需要使用 NFA 算法进行匹配。
  *       - 任意次匹配(零次或多次匹配)。
  \{m,n\} - 至少 m 次,至多 n 次匹配;\{m\} 表示 m 次精确匹配;\{m,\} 表示至少 m
            次匹配。

  ERE 修改了 BRE 中的部分语法,并增加了以下语法符号:

  ?       - 最多一次匹配(零次或一次匹配)。
  +       - 至少一次匹配(一次或更多次匹配)。
  |       - 或运算,其左右操作数均可以为一个子表达式。

  同时,ERE 取消了子表达式 "()" 和 次数匹配 "{m,n}" 语法符号的转义符引用语法,在
  使用这两种语法符号时,不在需要添加转义符。 与此同时, ERE 也取消了非正则语义的
  子表达式向前引用能力。

  BRE 和 ERE 共享同样的 POSIX 字符类定义。同时,它们还支持字符类比较操作 "[. .]"
  和字符来等效体 "[= =]" 操作,但很少被使用。

  f / fr / wfr / bwfr 等工具默认使用 ERE 模式,同时支持以下 perl 风格的字符类:

 	POSIX 类        perl类     描述
    ----------------------------------------------------------------------------
	[:alnum:]	               字母和数字
	[:alpha:]       \a         字母
	[:lower:]       \l         小写字母
	[:upper:]       \u         大写字母
	[:blank:]                  空白字符(空格和制表符)
	[:space:]       \s         所有空格符(比[:blank:]包含的范围广)
	[:cntrl:]                  不可打印的控制字符(退格、删除、警铃...)
	[:digit:]       \d         十进制数字
	[:xdigit:]      \x         十六进制数字
	[:graph:]                  可打印的非空白字符
	[:print:]       \p         可打印字符
	[:punct:]                  标点符号

  - 此外,还有以下特殊字符类:

	perl类    等效POSIX表达式   描述
    ----------------------------------------------------------------------------
	\o        [0-7]             八进制数字
	\O        [^0-7]            非八进制数字
	\w        [[:alnum:]_]      单词构成字符
	\W        [^[:alnum:]_]     非单词构成字符
	\A        [^[:alpha:]]      非字母
	\L        [^[:lower:]]      非小写字母
	\U        [^[:upper:]]      非大写字母
	\S	 [^[:space:]]      非空格符
	\D        [^[:digit:]]      非数字
	\X        [^[:xdigit:]]     非十六进制数字
	\P        [^[:print:]]      非可打印字符

  - 还可以使用以下特殊字符换码序列:

	\r  -  回车
	\n  -  换行
	\b  -  退格
	\t  -  制表符
	\v  -  垂直制表符
	\"  -  双引号
	\'  -  单引号

python 的与或非

def intersect(a, b):

“”” return the intersection of two lists “””
return list(set(a) & set(b))

def union(a, b):
“”” return the union of two lists “””
return list(set(a) | set(b))

def difference(a, b):
“”” show whats in list b which isn’t in list a “””
return list(set(b).difference(set(a)))
备注:这里应该是list(set(b)-set(a))

这个代码非常方便的使用在比较两份海量url的共同元素上