深入理解PHP原理之Session Gc的一个小概率Notice


Posted in PHP onApril 12, 2011

如果在ubuntu/Debian下, 采用apt安装的PHP, 那么在使用Session的时候, 就可能会有小概率遇到这个提示.

PHP Notice: session_start(): ps_files_cleanup_dir: 
opendir(/var/lib/php5) failed: Permission denied (13) 
in /home/laruence/www/htdocs/index.php on line 22

这是因为, 在PHP中, 如果使用file_handler作为Session的save handler, 那么就有概率在每次session_start的时候运行Session的Gc过程.
//有省略 
int nrdels = -1; 
nrand = (int) ((float) PS(gc_divisor) * php_combined_lcg(TSRMLS_C)); 
if (nrand < PS(gc_probability)) { 
PS(mod)->s_gc(&PS(mod_data), PS(gc_maxlifetime), &nrdels TSRMLS_CC); 
} 
//有省略

这个警告的原因是因为在apt的PHP中, session的默认目录/var/lib/php5的权限是733 with sticky bit, 也就是
drwx-wx-wt root roo

而一般PHP的worker都运行在非root身份下, 所以是没有权限来打开这个文件夹的(但是因为可以write, 所以不影响正常的Session文件读取). 于是在s_gc中的如下代码, 就会触发开头所说的Notice:
//对于file handler来说, s_gc间接调用ps_files_cleanup_dir: 
dir = opendir(dirname); 
if (!dir) { 
php_error_docref(NULL TSRMLS_CC, E_NOTICE, 
"ps_files_cleanup_dir: opendir(%s) failed: %s (%d)", 
dirname, strerror(errno), errno); 
return (0); 
}

当然, 在ubuntu/Debian下, 还是有gc回收的, 只不过是外部的cron进程来完成的, 默认的在/etc/cron.d/php5:,
09,39 * * * * root [ -x /usr/lib/php5/maxlifetime ] 
&& [ -d /var/lib/php5 ] && find /var/lib/php5/ 
-type f -cmin +$(/usr/lib/php5/maxlifetime) -print0 
| xargs -n 200 -r -0 r

另外, 可以看到, 在判别s_gc是否运行的时候, 有俩个关键变量: PS(gc_divisor)和PS(gc_probability), 这俩个变量分别对应着session的运行时配置项的俩个同名配置项:
session.gc_probability和session.gc_divisor, 他们分别默认为1和100.
而php_combined_lcg是一个随机数发生器, 生成0到1范围的随机数, 所以上面的判别相当于:
rand < probability / gc_diviso

也就是说, 默认情况下, 差不多是100次能调用一次gc过程. 所以也就是小概率的可以看到这个Notice.
要关闭这个Notice, 只需要设置:
session.gc_probability = 0, 让s_gc完全没有运行的可能即可.
当然, 你也可以改变这个文件夹的权限…
最后, 感谢CFC4N提供这个问题.
作者: Laruence( )
本文地址: http://www.laruence.com/2011/03/29/1949.html
PHP 相关文章推荐
PHP 和 XML: 使用expat函数(一)
Oct 09 PHP
php set_magic_quotes_runtime() 函数过时解决方法
Jul 08 PHP
PHP垃圾回收机制引用计数器概念分析
Jun 24 PHP
php常用文件操作函数汇总
Nov 22 PHP
php限制ip地址范围的方法
Mar 31 PHP
刷新PHP缓冲区为你的站点加速
Oct 10 PHP
支付宝服务窗API接口开发php版本
Jul 20 PHP
PHP 微信扫码支付源代码(推荐)
Nov 03 PHP
PHP中的使用curl发送请求(GET请求和POST请求)
Feb 08 PHP
PHP中类型转换 ,常量,系统常量,魔术常量的详解
Oct 26 PHP
php实现表单提交上传文件功能
May 28 PHP
laravel批量生成假数据的方法
Oct 09 PHP
php表单提交问题的解决方法
Apr 12 #PHP
使用NetBeans + Xdebug调试PHP程序的方法
Apr 12 #PHP
php产生随机数的两种方法实例代码 输出随机IP
Apr 08 #PHP
PHP随机数生成代码与使用实例分析
Apr 08 #PHP
PHP的cURL库功能简介 抓取网页、POST数据及其他
Apr 07 #PHP
php curl 登录163邮箱并抓取邮箱好友列表的代码(经测试)
Apr 07 #PHP
The specified CGI application misbehaved by not returning a complete set of HTTP headers
Mar 31 #PHP
You might like
PHP下10件你也许并不了解的事情
2008/09/11 PHP
显示程序执行时间php函数代码
2013/08/29 PHP
smarty内置函数section的用法
2015/01/22 PHP
Zend Framework教程之MVC框架的Controller用法分析
2016/03/07 PHP
JS 实现双色表格实现代码
2009/11/24 Javascript
拖动table标题实现改变td的大小(css+js代码)
2013/04/16 Javascript
jquery实现清新实用的网页菜单效果
2015/08/28 Javascript
React组件的三种写法总结
2017/01/12 Javascript
Vue 组件传值几种常用方法【总结】
2018/05/28 Javascript
JS内部事件机制之单线程原理
2018/07/02 Javascript
vue微信分享到朋友圈 vue微信发送给好友
2018/11/28 Javascript
angular中两种表单的区别(响应式和模板驱动表单)
2018/12/06 Javascript
vue选项卡切换登录方式小案例
2019/09/27 Javascript
Javascript执行上下文顺序的深入讲解
2020/11/04 Javascript
[42:32]完美世界DOTA2联赛循环赛 Magma vs PXG BO2第二场 10.28
2020/10/28 DOTA
python 判断一个进程是否存在
2009/04/09 Python
pyqt4教程之widget使用示例分享
2014/03/07 Python
Python Tkinter GUI编程入门介绍
2015/03/10 Python
在Python中操作字典之update()方法的使用
2015/05/22 Python
python和opencv实现抠图
2018/07/18 Python
PyCharm搭建Spark开发环境的实现步骤
2019/09/05 Python
浅谈PyQt5中异步刷新UI和Python多线程总结
2019/12/13 Python
如何学习Python time模块
2020/06/03 Python
爱尔兰电子产品购物网站:Komplett.ie
2018/04/04 全球购物
Saucony澳大利亚官网:美国跑鞋品牌,运动鞋中的劳斯莱斯
2018/05/05 全球购物
为您搜罗全球潮流時尚品牌:HBX
2019/12/04 全球购物
美国农场商店:Blain’s Farm & Fleet
2020/01/17 全球购物
年度考核自我评价
2014/01/25 职场文书
安全生产中长期规划实施方案
2014/02/21 职场文书
好听的队名和口号
2014/06/09 职场文书
学用政策心得体会
2014/09/10 职场文书
乡镇党的群众路线教育实践活动个人整改方案
2014/10/31 职场文书
护理心得体会范文
2016/01/22 职场文书
诗词赏析-(浣溪沙)
2019/08/13 职场文书
PHP命令行与定时任务
2021/04/01 PHP
golang gopm get -g -v 无法获取第三方库的解决方案
2021/05/05 Golang