Welcome to Snooda's Blog
lighttpd的一个日志文件打印切分bug
[| 2013/10/23 15:16]
lighttpd有一个功能,就是收到SIGHUP信号时会重新打开日志文件。这样在日志切分时很有用。但最近发现了一个bug。
就是如果有子进程挂掉。父进程新fork出的子进程accesslog会默认打日志到最最开始父进程启动时的那个文件里。
看了下代码。原来父进程在收到SIGHUP的时候只是把errorlog重新打开了下。没有重新打开accesslog(没办法,这个句柄是mod_accesslog模块搞的)。所以父进程维护的accesslog句柄一直是最老的。它本身不打accesslog日志倒无所谓。但它fork出的子进程是打的。这样就有问题了。
一个最简单方法。就是外部脚本判断进程有更新的时候发一个SIGHUP信号过去。
根治方法就是父进程重新启动子进程时给其发一个SIGHUP信号。
至于父进程自己处理SIGHUP时重新打开句柄这个我感觉不太好。毕竟那是模块内部数据。lighttpd主干不应该关心。
就是如果有子进程挂掉。父进程新fork出的子进程accesslog会默认打日志到最最开始父进程启动时的那个文件里。
看了下代码。原来父进程在收到SIGHUP的时候只是把errorlog重新打开了下。没有重新打开accesslog(没办法,这个句柄是mod_accesslog模块搞的)。所以父进程维护的accesslog句柄一直是最老的。它本身不打accesslog日志倒无所谓。但它fork出的子进程是打的。这样就有问题了。
一个最简单方法。就是外部脚本判断进程有更新的时候发一个SIGHUP信号过去。
根治方法就是父进程重新启动子进程时给其发一个SIGHUP信号。
至于父进程自己处理SIGHUP时重新打开句柄这个我感觉不太好。毕竟那是模块内部数据。lighttpd主干不应该关心。
lighttpd中CONST_STR_LEN的用法
[| 2012/07/05 19:49]
今天遇到一个问题,在获取http头的时候怎么也获取不到,手动core出来和gdb上去调试发现都是空的,应该是开了O2优化的缘故,于是在程序中打印http头,正常。
不得已,单步gdb进匹配函数里,发现一个四字符的key值长度被判定为8,很奇怪,查代码原来是用了个CONST_STR_LEN来代替了本来应该填ptr, strlen(ptr)的位置。而CONST_STR_LEN是一个宏,内容为:x, x ? sizeof(x) - 1 : 0。显然,如果传一个指针进去的话,sizeof指针的结果是8(字节,x64),这个宏只能在内容是字符串常量的时候用,不可以用在指针上。当时用的时候看lighttpd代码中一些地方用了这个宏,于是想当然认为到处都可用。。看来还是要注意一些。
不得已,单步gdb进匹配函数里,发现一个四字符的key值长度被判定为8,很奇怪,查代码原来是用了个CONST_STR_LEN来代替了本来应该填ptr, strlen(ptr)的位置。而CONST_STR_LEN是一个宏,内容为:x, x ? sizeof(x) - 1 : 0。显然,如果传一个指针进去的话,sizeof指针的结果是8(字节,x64),这个宏只能在内容是字符串常量的时候用,不可以用在指针上。当时用的时候看lighttpd代码中一些地方用了这个宏,于是想当然认为到处都可用。。看来还是要注意一些。
lighttpd打印日志出core的问题
[| 2012/06/15 17:17]
有一个问题,是在一个环境上的lighttpd一打日志就出core,很奇怪,看堆栈信息是出在mod_accesslog里,今天看了下,发现原来是试图打印%i导致的。
lighttpd支持在日志中打印请求头中的字段,方法是%{key}i,这样就能在请求头中的key字段打印到日志里,打印referer等东西的时候比较方便。
但如果直接写%i的话,由于没有指定key,导致NULL指针,lighttpd没有校验导致出core。
恰好%I是打印请求长度,大写I还是比较容易误按成小写的。所以有了这个问题
lighttpd支持在日志中打印请求头中的字段,方法是%{key}i,这样就能在请求头中的key字段打印到日志里,打印referer等东西的时候比较方便。
但如果直接写%i的话,由于没有指定key,导致NULL指针,lighttpd没有校验导致出core。
恰好%I是打印请求长度,大写I还是比较容易误按成小写的。所以有了这个问题
lighttpd中钩子(hook)函数的使用
[| 2012/04/24 22:57]
lighttpd内部使用了状态机处理每个请求,在状态机中插入了若干个钩子来供扩展使用,在执行到钩子函数那里时,会按扩展载入顺序,依次回调使用了该钩子的各扩展指定的函数,这样会有一些编程中隐藏的易错点。
1,顺序在后面的钩子不能假定前面的钩子函数一定会被执行到。
之前遇到过这样的问题,在一个扩展中使用了两个钩子函数,第一个里面申请了一些资源,第二个里面使用并释放,结果实际中发现对于某些请求,第一个钩子可能没有被执行就到了第二个钩子那里,于是出core。
查了一下原因,原来排在该扩展前面的mod_access扩展在第一个钩子被调用时返回了HANDLER_FINISH,这样,对于后续调用该钩子的其他扩展不会被回调。于是该扩展的第一个钩子函数未被调用到。
2,同一个钩子可能会被调用多次。
一些情况下,连接状态会rollback,这样的话同一个hook会被回调多次,还有一些情况会导致调用多次,比如给多个钩子指定了同一个处理函数。
有时我们需要为每个扩展在每个连接生命周期内维护一个变量,这时可以用到con->plugin_ctx[p->id],这是一个void *指针,把数据指针存入该变量,并在连接释放时释放掉即可。
1,顺序在后面的钩子不能假定前面的钩子函数一定会被执行到。
之前遇到过这样的问题,在一个扩展中使用了两个钩子函数,第一个里面申请了一些资源,第二个里面使用并释放,结果实际中发现对于某些请求,第一个钩子可能没有被执行就到了第二个钩子那里,于是出core。
查了一下原因,原来排在该扩展前面的mod_access扩展在第一个钩子被调用时返回了HANDLER_FINISH,这样,对于后续调用该钩子的其他扩展不会被回调。于是该扩展的第一个钩子函数未被调用到。
2,同一个钩子可能会被调用多次。
一些情况下,连接状态会rollback,这样的话同一个hook会被回调多次,还有一些情况会导致调用多次,比如给多个钩子指定了同一个处理函数。
有时我们需要为每个扩展在每个连接生命周期内维护一个变量,这时可以用到con->plugin_ctx[p->id],这是一个void *指针,把数据指针存入该变量,并在连接释放时释放掉即可。
etag生成规则的配置-lighttpd
[| 2012/04/11 15:20]
最近两天调试一个程序的时候遇到一个问题,发现把一个文件两行对换位置的时候lighttpd不会载入新文件,增加或删除一行就会,考虑到lighttpd有stat cache,怀疑是不是不考虑mtime,只看inode,于是cp了一下,发现还是不行。没办法开gdb调试了一下,囧,原来生成的etag只用到了文件size这一个参数。怪不得。
# 生成ETag的时候是否考虑文件的inode
etag.use-inode = "enable"
# 生成ETag的时候是否考虑文件的mtime
etag.use-mtime = "enable"
# 生成ETag的时候是否考虑文件的size
etag.use-size = "enable"
这是引发困扰的三个参数。平时建议全部开启,或开启后两个。
# 生成ETag的时候是否考虑文件的inode
etag.use-inode = "enable"
# 生成ETag的时候是否考虑文件的mtime
etag.use-mtime = "enable"
# 生成ETag的时候是否考虑文件的size
etag.use-size = "enable"
这是引发困扰的三个参数。平时建议全部开启,或开启后两个。
lighttpd日志切分
[| 2012/03/09 18:56]
之前在读代码的时候发现lighttpd在收到SIGHUP信号后会把日志重新打开一下,一直没有理解这么做的意义是什么。今天终于用到了这个功能。
一个新模块没有使用cronlog等日志切分工具,直接打印日志到文件,(使用管道切分日志有风险,被打印程序一旦hang住,lighttpd也就卡住了),但如何切分日志文件就变成了一个问题。mv的话由于不改变inode,还是往同一个文件打。cp代价太大。直接清空日志的话又太粗暴。这里就用到了sighup功能。只要将文件mv到新名字,然后用killall -s SIGHUP lighttpd,这样lighttpd就会自动重新打开lighttpd.log打印了。
一个新模块没有使用cronlog等日志切分工具,直接打印日志到文件,(使用管道切分日志有风险,被打印程序一旦hang住,lighttpd也就卡住了),但如何切分日志文件就变成了一个问题。mv的话由于不改变inode,还是往同一个文件打。cp代价太大。直接清空日志的话又太粗暴。这里就用到了sighup功能。只要将文件mv到新名字,然后用killall -s SIGHUP lighttpd,这样lighttpd就会自动重新打开lighttpd.log打印了。
HTTP请求返回码204
[| 2011/10/27 18:49]
今天测试lighttpd是否支持delete请求,发现webdav模块可以实现此功能。不过发现http返回码是204,查了一下,原来此状态码的意思是说请求成功了,但是没有结果返回来。搜到鸟哥一篇文章,讲的很不错,转载一下:
http://www.laruence.com/2011/01/20/1844.html
之前和人讨论过这个问题,,, 今天感冒在家休息, 就回忆了一下, 整理如下.
我们很多的应用在使用Ajax的时候, 大多数情况都是询问型操作, 比如提交数据, 则Ajax只是期待服务器返回:
{status: 0, message:""} //status 0代表成功, 非零的时候, message中包含出错信息.
我们知道HTTP的状态码, 2xx都是表示成功, 而HTTP的204(No Content)响应, 就表示执行成功, 但是没有数据, 浏览器不用刷新页面.也不用导向新的页面.
在HTTP RFC 2616中关于204的描述如下:
类似的还有205 Reset Content, 表示执行成功, 重置页面(Form表单).
于是, 当有一些服务, 只是返回成功与否的时候, 可以尝试使用HTTP的状态码来作为返回信息, 而省掉多余的数据传输, 比如REST中的DELETE和如上所述的查询式Ajax请求.
最后说说205, 205的意思是在接受了浏览器POST请求以后处理成功以后, 告诉浏览器, 执行成功了, 请清空用户填写的Form表单, 方便用户再次填写,
总的来说, 204适合多次对一个Item进行更新, 而205则适合多次提交一个系列的Item.
但, 请注意, 目前还没有一个浏览器支持205, 大部分的浏览器, 都会把205当做204或者200同样对待.
http://www.laruence.com/2011/01/20/1844.html
之前和人讨论过这个问题,,, 今天感冒在家休息, 就回忆了一下, 整理如下.
我们很多的应用在使用Ajax的时候, 大多数情况都是询问型操作, 比如提交数据, 则Ajax只是期待服务器返回:
{status: 0, message:""} //status 0代表成功, 非零的时候, message中包含出错信息.
我们知道HTTP的状态码, 2xx都是表示成功, 而HTTP的204(No Content)响应, 就表示执行成功, 但是没有数据, 浏览器不用刷新页面.也不用导向新的页面.
在HTTP RFC 2616中关于204的描述如下:
引用
If the client is a user agent, it SHOULD NOT change its document view from that which caused the request to be sent. This response is primarily intended to allow input for actions to take place without causing a change to the user agent’s active document view, although any new or updated metainformation SHOULD be applied to the document currently in the user agent’s active view.
类似的还有205 Reset Content, 表示执行成功, 重置页面(Form表单).
引用
The server has fulfilled the request and the user agent SHOULD reset the document view which caused the request to be sent. This response is primarily intended to allow input for actions to take place via user input, followed by a clearing of the form in which the input is given so that the user can easily initiate another input action.
于是, 当有一些服务, 只是返回成功与否的时候, 可以尝试使用HTTP的状态码来作为返回信息, 而省掉多余的数据传输, 比如REST中的DELETE和如上所述的查询式Ajax请求.
最后说说205, 205的意思是在接受了浏览器POST请求以后处理成功以后, 告诉浏览器, 执行成功了, 请清空用户填写的Form表单, 方便用户再次填写,
总的来说, 204适合多次对一个Item进行更新, 而205则适合多次提交一个系列的Item.
但, 请注意, 目前还没有一个浏览器支持205, 大部分的浏览器, 都会把205当做204或者200同样对待.